Introduction

@morva/sdk is a headless TypeScript payment engine: it accepts crypto payments settled in a merchant's chosen token on Arbitrum One, while the buyer pays from a single balance spread across whatever chains they actually hold assets on. This section walks through what it does, how it's built, and how to put it into your own platform.

The problem

A buyer's crypto is rarely in one place. Some USDC on Base, a little ETH on Arbitrum, maybe something on Polygon from an old airdrop. Every existing checkout flow forces the buyer to solve that fragmentation themselves — pick a chain, bridge if the funds aren't there, approve, swap, and only then pay. Most people abandon the cart before finishing that sequence.

Merchants have the opposite problem: they want to receive one specific token, on one specific chain, every time — not a different asset from every buyer that they then have to manage, swap, or bridge themselves.

Morva sits between the two. The buyer signs once. The merchant receives exactly what they configured, every time, regardless of what the buyer actually held.

How it actually works

This isn't a custodial middle step — Morva never holds funds. Three pieces of existing infrastructure do the real work, and the SDK is the layer that wires them together for a payment flow specifically:

  • Particle Network's Universal Accounts, in EIP-7702mode, upgrade the buyer's own EOA in place into a chain-abstracted account — no new address, no deposit step — and handle reading the buyer's balance across chains and routing liquidity to the settlement chain.
  • An embedded wallet provider (Magic in the reference frontend; any provider that can produce EIP-7702 authorization signatures works) is what the buyer actually authenticates with and signs through — the SDK never sees or touches a private key.
  • Arbitrum Oneis the default settlement chain — merchants can choose any of the five chains Particle's Universal Account SDK supports in EIP-7702 mode. Whatever the buyer holds and wherever they hold it, the merchant's configured token lands on the chain they chose.

The infrastructure page goes deep on why each piece was chosen and exactly how the SDK talks to it. If you just want to see it work first, jump to the quickstart.

The shape of an integration

Five calls cover the entire buyer-facing flow — no React, no UI, no wallet-connect modal. You bring the signer (an embedded wallet integration, or a raw key for scripts/tests) and the UI; the SDK handles the payment mechanics.

import { createMorva } from "@morva/sdk";

const morva = createMorva({ particle: { projectId, projectClientKey, projectAppUuid } });
const session = await morva.connect(signer);

const intent = morva.createDirectIntent({
  amount: "4.99",
  orderId: "order-123",
  settlementToken: "0xaf88…e5831", // USDC, Arbitrum One
  settlementRecipient: "0xYourMerchantAddress",
});

const result = await session.pay(intent, { onStatus: console.log });