TypeScript / JavaScript SDK
Official typed SDK for Wirex BaaS — authentication, BaaS API, on-chain wallet operations, and crypto transfers in a single npm package.
Before You Start
| Requirement | Notes |
|---|---|
| Node.js ≥ 18 | Required runtime |
viem ^2.0.0 | Peer dependency — install separately |
CLIENT_ID / CLIENT_SECRET | OAuth2 credentials from Wirex partner onboarding |
COMPANY_ID | Your company identifier in hex format |
@wirexapp/wpay-baas-sdk is the official TypeScript/JavaScript SDK for the Wirex BaaS platform. It wraps the full OAuth2 token flow, all BaaS REST endpoints, and on-chain Account Abstraction wallet operations (ZeroDev Kernel V3.1) into a single typed package.
The SDK is published on npm: @wirexapp/wpay-baas-sdk.
Installation
npm install @wirexapp/wpay-baas-sdk
npm install viem
Initialisation
import { createSDK, type WirexPaySDK } from '@wirexapp/wpay-baas-sdk';
const sdk: WirexPaySDK = await createSDK({
env: 'dev', // 'dev' → sandbox | 'prod' → production
companyId: process.env.COMPANY_ID, // hex company ID from Wirex onboarding
getMainWalletClient: () => mainWalletClient,
rhinoApiKey: process.env.RHINO_API_KEY, // optional, enables Smart Deposit Addresses
enableLogging: false, // optional
logger: customLogger, // optional, requires enableLogging: true
});Configuration Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
env | 'dev' | 'prod' | Yes | 'dev' → api-baas.wirexapp.tech + Base Sepolia (84532); 'prod' → api-baas.wirexapp.com + Base Mainnet (8453) |
companyId | string | Yes | Company identifier in hex format |
getMainWalletClient | () => MainWalletClient | Yes | Factory returning the user's embedded wallet client |
rhinoApiKey | string | No | Rhino.fi API key. Required only for Smart Deposit Addresses (sdk.crypto.smartDepositAddress). If omitted, accessing that service throws ConfigurationError. |
enableLogging | boolean | No | Enable SDK-level logging (default false) |
logger | Logger | No | Custom logger instance |
MainWalletClient Contract
getMainWalletClient must return an object implementing this interface:
interface MainWalletClient {
address: string;
getEthereumProvider(): Promise<{
request(args: { method: string; params?: unknown[] }): Promise<unknown>;
}>;
}The EIP-1193 provider must handle at minimum:
| RPC Method | Used for |
|---|---|
eth_accounts | Resolve the signer address |
personal_sign | Sign messages (SIWE, auth challenges) |
eth_signTypedData_v4 | Sign typed data (UserOperations, EIP-712) |
Adapter example — raw private key (tests / embedded wallets)
import { createWalletClient, http } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
import { baseSepolia } from 'viem/chains';
import type { MainWalletClient } from '@wirexapp/wpay-baas-sdk';
export function createWalletClientFromKey(
privateKey: `0x${string}`,
rpcUrl: string,
): MainWalletClient {
const account = privateKeyToAccount(privateKey);
const client = createWalletClient({ account, chain: baseSepolia, transport: http(rpcUrl) });
return {
address: account.address,
getEthereumProvider: async () => ({
request: async ({ method, params = [] }) => {
if (method === 'eth_accounts') return [account.address];
if (method === 'personal_sign') {
const [data] = params as [`0x${string}`, string];
return client.signMessage({ account, message: { raw: data } });
}
if (method === 'eth_signTypedData_v4') {
const [, json] = params as [string, string];
const { domain, types, primaryType, message } = JSON.parse(json);
const { EIP712Domain: _, ...filteredTypes } = types;
return client.signTypedData({ account, domain, types: filteredTypes, primaryType, message });
}
return (client.transport as any).request({ method, params });
},
}),
};
}Adapter example — Privy embedded wallet
import type { MainWalletClient } from '@wirexapp/wpay-baas-sdk';
// Inside a React component / hook where usePrivy is available:
function getPrivyWalletClient(wallet: ConnectedWallet): MainWalletClient {
return {
address: wallet.address,
getEthereumProvider: () => wallet.getEthereumProvider(),
};
}Authentication
The SDK supports three authentication paths depending on your integration type.
Option A — Company OAuth2 (client_credentials)
Used when your backend calls the Wirex API on behalf of users. This is the standard B2B partner flow.
// Step 1 — Exchange company credentials
const tokenRes = await sdk.api.baas.token.getToken({
grant_type: 'client_credentials',
client_id: process.env.CLIENT_ID,
client_secret: process.env.CLIENT_SECRET,
audience: 'https://api-business.wirexpaychain.tech', // same for dev and prod
});
// Step 2 — Prime SDK auth state with the company token + user EOA wallet
sdk.auth.setAuthState(
{ access_token: tokenRes.access_token, expires_at: tokenRes.expires_at },
userEoaWallet,
);
// Step 3 — (After user registration) Login to get a per-user PSI token.
// All sdk.api.baas.* calls automatically use the PSI token after this.
await sdk.auth.login({
authorizationToken: tokenRes.access_token,
userWallet: userEoaWallet,
});
console.log('Authenticated:', sdk.auth.isAuthenticated()); // true
console.log('Token:', sdk.auth.getAccessToken());Option B — Privy
Used in consumer apps where users authenticate through Privy.
import { getAccessToken, useIdentityToken } from '@privy-io/react-auth';
const accessToken = await getAccessToken();
const { identityToken } = useIdentityToken();
// Login (existing user)
const authResponse = await sdk.auth.login({
privy: { accessToken, identityToken },
});
// Or register (new user)
const userResponse = await sdk.auth.registerUser({
privy: { accessToken, identityToken },
country: 'FR',
});Option C — JWT
Used when you issue your own tokens or use an auth provider other than Privy.
// Login
const authResponse = await sdk.auth.login({
authorizationToken: 'your-jwt-token',
userWallet: userEoaWallet,
});
// Register
const userResponse = await sdk.auth.registerUser({
authorizationToken: 'your-jwt-token',
country: 'FR',
});Token Management
After login the SDK holds the token internally. Use these methods to inspect or manage auth state:
| Method | Returns | Description |
|---|---|---|
sdk.auth.isAuthenticated() | boolean | Whether a valid token is held |
sdk.auth.getAccessToken() | string | null | Current token, or null if expired |
sdk.auth.ensureAuthenticated() | void | Throws AuthenticationError if not authenticated |
sdk.auth.getAuthHeaders() | object | { Authorization, X-User-Wallet } headers |
sdk.auth.getUserWallet() | string | Current user wallet address |
sdk.auth.setUserWallet(wallet) | void | Update user wallet address |
sdk.auth.setAuthState(response, wallet?) | void | Restore auth state from a stored response |
sdk.auth.clearAuth() | void | Clear all auth state (logout) |
User Registration Flow
Complete flow from fresh account to authenticated user. Steps 1–5 are on-chain; steps 6–7 are API calls.
sequenceDiagram
participant App as Your App
participant SDK as wpay-baas-sdk
participant Chain as Base Blockchain
participant BaaS as Wirex BaaS
Note over App,Chain: On-chain setup
App->>SDK: getSmartWalletAddress()
SDK-->>App: smartWalletAddress
App->>SDK: isPolicyInstalled() / isExecutorInstalled()
SDK-->>App: false / false
App->>SDK: signInPolicyAndExecutor()
SDK->>Chain: UserOperation (install executor + policy)
Chain-->>SDK: tx receipt
App->>SDK: registerInAccounts()
SDK->>Chain: createUserAccountWithWallet(companyId)
Chain-->>SDK: tx receipt
Note over App,BaaS: API registration
App->>SDK: createUser({ email, country, wallet_address })
SDK->>BaaS: POST /api/v1/user
BaaS-->>SDK: user_id
App->>SDK: auth.login({ authorizationToken, userWallet })
SDK->>BaaS: POST /api/v1/user/authorize
BaaS-->>SDK: PSI token (stored internally)
SDK-->>App: AuthResponse
Step 1 — Get Smart Wallet Address
const smartWalletAddress = await sdk.crypto.wallet.getSmartWalletAddress();
console.log('Smart Wallet:', smartWalletAddress);Step 2 — Check Policy & Executor Status
const isPolicyInstalled = await sdk.crypto.accountAbstraction.isPolicyInstalled();
const isExecutorInstalled = await sdk.crypto.accountAbstraction.isExecutorInstalled();Step 3 — Install Policy & Executor
if (!isPolicyInstalled || !isExecutorInstalled) {
const result = await sdk.crypto.accountAbstraction.signInPolicyAndExecutor();
console.log('TX hash:', result?.receipt?.transactionHash);
}To install separately:
await sdk.crypto.accountAbstraction.signInPolicy(); // ExecutionDelayPolicy only
await sdk.crypto.accountAbstraction.signInExecutor(); // FundsManagementExecutor onlyStep 4 — Link Smart Wallet to Privy (SIWE) — optional
Required only when using Privy as the auth provider. Skip for JWT / OAuth2 flows.
import { useLinkWithSiwe } from '@privy-io/react-auth';
const { generateSiweMessage, linkWithSiwe } = useLinkWithSiwe();
const smartWalletClient = await sdk.crypto.wallet.getSmartWalletClient();
const message = await generateSiweMessage({
address: smartWalletClient.account.address,
chainId: 'eip155:' + smartWalletClient.chain?.id,
});
const signature = await smartWalletClient.signMessage({
account: smartWalletClient.account,
message,
});
await linkWithSiwe({
message,
chainId: 'eip155:' + smartWalletClient.chain?.id,
signature,
walletClientType: 'smart_wallet',
connectorType: 'kernel',
});Step 5 — Register in Accounts Contract
const isRegistered = await sdk.crypto.accountContract.isWalletInAccounts();
if (!isRegistered) {
await sdk.crypto.accountContract.registerInAccounts();
}For B2B (corporate) accounts:
await sdk.crypto.accountContract.registerInCorporateAccounts();Step 6 — Register User in API
// Option A — Privy
const user = await sdk.auth.registerUser({
privy: { accessToken, identityToken },
country: 'FR',
});
// Option B — JWT / OAuth2
const user = await sdk.auth.registerUser({
authorizationToken: companyToken,
country: 'FR',
});
console.log('User ID:', user.id);For company/corporation registration:
await sdk.auth.registerCompany({
authorizationToken: companyToken,
companyAddress: '0x...',
companyName: 'Acme Corp',
registrationCountry: 'GB',
registrationNumber: '12345678',
});Step 7 — Login
// Option A — Privy
const auth = await sdk.auth.login({
privy: { accessToken, identityToken },
});
// Option B — JWT / OAuth2
const auth = await sdk.auth.login({
authorizationToken: companyToken,
userWallet: userEoaAddress,
});
console.log('Access token:', auth.access_token);
// All subsequent sdk.api.baas.* calls now use this token automatically.SDK Modules
sdk.auth — Authentication
sdk.auth — Authentication| Method | Description |
|---|---|
login(params) | Login retail user (Privy or JWT) |
loginCompany(params) | Login company/corporation |
registerUser(params) | Register retail user |
registerCompany(params) | Register company/corporation |
isAuthenticated() | Check if a valid token is held |
getAccessToken() | Returns current token or null if expired |
ensureAuthenticated() | Throws AuthenticationError if not authenticated |
getAuthHeaders() | Returns { Authorization, X-User-Wallet } headers |
getUserWallet() | Get current user wallet address |
setUserWallet(wallet) | Set user wallet address |
setAuthState(response, wallet?) | Manually restore auth state |
clearAuth() | Clear all auth state (logout) |
sdk.api.baas.token — OAuth2 Token
sdk.api.baas.token — OAuth2 Token| Method | Description |
|---|---|
getToken(request) | Exchange client_credentials for an access token |
const tokenRes = await sdk.api.baas.token.getToken({
grant_type: 'client_credentials',
client_id: process.env.CLIENT_ID,
client_secret: process.env.CLIENT_SECRET,
audience: 'https://api-business.wirexpaychain.tech',
});
// → { access_token, token_type: 'Bearer', expires_at }sdk.api.baas.user — User Service
sdk.api.baas.user — User Service| Method | Description |
|---|---|
getUser() | Get current user (v1) |
getUserV2() | Get current user with capabilities array |
createUser(request) | Create a new user ({ email, country, wallet_address }) |
createRetailUser(request) | Create a retail user |
validateRetailUser() | Validate retail user |
authorizeUser(params) | Authorize user — returns PSI token |
updatePhoneNumber(request) | Update phone number |
confirmPhoneNumber(request) | Confirm phone number via OTP |
uploadDocument(formData) | Upload KYC document |
getVerificationToken() | Get verification token (Wirex-hosted KYC) |
getVerificationLink() | Get verification link (Wirex-hosted KYC) |
getSharingToken(request) | Get SumSub sharing token |
setSharingToken(request) | Set SumSub sharing token |
updateFreshdeskId(request) | Update Freshdesk ID |
// Check user capabilities (e.g. card issuance eligibility)
const user = await sdk.api.baas.user.getUserV2();
const caps = user.capabilities;
const canIssueVirtualCard = caps.find(c => c.type === 'VisaVirtualCard')?.status === 'Active';sdk.api.baas.wallet — Wallet Service
sdk.api.baas.wallet — Wallet Service| Method | Description |
|---|---|
getWallet(request?) | Get wallet by ID or default wallet |
getWallets() | Get all user wallets |
createGlobalWallet(request) | Create a global (multi-chain deposit) wallet |
const wallet = await sdk.api.baas.wallet.getWallet();
// Response: { balances: [{ token_symbol, token_address, balance }] }
const balances = wallet.balances;sdk.api.baas.cards — Cards Service
sdk.api.baas.cards — Cards Service| Method | Description |
|---|---|
issueVirtualCard(request) | Issue a virtual card ({ card_name }) |
issuePlasticCard(request) | Issue a physical card |
getCards(request?) | List cards — returns { data: Card[] } |
getCard(cardId) | Get card details — { id, status, card_data: { card_name, format } } |
getCardTransactions(request?) | Get card transactions |
activateCard(cardId, request) | Activate card |
blockCard(cardId) | Block card |
unblockCard(cardId) | Unblock card |
closeCard(cardId) | Close card (terminal state) |
getCardDetails(cardId, request) | Get PAN and expiry — requires action token |
getCardCvv(cardId, request) | Get CVV — requires action token |
getCardPin(cardId, request) | Get PIN — requires action token (physical cards) |
changeCardLimit(cardId, request) | Change spending limit |
changeCardName(cardId, request) | Rename card |
estimateCardTransfer(request) | Estimate card top-up |
executeCardTransfer(request) | Execute card top-up |
estimateCardWithdrawal(cardId, request) | Estimate withdrawal from card |
executeCardWithdrawal(cardId, request) | Execute withdrawal from card |
getActive3dsRequests() | Get pending 3DS challenges — returns Array |
approve3dsRequest(transactionId) | Approve a 3DS challenge |
decline3dsRequest(transactionId) | Decline a 3DS challenge |
getDeliveryCountries() | List countries available for physical card delivery |
getDeliveryMethods(country) | Get delivery methods for a country |
getOrderFees(type, country) | Get card order fees |
createOrderFeesInvoice(type, country, request) | Create invoice for card order fees |
Sensitive card data (PAN, CVV, PIN) requires an action token obtained via SMS OTP:
// 1. Request SMS OTP
const session = await sdk.api.baas.confirmation.requestSms({
action_type: 'GetCardDetails',
});
// 2. Verify OTP → receive action token (UAT code is '000000')
const tokenRes = await sdk.api.baas.confirmation.verifySms({
session_id: session.session_id,
code: userInputCode,
});
const actionToken = tokenRes.token;
// 3. Use action token to retrieve sensitive data
const details = await sdk.api.baas.cards.getCardDetails(cardId, { action_token: actionToken });
// → { card_number: '4111111111111111', expiry_date: '12/2028' }
const cvv = await sdk.api.baas.cards.getCardCvv(cardId, { action_token: actionToken });
// → { cvv: '123' }sdk.api.baas.confirmation — Confirmation Service
sdk.api.baas.confirmation — Confirmation Service| Method | Description |
|---|---|
requestSms(request) | Request SMS OTP ({ action_type }) — returns { session_id } |
verifySms(request) | Verify OTP ({ session_id, code }) — returns { token } |
verifySignature(request) | Verify signature for action confirmation |
sdk.api.baas.bank — Bank Service
sdk.api.baas.bank — Bank Service| Method | Description |
|---|---|
getAccounts(request?) | Get bank accounts — returns { data: BankAccount[] } |
activateAccount(request) | Activate bank account |
estimateTransfer(request) | Estimate bank transfer |
executeTransfer(request) | Execute bank transfer |
estimateCorridorTransferV2(corridor, request) | Estimate SEPA / corridor transfer |
executeCorridorTransferV2(corridor, request) | Execute SEPA / corridor transfer |
// Estimate a SEPA transfer
const estimate = await sdk.api.baas.bank.estimateCorridorTransferV2('SEPA', {
destination_amount: 100,
recipient_id: recipientId,
recipient_payment_details_id: paymentDetailsId,
account_id: eurAccountId,
});
// → { estimation_id, fee, ... }sdk.api.baas.recipients — Recipients Service
sdk.api.baas.recipients — Recipients Service| Method | Description |
|---|---|
getRecipients(request?) | List recipients — returns { data: Recipient[] } |
getRecipientById(recipientId) | Get recipient — { id, personal_info: { first_name, last_name } } |
getRecipientsByCatalog(request) | Filter by catalog |
getRecipientsByCurrency(request) | Filter by currency |
getRecipientsByName(request) | Search by name |
getRecipientsByType(request) | Filter by type |
createRecipient(request) | Create individual recipient |
createRecipientV2(request) | Create recipient (v2) |
updateRecipient(recipientId, request) | Update recipient |
deleteRecipient(recipientId) | Delete recipient |
createRecipientPaymentDetails(recipientId, request) | Add payment details (SEPA/SWIFT/etc.) |
updateRecipientPaymentDetails(recipientId, detailsId, request) | Update payment details |
deleteRecipientPaymentDetails(recipientId, detailsId) | Delete payment details |
incrementRecipientUsage(recipientId) | Increment usage counter |
// Create recipient with SEPA payment details
const recipient = await sdk.api.baas.recipients.createRecipient({
first_name: 'John',
last_name: 'Doe',
is_business: false,
});
await sdk.api.baas.recipients.createRecipientPaymentDetails(recipient.id, {
type: 'Sepa',
currencies: ['EUR'],
sepa: {
iban: 'DE89370400440532013000',
bic: 'COBADEFFXXX',
},
});sdk.api.baas.activity — Activity Service
sdk.api.baas.activity — Activity Service| Method | Description |
|---|---|
getFeed(request?) | Get activity feed — returns { data: Activity[] } |
getById(request) | Get activity item by ID |
getFullStatement(request) | Get statement for a date range ({ start, end } — Unix timestamps in seconds) |
getRequestedErcWithdrawals() | Get pending ERC-20 withdrawal requests |
// Paginated feed
const feed = await sdk.api.baas.activity.getFeed({ page_number: 0, page_size: 20 });
// Statement for the last 30 days
const statement = await sdk.api.baas.activity.getFullStatement({
start: Math.floor((Date.now() - 30 * 24 * 60 * 60 * 1000) / 1000),
end: Math.floor(Date.now() / 1000),
});Activity item type values: CardTransaction, BankTransfer, Crypto. Activity item direction values: Inbound, Outbound.
sdk.api.withdrawal — Withdrawal API
sdk.api.withdrawal — Withdrawal API| Method | Description |
|---|---|
getWithdrawalRequests() | List pending ERC-20 withdrawal requests |
Used in the two-phase transfer flow to retrieve the call_data needed for phase 2.
sdk.api.baas.rates — Rates Service
sdk.api.baas.rates — Rates Service| Method | Description |
|---|---|
getRates(request) | Get exchange rates |
sdk.api.baas.config — Config Service
sdk.api.baas.config — Config Service| Method | Description |
|---|---|
getConfig() | Get client app config |
sdk.crypto.wallet — Wallet Service
sdk.crypto.wallet — Wallet Service| Method | Description |
|---|---|
getSmartWalletAddress() | Get the Smart (AA) wallet address |
getSmartWalletClient() | Get Kernel client with ExecutionDelayPolicy |
getSmartWalletClientWithoutPolicy() | Get Kernel client without policy |
getSmartAccountSigner() | Get signer for Smart Account |
getMainWalletClient() | Get the main (EOA) wallet client |
sendUserOperationsAndWaitReceipt(callData, client?) | Send UserOperation and wait for receipt |
sendUserOperationsWithNonceAndWaitReceipt(callData, nonce) | Send UserOperation with a specific nonce |
invalidateLocalCache() | Clear cached wallet clients (force re-init) |
sdk.crypto.accountAbstraction — Account Abstraction
sdk.crypto.accountAbstraction — Account Abstraction| Method | Description |
|---|---|
isPolicyInstalled() | Check if ExecutionDelayPolicy is installed as root validator |
isExecutorInstalled() | Check if FundsManagementExecutor is installed |
signInPolicyAndExecutor() | Install both in one UserOperation |
signInPolicy() | Install ExecutionDelayPolicy only |
signInExecutor() | Install FundsManagementExecutor only |
sdk.crypto.accountContract — Account Contract
sdk.crypto.accountContract — Account Contract| Method | Description |
|---|---|
isWalletInAccounts() | Check registration in retail Accounts contract |
registerInAccounts() | Register wallet (retail) |
isWalletInCorporateAccounts() | Check registration in corporate Accounts contract |
registerInCorporateAccounts() | Register wallet (B2B) |
sdk.crypto.transfer — Transfer Service
sdk.crypto.transfer — Transfer Service| Method | Description |
|---|---|
makeFullErc20Transfer(params) | Both phases in one call |
makeErc20TransferFirstPart(params) | Phase 1: submit withdrawal request |
makeErc20TransferFinal(callData) | Phase 2: execute after delay expires |
makeErc20TransferSynthetic(params) | Transfer synthetic (wrapped) tokens |
batchTransfer(params) | Multiple transfers in one UserOperation |
ERC-20 withdrawals use a two-phase flow enforced by ExecutionDelayPolicy. A minimum delay (~3 seconds in sandbox, longer in production) separates the request and execution.
interface Erc20TransferParams {
tokenAddress: `0x${string}`;
recipientAddress:`0x${string}`;
amount: number;
}
interface BatchTransferItem {
to: `0x${string}`;
amount: string;
token: string; // e.g. 'USDC'
guid: string; // unique transfer identifier for deduplication
}sdk.crypto.yield — Yield Service
sdk.crypto.yield — Yield Service| Method | Description |
|---|---|
fetchYieldData() | Get APY, current, weekly, and lifetime yield |
getYieldDataForGraphic() | Get time-series data points for chart display |
getWeeklyYield() | Get yield earned in the current week |
withdraw() | Withdraw accumulated yield to wallet balance |
switchYieldToken(token) | Change the token used for yield accumulation |
interface YieldData {
tokenSymbol: string; // yield token symbol
apy: string; // annual percentage yield
currentYield: string; // accumulated yield pending withdrawal
weeklyYield: string; // yield earned this week
lifetimeYield: string; // total yield since account creation
}sdk.crypto.smartDepositAddress — Smart Deposit Addresses
sdk.crypto.smartDepositAddress — Smart Deposit AddressesRequires rhinoApiKey in the createSDK config. If it was not provided, accessing this service throws ConfigurationError: "rhinoApiKey is required to use smartDepositAddress.".
| Method | Description |
|---|---|
initializeSmartDepositAddresses(forceRefresh?) | Create or fetch all deposit addresses |
getAddresses() | Return cached addresses (no API call) |
clearAddresses() | Clear the local address cache |
Supported deposit networks: Base, Arbitrum, BNB Chain, Ethereum, Kaia, Optimism, Polygon, Solana, TRON.
Examples
Full ERC-20 Transfer
const result = await sdk.crypto.transfer.makeFullErc20Transfer({
tokenAddress: '0x920D17f7A226Ce306f2B51F74a0f0dA89C3b8dF3',
recipientAddress: '0xRecipientAddress',
amount: 100,
});
console.log('Phase 1 tx:', result.firstPartTxHash);
console.log('Phase 2 tx:', result.finalTxHash);
console.log('Success: ', result.success);Two-Phase Transfer (Manual)
Use when you need to inspect or cancel the request between phases.
// Phase 1 — submit request
await sdk.crypto.transfer.makeErc20TransferFirstPart({
tokenAddress: '0x920D17f7A226Ce306f2B51F74a0f0dA89C3b8dF3',
recipientAddress: '0xRecipientAddress',
amount: 100,
});
// Fetch pending requests to get call_data
const withdrawals = await sdk.api.withdrawal.getWithdrawalRequests();
const pending = withdrawals.find(w => w.status === 'Requested');
// Phase 2 — execute after valid_after timestamp
await sdk.crypto.transfer.makeErc20TransferFinal(pending.call_data);Batch Transfer
await sdk.crypto.transfer.batchTransfer({
items: [
{ to: '0xAddress1', amount: '100', token: 'USDC', guid: 'transfer-001' },
{ to: '0xAddress2', amount: '50', token: 'USDC', guid: 'transfer-002' },
],
});Yield Operations
const data = await sdk.crypto.yield.fetchYieldData();
console.log('APY: ', data.apy);
console.log('Earned: ', data.currentYield);
await sdk.crypto.yield.withdraw();
await sdk.crypto.yield.switchYieldToken('WEUR');Smart Deposit Addresses
const addresses = await sdk.crypto.smartDepositAddress.initializeSmartDepositAddresses();
for (const addr of addresses) {
console.log(`Chain: ${addr.depositChain}`);
console.log(`Address: ${addr.depositAddress}`);
console.log(`Tokens: ${addr.supportedTokens.join(', ')}`);
}Issue and Use a Virtual Card
// Issue
const card = await sdk.api.baas.cards.issueVirtualCard({ card_name: 'My Card' });
const cardId = card.id;
// Block / Unblock
await sdk.api.baas.cards.blockCard(cardId);
await sdk.api.baas.cards.unblockCard(cardId);
// Get PAN (requires SMS OTP)
const session = await sdk.api.baas.confirmation.requestSms({ action_type: 'GetCardDetails' });
const tokenRes = await sdk.api.baas.confirmation.verifySms({ session_id: session.session_id, code: '000000' });
const details = await sdk.api.baas.cards.getCardDetails(cardId, { action_token: tokenRes.token });
console.log('PAN:', details.card_number);
// Close
await sdk.api.baas.cards.closeCard(cardId);TypeScript Types
import type {
WirexPaySDK,
SDKConfig,
SDKEnvironment,
MainWalletClient,
Logger,
// Auth
PrivyAuth,
LoginUserParams,
LoginCompanyParams,
RegisterUserParams,
RegisterCompanyParams,
AuthResponse,
RegisterUserResponse,
// Crypto
Hex,
TransactionHash,
TransferRequest,
TransferResult,
BatchTransferItem,
BatchTransferResult,
YieldData,
YieldGraphicDataPoint,
// Wallet / contract
TokenInfo,
ContractAddresses,
AccountStatus,
PolicyStatus,
} from '@wirexapp/wpay-baas-sdk';Error Handling
All SDK errors extend a typed base class, allowing instanceof checks:
| Error class | Cause |
|---|---|
SDKError | Base class for all SDK errors |
ConfigurationError | Invalid or missing SDK configuration |
NetworkError | HTTP failure — exposes statusCode |
ContractError | Smart contract interaction failure |
WalletError | Wallet client unavailable or misconfigured |
TransactionError | UserOperation reverted or timed out |
AuthenticationError | Token missing, expired, or invalid |
ValidationError | Input validation failure |
import {
AuthenticationError,
NetworkError,
TransactionError,
ContractError,
} from '@wirexapp/wpay-baas-sdk';
try {
await sdk.crypto.transfer.makeFullErc20Transfer(params);
} catch (error) {
if (error instanceof AuthenticationError) {
// re-login
} else if (error instanceof NetworkError) {
console.error('HTTP', error.statusCode);
} else if (error instanceof ContractError) {
// execution delay not expired, or invalid calldata
} else if (error instanceof TransactionError) {
// UserOperation reverted on-chain
}
}Next Steps
| Guide | Description |
|---|---|
| Getting Started | Platform overview and environments |
| Wallet Deployment | Full ZeroDev / Crossmint deployment options |
| Developer Onboarding | User registration and KYC flows |
| Authentication | Token exchange and header management |
Updated 15 days ago

