Wallet Infrastructure
Wallet Infrastructure
Wallets

Creating Wallets

Non-treasury and treasury wallets, passkeys, and the networks and assets each supports.

Networks and assets

Each wallet type is a moduleId.

moduleIdNetworksAssets
evm_erc4337Ethereum, Base, Arbitrum, Polygon, Celo, Optimism and PlasmaUSD₮ on every network (also USD₮0 on Optimism); XAUT on Ethereum, Arbitrum, Polygon and Plasma
bitcoinBitcoinBTC
sparkSparkBTC
solanaSolanaUSD₮
tronTronUSD₮
tonTONUSD₮

On the EVM networks the wallet is a Safe smart account, with the same address on every chain.

How wallets are secured

NetworkWho holds the keyWhat the customer's passkey does
EVMThe passkey is an owner of the wallet's SafeSigns each payment itself; the Safe on chain enforces it.
Bitcoin, Spark, Solana, Tron, TONThe wallet key is held in our signing enclaveApproves the exact transfer; the enclave signs only after verifying it.

On every network, an API key alone cannot move funds.

Get wallet control shows, for each EVM network, the Safe's owners, how many are passkeys, its signing threshold, and whether the customer's passkey is the only key.

Passkeys

A wallet is secured by your customer's passkey. There is no seed phrase. Register a passkey on the customer's device and send its registration:

FieldValue
credentialIdThe passkey's credential ID.
credentialPublicKeyThe passkey's public key.
rpIdYour domain, the relying party of the passkey.
originsThe origins the passkey is used from.

One network or all

RequestCreates
Provision walletsA wallet on every network, all secured by the same passkey.
Create walletA wallet for one moduleId.

Both take the customer in the x-customer-id header.

Non-treasury and treasury

Wallets are non-treasury by default. Set isTreasury: true to create a treasury wallet, which supports multiple signers, approvals and spending limits. See Treasury.

Adding another passkey

Add passkey registers a second passkey, for example a new device, approved with a passkey the customer already has. On EVM the new passkey also becomes an owner of the Safe.

If that on-chain step does not start, the response says onChain.status: "not_started" with retryable: true. Finish it with Retry passkey enrolment, naming the current owner (existingOwner) by the passkeyPublicKey from List passkeys.

On this page