Skip to content
Integra Agentic Terms

Signers

The signer contract, every kind of signing request the gate hands out, and the answer each one takes.

The gate never holds a key. It hands your signer one request at a time, each built with the hash the gate computed, and it reads the answer back to complete the payment. This page is the contract between the two.

The contract

import type { ,  } from "@integraledger/terms";

interface Signer {
  /** The payer, CAIP-10: `eip155:84532:0xf39F…2266`. */
  readonly : string;
  /** Signs exactly `request`. */
  (: ): <>;
}

In Python, any object with an account string and an async def sign(self, request) method is a signer.

  • account is CAIP-10: the chain namespace, the network reference and the address. It chooses the option the gate pays, and for most pairings it is the payer.
  • sign(request) signs exactly what it is handed. It changes nothing: not a field, not an amount, not a deadline. If it cannot sign a request, it throws (TypeScript) or raises (Python), and the gate declines with signer-failed.

The gate calls sign only after the comparison matched, at most twice for one payment (a funding and then a voucher), and never for the payment of a pairing whose build gives the buyer nothing to sign (it may sign that pairing's agreement payment).

Requests and answers

Each request has a kind. The kind says what is signed and what the answer is. The TypeScript type SigningRequest is the union of every kind.

Byte strings. In TypeScript, the request is exactly as the binding built it: byte strings are Uint8Array, and a few integers are bigint. In Python, every byte string in the request is 0x and lower-case hex. In both languages, an answer's byte strings are 0x hex, except where the row names another form: base58, base64, or hex digits without 0x.

EVM and Tempo

KindWhat the signer signsAnswer
eip712EIP-712 typed data (request.typedData): an EIP-3009 transfer authorization, a Permit2 transfer, a channel voucher.The 65-byte signature, 0x hex.
erc7710An ERC-7710 delegation request for the option.{ delegationManager, permissionContext, delegator }, each 0x hex.
evm-callOne contract call on the chain. With broadcast: true the signer sends it itself.Without broadcast: the signed EIP-1559 transaction, 0x hex, for the request's chainId; another chain is declined signed-not-bound (evm/chain-mismatch), as are bytes that are not an EIP-1559 transaction (mpp/credential-malformed). With broadcast: the transaction hash, 0x hex.
evm-callsSeveral calls, in order, which the signer broadcasts (a session's opening).The opening's transaction hash, 0x hex.
gateway-burn-intentA Circle Gateway burn intent. The client computes the salt from the preimage the request gives and signs.{ source, sourceNetwork, destinationNetwork, maxFee, burnIntent, signature }.
tempo-call, tempo-callsA Tempo 0x76 transaction with one call, or several in order (a charge with splits). With broadcast: true the signer sends it.Without broadcast: the signed transaction, 0x hex. With broadcast: { hash, landed }, the hash it sent and, where it has it, the landed receipt { transaction, blockNumber, logs }.
tempo-key-authorizationThe digest of a Tempo key authorization, signed by the root key (a subscription).The root key's signature, 0x hex.

Other chains

KindWhat the signer signsAnswer
solana-messageA Solana v0 transaction message (request.message).The payer's 64-byte Ed25519 signature, 0x hex (base58 for the batch-settlement opening and voucher).
solana-session-openThe values of an MPP session opening, which the buyer's channel client composes into an open.The open payload. Under the challenge's operator voucher signer, the open instruction's authorizedSigner (account 4) is the challenge's operator. The gate reads no address lookup table, so an open whose message has lookups is refused svm/read-first.
ed25519-rawRaw Ed25519 over the bytes given (request.message), by the key request.signer names.The 64-byte signature, base58.
stellar-authA Soroban authorization preimage (request.preimage).The 64-byte Ed25519 signature over its SHA-256, 0x hex.
xrpl-txAn XRPL transaction as txJson.The signed blob, hex digits without 0x, as the XRP Ledger writes it, signed with a single key: a blob that carries Signers is declined signed-not-bound. The blob carries NetworkID as rippled requires of the network, none where its id is at most 1024 and that id above 1024; any other is declined signed-not-bound (xrpl/network-mismatch).
xrpl-session-openA PaymentChannelCreate and the first claim.{ signedBlob, claimSignature }, each hex digits without 0x, as the XRP Ledger writes them, the blob signed with a single key and carrying no NetworkID, which rippled refuses on each network the challenge can name: one that carries it is declined signed-not-bound (xrpl/network-mismatch).
xrpl-claimOne claim on the session's payment channel, or a close's final claim, inside a batch: { channelId, drops, bytes }, where bytes is CLM\0, the channel id and drops as a big-endian u64.The signature over bytes by the channel's key, hex digits without 0x.
hedera-bodyA Hedera transaction body (request.bodyBytes). With broadcast: true the signer signs and sends it.{ publicKey, signature, type }, with type ed25519 or ecdsa-secp256k1. With broadcast: { transactionId }.
hedera-executorThe executors, asset, payee, amount and validBefore for the buyer's transfer-executor tooling.{ payer, executor, authorization }.
hedera-session-openAn MPP session opening on Hedera, which the signer broadcasts, and its zero voucher.{ openTx, signature }, with landed where the signer has the opening's receipt.
algorand-txnAn Algorand asset transfer whose note carries H.The 64-byte Ed25519 signature, 0x hex.
aptos-transactionThe option to pay. The wallet builds and signs the scheme's own payment.{ transaction }, base64: the transaction's BCS bytes, or x402's reference form.
sui-transactionThe option and a pureInput. The wallet builds the payment, adds the input, and signs.{ signature, transaction }, each base64, as Sui serializes them.
cardano-transactionThe option and the auxiliary data. The wallet builds the payment with a TTL, attaches exactly those auxiliary data, and signs without broadcasting.{ transaction, nonce }, the transaction as base64. Metadata that holds label 674 again, or a label-674 map that repeats a key, is declined signed-not-bound.
near-delegateThe NEP-461 hash of a delegate action whose ft_transfer memo carries H.{ keyType, bytes }, the signature as 0x hex.
starknet-snip12SNIP-12 typed data for a SNIP-9 outside execution.The account's signature, a list of felts.
substrate-callThe profile's call, which the wallet signs as a v4 extrinsic with its own extensions.The extrinsic's bytes, 0x hex.
tron-txidThe id of a TRC-20 transfer whose memo carries H.The 65-byte secp256k1 signature r ‖ s ‖ v, 0x hex.
ton-w5The representation hash of a W5 wallet request.The 64-byte Ed25519 signature, 0x hex.
casper-eip712CEP-3009 typed data whose nonce is H.{ publicKey, signature }, each hex digits without 0x, led by its one-byte algorithm tag (01 or 02).
ccd-transferA Concordium transfer whose memo carries H, which the wallet assembles.The sender-signed V1 sponsored transaction in x402's wire form: with @concordium/web-sdk, JSON.parse(Transaction.toJSONString(tx)).
stacks-contract-callA SIP-010 transfer whose memo is H, on the chain the request's chainId names.The signed transaction's bytes, 0x hex: 1 to 16,384 bytes, signed for chainId at that network's version, 0x00 on chain 1 (mainnet) and 0x80 on any other, as a Stacks node requires. Chain 1 is read as mainnet by the CAIP-2 convention, under which stacks:1 is Stacks mainnet. Another chain id or version is declined signed-not-bound (stacks/chain-mismatch).
bolt11-payA BOLT11 invoice. Your Lightning node pays exactly this invoice.The payment preimage: 64 lower-case hex digits, no 0x.

Protocols without a chain signature

KindWhat the signer signsAnswer
tap-fieldThe lcp-hash field for a Visa Trusted Agent Protocol agent-payer-auth message signature.{ signatureInput, signature, lcpHash }, lcpHash being every lcp-hash field line sent, in order.
vi-checkout-mandateA Mastercard Verifiable Intent checkout mandate.{ l2 } from the user's wallet (immediate), or { l1, l2, l3b } from the agent (autonomous).
ap2-checkout-mandateThe claims of a closed AP2 checkout mandate.The mandate as issued, an SD-JWT string, or AP2's chained presentation: the open mandate's SD-JWT and the closed mandate's, joined by ~~. The closed mandate is the one read.
ucp-checkoutA UCP checkout for the buyer's AP2 mandate issuer.The checkout mandate as issued, an SD-JWT string, or AP2's chained presentation: the open mandate's SD-JWT and the closed mandate's, joined by ~~. The closed mandate is the one read.
acp-allowanceAn ACP delegate_payment allowance.The delegate_payment request the agent signed, as an object.
batchSeveral requests, signed in order (a channel's opening and first voucher, an in-channel voucher).A list of answers, in the same order.

Signers that move the payment

For some requests your signer's action moves the payment itself: a Lightning node paying an invoice, a signer that broadcasts an evm-call, tempo-call or hedera-body marked broadcast: true, a session opening the signer sends. If the gate declines after that (for example because the pairing does not read H from what came back), the decline carries moved: the payment as signed, the ATR's bytes and their hash. Keep it, and present it again rather than signing a new payment.

A signer for several kinds

A real signer dispatches on kind and refuses what it does not handle:

import type { , Signer,  } from "@integraledger/terms";
import {  } from "viem/accounts";

// The published Anvil development key. Never use it for real funds.
const  = ("0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80");

const : Signer = {
  : `eip155:84532:${.}`,
  async (: ): <> {
    switch (.) {
      case "eip712":
        return .(. as <typeof .>[0]);
      case "batch": {
        const : [] = [];
        for (const  of .) .(await this.( as ));
        return ;
      }
      default:
        throw new (`this signer does not sign ${.}`);
    }
  },
};

.(.);
eip155:84532:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266

The rails guide lists, for each pairing, the kind its request has and the inputs its build reads.

Edit on GitHub

Last updated on

On this page