Skip to main content
MoonPay WaaS gives your users a self-custodial, embedded wallet without asking them to install an extension, manage a seed phrase, or leave your app. A wallet is minted with a single SDK call for Ethereum/EVM, Solana/SVM, or Tron, and it is ready to receive, hold, and send stablecoins immediately. WaaS is a separate integration with its own SDK, credentials, and dashboard. It does not run on your MoonPay Enterprise API key, and you can adopt it with or without the rest of MoonPay Enterprise.

Multi-chain

Ethereum/EVM, Solana/SVM, and Tron from one integration.

Self-custodial by construction

2-of-2 MPC signing. No party, including MoonPay, can sign alone.

On-demand creation

Mint a wallet the moment a user needs one. Never automatic at signup.

Exportable

Users can export their private key at any time. No lock-in.

How it works

A wallet key is never stored whole. It exists as two MPC (multi-party computation) shares: one held by the user’s browser and protected by their passkey, one held by an isolated server-side signer. Both must participate to produce a signature, so neither MoonPay nor your app can move funds unilaterally.

MoonPay WaaS SDK documentation

Install the SDK, log a user in, and create a wallet.

Why it matters

Partners building banks, fintechs, remittance platforms, payroll products, and PSPs on MoonPay Enterprise all face the same problem. Once fiat becomes a stablecoin, it has to live somewhere. Standing up wallet infrastructure yourself means owning key management, custody risk, and passkey and recovery UX that has nothing to do with your core product. Wallet as a Service removes that build. If you also run MoonPay Enterprise, the two compose in your own code: Virtual Accounts turn incoming fiat into stablecoins, and a WaaS wallet is one place those stablecoins can land, self-custodial and under the end customer’s control. You pass the address the SDK returns into the MoonPay Enterprise flow yourself.
Sending funds to a WaaS wallet through an Autoramp flow means registering its address against the customer first, the same as any other external wallet. See Crypto Addresses.

Chain support

Every chain shares the same wallet creation, passkey protection, import/export, and delegated signing model described below. Only the signing surface differs per chain.

Wallet lifecycle

Creation

Wallets are never minted automatically at signup or login. Your app calls the chain-specific creation hook explicitly. The first wallet a user creates also triggers passkey enrollment, since the passkey is what protects the wallet’s key material from then on.
For a brand-new user, collapse passkey enrollment and the first wallets into a single biometric prompt instead of two:

Listing a user’s wallets

Importing an existing wallet

Users can bring a wallet they already hold, from either a raw private key or a 12 or 24 word BIP-39 seed phrase, with optional passphrase and account/address index selection matching the derivation conventions of MetaMask, Ledger Live, Phantom, and Solflare. The import runs the split into MPC shares client-side. The plaintext key is never sent to MoonPay and is discarded after the ceremony.
A bulkImport variant imports up to 20 keys, potentially mixing chains, in a single passkey prompt instead of one prompt per key. It returns per-key success and failure detail. Imported addresses are screened for sanctions and AML risk before the wallet is persisted, the same as newly created ones.

Exporting a private key

Export is the one flow where a complete private key is ever assembled, and it happens only in the user’s own browser after a fresh passkey check. Never on MoonPay servers. This is what keeps the model self-custodial: a user can always take their assets and leave.
Export stays available even to compliance-blocked accounts. Blocking prevents new platform activity, it does not confiscate funds.

Security model

Passkeys protect the key, not login

A passkey here is not a login method. Users sign in with email OTP or OAuth. Each enrolled passkey wraps the encryption key that protects a user’s wallet share, and a fresh passkey assertion proves the user is present for sensitive operations: signing, export, adding a passkey, revoking an agent.
On passkey-only apps, losing every enrolled passkey with no synced copy means the wallet cannot be recovered. Prompt users to enroll more than one, or enable identity-backed encryption for a recovery path.

Identity-backed encryption (no passkey)

