Files
zeekayandHanzo Dev c381a82ac4 say who holds the keys, on the screens where it matters
The landing page claimed a non-custodial wallet and non-custodial vaults
— the term the April interface relief is defined around — for a product
where bankd derives every signing key from the deploy mnemonic, holds it,
and signs with it. The threshold-MPC claim was false twice: it described
custody the customer does not have, by a mechanism that does not exist.

Two errors underneath the copy. Wallet hardcoded note="Testnet" whatever
the network, so real holdings would have read as play money on mainnet.
And the Earn note put the collateral at the account's address when
evmMarket.Deposit transfers it into the market contract and mints the
position NFT to the account — the money was in the wrong place in the
sentence describing where the money is.

A plan perk still advertised a non-custodial crypto wallet; its mirror in
lux-apps/credit moves with it, as the two are one list.

The custody note states one mechanical fact, who signs, and sits where
the customer commits rather than in a footer — on Wallet, on Earn, and
inside the Earn modal, because the modal covers the page at the moment of
commitment.

What it does not cover, and the document now says so: the wallet's ETH
and BTC are bridged tokens, so a holder has a claim on bridge backing
rather than the asset, and no screen says that. Who backs that bridge is
not established anywhere either, which is why the gap is recorded instead
of written around.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-26 16:33:49 -07:00

103 lines
3.3 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package collections
import "github.com/hanzoai/base/core"
// Plan is a Lux membership tier — one ladder across the bank
// (lux.finance), the card program (lux.credit), and the platform.
// Monetary values are minor units (cents); percentages are on majors.
// Priced above the issuer cost basis (see the sfprivate fee schedule
// on docs.lux.financial): account + card stack $25/mo, wires $75,
// ACH $10, FX 1.75–2.55%, deposit 1%.
type Plan struct {
ID string `json:"id"`
Name string `json:"name"`
Monthly int64 `json:"monthly"`
Card string `json:"card"` // included card: virtual | plastic | metal
IBAN bool `json:"iban"` // wallet bank account included
FreeACH int `json:"freeACH"`
FreeWires int `json:"freeWires"`
ACHFee int64 `json:"achFee"` // beyond allowance
WireFee int64 `json:"wireFee"` // beyond allowance
FXPct float64 `json:"fxPct"`
DepositPct float64 `json:"depositPct"`
DailyLimit int64 `json:"dailyLimit"`
MonthlyLimit int64 `json:"monthlyLimit"`
Holders int `json:"holders"`
Invite bool `json:"invite,omitempty"`
Perks []string `json:"perks"`
}
// Plans is the published ladder, lowest to highest.
var Plans = []Plan{
{
ID: "silver", Name: "Silver", Monthly: 29_00,
Card: "virtual", IBAN: false,
FreeACH: 2, FreeWires: 0, ACHFee: 15_00, WireFee: 95_00,
FXPct: 2.25, DepositPct: 1.5,
DailyLimit: 10_000_00, MonthlyLimit: 100_000_00, Holders: 1,
Perks: []string{
"Virtual card in Apple Pay + Google Pay",
"Multi-currency ewallet + P2P",
"Built-in crypto wallet",
},
},
{
ID: "gold", Name: "Gold", Monthly: 99_00,
Card: "plastic", IBAN: true,
FreeACH: 10, FreeWires: 1, ACHFee: 12_00, WireFee: 85_00,
FXPct: 1.95, DepositPct: 1.25,
DailyLimit: 50_000_00, MonthlyLimit: 500_000_00, Holders: 1,
Perks: []string{
"Dedicated IBAN account",
"Plastic card, shipped worldwide",
"Priority support",
},
},
{
ID: "black", Name: "Black", Monthly: 299_00,
Card: "metal", IBAN: true,
FreeACH: 100, FreeWires: 3, ACHFee: 0, WireFee: 85_00,
FXPct: 1.45, DepositPct: 1.0,
DailyLimit: 250_000_00, MonthlyLimit: 2_500_000_00, Holders: 2,
Perks: []string{
"Metal card (annual commitment)",
"Free ACH, 3 free wires monthly",
"Borrow against your crypto — Liquid Protocol",
"Pairs with the lux.credit Black Card",
},
},
{
ID: "sovereign", Name: "Sovereign", Monthly: 999_00,
Card: "metal", IBAN: true, Invite: true,
FreeACH: 100, FreeWires: 10, ACHFee: 0, WireFee: 75_00,
FXPct: 0.95, DepositPct: 0.75,
DailyLimit: 1_000_000_00, MonthlyLimit: 10_000_000_00, Holders: 3,
Perks: []string{
"Private banker + concierge",
"10 free wires monthly, FX under 1%",
"Up to 3 account holders",
"Pairs with the lux.credit Sovereign Card",
},
},
}
// planField is the accounts-collection membership field; empty means the
// entity-type default limits apply.
func planField() *core.SelectField {
ids := make([]string, len(Plans))
for i, p := range Plans {
ids[i] = p.ID
}
return &core.SelectField{Name: "plan", Values: ids, MaxSelect: 1}
}
// PlanByID returns the plan, or false when the id names no tier.
func PlanByID(id string) (Plan, bool) {
for _, p := range Plans {
if p.ID == id {
return p, true
}
}
return Plan{}, false
}