@agirails/sdk 4.4.9 → 4.5.2

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 (93) hide show
  1. package/dist/builders/DeliveryProofBuilder.d.ts +224 -13
  2. package/dist/builders/DeliveryProofBuilder.d.ts.map +1 -1
  3. package/dist/builders/DeliveryProofBuilder.js +247 -13
  4. package/dist/builders/DeliveryProofBuilder.js.map +1 -1
  5. package/dist/cli/agirails.d.ts +85 -1
  6. package/dist/cli/agirails.d.ts.map +1 -1
  7. package/dist/cli/agirails.js +429 -154
  8. package/dist/cli/agirails.js.map +1 -1
  9. package/dist/cli/commands/init.d.ts +54 -0
  10. package/dist/cli/commands/init.d.ts.map +1 -1
  11. package/dist/cli/commands/init.js +193 -1
  12. package/dist/cli/commands/init.js.map +1 -1
  13. package/dist/cli/commands/receipt.d.ts +70 -2
  14. package/dist/cli/commands/receipt.d.ts.map +1 -1
  15. package/dist/cli/commands/receipt.js +218 -3
  16. package/dist/cli/commands/receipt.js.map +1 -1
  17. package/dist/cli/commands/test.d.ts +77 -1
  18. package/dist/cli/commands/test.d.ts.map +1 -1
  19. package/dist/cli/commands/test.js +264 -2
  20. package/dist/cli/commands/test.js.map +1 -1
  21. package/dist/cli/lib/runRequest.d.ts +90 -0
  22. package/dist/cli/lib/runRequest.d.ts.map +1 -1
  23. package/dist/cli/lib/runRequest.js +300 -9
  24. package/dist/cli/lib/runRequest.js.map +1 -1
  25. package/dist/cli/lib/sentinelReflections.d.ts +111 -0
  26. package/dist/cli/lib/sentinelReflections.d.ts.map +1 -0
  27. package/dist/cli/lib/sentinelReflections.js +193 -0
  28. package/dist/cli/lib/sentinelReflections.js.map +1 -0
  29. package/dist/delivery/MockDeliveryChannel.d.ts +208 -0
  30. package/dist/delivery/MockDeliveryChannel.d.ts.map +1 -0
  31. package/dist/delivery/MockDeliveryChannel.js +445 -0
  32. package/dist/delivery/MockDeliveryChannel.js.map +1 -0
  33. package/dist/delivery/RelayDeliveryChannel.d.ts +176 -0
  34. package/dist/delivery/RelayDeliveryChannel.d.ts.map +1 -0
  35. package/dist/delivery/RelayDeliveryChannel.js +377 -0
  36. package/dist/delivery/RelayDeliveryChannel.js.map +1 -0
  37. package/dist/delivery/channel.d.ts +282 -0
  38. package/dist/delivery/channel.d.ts.map +1 -0
  39. package/dist/delivery/channel.js +76 -0
  40. package/dist/delivery/channel.js.map +1 -0
  41. package/dist/delivery/channelLog.d.ts +115 -0
  42. package/dist/delivery/channelLog.d.ts.map +1 -0
  43. package/dist/delivery/channelLog.js +94 -0
  44. package/dist/delivery/channelLog.js.map +1 -0
  45. package/dist/delivery/crypto.d.ts +312 -0
  46. package/dist/delivery/crypto.d.ts.map +1 -0
  47. package/dist/delivery/crypto.js +495 -0
  48. package/dist/delivery/crypto.js.map +1 -0
  49. package/dist/delivery/eip712.d.ts +248 -0
  50. package/dist/delivery/eip712.d.ts.map +1 -0
  51. package/dist/delivery/eip712.js +397 -0
  52. package/dist/delivery/eip712.js.map +1 -0
  53. package/dist/delivery/envelopeBuilder.d.ts +531 -0
  54. package/dist/delivery/envelopeBuilder.d.ts.map +1 -0
  55. package/dist/delivery/envelopeBuilder.js +832 -0
  56. package/dist/delivery/envelopeBuilder.js.map +1 -0
  57. package/dist/delivery/index.d.ts +53 -0
  58. package/dist/delivery/index.d.ts.map +1 -0
  59. package/dist/delivery/index.js +143 -0
  60. package/dist/delivery/index.js.map +1 -0
  61. package/dist/delivery/keys.d.ts +344 -0
  62. package/dist/delivery/keys.d.ts.map +1 -0
  63. package/dist/delivery/keys.js +513 -0
  64. package/dist/delivery/keys.js.map +1 -0
  65. package/dist/delivery/nonce-keys.d.ts +93 -0
  66. package/dist/delivery/nonce-keys.d.ts.map +1 -0
  67. package/dist/delivery/nonce-keys.js +88 -0
  68. package/dist/delivery/nonce-keys.js.map +1 -0
  69. package/dist/delivery/setupBuilder.d.ts +403 -0
  70. package/dist/delivery/setupBuilder.d.ts.map +1 -0
  71. package/dist/delivery/setupBuilder.js +554 -0
  72. package/dist/delivery/setupBuilder.js.map +1 -0
  73. package/dist/delivery/types.d.ts +722 -0
  74. package/dist/delivery/types.d.ts.map +1 -0
  75. package/dist/delivery/types.js +150 -0
  76. package/dist/delivery/types.js.map +1 -0
  77. package/dist/delivery/validate.d.ts +288 -0
  78. package/dist/delivery/validate.d.ts.map +1 -0
  79. package/dist/delivery/validate.js +648 -0
  80. package/dist/delivery/validate.js.map +1 -0
  81. package/dist/level1/Agent.d.ts +130 -0
  82. package/dist/level1/Agent.d.ts.map +1 -1
  83. package/dist/level1/Agent.js +248 -0
  84. package/dist/level1/Agent.js.map +1 -1
  85. package/dist/level1/types/Options.d.ts +62 -0
  86. package/dist/level1/types/Options.d.ts.map +1 -1
  87. package/dist/level1/types/Options.js +22 -0
  88. package/dist/level1/types/Options.js.map +1 -1
  89. package/dist/runtime/MockRuntime.d.ts +32 -0
  90. package/dist/runtime/MockRuntime.d.ts.map +1 -1
  91. package/dist/runtime/MockRuntime.js +44 -0
  92. package/dist/runtime/MockRuntime.js.map +1 -1
  93. package/package.json +6 -1
