On this page

Payment SDK

Load the SDK from the protocol checkout and set up its payment ledgers.

Load the SDK#

Import the CommonJS entrypoint shown below from the protocol repository root. It exports managers, low-level clients and gateways, backends, funding drivers and the SQLite store. The directory is not a published npm package.

Install the lockfile first. The SDK expects ethers 5.8.0; check compatibility before substituting a different major version.

javascript
const {
  createSessionManager,
  createSessionClient,
  createSessionGateway,
  createEthersBackend,
  createSqliteStore,
  createFundingDriver,
} = require("./sdk/payment-sessions/index.cjs");

Create a ledger#

Choose a private directory owned by the process user for each SQLite ledger. The store creates missing private directories and its database, serializes transactions across local Node processes and rolls back failed transactions.

Use createMemoryStore only for single-process development. It has no crash durability or cross-process lock, so it cannot safely authorize production purchases.

javascript
const path = require("node:path");
const { createSqliteStore } = require("./sdk/payment-sessions/index.cjs");
const store = createSqliteStore({
  path: path.resolve("var/fuyu/merchant/ledger.sqlite"),
});

Configure the backend#

Set the session backend's chain, core and asset. readConfirmations selects how far behind the latest block to read; confirmations sets how many confirmations a submitted transaction waits for. The signer must use the same provider object as the reader.

Subscription, Authorization, Splitter and generic funding backends also require reviewed runtime hash manifests and decimals. For a proxy, check its implementation as well as the proxy runtime hash.

Sessions, subscriptions and payment holds
Sessions, subscriptions and payment holds

Choose a manager or lower-level client#

SessionManager handles budgeted preparation, request acceptance and settlement recovery. If you already manage those steps, use createSessionClient and createSessionGateway directly. In either case, keep purchase and resource-request signatures separate.

On multiple hosts, supply a database adapter that preserves nested atomicity and locking across them. The bundled SQLite store coordinates local processes only.

Configure buyer and merchant#

The buyer signs with the funded session's voucherSigner. The merchant's settlement signer can submit claims, but the rail always pays the fixed merchant. Each backend uses one provider object for reads and writes. Buyer and merchant keep separate durable stores.

The example takes already funded terms and a policy from the host. Save that policy with the terms. Recalculating expiresAt on restart changes it and causes a store mismatch. This configures accounting; token approval, session opening, asset transfers and provider execution still need their own calls.

javascript
const path = require("node:path");
const {
  createSessionManager, createSqliteStore, createEthersBackend,
} = require("./sdk/payment-sessions/index.cjs");

function configurePayment({ provider, sessionSigner, settlementSigner, terms, policy }) {
  const buyerStore = createSqliteStore({
    path: path.resolve("var/fuyu/buyer/ledger.sqlite"),
  });
  const merchantStore = createSqliteStore({
    path: path.resolve("var/fuyu/merchant/ledger.sqlite"),
  });
  const buyerBackend = createEthersBackend({
    provider, chainId: terms.chainId, core: terms.core, asset: terms.asset,
    readConfirmations: 2,
  });
  const merchantBackend = createEthersBackend({
    provider, signer: settlementSigner,
    chainId: terms.chainId, core: terms.core, asset: terms.asset,
    readConfirmations: 2, confirmations: 2,
  });
  return {
    buyer: createSessionManager({
      backend: buyerBackend, signer: sessionSigner,
      store: buyerStore, terms, policy,
    }),
    merchant: createSessionManager({
      backend: merchantBackend, store: merchantStore, terms, policy,
    }),
  };
}
module.exports = { configurePayment };

Set the budget#

Use atomic units for budget and purchaseStep. budget must be positive and no greater than terms.maxDeposit; purchaseStep cannot exceed budget. The session must have enough deposited capacity for the next purchase before prepare succeeds.

A six-decimal token has 1,000,000 atomic units per display unit. budget 1,000,000 and purchaseStep 100,000 buy up to one unit in increments of one tenth. Choose values for your own prices. Fixed-budget private escrows reject topUp; public session calls have their own payer authority.

Keep nested updates atomic#

SessionManager nests updates to manager, buyer-client and merchant-gateway records. An inner credit acceptance must roll back if the outer receive operation fails. In a custom store, await signing, chain reads and updates before the transaction callback returns.

SQLite uses a local write lock and nested savepoints. It works across processes on one host, not across hosts. When archiving requests, preserve their IDs for deduplication and keep every transport for the merchant session on the same accounting store.

Restart from the saved ledger#

Recreate managers with their original terms and policy, reopen the existing ledgers and call recover before accepting work. The backend and ledger reject backward movement in the block, timestamp, deposited, claimed and closure observations they retain.

After a reorganization, investigate the changed chain state. Deleting the database would discard prepared reservations, accepted credit and debit receipts. Keep the uncertain intent and reconcile it before retrying the same settlement operation and amount.

Use fresh reads and settle on time#

maxReadAge controls the session backend's RPC freshness check, and nowSeconds supplies its authorization clock. The default freshness allowance is 120 seconds. Configure readConfirmations and transaction confirmations separately.

Use synchronized clocks and leave time inside the deployed close period for settlement. Older reads can miss closure. The smallest permitted dispute period may be too short for your RPC lag and worker recovery; choose it around those conditions and monitor earned vouchers.