Skip to main content

Client operations

Every field on the client is an intent-builder sub-client: an entry captures what to do (client.deposit.of(...)), a route pin narrows how (.selfFunded()), and a terminal does it (.send(), .approve(), .action()). Settlement is cycle-based. Core nets each participant’s obligations for a clearing cycle into a single net-debit or net-credit committed to an on-chain Merkle root. Participants settle by fetching their prepared clearing action (contract address, amount, and Merkle proof) from core, then calling the ClearingHouse. cycleId is core’s text cycle id (cycle_id_text in clearing proofs and actions, "{asset}:{period_start}"); core does not resolve the on-chain bytes32 id in this path.

Deposits and withdrawals

Deposit collateral, then sign a payment:
To deposit an ERC20 token, grant the allowance first:
approve() returns undefined when the existing allowance is already sufficient. A deposit with a missing allowance is refused with a typed Erc20AllowanceRequiredError before any gas is spent.
Withdrawals are timelocked, one builder per step:

Payment guarantees

The payer signs a payment; the recipient redeems it for the operator’s receipt and verifies it:

client.payment methods

  • newPayment(recipient, amount, asset?) — a payment payload scoped to the asset’s active settlement cycle.
  • signRequest(payload) — sign the payload as the payer, returning a PaymentRequest.
  • issueGuarantee(request) — redeem a signed request for the operator’s GuaranteeReceipt.
  • verifyGuarantee(receipt) — check the receipt was signed by the operator signer core publishes, and return the Guarantee it attests.
  • listReceived() — payments guaranteed to the signer as a recipient.
  • checkpointActiveCycle(asset?) / checkpointCycle(asset, cycleId) — sign and submit a checkpoint (see Checkpoints).
Verification is offline. A service that never builds a Client can run the same check with verifyGuaranteeReceipt(receipt, guaranteeRegistryDomain(chainId, guaranteeRegistryAddress), guaranteeSigner), taking the three values from core’s public parameters.

Settling a cleared cycle

The debtor pays what they owe; the creditor claims what they are owed. Terms always come from core’s prepared action — the caller only names which cycle.

Gasless routes

With a facilitatorUrl configured, deposits, withdrawals, and settlement can run without the signer paying gas: the signer produces an EIP-712 authorization and the facilitator submits it at its own expense. Every route credits the authorization’s signer — the choice only changes who pays — and the receipt’s route field reports which one ran.
Native ETH has no gasless deposit route — no authorization scheme covers it — and native-asset debits cannot be pulled by signature. Both self-fund. client.deposit.isGaslessAvailable() reports whether a facilitator is configured at all. A rejection surfaces as FacilitatorRejectedError carrying the facilitator’s snake_case reason (such as rate_limited) as code; an OutcomeUnknownError means the facilitator may already have submitted — do not blindly retry it.

Balances

client.account.stablecoinPosition(token) reports a stablecoin pool position: the principal and yield split, plus the pool’s share accounting — userShares, totalUserShares, protocolShares, poolShares, poolAssets, and the strategy backing the pool (the zero address while its assets sit idle).

Building payments

Build payments with client.payment.newPayment. A payment is scoped to the asset’s active settlement cycle, which it reads from core, so it cannot be built offline. It is stamped by core’s clock rather than this machine’s, gets a random uint256 reqId, and a random salt that blinds the recipient. The asset defaults to the zero address, which represents native ETH.
signRequest signs it as an EIP-712 PaymentAuthorization under the ClearingHouse domain, through the signer’s signTypedData:

Validated guarantees

A payer can agree that a guarantee only becomes payable once an external validator approves it, by attaching a ValidationRequirement to the payload before signing. The requirement is bound into the salted recipient commitment the payer signs:
In the x402 flow, the same requirement travels as extra.validation on the payment requirements and is attached automatically.

Checkpoints

A checkpoint is the payer’s signed running total of its payments in a cycle. Core caps how many guarantees a payer may hold past its latest checkpoint; past the cap, issuance is refused with a CheckpointRequiredError. Only the payer can sign its checkpoint, so run these on the payer’s client.
Both methods retry once when core answers CheckpointMismatchError because the batch moved while it was being signed. cycleId here is the on-chain bytes32 id, not the text id settlement takes.
Core’s batch is checked before it is signed: every payment must be one the payer signed, in this cycle and asset, past the previous checkpoint, and counted once. A batch that fails those checks throws UntrustedCheckpointBatchError rather than being signed, since signing it could inflate what the payer can be charged on default.

Transaction receipt options

On-chain terminals accept an optional final waitOptions argument to override receipt polling: { timeout?, pollingInterval?, gas? }.

Next steps

X402 flow

Sign payment headers for 402-protected HTTP resources.

Payment middleware

Charge for a route with @4mica/x402’s Express middleware.

Error handling

Catch and distinguish 4Mica SDK errors.