@@ -0,0 +1,531 @@
1
+ /**
2
+ * AIP-16 Delivery Surface — Provider Envelope Builder + Verifier + Decryptor (Phase 2b)
3
+ * =======================================================================================
4
+ *
5
+ * Constructs and verifies the provider-signed `DeliveryEnvelopeV1` payload —
6
+ * the load-bearing artifact of the AIP-16 Rev 5 delivery surface. The
7
+ * provider posts this signed object to the delivery channel after the
8
+ * buyer's setup is received (and after the on-chain transaction reaches
9
+ * `COMMITTED`), carrying:
10
+ *
11
+ * - the EIP-712 binding to a specific kernel, chain, and `txId`,
12
+ * - the on-chain identity acting as the provider, plus the EOA that
13
+ * signed (smart-wallet two-step auth),
14
+ * - the cryptographic scheme used to protect the body (`public-v1` or
15
+ * `x25519-aes256gcm-v1`),
16
+ * - the provider's ephemeral X25519 pubkey (encrypted scheme) or
17
+ * canonical-empty bytes32 (public scheme),
18
+ * - the AES-256-GCM nonce + tag (encrypted) or canonical-empty
19
+ * bytes12 / bytes16 (public),
20
+ * - `payloadHash = keccak256(bodyBytes)` — the on-chain anchor for the
21
+ * exact bytes the buyer will receive,
22
+ * - the body bytes themselves (alongside the signed projection, in the
23
+ * wire envelope).
24
+ *
25
+ * ## Body encoding (SCHEME-AWARE — FIX-1, AIP-16 Phase 3.5)
26
+ *
27
+ * The wire encoding is scheme-dependent so the SDK and the Platform
28
+ * verifier (`Platform/agirails.app/web/lib/delivery/auth.ts`) hash the
29
+ * SAME bytes in BOTH locations:
30
+ *
31
+ * - `public-v1`: `wire.body = JSON.stringify(payload)` — plaintext
32
+ * UTF-8 JSON string, NOT hex. `payloadHash = keccak256(utf8Bytes(body))`.
33
+ * The Platform verifier computes `keccak256(toUtf8Bytes(body))`
34
+ * directly on the wire body. Hex-encoding the plaintext here would
35
+ * make the Platform recompute `keccak256(utf8Bytes("0x7b22…"))` —
36
+ * a different digest — and every public envelope would 400 with
37
+ * `payload_hash_mismatch`.
38
+ *
39
+ * - `x25519-aes256gcm-v1`: `wire.body = "0x" + hex(aesGcmCiphertext)`.
40
+ * `payloadHash = keccak256(rawCiphertextBytes)`. The Platform
41
+ * verifier hex-decodes `wire.body` and then keccak256s the bytes.
42
+ * Ciphertext is a byte string that does NOT round-trip through UTF-8
43
+ * (it contains arbitrary 0..255 bytes incl. 0x00 and high bits),
44
+ * so hex is the only safe text encoding — base64 would also work but
45
+ * AIP-16 standardizes on hex for cross-language SDK consistency.
46
+ *
47
+ * Rationale for the asymmetry:
48
+ * 1. **Public payloads are already text.** JSON serializes to valid
49
+ * UTF-8 — no encoding wrapper needed. The plaintext IS the wire.
50
+ * 2. **Ciphertext is binary.** Cannot travel naked in JSON; hex is the
51
+ * chosen text encoding (matches `nonce`, `tag`, `payloadHash`,
52
+ * `providerEphemeralPubkey`).
53
+ * 3. **Spec match.** AIP-16 §6.2 sign-side and the Platform verify-
54
+ * side both implement this exact rule.
55
+ *
56
+ * ## Builder shape (matches DeliverySetupBuilder)
57
+ *
58
+ * - `constructor(signer?)` — signer required for `build*()`, optional
59
+ * for `verify()` / `computeHash()` / `decryptPayload()`. The static
60
+ * helpers do not consult builder state.
61
+ * - `buildPublic(params)` / `buildEncrypted(params)` are `async`
62
+ * because EIP-712 signing on real wallets is async.
63
+ * - `verify`, `decryptPayload`, `verifyAndDecrypt`, `computeHash` are
64
+ * `static` — mirrors {@link DeliverySetupBuilder} and the existing
65
+ * delivery-proof / quote builders.
66
+ *
67
+ * ## Smart-wallet two-step auth (DEC-10 / V2 receipts)
68
+ *
69
+ * `providerAddress` (on-chain participant — possibly a Smart Wallet)
70
+ * and `signerAddress` (the EOA that actually signed) are accepted
71
+ * SEPARATELY. The SDK does NOT derive one from the other; the smart-
72
+ * wallet equality check
73
+ * computeSmartWalletFromSigner(signerAddress) === providerAddress
74
+ * is the SERVER'S responsibility (cross-vendor factory ABI agnostic).
75
+ *
76
+ * What the SDK enforces in `build*()` is the cheaper invariant:
77
+ * `signerAddress === await signer.getAddress()`.
78
+ *
79
+ * ## payloadHash defends against body-after-sign tamper
80
+ *
81
+ * Because `payloadHash = keccak256(bodyBytes)` is part of the SIGNED
82
+ * EIP-712 projection, any post-signature mutation of `wire.body`
83
+ * causes `bodyHash(wire.body)` to diverge from `signed.payloadHash`.
84
+ * The verifier short-circuits with `envelope_payload_hash_mismatch`
85
+ * before signature recovery, so a malicious relay cannot swap bodies
86
+ * even within an otherwise valid signed envelope.
87
+ *
88
+ * ## Verification order (first failure short-circuits)
89
+ *
90
+ * 1. `validateEnvelopeWire(wire)` — structural shape, types, lengths,
91
+ * and scheme/canonical-empty consistency in one pass.
92
+ * 2. `validateSchemeConsistency(signed)` — defense-in-depth re-check
93
+ * (already covered by step 1 but called explicitly so future
94
+ * refactors of the validator do not silently weaken the contract).
95
+ * 3. `signed.chainId === expectedChainId` → `envelope_chain_mismatch`.
96
+ * 4. `signed.kernelAddress` (lc) === `expectedKernelAddress` (lc)
97
+ * → `envelope_kernel_mismatch`.
98
+ * 5. `bodyHash(wire.body) === signed.payloadHash`
99
+ * → `envelope_payload_hash_mismatch`.
100
+ * 6. `recoverEnvelopeSigner(signed, providerSig, expectedKernel)`
101
+ * (lc) === `signed.signerAddress` (lc)
102
+ * → `envelope_signature_invalid`.
103
+ * 7. `|now - signed.createdAt| <= ENVELOPE_TIMESTAMP_SKEW_SEC`
104
+ * → `envelope_timestamp_skew`.
105
+ *
106
+ * Note that timestamp skew is checked LAST — a forged signature is a
107
+ * more severe error than a stale-but-genuine envelope and we want the
108
+ * caller to see the more severe failure first.
109
+ *
110
+ * @module delivery/envelopeBuilder
111
+ * @see ./types — signed/wire interfaces and {@link BuildEnvelopeResult}.
112
+ * @see ./eip712 — domain, types, and {@link recoverEnvelopeSigner}.
113
+ * @see ./validate — {@link validateEnvelopeWire},
114
+ * {@link validateSchemeConsistency}.
115
+ * @see ./keys — X25519 keygen + ECDH + HKDF.
116
+ * @see ./crypto — AES-256-GCM seal/open + {@link bodyHash}.
117
+ * @see ./setupBuilder — sibling builder; same shape conventions.
118
+ */
119
+ import { type Signer } from 'ethers';
120
+ import { type EphemeralKeyPair } from './keys';
121
+ import { type BuildEnvelopeResult, type DeliveryEnvelopeSignedV1, type DeliveryEnvelopeWireV1 } from './types';
122
+ /**
123
+ * Maximum tolerated clock-skew, in seconds, between the signed
124
+ * `createdAt` and the verifier's wall clock. Symmetric (past + future).
125
+ *
126
+ * 900s (15 min) matches {@link DeliverySetupBuilder}'s
127
+ * `SETUP_TIMESTAMP_SKEW_SEC`, the receipts-V2 freshness window, and
128
+ * the AIP-3 anchor-receipt skew bound.
129
+ */
130
+ export declare const ENVELOPE_TIMESTAMP_SKEW_SEC = 900;
131
+ /**
132
+ * Length (in bytes) of the AES-256-GCM AAD used by the encrypted
133
+ * scheme — `txId_bytes (32) || signerAddress_bytes (20) = 52`.
134
+ *
135
+ * H5 binding: GCM authenticates the AAD; a misrouted envelope (correct
136
+ * ciphertext + nonce + tag + sessionKey, but delivered as if for a
137
+ * different `txId` or `signerAddress`) fails the tag check on decrypt.
138
+ * The hash-input `payloadHash` in the EIP-712 signature already binds
139
+ * the body to a specific `txId` at the signature layer; this AAD adds
140
+ * the same binding INSIDE the GCM authentication, defense-in-depth.
141
+ *
142
+ * Bytes layout (network byte order, no padding):
143
+ * - [0..32): `txId` raw 32 bytes (from the 0x + 64 hex chars).
144
+ * - [32..52): `signerAddress` raw 20 bytes (from the 0x + 40 hex chars).
145
+ */
146
+ export declare const ENVELOPE_AAD_LENGTH: 52;
147
+ /**
148
+ * Construct the AES-256-GCM AAD for the `x25519-aes256gcm-v1` scheme.
149
+ *
150
+ * Format: `txId (32 bytes) || signerAddress (20 bytes) = 52 bytes`.
151
+ *
152
+ * Both the build side (in {@link DeliveryEnvelopeBuilder.buildEncrypted})
153
+ * and the decrypt side (in {@link DeliveryEnvelopeBuilder.decryptPayload})
154
+ * call this helper with the SAME txId/signerAddress so the GCM tag
155
+ * commits to identical AAD bytes. Address case is normalized via
156
+ * `bytesFromHex` (which is case-insensitive on the hex characters), so
157
+ * checksum vs lowercase inputs round-trip to the same 20 raw bytes.
158
+ *
159
+ * @param txId - On-chain transaction id, `0x` + 64 hex chars.
160
+ * @param signerAddress - EOA address, `0x` + 40 hex chars.
161
+ * @returns 52-byte AAD buffer (`txId_bytes || signerAddress_bytes`).
162
+ * @throws {DeliveryCryptoError} `crypto_decrypt_failed` if either
163
+ * parameter has the wrong byte length (decoded via `bytesFromHex`
164
+ * from `./crypto`); the underlying helper raises this code.
165
+ *
166
+ * @internal Used by the envelope builder; exposed for cross-SDK
167
+ * fixtures and the H5 test suite.
168
+ */
169
+ export declare function buildEnvelopeAad(txId: `0x${string}`, signerAddress: `0x${string}`): Uint8Array;
170
+ /**
171
+ * Replace the wall-clock implementation used inside this module.
172
+ *
173
+ * **TEST-ONLY.** Production code MUST NOT call this. Pass `null` (or
174
+ * call {@link resetSecondsNowForTests}) to restore the real-clock
175
+ * implementation.
176
+ *
177
+ * @param impl - Replacement function returning Unix seconds, or `null`
178
+ * to restore the default real-clock implementation.
179
+ */
180
+ export declare function setSecondsNowForTests(impl: (() => number) | null): void;
181
+ /**
182
+ * Restore {@link secondsNow} to its default real-clock implementation.
183
+ *
184
+ * **TEST-ONLY.** Safe to call when no override is active.
185
+ */
186
+ export declare function resetSecondsNowForTests(): void;
187
+ /**
188
+ * Parameters accepted by {@link DeliveryEnvelopeBuilder.buildPublic}.
189
+ *
190
+ * Every address is passed explicitly — no implicit derivation of one
191
+ * address from another. `providerAddress` and `signerAddress` are
192
+ * separate so the SDK is agnostic to which Smart Wallet factory the
193
+ * caller is using.
194
+ */
195
+ export interface BuildPublicEnvelopeParams {
196
+ /**
197
+ * On-chain transaction id this envelope is bound to.
198
+ * 32-byte hex (`0x` + 64 hex chars). MUST equal the corresponding
199
+ * setup's `txId`.
200
+ */
201
+ txId: `0x${string}`;
202
+ /**
203
+ * EVM chain id (e.g. `8453` for Base mainnet, `84532` for Base Sepolia).
204
+ * Encoded into BOTH the EIP-712 domain and the signed payload.
205
+ */
206
+ chainId: number;
207
+ /**
208
+ * Address of the ACTP kernel contract on `chainId`. Becomes the
209
+ * EIP-712 `verifyingContract`.
210
+ */
211
+ kernelAddress: `0x${string}`;
212
+ /**
213
+ * On-chain identity acting as the provider. Smart-wallet flows pass
214
+ * the Smart Wallet address here; non-smart-wallet flows pass the EOA.
215
+ * The SDK does NOT derive this from `signer`.
216
+ */
217
+ providerAddress: `0x${string}`;
218
+ /**
219
+ * EOA address that will produce the signature. MUST equal
220
+ * `await signer.getAddress()` — `buildPublic()` enforces this and
221
+ * throws on mismatch.
222
+ */
223
+ signerAddress: `0x${string}`;
224
+ /**
225
+ * The actual deliverable payload. Any JSON-serializable value.
226
+ * `buildPublic` will `JSON.stringify(payload)` and treat the UTF-8
227
+ * bytes of the resulting string as the body bytes.
228
+ */
229
+ payload: unknown;
230
+ /**
231
+ * Override the `createdAt` timestamp. Defaults to {@link secondsNow}.
232
+ * Tests SHOULD pass an explicit value here for determinism rather
233
+ * than relying on {@link setSecondsNowForTests}.
234
+ */
235
+ createdAt?: number;
236
+ /**
237
+ * CoinbaseSmartWallet factory nonce used to derive `providerAddress`
238
+ * from `signerAddress`. Defaults to `0` (the first wallet per owner).
239
+ *
240
+ * H4 fix (AIP-16 Phase 3 HIGH): providers whose Smart Wallet was
241
+ * deployed at a non-zero factory nonce MUST pass that nonce here so
242
+ * the server's smart-wallet derivation lands on the correct address.
243
+ *
244
+ * Must be a non-negative integer; `buildPublic()` rejects negatives
245
+ * with `BUILDER_INVALID_SMART_WALLET_NONCE`.
246
+ */
247
+ smartWalletNonce?: number;
248
+ }
249
+ /**
250
+ * Parameters accepted by {@link DeliveryEnvelopeBuilder.buildEncrypted}.
251
+ *
252
+ * Extends {@link BuildPublicEnvelopeParams} with the buyer's ephemeral
253
+ * pubkey (from the corresponding setup) and an optional override for
254
+ * the provider's own ephemeral keypair (tests use this for determinism;
255
+ * production callers SHOULD omit it).
256
+ */
257
+ export interface BuildEncryptedEnvelopeParams {
258
+ /** See {@link BuildPublicEnvelopeParams.txId}. */
259
+ txId: `0x${string}`;
260
+ /** See {@link BuildPublicEnvelopeParams.chainId}. */
261
+ chainId: number;
262
+ /** See {@link BuildPublicEnvelopeParams.kernelAddress}. */
263
+ kernelAddress: `0x${string}`;
264
+ /** See {@link BuildPublicEnvelopeParams.providerAddress}. */
265
+ providerAddress: `0x${string}`;
266
+ /** See {@link BuildPublicEnvelopeParams.signerAddress}. */
267
+ signerAddress: `0x${string}`;
268
+ /**
269
+ * The actual deliverable payload. Any JSON-serializable value.
270
+ * `buildEncrypted` will `JSON.stringify(payload)`, UTF-8 encode, then
271
+ * AES-256-GCM seal under the X25519+HKDF-derived session key.
272
+ */
273
+ payload: unknown;
274
+ /**
275
+ * The buyer's ephemeral X25519 public key (32 bytes, hex), copied
276
+ * from the corresponding `DeliverySetupSignedV1.buyerEphemeralPubkey`.
277
+ * `buildEncrypted` runs ECDH with this and the provider's own
278
+ * ephemeral private key to derive the shared secret.
279
+ *
280
+ * MUST NOT be {@link CANONICAL_EMPTY_BYTES32} — the canonical-empty
281
+ * value is reserved for the public scheme.
282
+ */
283
+ buyerEphemeralPubkey: `0x${string}`;
284
+ /**
285
+ * Override for the provider's ephemeral X25519 keypair. When omitted
286
+ * (the production path), a fresh keypair is generated via
287
+ * {@link generateEphemeralKeyPair}.
288
+ *
289
+ * **TEST-ONLY in practice.** Production callers SHOULD let the
290
+ * builder generate the keypair so the private key never crosses a
291
+ * call boundary; passing one in increases the risk of accidental
292
+ * persistence.
293
+ */
294
+ providerEphemeralKeyPair?: EphemeralKeyPair;
295
+ /**
296
+ * Override the `createdAt` timestamp. Defaults to {@link secondsNow}.
297
+ */
298
+ createdAt?: number;
299
+ /**
300
+ * CoinbaseSmartWallet factory nonce used to derive `providerAddress`
301
+ * from `signerAddress`. Defaults to `0` (the first wallet per owner).
302
+ *
303
+ * H4 fix (AIP-16 Phase 3 HIGH): symmetric to
304
+ * {@link BuildPublicEnvelopeParams.smartWalletNonce}. Allows providers
305
+ * with non-zero-nonce Smart Wallets to authenticate.
306
+ */
307
+ smartWalletNonce?: number;
308
+ }
309
+ /**
310
+ * Builder + verifier + decryptor for AIP-16 delivery envelopes.
311
+ *
312
+ * Instances are cheap to construct and have no I/O side effects.
313
+ * `verify()`, `decryptPayload()`, `verifyAndDecrypt()`, and
314
+ * `computeHash()` are static — call them without constructing an
315
+ * instance.
316
+ *
317
+ * @example Provider build (public)
318
+ * ```typescript
319
+ * const builder = new DeliveryEnvelopeBuilder(wallet);
320
+ * const { wire } = await builder.buildPublic({
321
+ * txId, chainId: 84532, kernelAddress: KERNEL,
322
+ * providerAddress: SMART_WALLET, signerAddress: EOA,
323
+ * payload: { result: 'ok' },
324
+ * });
325
+ * await postToRelay(wire);
326
+ * ```
327
+ *
328
+ * @example Provider build (encrypted)
329
+ * ```typescript
330
+ * const { wire, blobKey } = await builder.buildEncrypted({
331
+ * txId, chainId: 84532, kernelAddress: KERNEL,
332
+ * providerAddress: SMART_WALLET, signerAddress: EOA,
333
+ * payload: { secret: 'data' },
334
+ * buyerEphemeralPubkey: setupSigned.buyerEphemeralPubkey,
335
+ * });
336
+ * ```
337
+ *
338
+ * @example Buyer decrypt
339
+ * ```typescript
340
+ * const result = await DeliveryEnvelopeBuilder.verifyAndDecrypt(
341
+ * wire,
342
+ * buyerEphemeralPrivKey,
343
+ * { expectedKernelAddress: KERNEL, expectedChainId: 84532 },
344
+ * );
345
+ * if (!result.ok) throw new Error(result.code);
346
+ * const payload = result.payload;
347
+ * ```
348
+ */
349
+ export declare class DeliveryEnvelopeBuilder {
350
+ private readonly signer?;
351
+ /**
352
+ * Construct a new builder.
353
+ *
354
+ * @param signer - EOA signer required for {@link buildPublic} and
355
+ * {@link buildEncrypted}. Pass `undefined` for a verify-/decrypt-only
356
+ * instance; all verification / decryption helpers are static and
357
+ * do not consult builder state.
358
+ */
359
+ constructor(signer?: Signer);
360
+ /**
361
+ * Construct, sign, and return a {@link DeliveryEnvelopeWireV1} using
362
+ * the `public-v1` scheme.
363
+ *
364
+ * Encoding (FIX-1, AIP-16 Phase 3.5):
365
+ * - `bodyString = JSON.stringify(params.payload)`.
366
+ * - `wire.body = bodyString` (plaintext UTF-8 JSON, NOT hex).
367
+ * - `payloadHash = keccak256(utf8Bytes(bodyString))`.
368
+ * - The Platform verifier recomputes `keccak256(toUtf8Bytes(body))`
369
+ * on the wire body directly, so the SDK and verifier hash the
370
+ * same bytes byte-for-byte.
371
+ *
372
+ * Canonical-empty enforcement:
373
+ * - `providerEphemeralPubkey = CANONICAL_EMPTY_BYTES32`.
374
+ * - `nonce = CANONICAL_EMPTY_BYTES12`.
375
+ * - `tag = CANONICAL_EMPTY_BYTES16`.
376
+ *
377
+ * Pre-checks:
378
+ * - signer MUST be present.
379
+ * - `signerAddress` MUST equal `await signer.getAddress()`.
380
+ *
381
+ * @param params - {@link BuildPublicEnvelopeParams}.
382
+ * @returns A {@link BuildEnvelopeResult} carrying the signed wire
383
+ * envelope and the raw plaintext bytes (`bodyBytes`) that the
384
+ * `payloadHash` was computed over. `blobKey` is `undefined` for
385
+ * the public scheme.
386
+ * @throws {DeliveryEip712Error} on signer absence or signer/address
387
+ * mismatch.
388
+ */
389
+ buildPublic(params: BuildPublicEnvelopeParams): Promise<BuildEnvelopeResult>;
390
+ /**
391
+ * Construct, sign, and return a {@link DeliveryEnvelopeWireV1} using
392
+ * the `x25519-aes256gcm-v1` scheme.
393
+ *
394
+ * Crypto flow:
395
+ * 1. Generate (or accept) a provider ephemeral X25519 keypair.
396
+ * 2. `shared = X25519(providerPriv, buyerPub)`.
397
+ * 3. `sessionKey = HKDF-SHA256(ikm=shared, salt=txId, info="agirails-delivery-v1", L=32)`.
398
+ * 4. `plaintextBytes = utf8Bytes(JSON.stringify(payload))`.
399
+ * 5. `{ciphertext, nonce, tag} = AES-256-GCM(plaintextBytes, sessionKey)`.
400
+ * 6. `wire.body = bytesToHex(ciphertext)`.
401
+ * 7. `payloadHash = keccak256(ciphertext)`.
402
+ * 8. Sign the EIP-712 projection containing `scheme = "x25519-aes256gcm-v1"`,
403
+ * the provider's ephemeral pubkey, the AES-GCM nonce + tag, and
404
+ * `payloadHash`.
405
+ *
406
+ * The provider's ephemeral PRIVATE key is dropped after step 5;
407
+ * forward secrecy w.r.t. provider long-term keys is provided by the
408
+ * fresh keypair per delivery.
409
+ *
410
+ * Pre-checks:
411
+ * - signer MUST be present.
412
+ * - `signerAddress` MUST equal `await signer.getAddress()`.
413
+ * - `buyerEphemeralPubkey` MUST NOT be {@link CANONICAL_EMPTY_BYTES32}.
414
+ *
415
+ * @param params - {@link BuildEncryptedEnvelopeParams}.
416
+ * @returns A {@link BuildEnvelopeResult} carrying the signed wire
417
+ * envelope, the ciphertext bytes (`bodyBytes`) the `payloadHash`
418
+ * was computed over, and the symmetric session `blobKey` (for
419
+ * provider-side observability / future reference-mode flows; the
420
+ * buyer derives the key independently).
421
+ * @throws {DeliveryEip712Error} on signer absence, signer/address
422
+ * mismatch, or canonical-empty buyer pubkey.
423
+ */
424
+ buildEncrypted(params: BuildEncryptedEnvelopeParams): Promise<BuildEnvelopeResult>;
425
+ /**
426
+ * Verify a {@link DeliveryEnvelopeWireV1} received from the relay.
427
+ *
428
+ * See the module-level header for the full check ordering and rationale.
429
+ *
430
+ * @param wire - The wire envelope received from the relay.
431
+ * @param opts.expectedKernelAddress - Trusted kernel address for the
432
+ * target chain (from the verifier's allowlist).
433
+ * @param opts.expectedChainId - Trusted chainId for the target chain.
434
+ * @param opts.now - Override for the verifier's wall clock (Unix
435
+ * seconds). Tests use this for deterministic timestamp-skew paths;
436
+ * production callers SHOULD omit.
437
+ * @returns `{ ok: true, signed }` on success, `{ ok: false, code, error }`
438
+ * on failure.
439
+ */
440
+ static verify(wire: DeliveryEnvelopeWireV1, opts: {
441
+ expectedKernelAddress: string;
442
+ expectedChainId: number;
443
+ now?: number;
444
+ }): {
445
+ ok: true;
446
+ signed: DeliveryEnvelopeSignedV1;
447
+ } | {
448
+ ok: false;
449
+ code: string;
450
+ error: string;
451
+ };
452
+ /**
453
+ * Decrypt the payload of an `x25519-aes256gcm-v1` envelope using the
454
+ * buyer's ephemeral private key.
455
+ *
456
+ * Does NOT verify the EIP-712 signature, the chainId / kernel binding,
457
+ * or the payloadHash. Callers that have not already run {@link verify}
458
+ * SHOULD use {@link verifyAndDecrypt} instead.
459
+ *
460
+ * Throws on:
461
+ * - non-encrypted scheme (`public-v1` envelopes are not decrypted),
462
+ * - malformed buyerEphemeralPrivKey length,
463
+ * - ECDH failure (low-order peer pubkey, etc.),
464
+ * - HKDF failure,
465
+ * - AES-GCM authentication failure (tag mismatch).
466
+ *
467
+ * @param wire - The envelope to decrypt.
468
+ * @param buyerEphemeralPrivKey - The buyer's 32-byte X25519 private
469
+ * key (the one whose pubkey was embedded in the setup).
470
+ * @returns The JSON-parsed payload (`unknown`).
471
+ * @throws {DeliveryCryptoError} via the underlying crypto helpers.
472
+ * @throws {DeliveryEip712Error} `BUILDER_PUBLIC_DECRYPT_NOT_APPLICABLE`
473
+ * when called on a `public-v1` envelope.
474
+ */
475
+ static decryptPayload(wire: DeliveryEnvelopeWireV1, buyerEphemeralPrivKey: Uint8Array): Promise<unknown>;
476
+ /**
477
+ * Combined {@link verify} + payload extraction.
478
+ *
479
+ * For `public-v1`: after a successful `verify`, the wire body (hex)
480
+ * is decoded to bytes, UTF-8 → string, JSON-parsed, and returned.
481
+ *
482
+ * For `x25519-aes256gcm-v1`: after a successful `verify`,
483
+ * {@link decryptPayload} is invoked with `buyerEphemeralPrivKey`.
484
+ *
485
+ * Verification failures are returned as `{ ok: false, code, error }`
486
+ * — the structured shape matches `verify`. Decryption failures are
487
+ * also returned as `{ ok: false, code: "envelope_decrypt_failed", ...}`
488
+ * (catching the underlying `DeliveryCryptoError`).
489
+ *
490
+ * @param wire - The envelope to verify + decrypt.
491
+ * @param buyerEphemeralPrivKey - 32-byte X25519 private key. Ignored
492
+ * for `public-v1` envelopes (pass `new Uint8Array(32)` if you do
493
+ * not have one — the value is never read in that branch).
494
+ * @param opts - Same as {@link verify}.
495
+ * @returns `{ ok: true, payload }` on success, `{ ok: false, code, error }`
496
+ * on any failure.
497
+ */
498
+ static verifyAndDecrypt(wire: DeliveryEnvelopeWireV1, buyerEphemeralPrivKey: Uint8Array, opts: {
499
+ expectedKernelAddress: string;
500
+ expectedChainId: number;
501
+ now?: number;
502
+ }): Promise<{
503
+ ok: true;
504
+ payload: unknown;
505
+ } | {
506
+ ok: false;
507
+ code: string;
508
+ error: string;
509
+ }>;
510
+ /**
511
+ * Compute a stable, cross-SDK identifier for an envelope wire object.
512
+ *
513
+ * The hash is `keccak256(utf8Bytes(canonicalJsonStringify(wire.signed)))`:
514
+ *
515
+ * - canonical JSON (sorted keys, no whitespace) guarantees byte-for-
516
+ * byte identical input across SDK languages,
517
+ * - `keccak256` matches the on-chain hashing convention,
518
+ * - hashing the SIGNED projection (not the full wire) excludes the
519
+ * signature, body, and any `serverMeta` so the hash is stable
520
+ * across relay-side decoration and signature malleability.
521
+ *
522
+ * This is NOT the EIP-712 signing hash; it is a content-addressing
523
+ * helper for logs, dedup sets, and cross-SDK fixtures.
524
+ *
525
+ * @param wire - The wire envelope to hash.
526
+ * @returns 32-byte hex-encoded keccak256 hash (`0x` + 64 hex chars).
527
+ */
528
+ static computeHash(wire: DeliveryEnvelopeWireV1): string;
529
+ }
530
+ export type { BuildEnvelopeResult } from './types';
531
+ //# sourceMappingURL=envelopeBuilder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"envelopeBuilder.d.ts","sourceRoot":"","sources":["../../src/delivery/envelopeBuilder.ts"],"names":[],"mappings":"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"}