@nickthelegend69/fund402 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,59 @@
1
+ import { KeyAlgorithm } from "casper-js-sdk";
2
+ import type { PaymentRequiredBody, PaymentRequirements } from "./types";
3
+ export interface Fund402ClientConfig {
4
+ /** Agent signing key — PEM contents or hex. */
5
+ agentSecretKey: string;
6
+ /** Agent account-key hex (01.. ed25519 / 02.. secp256k1). */
7
+ agentPublicKey: string;
8
+ /** Fund402 vault (lending pool) contract hash, 64 hex. */
9
+ vaultContract: string;
10
+ /** CAIP-2 network. Default "casper:casper-test". */
11
+ network?: string;
12
+ /** Casper JSON-RPC node. Default derived from network (CSPR.cloud public node). */
13
+ nodeUrl?: string;
14
+ /** Chain name. Default derived ("casper-test" / "casper"). */
15
+ chainName?: string;
16
+ keyAlgorithm?: KeyAlgorithm;
17
+ /** Over-collateralisation ratio the agent posts (vault re-checks on-chain). Default 1.5. */
18
+ collateralRatio?: number;
19
+ /** Gas (motes) for the borrow_and_pay deploy. Default 5 CSPR. */
20
+ borrowGasMotes?: string;
21
+ /** Underlying fetch implementation. Default global fetch. */
22
+ fetchImpl?: typeof fetch;
23
+ onEvent?: (event: Fund402Event) => void;
24
+ }
25
+ export interface Fund402Event {
26
+ type: "intercepted_402" | "borrowing" | "borrow_submitted" | "payment_settled" | "payment_sent" | "request_retried" | "payment_confirmed";
27
+ data: Record<string, unknown>;
28
+ timestamp: number;
29
+ }
30
+ /** Decode an x402 challenge from a `payment-required` header or a JSON body. */
31
+ export declare function decodeChallenge(paymentRequiredHeader: string | null | undefined, body: unknown): PaymentRequiredBody | null;
32
+ /** Pick the casper:* payment option from a challenge. */
33
+ export declare function selectCasperOption(challenge: PaymentRequiredBody): PaymentRequirements | undefined;
34
+ /**
35
+ * Settle one x402 challenge through the lending pool: borrow_and_pay on the vault,
36
+ * wait, and build the signed `exact` payload + base64 `payment-signature` header.
37
+ */
38
+ export declare function payViaPool(config: Fund402ClientConfig, option: PaymentRequirements, resource: string): Promise<{
39
+ paymentHeader: string;
40
+ deployHash: string;
41
+ }>;
42
+ /**
43
+ * A `fetch` that transparently pays x402-gated endpoints via the Fund402 pool.
44
+ *
45
+ * ```ts
46
+ * const f = fund402Fetch({ agentSecretKey, agentPublicKey, vaultContract });
47
+ * const res = await f("https://merchant.example/v/vault_1/price/BTC-USD");
48
+ * const data = await res.json(); // paid + served, agent balance can be zero
49
+ * ```
50
+ */
51
+ export declare function fund402Fetch(config: Fund402ClientConfig): typeof fetch;
52
+ /**
53
+ * Axios variant — returns an AxiosInstance that pays 402s via the pool. Axios is
54
+ * an optional peer dependency, required lazily so the server side stays dep-free.
55
+ */
56
+ export declare function withPaymentInterceptor(config: Fund402ClientConfig): any;
57
+ /** Convenience presets. */
58
+ export declare function testnetClient(): Partial<Fund402ClientConfig>;
59
+ export declare function mainnetClient(): Partial<Fund402ClientConfig>;
package/dist/client.js ADDED
@@ -0,0 +1,179 @@
1
+ "use strict";
2
+ // Fund402 CLIENT side — let an autonomous agent PAY x402 endpoints with
3
+ // just-in-time credit from the Fund402 lending pool.
4
+ //
5
+ // `fund402Fetch(config)` returns a drop-in `fetch`. When a request comes back
6
+ // `402 Payment Required`, it:
7
+ // 1. decodes the x402 challenge,
8
+ // 2. calls the vault `borrow_and_pay` (the pool fronts the CEP-18 payment to the
9
+ // merchant) and waits for settlement,
10
+ // 3. builds the signed x402 `exact` payload, and
11
+ // 4. replays the request with a `payment-signature` header — returning the real
12
+ // 200 response. The agent's own balance can be zero; the pool covers it.
13
+ //
14
+ // `withPaymentInterceptor(config)` is the same behaviour as an Axios instance
15
+ // (Axios is an optional peer dependency, required lazily).
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.decodeChallenge = decodeChallenge;
18
+ exports.selectCasperOption = selectCasperOption;
19
+ exports.payViaPool = payViaPool;
20
+ exports.fund402Fetch = fund402Fetch;
21
+ exports.withPaymentInterceptor = withPaymentInterceptor;
22
+ exports.testnetClient = testnetClient;
23
+ exports.mainnetClient = mainnetClient;
24
+ const casper_1 = require("./casper");
25
+ const DEFAULT_NETWORK = "casper:casper-test";
26
+ function chainNameFor(network) {
27
+ return network.includes("test") ? "casper-test" : "casper";
28
+ }
29
+ function nodeUrlFor(network) {
30
+ return network.includes("test")
31
+ ? "https://node.testnet.cspr.cloud/rpc"
32
+ : "https://node.mainnet.cspr.cloud/rpc";
33
+ }
34
+ function wiringFrom(config) {
35
+ const network = config.network ?? DEFAULT_NETWORK;
36
+ return {
37
+ network,
38
+ nodeUrl: config.nodeUrl ?? nodeUrlFor(network),
39
+ chainName: config.chainName ?? chainNameFor(network),
40
+ vaultContractHash: config.vaultContract.replace(/^hash-/, ""),
41
+ agentSecretKey: config.agentSecretKey,
42
+ agentPublicKey: config.agentPublicKey,
43
+ keyAlgorithm: config.keyAlgorithm,
44
+ borrowGasMotes: config.borrowGasMotes,
45
+ };
46
+ }
47
+ function emit(config, type, data) {
48
+ config.onEvent?.({ type, data, timestamp: Date.now() });
49
+ }
50
+ function deriveVaultId(resource) {
51
+ const m = resource.match(/\/v\/([^/]+)/);
52
+ return m ? m[1] : "vault_1";
53
+ }
54
+ /** Decode an x402 challenge from a `payment-required` header or a JSON body. */
55
+ function decodeChallenge(paymentRequiredHeader, body) {
56
+ if (paymentRequiredHeader) {
57
+ try {
58
+ return JSON.parse(Buffer.from(paymentRequiredHeader, "base64").toString("utf-8"));
59
+ }
60
+ catch {
61
+ /* fall through to body */
62
+ }
63
+ }
64
+ if (body && typeof body === "object" && "accepts" in body) {
65
+ return body;
66
+ }
67
+ return null;
68
+ }
69
+ /** Pick the casper:* payment option from a challenge. */
70
+ function selectCasperOption(challenge) {
71
+ return challenge.accepts.find((o) => o.network.startsWith("casper")) ?? challenge.accepts[0];
72
+ }
73
+ /**
74
+ * Settle one x402 challenge through the lending pool: borrow_and_pay on the vault,
75
+ * wait, and build the signed `exact` payload + base64 `payment-signature` header.
76
+ */
77
+ async function payViaPool(config, option, resource) {
78
+ const wiring = wiringFrom(config);
79
+ const amount = BigInt(option.amount);
80
+ const ratio = config.collateralRatio ?? 1.5;
81
+ const collateral = (amount * BigInt(Math.round(ratio * 100))) / 100n;
82
+ emit(config, "borrowing", { amount: amount.toString(), collateral: collateral.toString() });
83
+ const { deployHash } = await (0, casper_1.borrowAndPayOnChain)(wiring, {
84
+ merchant: option.payTo,
85
+ amount,
86
+ collateral,
87
+ vaultId: deriveVaultId(option.resource ?? resource),
88
+ });
89
+ emit(config, "borrow_submitted", { deployHash });
90
+ const ok = await (0, casper_1.waitForDeploy)(wiring, deployHash);
91
+ emit(config, "payment_settled", { deployHash, success: ok });
92
+ if (!ok)
93
+ throw new Error(`vault borrow_and_pay deploy failed: ${deployHash}`);
94
+ const payload = await (0, casper_1.buildExactPayload)(wiring, option, { deployHash });
95
+ const paymentHeader = Buffer.from(JSON.stringify(payload)).toString("base64");
96
+ emit(config, "payment_sent", { deployHash });
97
+ return { paymentHeader, deployHash };
98
+ }
99
+ /**
100
+ * A `fetch` that transparently pays x402-gated endpoints via the Fund402 pool.
101
+ *
102
+ * ```ts
103
+ * const f = fund402Fetch({ agentSecretKey, agentPublicKey, vaultContract });
104
+ * const res = await f("https://merchant.example/v/vault_1/price/BTC-USD");
105
+ * const data = await res.json(); // paid + served, agent balance can be zero
106
+ * ```
107
+ */
108
+ function fund402Fetch(config) {
109
+ const baseFetch = config.fetchImpl ?? globalThis.fetch;
110
+ if (!baseFetch)
111
+ throw new Error("fund402Fetch: no fetch implementation available");
112
+ const wrapped = async (input, init) => {
113
+ const res = await baseFetch(input, init);
114
+ if (res.status !== 402)
115
+ return res;
116
+ const url = typeof input === "string" || input instanceof URL ? input.toString() : input.url;
117
+ const hdr = res.headers.get("payment-required");
118
+ const body = await res.clone().json().catch(() => undefined);
119
+ const challenge = decodeChallenge(hdr, body);
120
+ if (!challenge)
121
+ return res; // not an x402 challenge we understand
122
+ const option = selectCasperOption(challenge);
123
+ if (!option)
124
+ throw new Error("no casper payment option in 402 challenge");
125
+ emit(config, "intercepted_402", { resource: option.resource, amount: option.amount });
126
+ const { paymentHeader, deployHash } = await payViaPool(config, option, url);
127
+ const headers = new Headers(init?.headers ?? (typeof input === "object" ? input.headers : undefined));
128
+ headers.set("payment-signature", paymentHeader);
129
+ emit(config, "request_retried", { url });
130
+ const retried = await baseFetch(url, { ...(init ?? {}), headers });
131
+ emit(config, "payment_confirmed", { deployHash });
132
+ return retried;
133
+ };
134
+ return wrapped;
135
+ }
136
+ /**
137
+ * Axios variant — returns an AxiosInstance that pays 402s via the pool. Axios is
138
+ * an optional peer dependency, required lazily so the server side stays dep-free.
139
+ */
140
+ function withPaymentInterceptor(config) {
141
+ let axios;
142
+ try {
143
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
144
+ axios = require("axios");
145
+ }
146
+ catch {
147
+ throw new Error("withPaymentInterceptor requires `axios` (npm i axios). Or use fund402Fetch().");
148
+ }
149
+ const instance = axios.create();
150
+ instance.interceptors.response.use((r) => r, async (error) => {
151
+ if (error.response?.status !== 402)
152
+ throw error;
153
+ const hdr = error.response.headers?.["payment-required"];
154
+ const challenge = decodeChallenge(hdr, error.response.data);
155
+ if (!challenge)
156
+ throw error;
157
+ const option = selectCasperOption(challenge);
158
+ if (!option)
159
+ throw new Error("no casper payment option in 402 challenge");
160
+ const resource = option.resource ?? error.config?.url ?? "";
161
+ emit(config, "intercepted_402", { resource, amount: option.amount });
162
+ const { paymentHeader, deployHash } = await payViaPool(config, option, resource);
163
+ const originalRequest = error.config;
164
+ originalRequest.headers = originalRequest.headers ?? {};
165
+ originalRequest.headers["payment-signature"] = paymentHeader;
166
+ emit(config, "request_retried", { url: originalRequest.url });
167
+ const retried = await instance(originalRequest);
168
+ emit(config, "payment_confirmed", { deployHash });
169
+ return retried;
170
+ });
171
+ return instance;
172
+ }
173
+ /** Convenience presets. */
174
+ function testnetClient() {
175
+ return { network: "casper:casper-test", chainName: "casper-test", nodeUrl: nodeUrlFor("casper:casper-test") };
176
+ }
177
+ function mainnetClient() {
178
+ return { network: "casper:casper", chainName: "casper", nodeUrl: nodeUrlFor("casper:casper") };
179
+ }
@@ -0,0 +1,19 @@
1
+ export declare function bytesToHex(b: Uint8Array): string;
2
+ export interface Eip712Domain {
3
+ name: string;
4
+ version: string;
5
+ chainName: string;
6
+ contractPackageHash: string;
7
+ }
8
+ export interface TransferAuthorization {
9
+ from: string;
10
+ to: string;
11
+ value: string;
12
+ validAfter: string;
13
+ validBefore: string;
14
+ nonce: string;
15
+ }
16
+ /** Final 32-byte EIP-712 digest to be signed by the agent key. */
17
+ export declare function transferAuthorizationDigest(domain: Eip712Domain, message: TransferAuthorization): Uint8Array;
18
+ /** Random 32-byte nonce as hex. */
19
+ export declare function randomNonce(): string;
package/dist/eip712.js ADDED
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ // casper-eip-712 TransferWithAuthorization typed-data digest, implemented to
3
+ // match make-software/casper-x402 + casper-ecosystem/casper-eip-712 exactly so
4
+ // the produced signature verifies against the CSPR.cloud x402 facilitator's
5
+ // POST /verify. Cross-checked against the canonical library in test/eip712.test.mjs.
6
+ //
7
+ // digest = keccak256( 0x19 0x01 || domainSeparator || structHash )
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.bytesToHex = bytesToHex;
10
+ exports.transferAuthorizationDigest = transferAuthorizationDigest;
11
+ exports.randomNonce = randomNonce;
12
+ const sha3_1 = require("@noble/hashes/sha3");
13
+ const enc = new TextEncoder();
14
+ function keccak(...parts) {
15
+ const total = parts.reduce((n, p) => n + p.length, 0);
16
+ const buf = new Uint8Array(total);
17
+ let o = 0;
18
+ for (const p of parts) {
19
+ buf.set(p, o);
20
+ o += p.length;
21
+ }
22
+ return (0, sha3_1.keccak_256)(buf);
23
+ }
24
+ function hexToBytes(hex) {
25
+ const h = hex.startsWith("0x") ? hex.slice(2) : hex;
26
+ const out = new Uint8Array(h.length / 2);
27
+ for (let i = 0; i < out.length; i++)
28
+ out[i] = parseInt(h.substr(i * 2, 2), 16);
29
+ return out;
30
+ }
31
+ function bytesToHex(b) {
32
+ return Array.from(b, (x) => x.toString(16).padStart(2, "0")).join("");
33
+ }
34
+ function uint256(value) {
35
+ let v = BigInt(value);
36
+ const out = new Uint8Array(32);
37
+ for (let i = 31; i >= 0; i--) {
38
+ out[i] = Number(v & 0xffn);
39
+ v >>= 8n;
40
+ }
41
+ return out;
42
+ }
43
+ /** EIP-712 `address` encoding for a Casper tagged address ("00.."/"01.." + hash). */
44
+ function encodeAddress(addr) {
45
+ const bytes = hexToBytes(addr); // expect 33 bytes (1 tag + 32 hash)
46
+ return (0, sha3_1.keccak_256)(bytes);
47
+ }
48
+ function typeHash(typeString) {
49
+ return (0, sha3_1.keccak_256)(enc.encode(typeString));
50
+ }
51
+ const DOMAIN_TYPE = "EIP712Domain(string name,string version,string chain_name,bytes32 contract_package_hash)";
52
+ const MESSAGE_TYPE = "TransferWithAuthorization(address from,address to,uint256 value,uint256 validAfter,uint256 validBefore,bytes32 nonce)";
53
+ function domainSeparator(d) {
54
+ return keccak(typeHash(DOMAIN_TYPE), (0, sha3_1.keccak_256)(enc.encode(d.name)), (0, sha3_1.keccak_256)(enc.encode(d.version)), (0, sha3_1.keccak_256)(enc.encode(d.chainName)), hexToBytes(d.contractPackageHash) // bytes32 raw
55
+ );
56
+ }
57
+ function structHash(m) {
58
+ return keccak(typeHash(MESSAGE_TYPE), encodeAddress(m.from), encodeAddress(m.to), uint256(m.value), uint256(m.validAfter), uint256(m.validBefore), hexToBytes(m.nonce) // bytes32 raw
59
+ );
60
+ }
61
+ /** Final 32-byte EIP-712 digest to be signed by the agent key. */
62
+ function transferAuthorizationDigest(domain, message) {
63
+ const prefix = new Uint8Array([0x19, 0x01]);
64
+ return keccak(prefix, domainSeparator(domain), structHash(message));
65
+ }
66
+ /** Random 32-byte nonce as hex. */
67
+ function randomNonce() {
68
+ const b = new Uint8Array(32);
69
+ if (typeof globalThis.crypto?.getRandomValues === "function") {
70
+ globalThis.crypto.getRandomValues(b);
71
+ }
72
+ else {
73
+ for (let i = 0; i < 32; i++)
74
+ b[i] = Math.floor(Math.random() * 256);
75
+ }
76
+ return bytesToHex(b);
77
+ }
@@ -0,0 +1,8 @@
1
+ export * from "./types";
2
+ export { paywall, buildPaymentRequirements, challengeBody, decodePaymentSignature, verifyPoolSettlement, verifyWithFacilitator, explorerTx, type PaywallConfig, type Fund402Paywall, type VerifyResult, type GuardResult, type RequestLike, type HttpResponseLike, } from "./server";
3
+ export { fund402Fetch, withPaymentInterceptor, payViaPool, decodeChallenge, selectCasperOption, testnetClient, mainnetClient, type Fund402ClientConfig, type Fund402Event, } from "./client";
4
+ export { borrowAndPayOnChain, repayLoanOnChain, ensureCollateralAllowance, buildExactPayload, waitForDeploy, agentTaggedAddress, loadPrivateKey, rpc, type CasperWiringConfig, } from "./casper";
5
+ export { transferAuthorizationDigest, randomNonce, bytesToHex } from "./eip712";
6
+ export { expressPaywall } from "./adapters/express";
7
+ export { honoPaywall } from "./adapters/hono";
8
+ export { withPaywall } from "./adapters/next";
package/dist/index.js ADDED
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ // @nickthelegend69/fund402 — the Fund402 SDK.
3
+ //
4
+ // SERVER (merchant): create x402-gated HTTP endpoints SETTLED BY THE LENDING POOL.
5
+ // import { paywall } from "@nickthelegend69/fund402";
6
+ // import { expressPaywall } from "@nickthelegend69/fund402/express";
7
+ //
8
+ // CLIENT (agent): pay any x402 endpoint with just-in-time credit from the pool.
9
+ // import { fund402Fetch } from "@nickthelegend69/fund402";
10
+ //
11
+ // Casper-native (CEP-18 + EIP-712 over the casper:* x402 `exact` scheme), verified
12
+ // live against the CSPR.cloud facilitator and the deployed Fund402 vault on testnet.
13
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ var desc = Object.getOwnPropertyDescriptor(m, k);
16
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
17
+ desc = { enumerable: true, get: function() { return m[k]; } };
18
+ }
19
+ Object.defineProperty(o, k2, desc);
20
+ }) : (function(o, m, k, k2) {
21
+ if (k2 === undefined) k2 = k;
22
+ o[k2] = m[k];
23
+ }));
24
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
25
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
26
+ };
27
+ Object.defineProperty(exports, "__esModule", { value: true });
28
+ exports.withPaywall = exports.honoPaywall = exports.expressPaywall = exports.bytesToHex = exports.randomNonce = exports.transferAuthorizationDigest = exports.rpc = exports.loadPrivateKey = exports.agentTaggedAddress = exports.waitForDeploy = exports.buildExactPayload = exports.ensureCollateralAllowance = exports.repayLoanOnChain = exports.borrowAndPayOnChain = exports.mainnetClient = exports.testnetClient = exports.selectCasperOption = exports.decodeChallenge = exports.payViaPool = exports.withPaymentInterceptor = exports.fund402Fetch = exports.explorerTx = exports.verifyWithFacilitator = exports.verifyPoolSettlement = exports.decodePaymentSignature = exports.challengeBody = exports.buildPaymentRequirements = exports.paywall = void 0;
29
+ __exportStar(require("./types"), exports);
30
+ // Server
31
+ var server_1 = require("./server");
32
+ Object.defineProperty(exports, "paywall", { enumerable: true, get: function () { return server_1.paywall; } });
33
+ Object.defineProperty(exports, "buildPaymentRequirements", { enumerable: true, get: function () { return server_1.buildPaymentRequirements; } });
34
+ Object.defineProperty(exports, "challengeBody", { enumerable: true, get: function () { return server_1.challengeBody; } });
35
+ Object.defineProperty(exports, "decodePaymentSignature", { enumerable: true, get: function () { return server_1.decodePaymentSignature; } });
36
+ Object.defineProperty(exports, "verifyPoolSettlement", { enumerable: true, get: function () { return server_1.verifyPoolSettlement; } });
37
+ Object.defineProperty(exports, "verifyWithFacilitator", { enumerable: true, get: function () { return server_1.verifyWithFacilitator; } });
38
+ Object.defineProperty(exports, "explorerTx", { enumerable: true, get: function () { return server_1.explorerTx; } });
39
+ // Client
40
+ var client_1 = require("./client");
41
+ Object.defineProperty(exports, "fund402Fetch", { enumerable: true, get: function () { return client_1.fund402Fetch; } });
42
+ Object.defineProperty(exports, "withPaymentInterceptor", { enumerable: true, get: function () { return client_1.withPaymentInterceptor; } });
43
+ Object.defineProperty(exports, "payViaPool", { enumerable: true, get: function () { return client_1.payViaPool; } });
44
+ Object.defineProperty(exports, "decodeChallenge", { enumerable: true, get: function () { return client_1.decodeChallenge; } });
45
+ Object.defineProperty(exports, "selectCasperOption", { enumerable: true, get: function () { return client_1.selectCasperOption; } });
46
+ Object.defineProperty(exports, "testnetClient", { enumerable: true, get: function () { return client_1.testnetClient; } });
47
+ Object.defineProperty(exports, "mainnetClient", { enumerable: true, get: function () { return client_1.mainnetClient; } });
48
+ // On-chain primitives + crypto (advanced use)
49
+ var casper_1 = require("./casper");
50
+ Object.defineProperty(exports, "borrowAndPayOnChain", { enumerable: true, get: function () { return casper_1.borrowAndPayOnChain; } });
51
+ Object.defineProperty(exports, "repayLoanOnChain", { enumerable: true, get: function () { return casper_1.repayLoanOnChain; } });
52
+ Object.defineProperty(exports, "ensureCollateralAllowance", { enumerable: true, get: function () { return casper_1.ensureCollateralAllowance; } });
53
+ Object.defineProperty(exports, "buildExactPayload", { enumerable: true, get: function () { return casper_1.buildExactPayload; } });
54
+ Object.defineProperty(exports, "waitForDeploy", { enumerable: true, get: function () { return casper_1.waitForDeploy; } });
55
+ Object.defineProperty(exports, "agentTaggedAddress", { enumerable: true, get: function () { return casper_1.agentTaggedAddress; } });
56
+ Object.defineProperty(exports, "loadPrivateKey", { enumerable: true, get: function () { return casper_1.loadPrivateKey; } });
57
+ Object.defineProperty(exports, "rpc", { enumerable: true, get: function () { return casper_1.rpc; } });
58
+ var eip712_1 = require("./eip712");
59
+ Object.defineProperty(exports, "transferAuthorizationDigest", { enumerable: true, get: function () { return eip712_1.transferAuthorizationDigest; } });
60
+ Object.defineProperty(exports, "randomNonce", { enumerable: true, get: function () { return eip712_1.randomNonce; } });
61
+ Object.defineProperty(exports, "bytesToHex", { enumerable: true, get: function () { return eip712_1.bytesToHex; } });
62
+ // Framework adapters (also available as subpath imports /express /hono /next)
63
+ var express_1 = require("./adapters/express");
64
+ Object.defineProperty(exports, "expressPaywall", { enumerable: true, get: function () { return express_1.expressPaywall; } });
65
+ var hono_1 = require("./adapters/hono");
66
+ Object.defineProperty(exports, "honoPaywall", { enumerable: true, get: function () { return hono_1.honoPaywall; } });
67
+ var next_1 = require("./adapters/next");
68
+ Object.defineProperty(exports, "withPaywall", { enumerable: true, get: function () { return next_1.withPaywall; } });
@@ -0,0 +1,112 @@
1
+ import type { PaymentRequirements, PaymentRequiredBody, ExactPaymentPayload } from "./types";
2
+ export interface PaywallConfig {
3
+ /** CAIP-2 network. Default "casper:casper-test". */
4
+ network?: string;
5
+ /** Merchant account that receives the payment — tagged "00" + 32-byte hash. */
6
+ payTo: string;
7
+ /** CEP-18 contract **package** hash (64 hex) — the settlement asset. */
8
+ asset: string;
9
+ /** Price per call, token base units. */
10
+ price: string | number | bigint;
11
+ /** The Fund402 vault (lending pool) contract hash — settlements must target it. */
12
+ vaultContract?: string;
13
+ /** CSPR.cloud REST base. Default derived from `network`. */
14
+ csprCloudRest?: string;
15
+ /** CSPR.cloud API key — required to verify settlement on-chain. */
16
+ csprCloudApiKey?: string;
17
+ /** Optional x402 facilitator base URL for defense-in-depth signature verification. */
18
+ facilitatorUrl?: string;
19
+ /** Human description shown in the 402 challenge. */
20
+ description?: string;
21
+ /** Token metadata echoed in the challenge `extra`. */
22
+ asset_meta?: {
23
+ name?: string;
24
+ version?: string;
25
+ decimals?: string;
26
+ symbol?: string;
27
+ };
28
+ /** Authorization validity window the agent should target. Default 900s. */
29
+ maxTimeoutSeconds?: number;
30
+ }
31
+ export interface VerifyResult {
32
+ valid: boolean;
33
+ reason?: string;
34
+ status?: string;
35
+ deployHash?: string;
36
+ settlement?: {
37
+ deployHash: string;
38
+ asset?: string;
39
+ };
40
+ /** base64 `payment-response` header value to echo back to the caller on success. */
41
+ paymentResponseHeader?: string;
42
+ paidMerchant?: boolean;
43
+ paidAmount?: boolean;
44
+ }
45
+ export interface HttpResponseLike {
46
+ status: number;
47
+ headers: Record<string, string>;
48
+ body: unknown;
49
+ }
50
+ export interface RequestLike {
51
+ method?: string;
52
+ /** Full resource URL if known (preferred); adapters compute this from the request. */
53
+ url: string;
54
+ headers: Record<string, string | string[] | undefined>;
55
+ }
56
+ export type GuardResult = {
57
+ paid: true;
58
+ deployHash: string;
59
+ settlement: VerifyResult;
60
+ paymentResponseHeader: string;
61
+ } | {
62
+ paid: false;
63
+ response: HttpResponseLike;
64
+ };
65
+ /** Build the x402 v2 `exact` PaymentRequirements for this paywall + resource. */
66
+ export declare function buildPaymentRequirements(cfg: PaywallConfig, resource: string, description?: string): PaymentRequirements;
67
+ /** Wrap requirements in the x402 v2 `402 Payment Required` envelope. */
68
+ export declare function challengeBody(req: PaymentRequirements): PaymentRequiredBody;
69
+ /** Decode a base64(JSON) x402 payment header. Returns null if malformed. */
70
+ export declare function decodePaymentSignature(header: string): ExactPaymentPayload | null;
71
+ /** cspr.live explorer URL for a deploy. */
72
+ export declare function explorerTx(network: string, deployHash: string): string;
73
+ /**
74
+ * Verify, on-chain via CSPR.cloud, that the Fund402 vault `borrow_and_pay` deploy
75
+ * actually executed and paid the required merchant + amount. THIS is the real
76
+ * settlement proof — the pool already moved the funds to the merchant; the gateway
77
+ * trusts the chain, not the caller.
78
+ */
79
+ export declare function verifyPoolSettlement(cfg: PaywallConfig, deployHash: string, opts?: {
80
+ tries?: number;
81
+ intervalMs?: number;
82
+ }): Promise<VerifyResult>;
83
+ /**
84
+ * Optional defense-in-depth: ask an x402 facilitator to verify the agent's signed
85
+ * `exact` authorization. Returns `{ isValid }`. Never throws — network/decode
86
+ * problems resolve to `{ isValid:false, reason }`.
87
+ */
88
+ export declare function verifyWithFacilitator(facilitatorUrl: string, payload: ExactPaymentPayload): Promise<{
89
+ isValid: boolean;
90
+ reason?: string;
91
+ }>;
92
+ export interface Fund402Paywall {
93
+ config: PaywallConfig;
94
+ /** The 402 challenge response for a resource. */
95
+ challenge(resource: string, description?: string): HttpResponseLike;
96
+ /** Verify a payment header (base64 x402 payload) settled on-chain. */
97
+ verify(paymentHeader: string): Promise<VerifyResult>;
98
+ /** One-call guard: inspect a request, return paid:true or the response to send. */
99
+ guard(req: RequestLike): Promise<GuardResult>;
100
+ }
101
+ /**
102
+ * Create a paywall. Drive it from any framework (or use ./adapters).
103
+ *
104
+ * ```ts
105
+ * const pay = paywall({ payTo, asset, price: "1000000", vaultContract,
106
+ * csprCloudApiKey: process.env.CSPR_CLOUD_API_KEY });
107
+ * const g = await pay.guard({ url: fullUrl, headers: req.headers });
108
+ * if (!g.paid) return send(g.response); // 402 challenge / error
109
+ * res.setHeader("payment-response", g.paymentResponseHeader); // settled — serve it
110
+ * ```
111
+ */
112
+ export declare function paywall(config: PaywallConfig): Fund402Paywall;