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.
Install the current toolkit
npm install @reapp-sdk/core@0.3.1 @reapp-sdk/stellar@0.2.2 \
@reapp-sdk/ap2@0.3.0 @reapp-sdk/express-middleware@0.2.2 \
@stellar/stellar-sdk express
npm install --global reapp-protocol-cli@0.1.7Run from a clean clone
git clone https://github.com/reapp-protocol/reapp-protocol.git
cd reapp-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, reapp } from "@reapp-sdk/core";
const agent = reapp.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,
createBoundReappPaidJsonRoute,
} from "@reapp-sdk/express-middleware";
const app = express();
// Demo only. Use a durable, shared BoundRedemptionStore in production.
const redemptionStore = new InMemoryBoundRedemptionStore();
const paidSource = createBoundReappPaidJsonRoute({
merchant: process.env.REAPP_MERCHANT_ADDRESS!,
sourceAccount: process.env.REAPP_READ_SOURCE_ADDRESS!,
audience: "https://api.example",
challengeSecret: process.env.REAPP_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 release targets
@reapp-sdk/core 0.3.1Mandates, contract-enforced payments, and bound-v2 agent.fetch()@reapp-sdk/stellar 0.2.2Typed contract client, testnet config, signers, and token helpers@reapp-sdk/ap2 0.3.0Signed, version-pinned AP2 IntentMandate validation@reapp-sdk/express-middleware 0.2.2Exact-request proof verification and safe same-resource recoveryreapp-protocol-cli 0.1.7Terminal setup, mandate, payment, reconciliation, and demo commandsCurrent 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.