@x1id/resolve 0.23.0 → 0.44.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 (49) hide show
  1. package/README.md +97 -0
  2. package/dist/accounts.d.ts +6 -0
  3. package/dist/accounts.js +6 -1
  4. package/dist/agent.d.ts +184 -8
  5. package/dist/agent.js +351 -3
  6. package/dist/agentPolicy.d.ts +238 -0
  7. package/dist/agentPolicy.js +364 -0
  8. package/dist/attestation.d.ts +25 -0
  9. package/dist/attestation.js +25 -0
  10. package/dist/checkout.d.ts +216 -0
  11. package/dist/checkout.js +327 -0
  12. package/dist/credentials.d.ts +466 -0
  13. package/dist/credentials.js +669 -0
  14. package/dist/gate.d.ts +94 -4
  15. package/dist/gate.js +206 -7
  16. package/dist/gateClient.d.ts +12 -0
  17. package/dist/giftLink.d.ts +272 -0
  18. package/dist/giftLink.js +452 -0
  19. package/dist/index.d.ts +13 -0
  20. package/dist/index.js +32 -0
  21. package/dist/loginButton.d.ts +69 -0
  22. package/dist/loginButton.js +207 -0
  23. package/dist/logo.d.ts +1 -0
  24. package/dist/logo.js +8 -0
  25. package/dist/messaging.d.ts +439 -0
  26. package/dist/messaging.js +979 -0
  27. package/dist/nsGate.d.ts +98 -0
  28. package/dist/nsGate.js +172 -0
  29. package/dist/oidc.d.ts +272 -0
  30. package/dist/oidc.js +641 -0
  31. package/dist/pay.d.ts +513 -0
  32. package/dist/pay.js +756 -0
  33. package/dist/payment.d.ts +9 -2
  34. package/dist/payment.js +9 -2
  35. package/dist/recovery.d.ts +186 -0
  36. package/dist/recovery.js +276 -0
  37. package/dist/recoveryNft.d.ts +183 -0
  38. package/dist/recoveryNft.js +291 -0
  39. package/dist/shield.d.ts +373 -0
  40. package/dist/shield.js +695 -0
  41. package/dist/subscription.d.ts +439 -0
  42. package/dist/subscription.js +642 -0
  43. package/dist/textRecords.d.ts +52 -6
  44. package/dist/textRecords.js +80 -8
  45. package/dist/types.d.ts +3 -0
  46. package/dist/x402Receipt.d.ts +246 -0
  47. package/dist/x402Receipt.js +374 -0
  48. package/package.json +18 -1
  49. package/schema/agent-manifest.json +91 -8
@@ -53,6 +53,25 @@
53
53
  * `ParsedHandle`), and a text record is `stale` when EITHER
54
54
  * `updated_at < registeredAt` OR `updated_at < recordsClearedAt`.
55
55
  *
56
+ * # `holder_epoch` (H5 / PR #466) — the THIRD staleness anchor
57
+ *
58
+ * A native tokenized `buy_handle` stamps ONLY `holder_epoch` (it must not
59
+ * move `registered_at`), so without it the seller's records — including the
60
+ * payment-routing `x1.*` keys — stayed live after a sale. The same functions
61
+ * take the handle's `holderEpoch` (0 if absent) and judge a text record
62
+ * stale when `updated_at < max(registeredAt, holderEpoch, recordsClearedAt)`
63
+ * — the on-chain `name_pays_to` rule and the address-record reader's rule.
64
+ *
65
+ * # Keys are compared BYTE-EXACT (BOM-preserving decode)
66
+ *
67
+ * The program accepts any UTF-8 key of 1..=64 bytes, including one that
68
+ * starts with a U+FEFF byte-order mark. A default `TextDecoder` STRIPS a
69
+ * leading BOM, so a key stored as `EF BB BF "x1.shield"` used to read back
70
+ * as `"x1.shield"` — a record delegate could spoof a routing key. Keys here
71
+ * are decoded with `ignoreBOM: true`, so the BOM survives into `key` and the
72
+ * decoded string is equal to a lookup key only when the raw bytes are. Use
73
+ * {@link findTextRecord} to look up a specific key.
74
+ *
56
75
  * # These records count (#7384)
57
76
  *
58
77
  * `create_text_record` increments — and `close_text_record` decrements —
