Agent payments, end to end.
A user signs a scoped budget, a consumer pays with agent.fetch(), and an Express API verifies the on-chain settlement before serving. MandateRegistry remains the authority for every spend.
Clean-clone testnet run
Clone the protocol repository, install its locked dependencies, then run npm run agents:testnet. No local keys or environment file are required.
Candidate toolkit
# Candidate set — confirm npm publication before installing
npm install @ackrate/core@0.3.3 @ackrate/stellar@0.2.5 \
@ackrate/ap2@0.3.2 @ackrate/express-middleware@0.2.4 \
@stellar/stellar-sdk express
npm install --global @ackrate/cli@0.1.10This is the source-repository candidate set. Confirm each version on npm before running the install commands.
Run from a clean clone
git clone https://github.com/ackrate/ackrate-protocol.git
cd ackrate-protocol
npm ci
npm run agents:testnetThe script creates and funds fresh testnet actors, signs a 3 XLM mandate, starts the protected Express API, and drives four sequential purchases through agent.fetch().
Consumer: pay with agent.fetch()
import { getSettlementReceipt, ackrate } from "@ackrate/core";
const agent = ackrate.agent({
mandate,
signer: agentSecret,
proofPolicy: "bound-v2-only",
receiptStore,
});
const response = await agent.fetch(`${serverUrl}/source/${id}`);
const receipt = getSettlementReceipt(response);
const resource = await response.json();
await persistAcceptedResult(resource, receipt);
await agent.acknowledgeDelivery(receipt);A 402 response carries an exact-request challenge. The SDK checks it against the mandate, settles through MandateRegistry.execute_payment, then signs the challenge and transaction with the mandate agent.
Express: verify before serving
import express from "express";
import {
InMemoryBoundRedemptionStore,
createBoundAckratePaidJsonRoute,
} from "@ackrate/express-middleware";
const app = express();
// Demo only. Use a durable, shared BoundRedemptionStore in production.
const redemptionStore = new InMemoryBoundRedemptionStore();
const paidSource = createBoundAckratePaidJsonRoute({
merchant: process.env.ACKRATE_MERCHANT_ADDRESS!,
sourceAccount: process.env.ACKRATE_READ_SOURCE_ADDRESS!,
audience: "https://api.example",
challengeSecret: process.env.ACKRATE_CHALLENGE_SECRET!,
redemptionStore,
amount: "1.00",
resource: (request) => request.originalUrl,
}, async ({ request, payment }) => ({
body: {
ok: true,
resource: request.params.id,
settledTx: payment.txHash,
data: "protected value",
},
}));
app.get("/source/:id", paidSource);The paid JSON route verifies challenge authentication, the exact origin and GET resource, the configured network, successful transaction, MandateRegistry event, matching SEP-41 transfer, and the chain-derived agent signature before the route handler runs. The redemption store prevents one transaction from authorizing a fresh challenge; the same signed proof may recover only the same idempotent resource. Use a durable shared store in production.
What the testnet run proves
Sources 1–3Each settles 1 XLM and is served after Express verifies the paymentSource 4The contract rejects it because the 3 XLM mandate budget is exhaustedFinal balanceThe merchant receives exactly 3 XLM; the fourth resource stays lockedThree resources are paid for and served. The fourth payment is rejected on-chain with the budget exhausted, so the fourth resource is not delivered.
Current candidate targets
@ackrate/core 0.3.3Mandates, contract-enforced payments, and bound-v2 agent.fetch()@ackrate/stellar 0.2.5Typed contract client, testnet and verified Mainnet config, signers, and token helpers@ackrate/ap2 0.3.2Signed, version-pinned AP2 IntentMandate validation@ackrate/express-middleware 0.2.4Exact-request proof verification and safe same-resource recovery@ackrate/cli 0.1.10Terminal setup, mandate, payment, reconciliation, and fail-closed Mainnet demo supportCurrent testnet contract
CCHQ5G4Y4YBMY6D3TYYJSVJVCKUM22Q6TMKCCHVAHY4X7K6QELQACZRMThis is the current upgradeable simple MandateRegistry used by the public testnet configuration. The contract re-checks caller, merchant scope, asset, budget, expiry, and sequence for every payment.
Verification boundary
- ✓ The user approves the SEP-41 allowance for the contract, never for the agent or SDK.
- ✓ MandateRegistry validates and consumes authorization before the token transfer in one transaction.
- ✓ The Express middleware independently verifies contract and transfer evidence before fulfillment.
- ✓ Repository tests and the gate check cover allowed payments and contract-enforced rejection paths.