@ashlar-blue/x402-trust 0.3.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.
Files changed (63) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +198 -0
  3. package/dist/attested-directory.d.ts +78 -0
  4. package/dist/attested-directory.d.ts.map +1 -0
  5. package/dist/attested-directory.js +163 -0
  6. package/dist/attested-directory.js.map +1 -0
  7. package/dist/badges.d.ts +131 -0
  8. package/dist/badges.d.ts.map +1 -0
  9. package/dist/badges.js +213 -0
  10. package/dist/badges.js.map +1 -0
  11. package/dist/catalog-mcp.d.ts +145 -0
  12. package/dist/catalog-mcp.d.ts.map +1 -0
  13. package/dist/catalog-mcp.js +409 -0
  14. package/dist/catalog-mcp.js.map +1 -0
  15. package/dist/census-reconcile.d.ts +69 -0
  16. package/dist/census-reconcile.d.ts.map +1 -0
  17. package/dist/census-reconcile.js +162 -0
  18. package/dist/census-reconcile.js.map +1 -0
  19. package/dist/directory-classify.d.ts +47 -0
  20. package/dist/directory-classify.d.ts.map +1 -0
  21. package/dist/directory-classify.js +54 -0
  22. package/dist/directory-classify.js.map +1 -0
  23. package/dist/discovery.d.ts +304 -0
  24. package/dist/discovery.d.ts.map +1 -0
  25. package/dist/discovery.js +926 -0
  26. package/dist/discovery.js.map +1 -0
  27. package/dist/evidence-ref.d.ts +96 -0
  28. package/dist/evidence-ref.d.ts.map +1 -0
  29. package/dist/evidence-ref.js +179 -0
  30. package/dist/evidence-ref.js.map +1 -0
  31. package/dist/facilitator-config.d.ts +83 -0
  32. package/dist/facilitator-config.d.ts.map +1 -0
  33. package/dist/facilitator-config.js +94 -0
  34. package/dist/facilitator-config.js.map +1 -0
  35. package/dist/index.d.ts +15 -0
  36. package/dist/index.d.ts.map +1 -0
  37. package/dist/index.js +18 -0
  38. package/dist/index.js.map +1 -0
  39. package/dist/manifest-sig.d.ts +131 -0
  40. package/dist/manifest-sig.d.ts.map +1 -0
  41. package/dist/manifest-sig.js +262 -0
  42. package/dist/manifest-sig.js.map +1 -0
  43. package/dist/merkle-transcript.d.ts +34 -0
  44. package/dist/merkle-transcript.d.ts.map +1 -0
  45. package/dist/merkle-transcript.js +162 -0
  46. package/dist/merkle-transcript.js.map +1 -0
  47. package/dist/open-catalog.d.ts +111 -0
  48. package/dist/open-catalog.d.ts.map +1 -0
  49. package/dist/open-catalog.js +307 -0
  50. package/dist/open-catalog.js.map +1 -0
  51. package/dist/reconcile.d.ts +150 -0
  52. package/dist/reconcile.d.ts.map +1 -0
  53. package/dist/reconcile.js +136 -0
  54. package/dist/reconcile.js.map +1 -0
  55. package/dist/trust-sdk.d.ts +127 -0
  56. package/dist/trust-sdk.d.ts.map +1 -0
  57. package/dist/trust-sdk.js +147 -0
  58. package/dist/trust-sdk.js.map +1 -0
  59. package/dist/types.d.ts +213 -0
  60. package/dist/types.d.ts.map +1 -0
  61. package/dist/types.js +68 -0
  62. package/dist/types.js.map +1 -0
  63. package/package.json +52 -0