@@ -125,13 +144,22 @@ export interface HandleTextRecord {
125
144
  readonly updatedAt: bigint;
126
145
  /**
127
146
  * The rule docs/record-trust.md mandates: this record is only the current
128
- * owner's if `updated_at >= handle.registered_at`. A stale record belongs
147
+ * owner's if `updated_at >= max(handle.registered_at, handle.holder_epoch,
148
+ * handle.records_cleared_at)`. A stale record belongs
129
149
  * to a previous, unrelated owner of the same name: it must never be
130
150
  * rendered as this name's website/avatar/social, and only ever offered to
131
151
  * the CURRENT owner as something to remove or overwrite.
132
152
  */
133
153
  readonly stale: boolean;
134
154
  }
155
+ /**
156
+ * Decode a stored KEY: strict UTF-8 with the byte-order mark PRESERVED
157
+ * (`ignoreBOM: true`). A default decoder silently drops a leading U+FEFF,
158
+ * which made `EF BB BF "x1.shield"` read back as `"x1.shield"`. With the BOM
159
+ * kept, `decoded === key` holds exactly when the raw bytes are identical
160
+ * (UTF-8 is a bijection on valid input). Null when not valid UTF-8.
161
+ */
162
+ export declare function textKeyFromBytes(keyBytes: Uint8Array): string | null;
135
163
  /**
136
164
  * Render stored value bytes as text: a STRICT UTF-8 decode, or null when the
137
165
  * bytes are not valid UTF-8 (binary values like `contenthash`). Callers
@@ -150,18 +178,34 @@ export declare function textValueToString(value: Uint8Array): string | null;
150
178
  * `registeredAt` is the owning Handle's `registered_at`, decoded by the
151
179
  * caller from the Handle account — it decides `stale`. `recordsClearedAt` is
152
180
  * that same Handle's `recordsClearedAt` (0 if never cleared, #8139), a
153
- * SECOND independent staleness anchor. There is intentionally no overload
154
- * without either (see the module docs).
181
+ * SECOND independent staleness anchor. `holderEpoch` is that Handle's
182
+ * `holderEpoch` (H5, 0 if absent): stale when
183
+ * `updated_at < max(registeredAt, holderEpoch, recordsClearedAt)`. It
184
+ * defaults to `0n` only for backward compatibility; every caller that has a
185
+ * decoded Handle should pass it (a payment-routing reader MUST).
155
186
  *
156
187
  * Returns null for anything that is not a TextRecord: wrong length, wrong
157
188
  * discriminator, lengths that do not fit, or a key that is not valid UTF-8
158
189
  * (the program's Borsh `String` guarantees it is, so that is not a
159
190
  * TextRecord).
160
191
  */
161
- export declare function decodeTextRecord(raw: Uint8Array, account: string, registeredAt: bigint, recordsClearedAt: bigint): HandleTextRecord | null;
192
+ export declare function decodeTextRecord(raw: Uint8Array, account: string, registeredAt: bigint, recordsClearedAt: bigint, holderEpoch?: bigint): HandleTextRecord | null;
162
193
  /** The text records the CURRENT owner actually has — `stale` ones excluded.
163
194
  * This is the list to render on a profile and count. */
164
195
  export declare function liveTextRecords(records: readonly HandleTextRecord[]): HandleTextRecord[];
196
+ /**
197
+ * The LIVE record whose stored key bytes are EXACTLY `key`'s UTF-8 bytes, or
198
+ * undefined. Use this (not `records.find((r) => r.key === key)`) for any key
199
+ * that routes funds or changes behaviour (`x1.shield`, `x1.pool`, ...).
200
+ *
201
+ * Byte-exact by construction: keys are decoded BOM-preserving, so a
202
+ * `U+FEFF`-prefixed look-alike never equals `key`; the raw bytes are compared
203
+ * again here as defence in depth. If more than one live record matches
204
+ * (impossible for well-formed PDAs, since the address is derived from
205
+ * sha256(key)), it returns undefined: ordering never decides which record
206
+ * routes.
207
+ */
208
+ export declare function findTextRecord(records: readonly HandleTextRecord[], key: string): HandleTextRecord | undefined;
165
209
  /**
166
210
  * Fetch every TextRecord account of a handle — one `getProgramAccounts`
167
211
  * call, filtered by the RPC on size (377), the TextRecord discriminator at
@@ -173,12 +217,14 @@ export declare function liveTextRecords(records: readonly HandleTextRecord[]): H
173
217
  * `registeredAt` is `Handle.registered_at` as decoded from the Handle
174
218
  * account the caller already has — the staleness rule needs it, and there
175
219
  * is no variant of this function without it. `recordsClearedAt` is that same
176
- * Handle's `recordsClearedAt` (0 if never cleared, #8139) — pass it through.
220
+ * Handle's `recordsClearedAt` (0 if never cleared, #8139) — pass it through,
221
+ * and `holderEpoch` (H5; defaults to 0n for backward compatibility, but pass
222
+ * it: a native tokenized sale moves only this anchor).
177
223
  * Every record is returned, stale ones flagged, so an owner surface can show
178
224
  * what a previous owner left behind; anything that renders a profile takes
179
225
  * {@link liveTextRecords}.
180
226
  */
