Ledger
What is the ledger?
The ledger is an immutable, append-only log of every payment attempt made through PQSafe AgentPay. It records:
- The envelope used (hash, not full content)
- The payment request (amount, recipient, rail)
- The outcome (settled, failed, pending)
- The ML-DSA-65 signature fingerprint
- Timestamps
The ledger is the primary audit mechanism for autonomous agent payments.
Ledger record structure
interface LedgerRecord { // Identity id: string // UUID v4 envelopeId: string // From signed envelope agentId: string // From envelope
// Payment amount: number currency: string recipient: string rail: string
// Outcome status: 'settled' | 'pending' | 'failed' | 'rejected' txId?: string // Rail transaction ID (when settled) failureReason?: string
// Cryptographic anchoring envelopeHash: string // SHA-256 of canonical envelope JSON sigFingerprint: string // First 16 bytes of ML-DSA-65 signature
// Timestamps submittedAt: Date settledAt?: Date
// Chain anchor (optional — Sprint 3) arbitrumTxHash?: string}Writing to the ledger
The SDK writes to the ledger automatically when you call executeAgentPayment(). You can also write manually:
import { buildLedgerRecord, submitToLedger } from '@pqsafe/agent-pay'
const record = buildLedgerRecord(signedEnvelope, paymentResult)const entry = await submitToLedger(record)
console.log('Ledger entry ID:', entry.id)console.log('Hash:', entry.hash) // Hash chain — each entry includes hash of previousconsole.log('Sequence:', entry.sequence)Hash chain integrity
Each ledger entry includes the hash of the previous entry, forming a chain:
entry[0]: hash = H(content[0])entry[1]: hash = H(content[1] + entry[0].hash)entry[2]: hash = H(content[2] + entry[1].hash)Tampering with any entry invalidates all subsequent hashes. You can verify the chain:
import { verifyLedgerChain } from '@pqsafe/agent-pay'
const entries = await getLedgerEntries({ agentId: 'my-agent' })const isIntact = verifyLedgerChain(entries)console.log('Chain intact:', isIntact) // trueOn-chain anchoring (Arbitrum)
For high-value payments or regulatory compliance, PQSafe can anchor ledger entries on Arbitrum:
import { commitEnvelopeToArbitrum } from '@pqsafe/agent-pay'
const { txHash } = await commitEnvelopeToArbitrum(signedEnvelope, { rpcUrl: process.env.ARBITRUM_RPC_URL!, privateKey: process.env.WALLET_PRIVATE_KEY!,})
console.log('On-chain proof:', txHash)Querying the ledger
import { getLedgerEntries } from '@pqsafe/agent-pay'
const entries = await getLedgerEntries({ agentId: 'procurement-agent', fromDate: new Date('2026-01-01'), status: 'settled', limit: 100,})
const total = entries.reduce((sum, e) => sum + e.amount, 0)console.log(`Total settled: $${total}`)