@@ -0,0 +1,136 @@
1
+ // GENERATED from src/x402/reconcile.ts by scripts/sdk/sync-sdk.ts — do not edit here.
2
+ // The canonical module is the one FlareClaw runs in production; this is a copy so
3
+ // that what we publish and what we run cannot diverge. Edit the canonical file.
4
+ const ADDR_RE = /^0x[0-9a-fA-F]{40}$/;
5
+ const NONCE_RE = /^0x[0-9a-fA-F]{64}$/;
6
+ export async function reconcileAuthorization(q, reader, scope, now) {
7
+ // `now` is defined by this port to return UNIX SECONDS, matching
8
+ // validBefore's units — the facilitator passes Math.floor(Date.now()/1000)
9
+ // and the tests pass a seconds constant. Do not re-scale it here.
10
+ const clockUnixSeconds = now();
11
+ // Read the height FIRST, so even a verdict that fails early carries the
12
+ // state it failed at. A height fetched after the decision would describe a
13
+ // different chain than the one the decision was made against.
14
+ let blockHeight = null;
15
+ if (reader.blockHeight) {
16
+ try {
17
+ blockHeight = await reader.blockHeight();
18
+ }
19
+ catch {
20
+ blockHeight = null;
21
+ }
22
+ }
23
+ /** Build the observation, marking whether the clock decided this verdict. */
24
+ const obs = (clockWasLoadBearing) => ({
25
+ blockHeight,
26
+ clockUnixSeconds,
27
+ clockWasLoadBearing,
28
+ replayable: blockHeight !== null,
29
+ });
30
+ const at = blockHeight === null
31
+ ? 'at an unknown height (this reader does not report one, so the verdict is not replayable)'
32
+ : `at block ${blockHeight}`;
33
+ const rederive = `Read authorizationState(payer, nonce) on the asset contract via any ${scope.network} RPC (${scope.rpc}) ${at}; `
34
+ + 'if consumed, filter AuthorizationUsed(payer, nonce) logs for the settlement tx and decode its Transfer events.';
35
+ if (!ADDR_RE.test(q.asset ?? '') || !ADDR_RE.test(q.payer ?? '') || !NONCE_RE.test(q.nonce ?? '')) {
36
+ return {
37
+ outcome: 'indeterminate', cause: 'invalid-query',
38
+ reason: 'asset and payer must be 0x addresses and nonce a 32-byte 0x-hex value',
39
+ observation: obs(false), rederive,
40
+ };
41
+ }
42
+ const symbol = scope.assets[q.asset.toLowerCase()];
43
+ if (!symbol) {
44
+ return {
45
+ outcome: 'indeterminate', cause: 'out-of-scope-asset',
46
+ reason: `asset ${q.asset} is not an EIP-3009 asset this rail settles — no verdict, not a refusal`,
47
+ observation: obs(false), rederive,
48
+ };
49
+ }
50
+ let consumed;
51
+ try {
52
+ consumed = await reader.authorizationConsumed(q.asset, q.payer, q.nonce);
53
+ }
54
+ catch (e) {
55
+ return {
56
+ outcome: 'indeterminate', cause: 'rail-unreachable',
57
+ reason: `rail unreachable (${e.message}) — unknown is not a verdict; retry`,
58
+ observation: obs(false), rederive,
59
+ };
60
+ }
61
+ if (consumed) {
62
+ // CONSUMED IS NOT SETTLED. It is used-or-cancelled, and a cancelled
63
+ // authorization moved no tokens. Resolve which by event before
64
+ // returning any verdict — the previous version returned `settled`
65
+ // here and told the reader to widen their log range, which is the
66
+ // one case where widening never helps and the advice is reassuring
67
+ // about a payment that never happened.
68
+ let record = null;
69
+ try {
70
+ record = await reader.findConsumption(q.asset, q.payer, q.nonce);
71
+ }
72
+ catch {
73
+ // Enumeration failed. We know the nonce is spent but not how,
74
+ // and the two possibilities are OPPOSITE verdicts — so this is
75
+ // indeterminate, never a coin-flip toward settled.
76
+ return {
77
+ outcome: 'indeterminate', cause: 'consumption-kind-unknown',
78
+ reason: 'nonce is consumed but the event read failed — consumed means used OR cancelled, and those are opposite verdicts; retry',
79
+ observation: obs(false), rederive,
80
+ };
81
+ }
82
+ if (record === null) {
83
+ return {
84
+ outcome: 'indeterminate', cause: 'consumption-kind-unknown',
85
+ reason: 'nonce is consumed but neither AuthorizationUsed nor AuthorizationCanceled was locatable in this reader\'s log range — re-derive with a wider range',
86
+ observation: obs(false), rederive,
87
+ };
88
+ }
89
+ if (record.kind === 'cancelled') {
90
+ return {
91
+ outcome: 'refused-not-charged', cause: 'authorization-cancelled',
92
+ reason: `authorization was CANCELLED (tx ${record.tx}, block ${record.blockNumber}) — the nonce is consumed but no tokens moved; the payer was not charged`,
93
+ consumption: record,
94
+ observation: obs(false), rederive,
95
+ };
96
+ }
97
+ return {
98
+ outcome: 'settled', cause: 'nonce-used',
99
+ reason: `authorization used on-chain; settlement tx ${record.tx} (block ${record.blockNumber}) carried ${record.transfers.length} ${symbol} transfer(s)`,
100
+ consumption: record,
101
+ observation: obs(false), rederive,
102
+ };
103
+ }
104
+ if (typeof q.validBefore === 'number') {
105
+ // THE CLOCK IS LOAD-BEARING HERE AND NOWHERE ELSE. Everything above is
106
+ // decided by chain state; this one comparison is decided by what time
107
+ // we think it is. The observation publishes the reading so a party who
108
+ // disagrees can recompute the comparison instead of disputing a verdict.
109
+ if (clockUnixSeconds > q.validBefore) {
110
+ return {
111
+ outcome: 'refused-not-charged', cause: 'window-closed-unconsumed',
112
+ // HONEST ABOUT WHAT THIS DOES NOT SAY (Circadian-agent, #3226):
113
+ // the rail cannot distinguish "a settle was attempted and
114
+ // failed" from "nobody ever tried". x402#3231 is a live
115
+ // instance of the first — a valid authorization the reference
116
+ // facilitator could not settle because of a stale nonce on its
117
+ // OWN relayer wallet. The OUTCOME is right either way (no
118
+ // tokens moved, the payer was not charged); the reason must not
119
+ // imply the payer withdrew.
120
+ reason: `authorization unconsumed and its window closed at ${q.validBefore} (clock ${clockUnixSeconds}) — it can never settle, so the payer was not charged. This does NOT say whether a settle was attempted and failed or never attempted; the rail cannot distinguish those.`,
121
+ observation: obs(true), rederive,
122
+ };
123
+ }
124
+ return {
125
+ outcome: 'indeterminate', cause: 'window-open-unconsumed',
126
+ reason: `authorization unconsumed but valid until ${q.validBefore} (clock ${clockUnixSeconds}) — it could still settle; re-query after expiry for a determinate verdict`,
127
+ observation: obs(true), rederive,
128
+ };
129
+ }
130
+ return {
131
+ outcome: 'indeterminate', cause: 'window-unknown-unconsumed',
132
+ reason: 'authorization unconsumed and no validBefore supplied — cannot rule out a future settle; supply validBefore for a determinate refused-not-charged',
133
+ observation: obs(false), rederive,
134
+ };
135
+ }
136
+ //# sourceMappingURL=reconcile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reconcile.js","sourceRoot":"","sources":["../src/reconcile.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,127 @@
1
+ /**
2
+ * @flareclaw/x402-trust — the trust layer for agents that spend money.
3
+ *
4
+ * An agent about to pay another agent has two questions, and an agent that just
5
+ * did work has one obligation. This module answers all three in a handful of
6
+ * lines, with zero dependencies and — for the verification half — zero network
7
+ * and zero trust in us:
8
+ *
9
+ * BEFORE YOU PAY checkService(domain) — discover a service, verify what can
10
+ * be verified, and get a plain safeToPay decision with the
11
+ * reasons behind it. Composes the hardened resolver
12
+ * (same-origin enforcement, SSRF/DoS guards, HTTPS-only,
13
+ * live cross-check) so a caller need not re-implement the
14
+ * adversarial edge cases.
15
+ *
16
+ * WHAT YOU'RE HANDED verifyReceipt / verifyDirectoryEntry / verifyReconcileRow
17
+ * — check ONE row of a Merkle-committed receipt, census, or
18
+ * reconciliation against its signed root, holding nothing
19
+ * else. Pure math (RFC 6962). It does not call us, and it
20
+ * does not trust us: if the proof verifies, the claim is
21
+ * true whoever produced it.
22
+ *
23
+ * WHAT YOU PRODUCE new Transcript() — accumulate {id, input, output} entries
24
+ * and emit a root plus per-entry inclusion proofs, so the
25
+ * work YOUR agent did is provable to a third party without
26
+ * disclosing the rest of the session.
27
+ *
28
+ * The verification functions are the point of the whole library: an enterprise
29
+ * does not have to trust FlareClaw to use FlareClaw's proofs. That is the only
30
+ * kind of trust layer worth adopting.
31
+ */
32
+ import { resolveX402, type ResolveResult } from './discovery.js';
33
+ import { type TranscriptEntry } from './merkle-transcript.js';
34
+ import { type DirectoryEntry } from './attested-directory.js';
35
+ import { type ReconcileRow } from './census-reconcile.js';
36
+ export interface ServiceTrust {
37
+ domain: string;
38
+ /** A discovery record or manifest resolved at all. */
39
+ reachable: boolean;
40
+ /** It resolved to a valid x402 discovery manifest. */
41
+ discoverable: boolean;
42
+ /** How the manifest was found. */
43
+ via?: 'dns-txt' | 'well-known';
44
+ /** The manifest carries a TEE/attestation claim. */
45
+ attested: boolean;
46
+ /**
47
+ * The attestation claim is INDEPENDENTLY CHECKABLE — a same-origin HTTPS
48
+ * verifier the caller could dereference. False for an absent, `none`, or
49
+ * off-origin verifier: a claim, not a verified claim.
50
+ */
51
+ attestationCheckable: boolean;
52
+ /** Live /supported cross-check outcome (ok/skipped/unreachable/malformed/refused). */
53
+ liveCheck?: ResolveResult['liveCheck'];
54
+ /** True when the facilitator's live kinds match its manifest kinds. */
55
+ liveConsistent: boolean | null;
56
+ /** Manifest entries the resolver DROPPED as off-domain — a spoofing signal, surfaced not hidden. */
57
+ warnings: string[];
58
+ /** The composed decision under the chosen policy. */
59
+ safeToPay: boolean;
60
+ /** Why, in plain words — safe to log, safe to show a human. */
61
+ reasons: string[];
62
+ /** The raw resolver result, for callers that want the detail. */
63
+ resolution?: ResolveResult;
64
+ }
65
+ export interface CheckServiceOptions {
66
+ /** Require an independently-checkable attestation for safeToPay (default false). */
67
+ requireAttestation?: boolean;
68
+ /** Require the live /supported cross-check to have PASSED (default false — 'skipped' is allowed). */
69
+ requireLiveConsistent?: boolean;
70
+ /** Pass-throughs for tests / custom transports. */
71
+ resolveTxt?: Parameters<typeof resolveX402>[1] extends infer O ? O extends {
72
+ resolveTxt?: infer T;
73
+ } ? T : never : never;
74
+ fetchImpl?: typeof fetch;
75
+ lookupImpl?: Parameters<typeof resolveX402>[1] extends infer O ? O extends {
76
+ lookupImpl?: infer L;
77
+ } ? L : never : never;
78
+ noCache?: boolean;
79
+ }
80
+ /**
81
+ * Resolve a domain and decide whether an agent should pay it. The default
82
+ * policy is deliberately conservative but not paranoid: a service is safe to
83
+ * pay when it is genuinely discoverable, nothing was dropped as a spoofing
84
+ * attempt, and the live cross-check did not REFUSE (a dead live signal is a
85
+ * warning, not a veto, unless you ask for one). Tighten with requireAttestation
86
+ * / requireLiveConsistent.
87
+ */
88
+ export declare function checkService(domain: string, opts?: CheckServiceOptions): Promise<ServiceTrust>;
89
+ /** One retail receipt proof: an entry, its position, the tree size, the path, the signed root. */
90
+ export interface ReceiptProof {
91
+ entry: TranscriptEntry;
92
+ index: number;
93
+ size: number;
94
+ proof: string[];
95
+ root: string;
96
+ }
97
+ /**
98
+ * Verify ONE draw/work receipt against its signed root, holding nothing else.
99
+ * Pure RFC 6962. Returns true iff the entry was genuinely in the committed
100
+ * transcript at that position — no network, no trust in the producer.
101
+ */
102
+ export declare function verifyReceipt(p: ReceiptProof): boolean;
103
+ /** Verify one directory-census entry against a census outputRoot. */
104
+ export declare function verifyDirectoryEntry(entry: DirectoryEntry, index: number, size: number, proof: string[], outputRoot: string): boolean;
105
+ /** Verify one reconciliation row against a reconciliation rowsRoot. */
106
+ export declare function verifyReconcileRow(row: ReconcileRow, index: number, size: number, proof: string[], rowsRoot: string): boolean;
107
+ /**
108
+ * Build a verifiable transcript of the work your agent did. Add {id, input,
109
+ * output} entries; emit a root you sign/anchor and per-entry inclusion proofs a
110
+ * counterparty can check with verifyReceipt — WITHOUT seeing the rest.
111
+ *
112
+ * `id` is committed (it distinguishes two otherwise-identical entries — the
113
+ * payment-intent identity), so the transcript cannot be made to undercount two
114
+ * distinct pieces of work.
115
+ */
116
+ export declare class Transcript {
117
+ private entries;
118
+ /** Append one unit of work: an identifier, its input, and its output. */
119
+ add(id: string, input: string, output: string): this;
120
+ /** Number of entries so far. */
121
+ get size(): number;
122
+ /** The Merkle root to sign or anchor — the single value that commits to all entries. */
123
+ root(): string;
124
+ /** A retail inclusion proof for entry `index`, ready to hand to a verifier. */
125
+ prove(index: number): ReceiptProof;
126
+ }
127
+ //# sourceMappingURL=trust-sdk.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trust-sdk.d.ts","sourceRoot":"","sources":["../src/trust-sdk.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,147 @@
1
+ // GENERATED from src/x402/trust-sdk.ts by scripts/sdk/sync-sdk.ts — do not edit here.
2
+ // The canonical module is the one FlareClaw runs in production; this is a copy so
3
+ // that what we publish and what we run cannot diverge. Edit the canonical file.
4
+ /**
5
+ * @flareclaw/x402-trust — the trust layer for agents that spend money.
6
+ *
7
+ * An agent about to pay another agent has two questions, and an agent that just
8
+ * did work has one obligation. This module answers all three in a handful of
9
+ * lines, with zero dependencies and — for the verification half — zero network
10
+ * and zero trust in us:
11
+ *
12
+ * BEFORE YOU PAY checkService(domain) — discover a service, verify what can
13
+ * be verified, and get a plain safeToPay decision with the
14
+ * reasons behind it. Composes the hardened resolver
15
+ * (same-origin enforcement, SSRF/DoS guards, HTTPS-only,
16
+ * live cross-check) so a caller need not re-implement the
17
+ * adversarial edge cases.
18
+ *
19
+ * WHAT YOU'RE HANDED verifyReceipt / verifyDirectoryEntry / verifyReconcileRow
20
+ * — check ONE row of a Merkle-committed receipt, census, or
21
+ * reconciliation against its signed root, holding nothing
22
+ * else. Pure math (RFC 6962). It does not call us, and it
23
+ * does not trust us: if the proof verifies, the claim is
24
+ * true whoever produced it.
25
+ *
26
+ * WHAT YOU PRODUCE new Transcript() — accumulate {id, input, output} entries
27
+ * and emit a root plus per-entry inclusion proofs, so the
28
+ * work YOUR agent did is provable to a third party without
29
+ * disclosing the rest of the session.
30
+ *
31
+ * The verification functions are the point of the whole library: an enterprise
32
+ * does not have to trust FlareClaw to use FlareClaw's proofs. That is the only
33
+ * kind of trust layer worth adopting.
34
+ */
35
+ import { resolveX402, X402NegativeCacheError, } from './discovery.js';
36
+ import { transcriptRoot, inclusionProof, verifyInclusion, } from './merkle-transcript.js';
37
+ import { verifyEntry } from './attested-directory.js';
38
+ import { verifyRow } from './census-reconcile.js';
39
+ /**
40
+ * Resolve a domain and decide whether an agent should pay it. The default
41
+ * policy is deliberately conservative but not paranoid: a service is safe to
42
+ * pay when it is genuinely discoverable, nothing was dropped as a spoofing
43
+ * attempt, and the live cross-check did not REFUSE (a dead live signal is a
44
+ * warning, not a veto, unless you ask for one). Tighten with requireAttestation
45
+ * / requireLiveConsistent.
46
+ */
47
+ export async function checkService(domain, opts = {}) {
48
+ const reasons = [];
49
+ let resolution;
50
+ try {
51
+ resolution = await resolveX402(domain, {
52
+ ...(opts.resolveTxt ? { resolveTxt: opts.resolveTxt } : {}),
53
+ ...(opts.fetchImpl ? { fetchImpl: opts.fetchImpl } : {}),
54
+ ...(opts.lookupImpl ? { lookupImpl: opts.lookupImpl } : {}),
55
+ ...(opts.noCache ? { noCache: true } : {}),
56
+ });
57
+ }
58
+ catch (e) {
59
+ // A resolver refusal (spoofing/malformed/SSRF/DoS) is a firm NO, and its
60
+ // reason is worth surfacing rather than collapsing to "unreachable".
61
+ const cached = e instanceof X402NegativeCacheError;
62
+ return {
63
+ domain, reachable: false, discoverable: false, attested: false,
64
+ attestationCheckable: false, liveConsistent: null, warnings: [],
65
+ safeToPay: false,
66
+ reasons: [`resolution ${cached ? 'refused (cached)' : 'failed'}: ${e.message}`],
67
+ };
68
+ }
69
+ const attested = !!resolution.manifest.attestation
70
+ && resolution.manifest.attestation.type !== 'none';
71
+ const attestationCheckable = resolution.attestationUsable === true;
72
+ const liveConsistent = resolution.kindsMatchLive ?? null;
73
+ const warnings = [
74
+ ...(resolution.droppedResources ?? []).map((r) => `dropped off-domain resource: ${r}`),
75
+ ...(resolution.droppedPeers ?? []).map((p) => `dropped peer hint: ${p}`),
76
+ ];
77
+ reasons.push(`discoverable via ${resolution.via}`);
78
+ if (attested)
79
+ reasons.push(attestationCheckable ? 'attestation claim is same-origin checkable' : 'attestation claim present but NOT independently checkable');
80
+ if (resolution.liveCheck)
81
+ reasons.push(`live cross-check: ${resolution.liveCheck}`);
82
+ if (liveConsistent === false)
83
+ reasons.push('WARNING: live /supported disagrees with the manifest');
84
+ for (const w of warnings)
85
+ reasons.push(`WARNING: ${w}`);
86
+ let safeToPay = resolution.liveCheck !== 'refused' && warnings.length === 0;
87
+ if (opts.requireAttestation && !attestationCheckable) {
88
+ safeToPay = false;
89
+ reasons.push('policy: attestation required, none checkable');
90
+ }
91
+ if (opts.requireLiveConsistent && liveConsistent !== true) {
92
+ safeToPay = false;
93
+ reasons.push('policy: live consistency required, not confirmed');
94
+ }
95
+ return {
96
+ domain, reachable: true, discoverable: true, via: resolution.via,
97
+ attested, attestationCheckable,
98
+ ...(resolution.liveCheck ? { liveCheck: resolution.liveCheck } : {}),
99
+ liveConsistent, warnings, safeToPay, reasons, resolution,
100
+ };
101
+ }
102
+ /**
103
+ * Verify ONE draw/work receipt against its signed root, holding nothing else.
104
+ * Pure RFC 6962. Returns true iff the entry was genuinely in the committed
105
+ * transcript at that position — no network, no trust in the producer.
106
+ */
107
+ export function verifyReceipt(p) {
108
+ return verifyInclusion(p.entry, p.index, p.size, p.proof, p.root);
109
+ }
110
+ /** Verify one directory-census entry against a census outputRoot. */
111
+ export function verifyDirectoryEntry(entry, index, size, proof, outputRoot) {
112
+ return verifyEntry(entry, index, size, proof, outputRoot);
113
+ }
114
+ /** Verify one reconciliation row against a reconciliation rowsRoot. */
115
+ export function verifyReconcileRow(row, index, size, proof, rowsRoot) {
116
+ return verifyRow(row, index, size, proof, rowsRoot);
117
+ }
118
+ // ──────────────────── WHAT YOU PRODUCE ────────────────────
119
+ /**
120
+ * Build a verifiable transcript of the work your agent did. Add {id, input,
121
+ * output} entries; emit a root you sign/anchor and per-entry inclusion proofs a
122
+ * counterparty can check with verifyReceipt — WITHOUT seeing the rest.
123
+ *
124
+ * `id` is committed (it distinguishes two otherwise-identical entries — the
125
+ * payment-intent identity), so the transcript cannot be made to undercount two
126
+ * distinct pieces of work.
127
+ */
128
+ export class Transcript {
129
+ entries = [];
130
+ /** Append one unit of work: an identifier, its input, and its output. */
131
+ add(id, input, output) {
132
+ this.entries.push({ drawId: id, nonce: input, seed: output });
133
+ return this;
134
+ }
135
+ /** Number of entries so far. */
136
+ get size() { return this.entries.length; }
137
+ /** The Merkle root to sign or anchor — the single value that commits to all entries. */
138
+ root() { return transcriptRoot(this.entries); }
139
+ /** A retail inclusion proof for entry `index`, ready to hand to a verifier. */
140
+ prove(index) {
141
+ const entry = this.entries[index];
142
+ if (!entry)
143
+ throw new Error(`index ${index} outside transcript of ${this.entries.length}`);
144
+ return { entry, index, size: this.entries.length, proof: inclusionProof(this.entries, index), root: this.root() };
145
+ }
146
+ }
147
+ //# sourceMappingURL=trust-sdk.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trust-sdk.js","sourceRoot":"","sources":["../src/trust-sdk.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,213 @@
1
+ /**
2
+ * x402 protocol wire types — EMITS v1, PARSES v1 and v2.
3
+ *
4
+ * Shapes follow the x402 spec (Coinbase/x402 Foundation): a resource
5
+ * server answers 402 with `PaymentRequiredResponse`; the client retries
6
+ * with an `X-PAYMENT` header carrying base64(JSON(PaymentPayload)); the
7
+ * facilitator verifies and settles; the server attaches
8
+ * `X-PAYMENT-RESPONSE` = base64(JSON(SettleResponse)).
9
+ *
10
+ * FlareClaw is the first x402 facilitator on Flare (Coston2 first —
11
+ * network id "coston2", eip155:114).
12
+ */
13
+ /**
14
+ * The version we EMIT in our own 402 challenges.
15
+ *
16
+ * We accept v2 payloads too (see `normalizeRequirements` /
17
+ * `decodePaymentHeader`) — being a co-author of x402 extensions while
18
+ * silently refusing the ecosystem's current wire format would be an
19
+ * embarrassing kind of wrong. Emission stays on v1 until every one of
20
+ * our own clients is v2-ready; acceptance is widened first, because
21
+ * accepting more than you emit is the only safe direction to move a
22
+ * protocol version.
23
+ */
24
+ export declare const X402_VERSION = 1;
25
+ /** Versions this implementation can PARSE. */
26
+ export declare const SUPPORTED_X402_VERSIONS: readonly [1, 2];
27
+ export type X402Version = (typeof SUPPORTED_X402_VERSIONS)[number];
28
+ /**
29
+ * How the payer authorizes the transfer (x402 v2 `extra.assetTransferMethod`).
30
+ *
31
+ * `eip3009` is the default and the only one we can SETTLE today — it is
32
+ * the reason a third-party ERC-20 cannot currently pay us, since the
33
+ * token itself must implement `transferWithAuthorization`. `permit2`
34
+ * is x402's universal fallback for arbitrary ERC-20s; we parse it so a
35
+ * v2 client's intent is never silently misread as EIP-3009, and refuse
36
+ * it explicitly rather than mis-settling.
37
+ */
38
+ export type AssetTransferMethod = 'eip3009' | 'permit2' | 'erc7710';
39
+ export declare const PAYMENT_HEADER = "X-PAYMENT";
40
+ /**
41
+ * v2 servers may deliver the challenge in a RESPONSE HEADER with a null body
42
+ * instead of in the body. Measured on a live commercial deployment
43
+ * (x402.glassnode.com, 2026-08-06): `payment-required:` base64, body `null`.
44
+ * A client that only reads the body sees nothing and cannot pay them.
45
+ */
46
+ export declare const PAYMENT_REQUIRED_HEADER = "payment-required";
47
+ export declare const PAYMENT_RESPONSE_HEADER = "X-PAYMENT-RESPONSE";
48
+ /** One acceptable way to pay for a resource. */
49
+ export interface PaymentRequirements {
50
+ scheme: 'exact';
51
+ /** Network id, e.g. "coston2" (chainId 114). */
52
+ network: string;
53
+ /**
54
+ * Price in the asset's atomic units, decimal string.
55
+ *
56
+ * v1 spells this `maxAmountRequired`; **v2 renamed it `amount`**.
57
+ * Both are optional at the type level so either wire shape parses;
58
+ * `requirementAmount()` is the single reader that resolves them, so
59
+ * no call site has to know which version it is holding.
60
+ */
61
+ maxAmountRequired?: string;
62
+ /** x402 v2 name for `maxAmountRequired`. */
63
+ amount?: string;
64
+ /** URL/path of the paid resource. */
65
+ resource: string;
66
+ description: string;
67
+ mimeType: string;
68
+ /** Receiving address (the platform treasury). */
69
+ payTo: string;
70
+ /** Seconds the client has to produce a settleable payment. */
71
+ maxTimeoutSeconds: number;
72
+ /** ERC-20 (EIP-3009) token contract address. */
73
+ asset: string;
74
+ /** EIP-712 domain of the asset — payers need name+version to sign.
75
+ * v2 additionally carries `assetTransferMethod` here. */
76
+ extra: {
77
+ name: string;
78
+ version: string;
79
+ assetTransferMethod?: AssetTransferMethod;
80
+ };
81
+ }
82
+ /** Body of every 402 response. */
83
+ export interface PaymentRequiredResponse {
84
+ x402Version: X402Version;
85
+ error: string;
86
+ /** The offered options. v1 AND v2 both spell this `accepts` (array). */
87
+ accepts?: PaymentRequirements[];
88
+ /**
89
+ * NOT a v2 rename of `accepts` — we had that wrong. In v2, `accepted` is a
90
+ * DIFFERENT field carrying the SINGLE requirement a payer chose, and it
91
+ * lives in the payment payload and settlement response, not in the 402.
92
+ * (v2 spec §5.1.2: `PaymentRequired.accepts` is a required array; §5.2
93
+ * `accepted` is "PaymentRequirements object indicating the payment method
94
+ * chosen".) Kept here only so a server that misuses it in a 402 still
95
+ * parses — being liberal in what we accept, not endorsing the shape.
96
+ */
97
+ accepted?: PaymentRequirements[] | PaymentRequirements;
98
+ }
99
+ /**
100
+ * The amount a requirement asks for, whichever version wrote it.
101
+ * Throws rather than defaulting: a missing price must never quietly
102
+ * become zero on a payment path.
103
+ */
104
+ export declare function requirementAmount(r: PaymentRequirements): string;
105
+ /**
106
+ * The offered requirements of a 402 body.
107
+ *
108
+ * `accepts` is the spec field in BOTH versions. The `accepted` fallback exists
109
+ * only to tolerate servers that put the chosen-requirement field in a 402 by
110
+ * mistake; it is normalised to an array so no caller has to care.
111
+ */
112
+ export declare function offeredRequirements(body: PaymentRequiredResponse): PaymentRequirements[];
113
+ /** Declared transfer method, defaulting per spec to `eip3009`. */
114
+ export declare function transferMethod(r: PaymentRequirements): AssetTransferMethod;
115
+ /** EIP-3009 TransferWithAuthorization message (all uints as decimal strings). */
116
+ export interface Eip3009Authorization {
117
+ from: string;
118
+ to: string;
119
+ value: string;
120
+ validAfter: string;
121
+ validBefore: string;
122
+ /** 32-byte hex nonce, unique per (from, nonce) — on-chain replay guard. */
123
+ nonce: string;
124
+ }
125
+ /** Scheme-specific payload for "exact" on EVM. */
126
+ export interface ExactEvmPayload {
127
+ /** 65-byte EIP-712 signature over the authorization, hex. */
128
+ signature: string;
129
+ authorization: Eip3009Authorization;
130
+ }
131
+ /** Decoded content of the X-PAYMENT header. */
132
+ export interface PaymentPayload {
133
+ x402Version: typeof X402_VERSION;
134
+ scheme: 'exact';
135
+ network: string;
136
+ payload: ExactEvmPayload;
137
+ }
138
+ /**
139
+ * Machine-readable failure classes for `verify`.
140
+ *
141
+ * ── WHY A CODE AND NOT JUST PROSE ──
142
+ * `invalidReason` is a human string, so a payer can only pattern-match
143
+ * it — and every implementer words it differently. The distinction that
144
+ * actually matters to a client is REMEDY: is this rejection permanent
145
+ * (do not retry — you would be signing a second payment for a claim
146
+ * that will never succeed), or is it a repairable local condition?
147
+ *
148
+ * Clock skew is the case that forced this. A payer whose clock is fast
149
+ * builds `validAfter` in the future, or one whose clock is slow builds
150
+ * `validBefore` too close to now; the facilitator rejects, and the
151
+ * payer reads a generic failure as "this venue refuses me" when the
152
+ * correct action is *resync your clock and re-sign*. That is a
153
+ * repairable condition being reported as a rejection — the payer gives
154
+ * up on a service that would have served them.
155
+ */
156
+ export type InvalidCode =
157
+ /** Payer's clock disagrees with the facilitator's. RESYNC AND RETRY. */
158
+ 'clock-skew'
159
+ /** Payment terms don't match the requirements (payTo, asset, amount, scheme). */
160
+ | 'terms-mismatch'
161
+ /** Signature invalid or recovers to the wrong address. */
162
+ | 'signature'
163
+ /** Nonce already used or canceled — this authorization is spent. */
164
+ | 'nonce-used'
165
+ /**
166
+ * A settlement for THIS (payer, nonce) is already broadcasting.
167
+ * Distinct from `nonce-used`: that one is spent, this one is
168
+ * in-flight and its outcome is not yet knowable. Retry after the
169
+ * first attempt resolves — do NOT sign a fresh nonce (the original
170
+ * may well succeed). Costs the payer nothing and the facilitator
171
+ * no gas.
172
+ */
173
+ | 'nonce-in-flight'
174
+ /** Payer lacks the funds. */
175
+ | 'insufficient-funds'
176
+ /** Authorization expired; a fresh one is required. */
177
+ | 'expired'
178
+ /** Malformed request the facilitator could not interpret. */
179
+ | 'malformed';
180
+ export interface VerifyResponse {
181
+ isValid: boolean;
182
+ invalidReason?: string;
183
+ /**
184
+ * Machine-readable class of `invalidReason`. Optional for backward
185
+ * compatibility — a client that ignores it behaves exactly as
186
+ * before; one that reads it can tell "fix your clock" from "this
187
+ * will never work".
188
+ */
189
+ invalidCode?: InvalidCode;
190
+ /**
191
+ * Present when the failure is clock-related: the facilitator's own
192
+ * unix seconds at verification, so the payer can measure its skew
193
+ * directly instead of guessing. This is the same courtesy HTTP
194
+ * `Date` provides — the server already knows the answer, and
195
+ * withholding it makes the payer's problem unsolvable.
196
+ */
197
+ serverTime?: number;
198
+ /** Recovered payer address (when the signature is valid). */
199
+ payer?: string;
200
+ }
201
+ export interface SettleResponse {
202
+ success: boolean;
203
+ errorReason?: string;
204
+ /** Same classification as VerifyResponse — settle verifies first. */
205
+ invalidCode?: InvalidCode;
206
+ /** Facilitator's unix seconds, present on clock-related failures. */
207
+ serverTime?: number;
208
+ /** Settlement transaction hash. */
209
+ transaction: string;
210
+ network: string;
211
+ payer: string;
212
+ }
213
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;GAWG;AAEH;;;;;;;;;;GAUG;AACH,eAAO,MAAM,YAAY,IAAI,CAAC;AAE9B,8CAA8C;AAC9C,eAAO,MAAM,uBAAuB,iBAAkB,CAAC;AACvD,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,uBAAuB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEnE;;;;;;;;;GASG;AACH,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;AAEpE,eAAO,MAAM,cAAc,cAAc,CAAC;AAC1C;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,qBAAqB,CAAC;AAC1D,eAAO,MAAM,uBAAuB,uBAAuB,CAAC;AAE5D,gDAAgD;AAChD,MAAM,WAAW,mBAAmB;IAChC,MAAM,EAAE,OAAO,CAAC;IAChB,gDAAgD;IAChD,OAAO,EAAE,MAAM,CAAC;IAChB;;;;;;;OAOG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,4CAA4C;IAC5C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,qCAAqC;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,iDAAiD;IACjD,KAAK,EAAE,MAAM,CAAC;IACd,8DAA8D;IAC9D,iBAAiB,EAAE,MAAM,CAAC;IAC1B,gDAAgD;IAChD,KAAK,EAAE,MAAM,CAAC;IACd;8DAC0D;IAC1D,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,mBAAmB,CAAC,EAAE,mBAAmB,CAAA;KAAE,CAAC;CACvF;AAED,kCAAkC;AAClC,MAAM,WAAW,uBAAuB;IACpC,WAAW,EAAE,WAAW,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,wEAAwE;IACxE,OAAO,CAAC,EAAE,mBAAmB,EAAE,CAAC;IAChC;;;;;;;;OAQG;IACH,QAAQ,CAAC,EAAE,mBAAmB,EAAE,GAAG,mBAAmB,CAAC;CAC1D;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,mBAAmB,GAAG,MAAM,CAIhE;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,uBAAuB,GAAG,mBAAmB,EAAE,CAIxF;AAED,kEAAkE;AAClE,wBAAgB,cAAc,CAAC,CAAC,EAAE,mBAAmB,GAAG,mBAAmB,CAE1E;AAED,iFAAiF;AACjF,MAAM,WAAW,oBAAoB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,2EAA2E;IAC3E,KAAK,EAAE,MAAM,CAAC;CACjB;AAED,kDAAkD;AAClD,MAAM,WAAW,eAAe;IAC5B,6DAA6D;IAC7D,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,oBAAoB,CAAC;CACvC;AAED,+CAA+C;AAC/C,MAAM,WAAW,cAAc;IAC3B,WAAW,EAAE,OAAO,YAAY,CAAC;IACjC,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,eAAe,CAAC;CAC5B;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,MAAM,WAAW;AACnB,wEAAwE;AACtE,YAAY;AACd,iFAAiF;GAC/E,gBAAgB;AAClB,0DAA0D;GACxD,WAAW;AACb,oEAAoE;GAClE,YAAY;AACd;;;;;;;GAOG;GACD,iBAAiB;AACnB,6BAA6B;GAC3B,oBAAoB;AACtB,sDAAsD;GACpD,SAAS;AACX,6DAA6D;GAC3D,WAAW,CAAC;AAElB,MAAM,WAAW,cAAc;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,6DAA6D;IAC7D,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qEAAqE;IACrE,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,qEAAqE;IACrE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mCAAmC;IACnC,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACjB"}