181
- export declare function fetchTextRecords(rpc: RpcFn, programId: string, handleAccount: string, registeredAt: bigint, recordsClearedAt: bigint): Promise<HandleTextRecord[]>;
227
+ export declare function fetchTextRecords(rpc: RpcFn, programId: string, handleAccount: string, registeredAt: bigint, recordsClearedAt: bigint, holderEpoch?: bigint): Promise<HandleTextRecord[]>;
182
228
  /** The delegate-aware trailing accounts every text-record builder shares —
183
229
  * the exact rules of `delegate.ts`'s module docs. */
184
230
  interface RecordEditAuthorityParams {
@@ -53,6 +53,25 @@
53
53
  * `ParsedHandle`), and a text record is `stale` when EITHER
54
54
  * `updated_at < registeredAt` OR `updated_at < recordsClearedAt`.
55
55
  *
56
+ * # `holder_epoch` (H5 / PR #466) — the THIRD staleness anchor
57
+ *
58
+ * A native tokenized `buy_handle` stamps ONLY `holder_epoch` (it must not
59
+ * move `registered_at`), so without it the seller's records — including the
60
+ * payment-routing `x1.*` keys — stayed live after a sale. The same functions
61
+ * take the handle's `holderEpoch` (0 if absent) and judge a text record
62
+ * stale when `updated_at < max(registeredAt, holderEpoch, recordsClearedAt)`
63
+ * — the on-chain `name_pays_to` rule and the address-record reader's rule.
64
+ *
65
+ * # Keys are compared BYTE-EXACT (BOM-preserving decode)
66
+ *
67
+ * The program accepts any UTF-8 key of 1..=64 bytes, including one that
68
+ * starts with a U+FEFF byte-order mark. A default `TextDecoder` STRIPS a
69
+ * leading BOM, so a key stored as `EF BB BF "x1.shield"` used to read back
70
+ * as `"x1.shield"` — a record delegate could spoof a routing key. Keys here
71
+ * are decoded with `ignoreBOM: true`, so the BOM survives into `key` and the
72
+ * decoded string is equal to a lookup key only when the raw bytes are. Use
73
+ * {@link findTextRecord} to look up a specific key.
74
+ *
56
75
  * # These records count (#7384)
57
76
  *
58
77
  * `create_text_record` increments — and `close_text_record` decrements —
@@ -149,6 +168,21 @@ export async function hashTextKey(key) {
149
168
  const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(key));
150
169
  return new Uint8Array(digest);
151
170
  }
171
+ /**
172
+ * Decode a stored KEY: strict UTF-8 with the byte-order mark PRESERVED
173
+ * (`ignoreBOM: true`). A default decoder silently drops a leading U+FEFF,
174
+ * which made `EF BB BF "x1.shield"` read back as `"x1.shield"`. With the BOM
175
+ * kept, `decoded === key` holds exactly when the raw bytes are identical
176
+ * (UTF-8 is a bijection on valid input). Null when not valid UTF-8.
177
+ */
178
+ export function textKeyFromBytes(keyBytes) {
179
+ try {
180
+ return new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(keyBytes);
181
+ }
182
+ catch {
183
+ return null;
184
+ }
185
+ }
152
186
  /**
153
187
  * Render stored value bytes as text: a STRICT UTF-8 decode, or null when the
154
188
  * bytes are not valid UTF-8 (binary values like `contenthash`). Callers
@@ -174,15 +208,18 @@ export function textValueToString(value) {
174
208
  * `registeredAt` is the owning Handle's `registered_at`, decoded by the
175
209
  * caller from the Handle account — it decides `stale`. `recordsClearedAt` is
176
210
  * that same Handle's `recordsClearedAt` (0 if never cleared, #8139), a
177
- * SECOND independent staleness anchor. There is intentionally no overload
178
- * without either (see the module docs).
211
+ * SECOND independent staleness anchor. `holderEpoch` is that Handle's
212
+ * `holderEpoch` (H5, 0 if absent): stale when
213
+ * `updated_at < max(registeredAt, holderEpoch, recordsClearedAt)`. It
214
+ * defaults to `0n` only for backward compatibility; every caller that has a
215
+ * decoded Handle should pass it (a payment-routing reader MUST).
179
216
  *
180
217
  * Returns null for anything that is not a TextRecord: wrong length, wrong
181
218
  * discriminator, lengths that do not fit, or a key that is not valid UTF-8
182
219
  * (the program's Borsh `String` guarantees it is, so that is not a
183
220
  * TextRecord).
184
221
  */
