API reference
Every exported function, class, and type, grouped the way you'll actually reach for them.
createMorva(config)
The entry point. Returns a Morva instance — construct once per app.
interface MorvaConfig {
particle: { projectId: string; projectClientKey: string; projectAppUuid: string };
registryAddress?: Address; // optional until you deploy MorvaRegistry
registryDeploymentBlock?: bigint; // required to call getAllMerchants()
registryRpcUrl?: string; // RPC for reading MorvaRegistry itself (always Arbitrum One)
settlementRpcUrls?: Partial<Record<SupportedSettlementChainId, string>>; // per-chain overrides for pay()
slippageBps?: number; // default 100 (1%)
settlementTimeoutMs?: number; // default 120_000 — how long pay() polls for settlement
}
function createMorva(config: MorvaConfig): MorvaMorva
| Method | Returns | Notes |
|---|---|---|
connect(signer) | Promise<BuyerSession> | Constructs the buyer's Universal Account (EIP-7702 mode). |
createDirectIntent(args) | PaymentIntent | Synchronous, no registry lookup. |
createPaymentIntent(args) | Promise<PaymentIntent> | Reads settlement config from MorvaRegistry; throws MerchantInactive if deactivated. |
registerMerchant(cfg, walletClient) | Promise<Hex> | Merchant-side. Needs a viem WalletClient for the merchant's own wallet. |
updateMerchant(cfg, walletClient) | Promise<Hex> | Same config shape as register. |
getMerchant(address) | Promise<MerchantConfig> | Throws MerchantNotFound if unregistered. |
getAllMerchants() | Promise<Array<{'{'}address{'}'} & MerchantConfig>> | Active merchants only; scans MerchantRegistered logs from registryDeploymentBlock. |
createDirectIntent / createPaymentIntent arguments
morva.createDirectIntent({
amount: string; // human units, e.g. "4.99"
orderId: string;
settlementToken: Address;
settlementRecipient: Address;
settlementChainId?: SupportedSettlementChainId; // defaults to 42161 (Arbitrum One)
}): PaymentIntent
morva.createPaymentIntent({
merchant: Address;
amount: string;
orderId: string;
}): Promise<PaymentIntent> // settlementChainId comes from the merchant's registry configBuyerSession
| Method | Returns | Notes |
|---|---|---|
getUnifiedBalance() | Promise<UnifiedBalance> | Cross-chain holdings, from getPrimaryAssets(). |
pay(intent, opts?) | Promise<PaymentResult> | The full sign → authorize → submit → settle sequence. |
interface PaymentResult { transactionId: string; explorerUrl: string }
type PaymentStatus =
| "building" | "authorizing" | "signing" | "submitted" | "settled"
| "unknown" // SettlementTimeout — genuinely unresolved, not a confirmed failure
| "failed";
session.pay(intent: PaymentIntent, opts?: {
onStatus?: (status: PaymentStatus) => void;
onDebug?: (event: string, detail?: Record<string, unknown>) => void;
// Already have a transactionId from an "unknown"-status attempt on this
// exact intent? Pass it here to resume polling instead of submitting a
// second transfer — see the errors page's retry-safety note.
resumeTransactionId?: string;
buildExplorerUrl?: (transactionId: string) => string; // defaults to universalx.app
}): Promise<PaymentResult>Types
PaymentIntent
interface PaymentIntent {
merchant?: Address; // present only when built via createPaymentIntent
orderId: string;
amount: string; // human-readable settlement-token units, e.g. "4.99"
settlementToken: Address;
settlementRecipient: Address;
settlementChainId: SupportedSettlementChainId; // 1 | 56 | 8453 | 196 | 42161 — defaults to 42161
}
// Every settlement chain this SDK supports — the EVM subset of what
// Particle's Universal Account SDK supports in EIP-7702 mode.
type SupportedSettlementChainId = 1 | 56 | 8453 | 196 | 42161;MerchantConfig / MerchantConfigInput
interface MerchantConfig {
settlementToken: Address;
settlementRecipient: Address;
active: boolean;
settlementChainId: number; // validated against SupportedSettlementChainId when building an intent
metadataURI: string; // off-chain JSON: { name, logoUrl, description }
metadata?: MerchantMetadata; // fetched from metadataURI, best-effort — never throws
}
type MerchantConfigInput = Omit<MerchantConfig, "metadata">;UnifiedBalance
interface UnifiedBalance {
totalUsd: string;
assets: UnifiedBalanceAsset[];
raw: IAssetsResponse; // untransformed getPrimaryAssets() response
}
interface UnifiedBalanceAsset {
symbol: string;
totalAmount: string;
usdValue: string;
chains: UnifiedBalanceChain[];
}
interface UnifiedBalanceChain { chainId: number; amount: string }Signers
interface MorvaSigner {
address: Address;
signMessage(message: Uint8Array): Promise<Hex>;
signAuthorization(auth: AuthorizationRequest): Promise<SignedAuthorization>;
}
interface AuthorizationRequest { contractAddress: Address; chainId: number; nonce: number }
class LocalSigner implements MorvaSigner {
constructor(privateKey: Hex)
}LocalSigner is for scripts and tests only
It signs directly with a raw private key held in memory. Real frontends implement MorvaSigner against an embedded wallet provider instead — see the integration guide for a complete Magic-backed implementation.
MORVA_REGISTRY_ABI
The full contract ABI, exported for direct use with viem if you need to interact with MorvaRegistry outside the Morvaclass's own methods.