@dynamic-labs-sdk/client/waas and @dynamic-labs-sdk/react-hooks. This page covers the parts that behave differently on device: the WaaS host origin, where the key share lives, and how to obtain an elevated token without a browser popup.
Before this: create and initialize a Dynamic client (see Creating a Dynamic Client, Initializing the Dynamic Client) and finish React Native Setup. For the account model (owners, admins, viewers, signers) and the full API, see Business Accounts.
Business Accounts are in early access. Talk to us if you’d like to participate.
What you need on React Native
- An embedded wallet extension registered on the client, for example
addWaasEvmExtension. See Adding Extensions. metadata.universalLinkset to a domain you control, and that domain allowlisted as an origin in your environment settings. On device there is nowindow.location.origin, so the SDK sends your universal link as the host origin of the hosted signer. If it is missing or not allowlisted, the signer refuses to load and wallet operations fail.react-native-keychaininstalled and the native app rebuilt, from Expo or Bare React Native setup.
dynamicClient.ts
The signer’s key share is stored in the device keychain, readable only while the device is unlocked and scoped to that device. It is excluded from iCloud Keychain sync and does not travel to a new device on an encrypted-backup restore, so a signer who changes device needs a fresh share. Add them again with
addBusinessAccountSigner on the new device, or use the wallet’s recovery flow.Create an account and a wallet
createBusinessAccount makes the caller the owner. createWalletForBusinessAccount then creates an embedded wallet owned by the account, on the chain you pass.
- JavaScript
- React
Mutations require an elevated token
Every operation that changes who can administer or sign for an account is protected server side by an elevated access token: a short lived JWT scoped to one action. The regular session token is not enough, and a missing or expired elevated token returns a403.
These do not require an elevated token:
createBusinessAccount, getBusinessAccount, listBusinessAccounts, and createWalletForBusinessAccount.
Obtain the token on device
Web apps often step up in a popup. React Native has no popup, so use a verification the user can complete in the app and passrequestedScopes to it. The SDK stores the elevated token from the response and attaches it to the next call, so you never handle the token yourself.
- Email or SMS OTP:
verifyOTPacceptsrequestedScopes, and the code is entered in your own UI. This works on Expo and bare React Native with no extra native modules. - Passkey or TOTP MFA:
authenticatePasskeyMFAandauthenticateTotpMfaDeviceacceptrequestedScopes. Passkeys need the native associations from React Native Passkeys before the OS will use them. - Your own backend: mint a scoped JWT and call
requestExternalAuthElevatedToken. See External auth step-up.
checkStepUpAuth tells you whether a verification is needed. It returns { isRequired: false } without a network call when a valid token for that scope is already in state.
addSigner.ts
Handle an expired token
Elevated tokens are short lived, so a user who leaves the app mid flow can come back to a403. Catch it and send them through verification again.
Sign with a business-account wallet
A business-account wallet is a standard embedded wallet, so signing is the usualsignMessage call. Wallets you can sign for come back from getWalletAccounts, and businessAccountId is set on the ones a business account owns.
- JavaScript
- React
Next steps
Business Accounts
The account model: owners, admins, viewers, and signers.
Manage signers
Grant and revoke signing access on a wallet.
Members and roles
Add admins and viewers, and transfer ownership.
Policies
Constrain what account wallets and signers can do.