185
- export function decodeTextRecord(raw, account, registeredAt, recordsClearedAt) {
222
+ export function decodeTextRecord(raw, account, registeredAt, recordsClearedAt, holderEpoch = 0n) {
186
223
  if (raw.length !== TEXT_RECORD_LEN)
187
224
  return null;
188
225
  for (let i = 0; i < 8; i++) {
@@ -207,9 +244,15 @@ export function decodeTextRecord(raw, account, registeredAt, recordsClearedAt) {
207
244
  const value = raw.slice(o, o + valueLen);
208
245
  o += valueLen;
209
246
  const updatedAt = dv.getBigInt64(o, true);
210
- const key = textValueToString(keyBytes);
247
+ // BOM-preserving: see textKeyFromBytes / the module docs.
248
+ const key = textKeyFromBytes(keyBytes);
211
249
  if (key === null)
212
250
  return null; // Borsh Strings are always valid UTF-8
251
+ // Same rule as name_pays_to and decodeRecord: written before the current
252
+ // ownership epoch (register, native tokenized sale, or clear_records).
253
+ let epoch = registeredAt > holderEpoch ? registeredAt : holderEpoch;
254
+ if (recordsClearedAt > epoch)
255
+ epoch = recordsClearedAt;
213
256
  return {
214
257
  account,
215
258
  handle,
@@ -217,7 +260,7 @@ export function decodeTextRecord(raw, account, registeredAt, recordsClearedAt) {
217
260
  value,
218
261
  text: textValueToString(value),
219
262
  updatedAt,
220
- stale: updatedAt < registeredAt || updatedAt < recordsClearedAt,
263
+ stale: updatedAt < epoch,
221
264
  };
222
265
  }
223
266
  /** The text records the CURRENT owner actually has — `stale` ones excluded.
@@ -225,6 +268,33 @@ export function decodeTextRecord(raw, account, registeredAt, recordsClearedAt) {
225
268
  export function liveTextRecords(records) {
226
269
  return records.filter((r) => !r.stale);
227
270
  }
271
+ /**
272
+ * The LIVE record whose stored key bytes are EXACTLY `key`'s UTF-8 bytes, or
273
+ * undefined. Use this (not `records.find((r) => r.key === key)`) for any key
274
+ * that routes funds or changes behaviour (`x1.shield`, `x1.pool`, ...).
275
+ *
276
+ * Byte-exact by construction: keys are decoded BOM-preserving, so a
277
+ * `U+FEFF`-prefixed look-alike never equals `key`; the raw bytes are compared
278
+ * again here as defence in depth. If more than one live record matches
279
+ * (impossible for well-formed PDAs, since the address is derived from
280
+ * sha256(key)), it returns undefined: ordering never decides which record
281
+ * routes.
282
+ */
283
+ export function findTextRecord(records, key) {
284
+ const want = new TextEncoder().encode(key);
285
+ let hit;
286
+ for (const r of records) {
287
+ if (r.stale)
288
+ continue;
289
+ const got = new TextEncoder().encode(r.key);
290
+ if (got.length !== want.length || got.some((b, i) => b !== want[i]))
291
+ continue;
292
+ if (hit !== undefined)
293
+ return undefined; // ambiguous: refuse, never pick
294
+ hit = r;
295
+ }
296
+ return hit;
297
+ }
228
298
  /**
229
299
  * Fetch every TextRecord account of a handle — one `getProgramAccounts`
230
300
  * call, filtered by the RPC on size (377), the TextRecord discriminator at
@@ -236,12 +306,14 @@ export function liveTextRecords(records) {
236
306
  * `registeredAt` is `Handle.registered_at` as decoded from the Handle
237
307
  * account the caller already has — the staleness rule needs it, and there
238
308
  * is no variant of this function without it. `recordsClearedAt` is that same
239
- * Handle's `recordsClearedAt` (0 if never cleared, #8139) — pass it through.
309
+ * Handle's `recordsClearedAt` (0 if never cleared, #8139) — pass it through,
310
+ * and `holderEpoch` (H5; defaults to 0n for backward compatibility, but pass
311
+ * it: a native tokenized sale moves only this anchor).
240
312
  * Every record is returned, stale ones flagged, so an owner surface can show
241
313
  * what a previous owner left behind; anything that renders a profile takes
242
314
  * {@link liveTextRecords}.
243
315
  */
244
- export async function fetchTextRecords(rpc, programId, handleAccount, registeredAt, recordsClearedAt) {
316
+ export async function fetchTextRecords(rpc, programId, handleAccount, registeredAt, recordsClearedAt, holderEpoch = 0n) {
245
317
  const res = (await rpc("getProgramAccounts", [
246
318
  programId,
247
319
  {
@@ -260,7 +332,7 @@ export async function fetchTextRecords(rpc, programId, handleAccount, registered
260
332
  const raw = new Uint8Array(bin.length);
261
333
  for (let i = 0; i < bin.length; i++)
262
334
  raw[i] = bin.charCodeAt(i);
263
- const decoded = decodeTextRecord(raw, a.pubkey, registeredAt, recordsClearedAt);
335
+ const decoded = decodeTextRecord(raw, a.pubkey, registeredAt, recordsClearedAt, holderEpoch);
264
336
  // Defence in depth: the memcmp filter should guarantee the handle
265
337
  // match, but a wrong offset would silently attribute someone else's
266
338
  // record to this handle. A malformed account is skipped, not fatal.
package/dist/types.d.ts CHANGED
@@ -98,6 +98,9 @@ export type ResolveErrorCode = "unrecognized" | "ambiguous" | "invalid-handle" |
98
98
  * isn't "any-verified"/{kind}/{anyOf}) — a programming error, surfaced as a
99
99
  * typed ResolveError rather than a raw TypeError. */
100
100
  | "invalid-input"
101
+ /** The name is held by the X1ID treasury (a reserved name): it is not a
102
+ * person and must never be offered as a payment target. */
103
+ | "reserved"
101
104
  /**
102
105
  * A reachable namespace exists for this name, but the adapter that would
103
106
  * resolve it is not configured on this deployment (e.g. no `ETH_RPC_URL` for
@@ -0,0 +1,246 @@
1
+ /**
2
+ * x402 payment receipts on chain (#8324, wired by [Pay 10] / WP 8833):
3
+ * `record_x402_receipt`, its `X402ReceiptRecorded` event and the per-handle
4
+ * `AgentPaymentStats` tally.
5
+ *
6
+ * Hand-rolled like the rest of this package — no Anchor client, no
7
+ * `@solana/web3.js`. The builder returns the transport-neutral
8
+ * {@link BuiltInstruction} (`delegate.ts` has the two-line web3.js adapter).
9
+ *
10
+ * # What a receipt proves (and what it does not)
11
+ *
12
+ * The instruction is ATTESTOR-SIGNED (`has_one = attestor` on
13
+ * `["attestor_config"]`). The program does NOT look at the payment itself: it
14
+ * does not introspect the Instructions sysvar, does not read `settled_sig`'s
15
+ * transaction, and does not check `amount` / `mint` against anything. A
16
+ * receipt therefore proves exactly one thing — "the configured attestor key
17
+ * stamped this payment" — and the attestor is trusted to have confirmed the
18
+ * settlement off chain first (`docs/x402-receipts.md`, option B). The
19
+ * `settled_sig` it carries is the audit anchor: anyone can fetch that
20
+ * transaction and check it. Never present a receipt as more than that.
21
+ *
22
+ * Both handles must be live `Handle` accounts and must differ
23
+ * (`X402SelfReceipt`, 6085). A scoped handle (`["handle", [len], label,
24
+ * name]`) needs its `["namespace", label]` account in `namespaces` (the
25
+ * program scans remaining accounts for it); a bare handle needs nothing.
26
+ *
27
+ * Cost: the attestor is the fee payer and pays the rent of each
28
+ * `AgentPaymentStats` account the first time a handle is touched (81 bytes
29
+ * each). On X1 the fee is 10 lamports per REQUESTED compute unit plus 1,500
30
+ * per signature, so always set a compute-unit limit: simulate and use
31
+ * {@link x402ReceiptCuLimitFromSimulation}, or fall back to
32
+ * {@link RECORD_X402_RECEIPT_CU_LIMIT}.
33
+ */
34
+ import type { AddressLike, BuiltInstruction } from "./delegate.js";
35
+ import type { PdaFinder } from "./namespacePricing.js";
36
+ /** Anchor instruction discriminator: `sha256("global:record_x402_receipt")[0..8]`. */
37
+ export declare const RECORD_X402_RECEIPT_DISCRIMINATOR: Uint8Array;
38
+ /** Anchor event discriminator: `sha256("event:X402ReceiptRecorded")[0..8]`.
39
+ * An emitted event is logged as `Program data: <base64(disc ‖ borsh)>`. */
40
+ export declare const X402_RECEIPT_RECORDED_EVENT_DISCRIMINATOR: Uint8Array;
41
+ /** Anchor account discriminator: `sha256("account:AgentPaymentStats")[0..8]`. */
42
+ export declare const AGENT_PAYMENT_STATS_DISCRIMINATOR: Uint8Array;
43
+ /** Seed prefix of the stats PDA: `["x402_stats", handleAccount]`. */
44
+ export declare const AGENT_PAYMENT_STATS_SEED = "x402_stats";
45
+ /** `AgentPaymentStats` size: disc(8) + handle(32) + 4×u64(32) + last_at(8) + bump(1). */
46
+ export declare const AGENT_PAYMENT_STATS_LEN = 81;
47
+ /** `X402ReceiptRecorded` encoded size: disc(8) + payer(32) + payee(32) +
48
+ * amount(8) + mint(32) + resource_hash(32) + settled_sig(64) + timestamp(8). */
49
+ export declare const X402_RECEIPT_EVENT_LEN = 216;
50
+ /** `record_x402_receipt` instruction data size: disc + amount + mint +
51
+ * resource_hash + settled_sig. */
52
+ export declare const RECORD_X402_RECEIPT_DATA_LEN: number;
53
+ /** `X402SelfReceipt`: payer and payee handle are the same account. */
54
+ export declare const X402_SELF_RECEIPT_ERROR = 6085;
55
+ /**
56
+ * Static compute-unit CEILING for a transaction carrying ONE
57
+ * `record_x402_receipt` (plus its compute-budget instruction), for callers
58
+ * that cannot simulate first. Measured in litesvm against the built program
59
+ * (programs/x1-handles/tests/x402_receipt_sdk_e2e.rs): ~40.0k CU when both
60
+ * stats accounts are created (first touch), ~28.7k CU after, with stats-PDA
61
+ * bumps 255/254. The cost is not constant: Anchor re-derives each stats PDA
62
+ * with `find_program_address` on every call, so a handle whose stats bump is
63
+ * lower costs ~1.5k CU more per step below 255. X1 charges the REQUESTED
64
+ * limit (10 lamports per CU), so the better practice — what dev-api does — is
65
+ * to simulate and request {@link x402ReceiptCuLimitFromSimulation} of the
66
+ * measured units, using this only as the fallback / upper bound.
67
+ */
68
+ export declare const RECORD_X402_RECEIPT_CU_LIMIT = 60000;
69
+ /** A tight limit from a simulation's `unitsConsumed`: +10% (at least 2,000
70
+ * CU), rounded up to a thousand, never above `ceiling`. */
71
+ export declare function x402ReceiptCuLimitFromSimulation(unitsConsumed: number, ceiling?: number): number;
72
+ /** A transaction signature as its 64 raw bytes (from base58 or bytes). */
73
+ export declare function x402SettledSigBytes(sig: string | Uint8Array): Uint8Array;
74
+ /**
75
+ * The `resource_hash` x1id stamps: sha256 of the x402 `resource` URL the
76
+ * payment bought, e.g. `https://api.x1id.io/v1/resolve`. The ENDPOINT, not the
77
+ * exact request — a receipt is public forever, and hashing the full request
78
+ * (`/v1/resolve/alice`) would let anyone brute-force what an agent looked up.
79
+ */
80
+ export declare function x402ResourceHash(resource: string): Uint8Array;
81
+ /** `["x402_stats", handleAccount]` — the second seed is the 32 raw bytes of
82
+ * the Handle ACCOUNT address. */
83
+ export declare function findAgentPaymentStatsPda(find: PdaFinder, programId: AddressLike, handle: AddressLike): Promise<string>;
84
+ export interface RecordX402ReceiptArgs {
85
+ /** Amount paid, in the asset's base units (u64). */
86
+ readonly amount: bigint;
87
+ /** The asset's mint (wrapped-native for XNT on the x402 X1 rail). */
88
+ readonly mint: AddressLike;
89
+ /** 32 bytes — see {@link x402ResourceHash}. */
90
+ readonly resourceHash: Uint8Array;
91
+ /** The settled payment's transaction signature (base58 or 64 bytes). */
92
+ readonly settledSig: string | Uint8Array;
93
+ }
94
+ /** Borsh args after the discriminator: amount u64, mint, resource_hash[32], settled_sig[64]. */
95
+ export declare function encodeRecordX402ReceiptArgs(a: RecordX402ReceiptArgs): Uint8Array;
96
+ export interface RecordX402ReceiptParams extends RecordX402ReceiptArgs {
97
+ /** The registry program id. */
98
+ readonly programId: AddressLike;
99
+ /** The configured attestor (`AttestorConfig.attestor`). Signer, writable:
100
+ * pays the stats accounts' first-touch rent. Use it as fee payer too. */
101
+ readonly attestor: AddressLike;
102
+ /** The `["attestor_config"]` PDA. */
103
+ readonly attestorConfig: AddressLike;
104
+ /** The paying agent's live Handle account. */
105
+ readonly payerHandle: AddressLike;
106
+ /** The paid agent's live Handle account. Must differ from payerHandle. */
107
+ readonly payeeHandle: AddressLike;
108
+ /** `["x402_stats", payerHandle]` ({@link findAgentPaymentStatsPda}). */
109
+ readonly payerStats: AddressLike;
110
+ /** `["x402_stats", payeeHandle]`. */
111
+ readonly payeeStats: AddressLike;
112
+ /** `["namespace", label]` accounts of any SCOPED handle among the two
113
+ * (remaining accounts, read-only). Omit for bare handles. */
114
+ readonly namespaces?: readonly AddressLike[];
115
+ }
116
+ /**
117
+ * Build `record_x402_receipt`. Accounts in `RecordX402Receipt` order:
118
+ * attestor(s,w) attestor_config payer_handle payee_handle payer_stats(w)
119
+ * payee_stats(w) system_program, then any namespace accounts.
120
+ */
121
+ export declare function buildRecordX402ReceiptIx(p: RecordX402ReceiptParams): BuiltInstruction;
122
+ /** A decoded `X402ReceiptRecorded` event. */
123
+ export interface X402ReceiptRecorded {
124
+ readonly payerHandle: string;
125
+ readonly payeeHandle: string;
126
+ readonly amount: bigint;
127
+ readonly mint: string;
128
+ readonly resourceHash: Uint8Array;
129
+ /** base58 transaction signature of the settled payment. */
130
+ readonly settledSig: string;
131
+ /** Unix seconds (cluster clock at recording). */
132
+ readonly timestamp: bigint;
133
+ }
134
+ /** Decode one event payload (the bytes of a `Program data:` line). null when
135
+ * it is not an `X402ReceiptRecorded`. */
136
+ export declare function decodeX402ReceiptRecorded(raw: Uint8Array): X402ReceiptRecorded | null;
137
+ /** Encode an event the way the program emits it (tests / fixtures). */
138
+ export declare function encodeX402ReceiptRecorded(e: {
139
+ payerHandle: AddressLike;
140
+ payeeHandle: AddressLike;
141
+ amount: bigint;
142
+ mint: AddressLike;
143
+ resourceHash: Uint8Array;
144
+ settledSig: string | Uint8Array;
145
+ timestamp: bigint;
146
+ }): Uint8Array;
147
+ /**
148
+ * Every `X402ReceiptRecorded` among a transaction's log lines, attributed to
149
+ * `programId`'s OWN invoke frames only (a look-alike `Program data:` line
150
+ * printed by another program is ignored).
151
+ */
152
+ export declare function parseX402ReceiptEvents(logs: readonly string[], programId: AddressLike): X402ReceiptRecorded[];
153
+ /** A decoded `AgentPaymentStats` account. `totalPaid` / `totalReceived` are
154
+ * raw sums across whatever mint each receipt used — never one asset figure;
155
+ * the counts are the unambiguous signal. */
156
+ export interface AgentPaymentStats {
157
+ readonly handle: string;
158
+ readonly paymentsMadeCount: bigint;
159
+ readonly totalPaid: bigint;
160
+ readonly paymentsReceivedCount: bigint;
161
+ readonly totalReceived: bigint;
162
+ readonly lastAt: bigint;
163
+ readonly bump: number;
164
+ }
165
+ /** Decode an `AgentPaymentStats` account (discriminator + exact length
166
+ * checked); null for anything else. */
167
+ export declare function decodeAgentPaymentStats(raw: Uint8Array): AgentPaymentStats | null;
168
+ /** Encode an `AgentPaymentStats` account (tests / fixtures). */
169
+ export declare function encodeAgentPaymentStats(s: Omit<AgentPaymentStats, "handle"> & {
170
+ handle: AddressLike;
171
+ }): Uint8Array;
172
+ /** Fee (lamports) of one receipt transaction on X1: 10 lamports per
173
+ * requested CU + 1,500 per signature (rent of new stats accounts excluded). */
174
+ export declare function x402ReceiptTxFeeLamports(cuLimit?: number, signatures?: number): number;
175
+ /** Seed of the receipt-signer singleton: `["receipt_signer_config"]`. */
176
+ export declare const RECEIPT_SIGNER_CONFIG_SEED = "receipt_signer_config";
177
+ /** Seed of a handle's O(1) payment tally (alias of {@link AGENT_PAYMENT_STATS_SEED}). */
178
+ export declare const X402_STATS_SEED = "x402_stats";
179
+ /** `sha256("global:record_x402_receipt_v2")[..8]`. */
180
+ export declare const RECORD_X402_RECEIPT_V2_DISCRIMINATOR: Uint8Array;
181
+ /** `sha256("global:set_receipt_signer")[..8]`. */
182
+ export declare const SET_RECEIPT_SIGNER_DISCRIMINATOR: Uint8Array;
183
+ /** `sha256("account:ReceiptSignerConfig")[..8]`. */
184
+ export declare const RECEIPT_SIGNER_CONFIG_DISCRIMINATOR: Uint8Array;
185
+ /** `RegistryError::NotReceiptSigner`: v2 signed by neither role. */
186
+ export declare const X402_NOT_RECEIPT_SIGNER_ERROR = 6157;
187
+ /** `RegistryError::X402ReceiptPayerIsSigner`: v2 with `payer == signer`
188
+ * (Sentinel run-011: the X1ID receipt key never pays). */
189
+ export declare const X402_RECEIPT_PAYER_IS_SIGNER_ERROR = 6232;
190
+ /** `["receipt_signer_config"]`. */
191
+ export declare function findReceiptSignerConfigPda(find: PdaFinder, programId: AddressLike): Promise<string>;
192
+ /** `["x402_stats", handle]` (alias of {@link findAgentPaymentStatsPda}). */
193
+ export declare function findX402StatsPda(find: PdaFinder, programId: AddressLike, handle: AddressLike): Promise<string>;
194
+ /** Decode a `ReceiptSignerConfig` (`signer` base58; the default key
195
+ * `11111111111111111111111111111111` means the role is disabled). */
196
+ export declare function decodeReceiptSignerConfig(data: Uint8Array): {
197
+ readonly signer: string;
198
+ readonly bump: number;
199
+ } | null;
200
+ export interface RecordX402ReceiptV2Params extends RecordX402ReceiptArgs {
201
+ readonly programId: AddressLike;
202
+ /** Signer: the receipt signer or the attestor. It only CO-SIGNS (owner
203
+ * rule: X1ID pays for nothing on chain). */
204
+ readonly signer: AddressLike;
205
+ /** REQUIRED signer (writable) that funds first-touch stats rent and
206
+ * should be the tx fee payer: the submitter (e.g. the API buyer or the
207
+ * merchant), never the receipt key. Must differ from `signer`; the
208
+ * program refuses `payer == signer` (6232). */
209
+ readonly payer: AddressLike;
210
+ /** `["attestor_config"]`. */
211
+ readonly attestorConfig: AddressLike;
212
+ /** `["receipt_signer_config"]` ({@link findReceiptSignerConfigPda}). */
213
+ readonly receiptSignerConfig: AddressLike;
214
+ readonly payerHandle: AddressLike;
215
+ /** Must differ from payerHandle. */
216
+ readonly payeeHandle: AddressLike;
217
+ /** {@link findAgentPaymentStatsPda}(payerHandle). */
218
+ readonly payerStats: AddressLike;
219
+ /** {@link findAgentPaymentStatsPda}(payeeHandle). */
220
+ readonly payeeStats: AddressLike;
221
+ /** Scoped-name handles only: their `["namespace", label]` accounts. */
222
+ readonly namespaces?: readonly AddressLike[];
223
+ }
224
+ /**
225
+ * Build `record_x402_receipt_v2`: the same args as v1. Accounts
226
+ * (`RecordX402ReceiptV2`): signer(s), payer(s,w), attestor_config,
227
+ * receipt_signer_config, payer_handle, payee_handle, payer_stats(w),
228
+ * payee_stats(w), system_program, then any namespaces. Make `payer` the
229
+ * transaction fee payer so the receipt signer's key holds no XNT. Throws when
230
+ * `payer` is missing or equals `signer`.
231
+ */
232
+ export declare function buildRecordX402ReceiptV2Ix(p: RecordX402ReceiptV2Params): BuiltInstruction;
233
+ export interface SetReceiptSignerParams {
234
+ readonly programId: AddressLike;
235
+ /** Signer: `Config.admin` (pays the one-time init). */
236
+ readonly admin: AddressLike;
237
+ /** `["config"]`. */
238
+ readonly config: AddressLike;
239
+ /** {@link findReceiptSignerConfigPda}. */
240
+ readonly receiptSignerConfig: AddressLike;
241
+ /** The new receipt signer; the default key (all zeros) disables the role. */
242
+ readonly signer: AddressLike;
243
+ }
244
+ /** `set_receipt_signer(signer)`. Accounts (`SetReceiptSigner`): admin(s,w),
245
+ * config, receipt_signer_config(w), system_program. */
246
+ export declare function buildSetReceiptSignerIx(p: SetReceiptSignerParams): BuiltInstruction;