An optional second encryption path lets a signed-in session read and write key shares, prove key ownership, and sign, with no passkey prompt. Users can then hold a wallet without ever enrolling a passkey. Enrolling or adding a wrap still takes a passkey assertion or an emailed code, and removing the identity wrap takes a passkey. This is a different trust trade. The share is wrapped by a cloud KMS key that MoonPay operates, which decrypts only for a request proving it acts for one specific user of one app. MoonPay is therefore in the unwrap path, where passkey wrapping leaves it unable to unwrap at all. Users gain recovery if they lose their passkeys and accept that custody risk. That fits consumer apps where device loss is common. It does not fit applications whose users expect that no party but themselves can ever reach key material. To run identity-first, ask MoonPay to enable it for your app, then:
  • Read kmsWrapEnabled, hasKmsWrap, and hasPasskey from usePasskeyStatus()
  • Call enableAccountRecovery() once per authenticated user who has no wrap yet
  • Gate wallet operations on hasPasskey === true || hasKmsWrap === true, not on hasPasskey alone
  • Offer registerPasskey() from settings as an optional upgrade
There is nothing to configure in your app. MoonPay enables identity-backed encryption per app during onboarding, and once your app stores its first identity-backed wrap the configuration behind it is fixed. See Identity-backed encryption and Identity-first setup.

Delegated and server-side signing

A user can authorize a scoped, revocable agent identity, such as a trading bot, a payroll scheduler, or an AI agent, to sign on their wallet’s behalf without handing over the private key. Provisioning runs inside an attested secure enclave. The browser verifies the enclave’s attestation before sealing key shares to it, and the resulting agent keypair is shown to your app exactly once. Server-side signing then requires two independent credentials, your app’s secret key and a signature from the agent’s own key, so neither one alone is enough to forge a signature. The user can revoke any agent at any time via a fresh passkey check.

Signing and transactions

Every chain exposes chain-specific hooks, imported from @moon-x/react-sdk/ethereum, /solana, or /tron, with a consistent shape. Pass the target wallet and get back a signature, signed transaction, or broadcast result.

Ethereum and EVM

Solana

Tron

UI components

Pre-built, brand-customizable modals cover the four sensitive wallet moments: sign message, sign transaction, send transaction, and export key. Each accepts uiConfig overrides for title, description, button copy, and success and failure screens, so the confirmation experience matches your product without you building custody UI from scratch.

Funding: onramp and cash out

A wallet can be funded directly and cashed back out to fiat without the user leaving your app. Both flows run inside the WaaS SDK and do not touch the MoonPay Enterprise API.
  • Card payments (onramp): debit and credit card, Apple Pay, Google Pay. Runs on a MoonPay Buy widget session, opened in a managed popup and signed server-side so the wallet address and amount cannot be tampered with after signing.
  • Cash out (offramp): the reverse flow. The user sells from their embedded wallet and receives fiat to a card or bank account. The wallet handles the on-chain deposit to the payment provider itself, behind a first-party confirmation the user approves before anything is sent.
Both directions run on your own payment-provider account, with keys configured per environment. Real transfers are mainnet only. Sandbox mode tests the full flow with no real money movement.

REST API

Wallet creation and signing are MPC ceremonies driven by the client SDK, not single REST calls. Key material only ever exists as shares assembled through the ceremony. The REST API’s role is server-side: querying a user’s existing wallets, running compliance actions, and submitting agent-signed requests for delegated signing.
WaaS credentials are issued with your WaaS account, separately from any MoonPay Enterprise API key. Contact your MoonPay representative for the Wallets API reference.

Get started

1

Request a WaaS account

Email developers@iron.xyz to get set up. WaaS is provisioned on its own, so there is nothing to switch on in the MoonPay Enterprise Partner Dashboard.
2

Install the SDK

Add the React or React Native SDK, point it at your WaaS credentials, and configure the chains you need. See the SDK documentation.
3

Decide on identity-backed encryption

Pick passkey-only for the strongest custody guarantee, or identity-backed to drop the passkey prompt from routine signing. Choose before your first users enroll, since it is provisioned per app up front.
4

Go live

Test wallet creation, signing, import and export, and funding flows in the SDK’s sandbox mode before switching to mainnet.

Contact sales

Tell the team what you are building and which chains you need.
Custodial wallets are in development. If you need MoonPay to hold keys on behalf of your users, we are working with a small number of design partners. Get in touch.