Documentation Index Fetch the complete documentation index at: https://mintlify.com/nhestrompia/shielded-x402/llms.txt
Use this file to discover all available pages before exploring further.
Overview
The MultiChainCreditClient class enables fast credit-based payments across multiple chains (Base, Solana) using sequencer-authorized intents. The sequencer enforces real-time nonce/balance constraints, while per-chain relayers execute payments only after sequencer authorization.
Constructor
const client = new MultiChainCreditClient ( config : MultiChainCreditClientConfig )
config
MultiChainCreditClientConfig
required
Configuration object for the client Credit sequencer endpoint (e.g., http://127.0.0.1:3200)
relayerUrls
Record<string, string>
required
Map of chain references to relayer URLs {
'eip155:8453' : 'http://127.0.0.1:3100' ,
'solana:devnet' : 'http://127.0.0.1:3101'
}
Custom fetch implementation (defaults to global fetch)
Admin token for sequencer operations (required for adminCredit)
Methods
pay
Execute a unified authorize + relay payment flow.
await client . pay (
request : UnifiedPayRequestV1
): Promise < UnifiedPayResultV1 >
request
UnifiedPayRequestV1
required
Chain reference (e.g., eip155:8453, solana:devnet)
Payment amount in micros (1 micro = 0.000001 USD)
Merchant service registry ID (e.g., demo/base)
Base64-encoded request body
agent
UnifiedPayAgentContext
required
Agent identifier (derived from public key)
Agent public key (e.g., Ed25519 key as hex)
Signature scheme (e.g., ed25519-sha256-v1)
Agent nonce (must be strictly increasing)
Function to sign the payment intent async ( input : {
intent : IntentV1 ;
canonicalBytes : Uint8Array ;
typedData : ReturnType < typeof buildIntentTypedDataPayload >;
}) => Promise < Hex > | Hex
Intent expiration in seconds (default: 300)
Custom request ID (auto-generated if omitted)
Optional service hash for additional binding
Sequencer authorization response The sequencer-signed authorization
Relayer execution response Execution status (e.g., EXECUTED)
Onchain transaction hash (if applicable)
Response from merchant API
Example
import { MultiChainCreditClient } from '@shielded-x402/client' ;
import { normalizeHex , deriveAgentIdFromPubKey } from '@shielded-x402/shared-types' ;
import { createHash , sign , createPrivateKey } from 'node:crypto' ;
const client = new MultiChainCreditClient ({
sequencerUrl: 'http://127.0.0.1:3200' ,
relayerUrls: {
'eip155:8453' : 'http://127.0.0.1:3100'
}
});
const agentPubKey = '0x...' ;
const agentId = deriveAgentIdFromPubKey ( agentPubKey );
const agentPrivateKeyPem = process . env . AGENT_ED25519_PRIVATE_KEY_PEM ;
const result = await client . pay ({
chainRef: 'eip155:8453' ,
amountMicros: '1500000' , // $1.50
merchant: {
serviceRegistryId: 'demo/base' ,
endpointUrl: 'https://merchant.example/pay'
},
merchantRequest: {
url: 'https://merchant.example/pay' ,
method: 'POST' ,
headers: { 'content-type' : 'application/json' },
bodyBase64: Buffer . from ( JSON . stringify ({ orderId: 'o-123' })). toString ( 'base64' )
},
agent: {
agentId ,
agentPubKey ,
signatureScheme: 'ed25519-sha256-v1' ,
agentNonce: '0' ,
signIntent : async ({ canonicalBytes }) => {
const digest = createHash ( 'sha256' ). update ( canonicalBytes ). digest ();
const privateKey = createPrivateKey ( agentPrivateKeyPem );
return normalizeHex ( `0x ${ sign ( null , digest , privateKey ). toString ( 'hex' ) } ` );
}
}
});
console . log ( 'Auth ID:' , result . authorize . authorization . authId );
console . log ( 'Execution TX:' , result . relay . executionTxHash );
console . log ( 'Status:' , result . relay . status );
authorize
Request sequencer authorization for a payment intent.
await client . authorize (
request : AuthorizeRequestV1
): Promise < AuthorizeResponseV1 >
request
AuthorizeRequestV1
required
Payment intent with agent/merchant details
Agent signature over canonical intent bytes
Sequencer-issued authorization
Example
import {
buildIntentTypedDataPayload ,
canonicalIntentBytes ,
deriveMerchantId
} from '@shielded-x402/shared-types' ;
const intent : IntentV1 = {
version: 1 ,
agentId ,
agentPubKey ,
signatureScheme: 'ed25519-sha256-v1' ,
agentNonce: '0' ,
amountMicros: '1500000' ,
merchantId: deriveMerchantId ({
serviceRegistryId: 'demo/base' ,
endpointUrl: 'https://merchant.example/pay'
}),
requiredChainRef: 'eip155:8453' ,
expiresAt: String ( Math . floor ( Date . now () / 1000 ) + 300 ),
requestId: '0x...'
};
const agentSig = signIntent ( intent , privateKey );
const authResponse = await client . authorize ({ intent , agentSig });
console . log ( 'Auth ID:' , authResponse . authorization . authId );
relayPay
Execute a payment via the chain-specific relayer.
await client . relayPay (
request : RelayPayRequestV1
): Promise < RelayPayResponseV1 >
request
RelayPayRequestV1
required
Sequencer-issued authorization
Merchant request details (url, method, headers, bodyBase64)
Transaction hash (if applicable)
adminCredit
Credit an agent’s balance (requires sequencerAdminToken).
await client . adminCredit (
request : AdminCreditRequestV1
): Promise < AdminCreditResponseV1 >
request
AdminCreditRequestV1
required
Amount to credit in micros
adminCredit is only for local test/dev environments. Production systems must use shielded settlement (FundingSignal) to credit balances.
Example
await client . adminCredit ({
agentId: '0x1234...' ,
amountMicros: '10000000' // $10.00
});
latestCommitment
Fetch the latest commitment epoch metadata.
await client . latestCommitment (): Promise < LatestCommitmentResponseV1 >
LatestCommitmentResponseV1
Merkle root for the epoch
Number of authorizations in epoch
Timestamp when posted onchain
Transaction hash of onchain commitment
Example
const latest = await client . latestCommitment ();
console . log ( 'Epoch:' , latest . latestEpochId );
console . log ( 'Root:' , latest . root );
commitmentProof
Fetch the inclusion proof for a specific authorization.
await client . commitmentProof (
authId : Hex
): Promise < InclusionProofV1 >
Authorization ID to prove
Epoch containing the authorization
Example
const proof = await client . commitmentProof ( '0xabc123...' );
console . log ( 'Epoch:' , proof . epochId );
console . log ( 'Leaf:' , proof . leafHash );
console . log ( 'Proof siblings:' , proof . siblings );
reclaim
Reclaim an expired or failed authorization.
await client . reclaim (
request : ReclaimRequestV1
): Promise < { ok : true ; authId : Hex } >
Authorization ID to reclaim
Caller type (e.g., sequencer, agent)
Unix timestamp of reclaim request
Example
await client . reclaim ({
authId: '0xexpired...' ,
callerType: 'sequencer' ,
requestedAt: String ( Math . floor ( Date . now () / 1000 ))
});
Multi-Chain Example
Execute payments on both Base and Solana:
const client = new MultiChainCreditClient ({
sequencerUrl: 'http://127.0.0.1:3200' ,
relayerUrls: {
'eip155:8453' : 'http://127.0.0.1:3100' ,
'solana:devnet' : 'http://127.0.0.1:3101'
},
sequencerAdminToken: 'change-me'
});
// Credit agent balance
await client . adminCredit ({
agentId ,
amountMicros: '10000000'
});
// Base payment
const baseResult = await client . pay ({
chainRef: 'eip155:8453' ,
amountMicros: '1500000' ,
merchant: {
serviceRegistryId: 'demo/base' ,
endpointUrl: 'https://merchant.base.example/pay'
},
merchantRequest: { /* ... */ },
agent: { agentNonce: '0' , /* ... */ }
});
// Solana payment (nonce incremented)
const solanaResult = await client . pay ({
chainRef: 'solana:devnet' ,
amountMicros: '2500000' ,
merchant: {
serviceRegistryId: 'demo/solana' ,
endpointUrl: 'https://merchant.solana.example/pay'
},
merchantRequest: { /* ... */ },
agent: { agentNonce: '1' , /* ... */ }
});
console . log ( 'Base TX:' , baseResult . relay . executionTxHash );
console . log ( 'Solana TX:' , solanaResult . relay . executionTxHash );
Best Practices
Agent nonces must be strictly increasing. Track the current nonce locally: let currentNonce = 0 ;
async function executePay ( params : UnifiedPayRequestV1 ) {
const result = await client . pay ({
... params ,
agent: {
... params . agent ,
agentNonce: String ( currentNonce ++ )
}
});
return result ;
}
Track remaining balance after each payment to avoid insufficient balance errors: let balance = 10_000_000 n ; // micros
const result = await client . pay ({ amountMicros: '1500000' , ... });
balance -= 1_500_000 n ;
console . log ( 'Remaining balance:' , balance );
Handle authorization and relay errors separately: try {
const result = await client . pay ( request );
console . log ( 'Success:' , result . relay . status );
} catch ( error ) {
if ( error . message . includes ( 'insufficient balance' )) {
// Top up balance
} else if ( error . message . includes ( 'nonce' )) {
// Resync nonce
} else {
// Other error
}
}
Periodically verify commitments are posted onchain: const latest = await client . latestCommitment ();
if ( latest . postedTxHash ) {
console . log ( 'Committed onchain:' , latest . postedTxHash );
}
See Also