@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.
- package/dist/builders/DeliveryProofBuilder.d.ts +224 -13
- package/dist/builders/DeliveryProofBuilder.d.ts.map +1 -1
- package/dist/builders/DeliveryProofBuilder.js +247 -13
- package/dist/builders/DeliveryProofBuilder.js.map +1 -1
- package/dist/cli/agirails.d.ts +85 -1
- package/dist/cli/agirails.d.ts.map +1 -1
- package/dist/cli/agirails.js +429 -154
- package/dist/cli/agirails.js.map +1 -1
- package/dist/cli/commands/init.d.ts +54 -0
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +193 -1
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/receipt.d.ts +70 -2
- package/dist/cli/commands/receipt.d.ts.map +1 -1
- package/dist/cli/commands/receipt.js +218 -3
- package/dist/cli/commands/receipt.js.map +1 -1
- package/dist/cli/commands/test.d.ts +77 -1
- package/dist/cli/commands/test.d.ts.map +1 -1
- package/dist/cli/commands/test.js +264 -2
- package/dist/cli/commands/test.js.map +1 -1
- package/dist/cli/lib/runRequest.d.ts +90 -0
- package/dist/cli/lib/runRequest.d.ts.map +1 -1
- package/dist/cli/lib/runRequest.js +300 -9
- package/dist/cli/lib/runRequest.js.map +1 -1
- package/dist/cli/lib/sentinelReflections.d.ts +111 -0
- package/dist/cli/lib/sentinelReflections.d.ts.map +1 -0
- package/dist/cli/lib/sentinelReflections.js +193 -0
- package/dist/cli/lib/sentinelReflections.js.map +1 -0
- package/dist/delivery/MockDeliveryChannel.d.ts +208 -0
- package/dist/delivery/MockDeliveryChannel.d.ts.map +1 -0
- package/dist/delivery/MockDeliveryChannel.js +445 -0
- package/dist/delivery/MockDeliveryChannel.js.map +1 -0
- package/dist/delivery/RelayDeliveryChannel.d.ts +176 -0
- package/dist/delivery/RelayDeliveryChannel.d.ts.map +1 -0
- package/dist/delivery/RelayDeliveryChannel.js +377 -0
- package/dist/delivery/RelayDeliveryChannel.js.map +1 -0
- package/dist/delivery/channel.d.ts +282 -0
- package/dist/delivery/channel.d.ts.map +1 -0
- package/dist/delivery/channel.js +76 -0
- package/dist/delivery/channel.js.map +1 -0
- package/dist/delivery/channelLog.d.ts +115 -0
- package/dist/delivery/channelLog.d.ts.map +1 -0
- package/dist/delivery/channelLog.js +94 -0
- package/dist/delivery/channelLog.js.map +1 -0
- package/dist/delivery/crypto.d.ts +312 -0
- package/dist/delivery/crypto.d.ts.map +1 -0
- package/dist/delivery/crypto.js +495 -0
- package/dist/delivery/crypto.js.map +1 -0
- package/dist/delivery/eip712.d.ts +248 -0
- package/dist/delivery/eip712.d.ts.map +1 -0
- package/dist/delivery/eip712.js +397 -0
- package/dist/delivery/eip712.js.map +1 -0
- package/dist/delivery/envelopeBuilder.d.ts +531 -0
- package/dist/delivery/envelopeBuilder.d.ts.map +1 -0
- package/dist/delivery/envelopeBuilder.js +832 -0
- package/dist/delivery/envelopeBuilder.js.map +1 -0
- package/dist/delivery/index.d.ts +53 -0
- package/dist/delivery/index.d.ts.map +1 -0
- package/dist/delivery/index.js +143 -0
- package/dist/delivery/index.js.map +1 -0
- package/dist/delivery/keys.d.ts +344 -0
- package/dist/delivery/keys.d.ts.map +1 -0
- package/dist/delivery/keys.js +513 -0
- package/dist/delivery/keys.js.map +1 -0
- package/dist/delivery/nonce-keys.d.ts +93 -0
- package/dist/delivery/nonce-keys.d.ts.map +1 -0
- package/dist/delivery/nonce-keys.js +88 -0
- package/dist/delivery/nonce-keys.js.map +1 -0
- package/dist/delivery/setupBuilder.d.ts +403 -0
- package/dist/delivery/setupBuilder.d.ts.map +1 -0
- package/dist/delivery/setupBuilder.js +554 -0
- package/dist/delivery/setupBuilder.js.map +1 -0
- package/dist/delivery/types.d.ts +722 -0
- package/dist/delivery/types.d.ts.map +1 -0
- package/dist/delivery/types.js +150 -0
- package/dist/delivery/types.js.map +1 -0
- package/dist/delivery/validate.d.ts +288 -0
- package/dist/delivery/validate.d.ts.map +1 -0
- package/dist/delivery/validate.js +648 -0
- package/dist/delivery/validate.js.map +1 -0
- package/dist/level1/Agent.d.ts +130 -0
- package/dist/level1/Agent.d.ts.map +1 -1
- package/dist/level1/Agent.js +248 -0
- package/dist/level1/Agent.js.map +1 -1
- package/dist/level1/types/Options.d.ts +62 -0
- package/dist/level1/types/Options.d.ts.map +1 -1
- package/dist/level1/types/Options.js +22 -0
- package/dist/level1/types/Options.js.map +1 -1
- package/dist/runtime/MockRuntime.d.ts +32 -0
- package/dist/runtime/MockRuntime.d.ts.map +1 -1
- package/dist/runtime/MockRuntime.js +44 -0
- package/dist/runtime/MockRuntime.js.map +1 -1
- package/package.json +6 -1
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* AIP-16 Delivery — Per-Builder Nonce Key Constants
|
|
4
|
+
* ===================================================
|
|
5
|
+
*
|
|
6
|
+
* The AGIRAILS delivery surface (AIP-16 Rev 5) uses two SEPARATE nonce
|
|
7
|
+
* spaces, one for the buyer-signed *setup* message and one for the
|
|
8
|
+
* provider-signed *envelope* message. These are deliberately distinct
|
|
9
|
+
* from the AIP-4 delivery-proof nonce key (`agirails.delivery.v1`) and
|
|
10
|
+
* from each other, so that:
|
|
11
|
+
*
|
|
12
|
+
* 1. A nonce burned for a setup message cannot be replayed as an
|
|
13
|
+
* envelope message (per-builder replay separation).
|
|
14
|
+
* 2. A nonce burned for an AIP-4 delivery proof cannot collide with
|
|
15
|
+
* the AIP-16 setup/envelope nonce spaces (cross-feature isolation).
|
|
16
|
+
* 3. The on-disk persistence file (`.actp/nonces.json`) keeps a
|
|
17
|
+
* clean, auditable per-key monotonic counter.
|
|
18
|
+
*
|
|
19
|
+
* Why per-builder separation matters (audit context):
|
|
20
|
+
* ----------------------------------------------------
|
|
21
|
+
* The existing `NonceManager` (`src/utils/NonceManager.ts`) keys nonces
|
|
22
|
+
* by *message-type string*. There is no central registry of known keys
|
|
23
|
+
* — any string is accepted. This file therefore acts as the canonical,
|
|
24
|
+
* type-safe constant source for AIP-16's two delivery nonce keys, so
|
|
25
|
+
* call sites (setup builder, envelope builder, future replay-cache
|
|
26
|
+
* server) all reach for the SAME literal and the TypeScript `as const`
|
|
27
|
+
* narrowing prevents silent drift.
|
|
28
|
+
*
|
|
29
|
+
* Reuse, NOT replace:
|
|
30
|
+
* -------------------
|
|
31
|
+
* These constants are intended to be passed straight into the existing
|
|
32
|
+
* `NonceManager` API (`getNextNonce`, `getAndIncrementNonce`,
|
|
33
|
+
* `recordNonce`, etc.) — they introduce no new manager, no new storage
|
|
34
|
+
* layer, and no behavioural change. They simply give the delivery layer
|
|
35
|
+
* a single authoritative spelling of its two nonce-key strings.
|
|
36
|
+
*
|
|
37
|
+
* @example Use with the existing nonce manager
|
|
38
|
+
* ```typescript
|
|
39
|
+
* import { createNonceManager } from '../utils/NonceManager';
|
|
40
|
+
* import {
|
|
41
|
+
* DELIVERY_NONCE_KEY_SETUP,
|
|
42
|
+
* DELIVERY_NONCE_KEY_ENVELOPE,
|
|
43
|
+
* } from './nonce-keys';
|
|
44
|
+
*
|
|
45
|
+
* const nonces = createNonceManager({ stateDirectory: process.cwd() });
|
|
46
|
+
*
|
|
47
|
+
* // Buyer setup signing path:
|
|
48
|
+
* const setupNonce = await (nonces as any).getAndIncrementNonce(
|
|
49
|
+
* DELIVERY_NONCE_KEY_SETUP,
|
|
50
|
+
* );
|
|
51
|
+
*
|
|
52
|
+
* // Provider envelope signing path (independent counter):
|
|
53
|
+
* const envelopeNonce = await (nonces as any).getAndIncrementNonce(
|
|
54
|
+
* DELIVERY_NONCE_KEY_ENVELOPE,
|
|
55
|
+
* );
|
|
56
|
+
* ```
|
|
57
|
+
*
|
|
58
|
+
* Reference: AIP-16 Rev 5 §replay-protection, §nonce-spaces
|
|
59
|
+
*
|
|
60
|
+
* @module delivery/nonce-keys
|
|
61
|
+
*/
|
|
62
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
63
|
+
exports.DELIVERY_NONCE_KEY_ENVELOPE = exports.DELIVERY_NONCE_KEY_SETUP = void 0;
|
|
64
|
+
/**
|
|
65
|
+
* Nonce key for buyer-signed AIP-16 delivery *setup* messages.
|
|
66
|
+
*
|
|
67
|
+
* Distinct from {@link DELIVERY_NONCE_KEY_ENVELOPE} (per-builder
|
|
68
|
+
* separation) and from the AIP-4 delivery-proof key
|
|
69
|
+
* `agirails.delivery.v1` (cross-feature separation).
|
|
70
|
+
*
|
|
71
|
+
* The `.v1` suffix matches the EIP-712 domain version for the v1
|
|
72
|
+
* delivery surface; a future v2 would introduce a new key string
|
|
73
|
+
* rather than incrementing in place.
|
|
74
|
+
*/
|
|
75
|
+
exports.DELIVERY_NONCE_KEY_SETUP = 'agirails.delivery.setup.v1';
|
|
76
|
+
/**
|
|
77
|
+
* Nonce key for provider-signed AIP-16 delivery *envelope* messages.
|
|
78
|
+
*
|
|
79
|
+
* Distinct from {@link DELIVERY_NONCE_KEY_SETUP} (per-builder
|
|
80
|
+
* separation) and from the AIP-4 delivery-proof key
|
|
81
|
+
* `agirails.delivery.v1` (cross-feature separation).
|
|
82
|
+
*
|
|
83
|
+
* The `.v1` suffix matches the EIP-712 domain version for the v1
|
|
84
|
+
* delivery surface; a future v2 would introduce a new key string
|
|
85
|
+
* rather than incrementing in place.
|
|
86
|
+
*/
|
|
87
|
+
exports.DELIVERY_NONCE_KEY_ENVELOPE = 'agirails.delivery.envelope.v1';
|
|
88
|
+
//# sourceMappingURL=nonce-keys.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nonce-keys.js","sourceRoot":"","sources":["../../src/delivery/nonce-keys.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2DG;;;AAEH;;;;;;;;;;GAUG;AACU,QAAA,wBAAwB,GAAG,4BAAqC,CAAC;AAE9E;;;;;;;;;;GAUG;AACU,QAAA,2BAA2B,GAAG,+BAAwC,CAAC"}
|
|
@@ -0,0 +1,403 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AIP-16 Delivery Surface — Buyer Setup Builder + Verifier (Phase 2b)
|
|
3
|
+
* =====================================================================
|
|
4
|
+
*
|
|
5
|
+
* Constructs and verifies the buyer-signed `DeliverySetupV1` payload —
|
|
6
|
+
* the first artifact of the AIP-16 Rev 5 delivery surface. The buyer
|
|
7
|
+
* (requester) posts this signed object to the delivery channel after
|
|
8
|
+
* the on-chain transaction reaches `COMMITTED`, declaring:
|
|
9
|
+
*
|
|
10
|
+
* - which kernel + chain the delivery is bound to,
|
|
11
|
+
* - which on-chain identity is acting as the requester,
|
|
12
|
+
* - which EOA produced the signature (smart-wallet two-step auth),
|
|
13
|
+
* - the buyer's ephemeral X25519 pubkey (or canonical-empty for `public`),
|
|
14
|
+
* - which channels the buyer accepts the envelope on,
|
|
15
|
+
* - the privacy posture the buyer expects,
|
|
16
|
+
* - and a creation timestamp + expiry for replay / staleness bounds.
|
|
17
|
+
*
|
|
18
|
+
* ## Builder shape
|
|
19
|
+
*
|
|
20
|
+
* Per the AIP-16 builder convention (and consistent with `QuoteBuilder`,
|
|
21
|
+
* `CounterOfferBuilder`, etc.):
|
|
22
|
+
*
|
|
23
|
+
* - `constructor(signer?, nonceManager?)` — both optional. A signer is
|
|
24
|
+
* REQUIRED for `build()`; `verify()` and `computeHash()` need
|
|
25
|
+
* neither, so verifying SDKs (relays, peer endpoints, dispute
|
|
26
|
+
* workers) can instantiate a no-arg builder.
|
|
27
|
+
*
|
|
28
|
+
* - `build()` is `async` because EIP-712 signing is async on real
|
|
29
|
+
* wallets (`Wallet.signTypedData` returns a `Promise`).
|
|
30
|
+
*
|
|
31
|
+
* - `verify()` and `computeHash()` are `static` — they take a wire
|
|
32
|
+
* object and need no builder state. This mirrors the existing
|
|
33
|
+
* `DeliveryProofBuilder` static-verify pattern.
|
|
34
|
+
*
|
|
35
|
+
* ## Smart-wallet two-step auth (DEC-10 / V2 receipts pattern)
|
|
36
|
+
*
|
|
37
|
+
* `requesterAddress` (the on-chain participant) and `signerAddress`
|
|
38
|
+
* (the EOA that produced the signature) are accepted SEPARATELY and
|
|
39
|
+
* are NOT derived from each other in this layer. When AutoWallet
|
|
40
|
+
* (AIP-12 Tier 1) is active, `requesterAddress` is the Smart Wallet
|
|
41
|
+
* contract and `signerAddress` is the controlling EOA; the SMART-WALLET
|
|
42
|
+
* DERIVATION (`computeSmartWalletFromSigner(signerAddress) ===
|
|
43
|
+
* requesterAddress`) is the SERVER'S responsibility, not the SDK's.
|
|
44
|
+
* Doing it here would silently couple the SDK to the Coinbase Smart
|
|
45
|
+
* Wallet factory ABI and break in cross-vendor flows.
|
|
46
|
+
*
|
|
47
|
+
* What the SDK DOES enforce in `build()` is the cheaper invariant:
|
|
48
|
+
* `signerAddress` MUST equal the address of the supplied `signer`.
|
|
49
|
+
* That catches the most common bug (caller passes the wrong
|
|
50
|
+
* `signerAddress`) without making assumptions about the participant.
|
|
51
|
+
*
|
|
52
|
+
* ## Nonce manager use
|
|
53
|
+
*
|
|
54
|
+
* The signed `DeliverySetupV1` schema has NO `nonce` field — replay
|
|
55
|
+
* binding is provided by `txId` (one tx per setup) and timestamps
|
|
56
|
+
* (`createdAt` / `expiresAt`). The `NonceManager` is still touched
|
|
57
|
+
* here so we have one place to hook future per-builder counters if
|
|
58
|
+
* the spec evolves; we use {@link DELIVERY_NONCE_KEY_SETUP} (distinct
|
|
59
|
+
* from the envelope key and the AIP-4 delivery-proof key) and the
|
|
60
|
+
* returned counter is reported back to the caller via
|
|
61
|
+
* {@link BuildSetupResult.nonceManagerKey} so the caller can audit
|
|
62
|
+
* the path was reached. Because the value is not signed, we tolerate
|
|
63
|
+
* a missing `NonceManager` gracefully — `build()` does NOT throw on
|
|
64
|
+
* undefined `nonceManager`, it simply skips the counter bump.
|
|
65
|
+
*
|
|
66
|
+
* ## Verification order
|
|
67
|
+
*
|
|
68
|
+
* `verify()` is `static` and runs checks in a fixed coarse → fine
|
|
69
|
+
* order, short-circuiting at the first failure with a stable
|
|
70
|
+
* structured code. The order is chosen so that cheap, unambiguous
|
|
71
|
+
* defects are reported BEFORE the more expensive signature recovery,
|
|
72
|
+
* but also so that signature failures are reported before policy
|
|
73
|
+
* failures (timestamp skew, expiry) — a forged signature is a more
|
|
74
|
+
* severe class of error and we want the caller to see it first.
|
|
75
|
+
*
|
|
76
|
+
* @module delivery/setupBuilder
|
|
77
|
+
* @see ./types — signed/wire interfaces and `BuildSetupResult`.
|
|
78
|
+
* @see ./eip712 — domain, types, and `recoverSetupSigner`.
|
|
79
|
+
* @see ./validate — `validateSetupWire` (structural validation).
|
|
80
|
+
* @see ./nonce-keys — `DELIVERY_NONCE_KEY_SETUP`.
|
|
81
|
+
*/
|
|
82
|
+
import { type Signer } from 'ethers';
|
|
83
|
+
import type { NonceManager } from '../utils/NonceManager';
|
|
84
|
+
import { type BuildSetupResult, type DeliveryPrivacy, type DeliverySetupSignedV1, type DeliverySetupWireV1 } from './types';
|
|
85
|
+
/**
|
|
86
|
+
* Default expiry, in seconds, applied when callers omit `expiresInSec`.
|
|
87
|
+
*
|
|
88
|
+
* 3600 (1 hour) matches the negotiation-layer default and is bounded
|
|
89
|
+
* by the relay's accepted-setup TTL. Callers facing high-latency
|
|
90
|
+
* counterparties may pass an explicit larger value, but the relay
|
|
91
|
+
* SHOULD cap at its own policy ceiling.
|
|
92
|
+
*/
|
|
93
|
+
export declare const DEFAULT_SETUP_EXPIRY_SEC = 3600;
|
|
94
|
+
/**
|
|
95
|
+
* Maximum tolerated clock-skew, in seconds, between the signed
|
|
96
|
+
* `createdAt` and the verifier's wall clock. Symmetric (past + future).
|
|
97
|
+
*
|
|
98
|
+
* 900s (15 min) matches the receipts-V2 freshness window and the
|
|
99
|
+
* AIP-3 anchor-receipt skew bound. Tighter would penalize NTP-skewed
|
|
100
|
+
* client machines; looser would meaningfully extend the replay
|
|
101
|
+
* window an attacker has to work with a leaked setup.
|
|
102
|
+
*/
|
|
103
|
+
export declare const SETUP_TIMESTAMP_SKEW_SEC = 900;
|
|
104
|
+
/**
|
|
105
|
+
* Default v1 channel list applied when callers omit `acceptedChannels`.
|
|
106
|
+
*
|
|
107
|
+
* The v1 channel registry has exactly one entry; future channels MUST
|
|
108
|
+
* be added by callers explicitly so that channel-selection is always
|
|
109
|
+
* an intentional choice, not a hidden default.
|
|
110
|
+
*/
|
|
111
|
+
export declare const DEFAULT_ACCEPTED_CHANNELS: readonly string[];
|
|
112
|
+
/**
|
|
113
|
+
* Replace the wall-clock implementation used inside this module.
|
|
114
|
+
*
|
|
115
|
+
* **TEST-ONLY.** Production code MUST NOT call this. The function is
|
|
116
|
+
* exported because Jest spies cannot intercept top-level `let`
|
|
117
|
+
* assignments cleanly across ESM/CJS boundaries; an explicit setter
|
|
118
|
+
* keeps the seam visible and grep-able.
|
|
119
|
+
*
|
|
120
|
+
* Pass `null` (or call {@link resetSecondsNowForTests}) to restore
|
|
121
|
+
* the real wall-clock implementation.
|
|
122
|
+
*
|
|
123
|
+
* @param impl - Replacement function returning Unix seconds, or `null`
|
|
124
|
+
* to restore the default real-clock implementation.
|
|
125
|
+
*
|
|
126
|
+
* @example
|
|
127
|
+
* ```typescript
|
|
128
|
+
* setSecondsNowForTests(() => 1_750_000_000);
|
|
129
|
+
* try {
|
|
130
|
+
* const { wire } = await new DeliverySetupBuilder(wallet).build(params);
|
|
131
|
+
* expect(wire.signed.createdAt).toBe(1_750_000_000);
|
|
132
|
+
* } finally {
|
|
133
|
+
* resetSecondsNowForTests();
|
|
134
|
+
* }
|
|
135
|
+
* ```
|
|
136
|
+
*/
|
|
137
|
+
export declare function setSecondsNowForTests(impl: (() => number) | null): void;
|
|
138
|
+
/**
|
|
139
|
+
* Restore {@link secondsNow} to its default real-clock implementation.
|
|
140
|
+
*
|
|
141
|
+
* **TEST-ONLY.** Called from `afterEach` blocks; safe to call when no
|
|
142
|
+
* override is active.
|
|
143
|
+
*/
|
|
144
|
+
export declare function resetSecondsNowForTests(): void;
|
|
145
|
+
/**
|
|
146
|
+
* Parameters accepted by {@link DeliverySetupBuilder.build}.
|
|
147
|
+
*
|
|
148
|
+
* Every field is explicit — no implicit derivation of one address
|
|
149
|
+
* from another. In particular, `requesterAddress` and `signerAddress`
|
|
150
|
+
* are passed SEPARATELY so the SDK is agnostic to which Smart Wallet
|
|
151
|
+
* factory the caller is using (see DEC-10 / V2 receipts pattern).
|
|
152
|
+
*/
|
|
153
|
+
export interface BuildSetupParams {
|
|
154
|
+
/**
|
|
155
|
+
* On-chain transaction id this setup is bound to.
|
|
156
|
+
* 32-byte hex-encoded value (`0x` + 64 hex chars).
|
|
157
|
+
*/
|
|
158
|
+
txId: `0x${string}`;
|
|
159
|
+
/**
|
|
160
|
+
* EVM chain id (e.g. `8453` for Base mainnet, `84532` for Base Sepolia).
|
|
161
|
+
* Encoded into BOTH the EIP-712 domain and the signed payload.
|
|
162
|
+
*/
|
|
163
|
+
chainId: number;
|
|
164
|
+
/**
|
|
165
|
+
* Address of the ACTP kernel contract on `chainId`. Becomes the
|
|
166
|
+
* EIP-712 `verifyingContract`.
|
|
167
|
+
*/
|
|
168
|
+
kernelAddress: `0x${string}`;
|
|
169
|
+
/**
|
|
170
|
+
* On-chain identity acting as the requester. Smart-wallet flows pass
|
|
171
|
+
* the Smart Wallet address here; non-smart-wallet flows pass the EOA.
|
|
172
|
+
* The SDK does NOT derive this from `signer` — callers must supply it.
|
|
173
|
+
*/
|
|
174
|
+
requesterAddress: `0x${string}`;
|
|
175
|
+
/**
|
|
176
|
+
* EOA address that will produce the signature. MUST equal
|
|
177
|
+
* `await signer.getAddress()` — `build()` enforces this and throws
|
|
178
|
+
* a {@link DeliveryEip712Error} on mismatch.
|
|
179
|
+
*/
|
|
180
|
+
signerAddress: `0x${string}`;
|
|
181
|
+
/**
|
|
182
|
+
* Buyer-side ephemeral X25519 public key as 32-byte hex.
|
|
183
|
+
*
|
|
184
|
+
* For `expectedPrivacy: "encrypted"`: a freshly generated X25519
|
|
185
|
+
* pubkey whose private key is held in memory by the requester
|
|
186
|
+
* (forward secrecy w.r.t. requester long-term keys).
|
|
187
|
+
*
|
|
188
|
+
* For `expectedPrivacy: "public"`: MUST be {@link CANONICAL_EMPTY_BYTES32}.
|
|
189
|
+
* `build()` enforces the canonical-empty rule on this field.
|
|
190
|
+
*/
|
|
191
|
+
buyerEphemeralPubkey: `0x${string}`;
|
|
192
|
+
/**
|
|
193
|
+
* Ordered list of delivery channels the buyer is willing to accept
|
|
194
|
+
* the envelope on. Defaults to {@link DEFAULT_ACCEPTED_CHANNELS}
|
|
195
|
+
* (`["agirails-relay-v1"]`) when omitted.
|
|
196
|
+
*/
|
|
197
|
+
acceptedChannels?: string[];
|
|
198
|
+
/**
|
|
199
|
+
* Privacy posture the buyer expects. The provider MUST select a
|
|
200
|
+
* `DeliveryScheme` consistent with this value.
|
|
201
|
+
*/
|
|
202
|
+
expectedPrivacy: DeliveryPrivacy;
|
|
203
|
+
/**
|
|
204
|
+
* Validity window for this setup, in seconds. Default
|
|
205
|
+
* {@link DEFAULT_SETUP_EXPIRY_SEC} (3600 = 1 hour).
|
|
206
|
+
* `expiresAt` is computed as `createdAt + expiresInSec`.
|
|
207
|
+
*/
|
|
208
|
+
expiresInSec?: number;
|
|
209
|
+
/**
|
|
210
|
+
* Override the `createdAt` timestamp. Defaults to {@link secondsNow}.
|
|
211
|
+
* Tests SHOULD pass an explicit value here for determinism rather
|
|
212
|
+
* than relying on {@link setSecondsNowForTests}; the test-clock
|
|
213
|
+
* setter is for callers that cannot reach into the params object
|
|
214
|
+
* (e.g. higher-level helpers that wrap the builder).
|
|
215
|
+
*/
|
|
216
|
+
createdAt?: number;
|
|
217
|
+
/**
|
|
218
|
+
* CoinbaseSmartWallet factory nonce used to derive `requesterAddress`
|
|
219
|
+
* from `signerAddress`. Defaults to `0` (the first wallet per owner).
|
|
220
|
+
*
|
|
221
|
+
* H4 fix (AIP-16 Phase 3 HIGH): callers whose Smart Wallet was
|
|
222
|
+
* deployed at a non-zero factory nonce MUST pass that nonce here so
|
|
223
|
+
* the server's smart-wallet derivation lands on the correct address.
|
|
224
|
+
* Omitting it (or passing `0`) reproduces the legacy behavior, which
|
|
225
|
+
* is correct for the vast majority of callers (auto-wallet always
|
|
226
|
+
* deploys at nonce=0).
|
|
227
|
+
*
|
|
228
|
+
* Must be a non-negative integer in the `uint256` range; `build()`
|
|
229
|
+
* rejects negative or non-integer values with `BUILDER_INVALID_SMART_WALLET_NONCE`.
|
|
230
|
+
*/
|
|
231
|
+
smartWalletNonce?: number;
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Builder + verifier for AIP-16 delivery setup messages.
|
|
235
|
+
*
|
|
236
|
+
* Instances are cheap to construct and have no I/O side effects.
|
|
237
|
+
* `verify()` and `computeHash()` are static — call them without
|
|
238
|
+
* constructing an instance.
|
|
239
|
+
*
|
|
240
|
+
* @example Buyer signing flow
|
|
241
|
+
* ```typescript
|
|
242
|
+
* const builder = new DeliverySetupBuilder(wallet, nonceManager);
|
|
243
|
+
* const { wire } = await builder.build({
|
|
244
|
+
* txId,
|
|
245
|
+
* chainId: 84532,
|
|
246
|
+
* kernelAddress: KERNEL,
|
|
247
|
+
* requesterAddress: SMART_WALLET,
|
|
248
|
+
* signerAddress: EOA,
|
|
249
|
+
* buyerEphemeralPubkey: '0x' + 'aa'.repeat(32),
|
|
250
|
+
* expectedPrivacy: 'encrypted',
|
|
251
|
+
* });
|
|
252
|
+
* await postToRelay(wire);
|
|
253
|
+
* ```
|
|
254
|
+
*
|
|
255
|
+
* @example Provider verification flow
|
|
256
|
+
* ```typescript
|
|
257
|
+
* const result = DeliverySetupBuilder.verify(wire, {
|
|
258
|
+
* expectedKernelAddress: KERNEL,
|
|
259
|
+
* expectedChainId: 84532,
|
|
260
|
+
* });
|
|
261
|
+
* if (!result.ok) {
|
|
262
|
+
* throw new Error(`Setup verification failed: ${result.code}`);
|
|
263
|
+
* }
|
|
264
|
+
* const setup = result.signed;
|
|
265
|
+
* ```
|
|
266
|
+
*/
|
|
267
|
+
export declare class DeliverySetupBuilder {
|
|
268
|
+
private readonly signer?;
|
|
269
|
+
private readonly nonceManager?;
|
|
270
|
+
/**
|
|
271
|
+
* Construct a new builder.
|
|
272
|
+
*
|
|
273
|
+
* @param signer - EOA signer required for {@link build}. Pass `undefined`
|
|
274
|
+
* to construct a verify-only instance; `verify()` and `computeHash()`
|
|
275
|
+
* are static and do not need a builder instance at all, but a
|
|
276
|
+
* no-arg constructor is supported for symmetry with peer builders.
|
|
277
|
+
* @param nonceManager - Optional nonce manager. The v1 setup schema
|
|
278
|
+
* has no `nonce` field, so this is purely an audit hook today;
|
|
279
|
+
* when supplied, `build()` calls `getNextNonce(DELIVERY_NONCE_KEY_SETUP)`
|
|
280
|
+
* to advance the counter. Missing manager is tolerated.
|
|
281
|
+
*/
|
|
282
|
+
constructor(signer?: Signer, nonceManager?: NonceManager);
|
|
283
|
+
/**
|
|
284
|
+
* Construct, sign, and return a {@link DeliverySetupWireV1}.
|
|
285
|
+
*
|
|
286
|
+
* Pre-checks:
|
|
287
|
+
* - signer MUST be present (throws `BUILDER_NO_SIGNER` otherwise).
|
|
288
|
+
* - `signerAddress` MUST equal `await signer.getAddress()`
|
|
289
|
+
* (throws `BUILDER_SIGNER_ADDRESS_MISMATCH` otherwise).
|
|
290
|
+
* - For `expectedPrivacy: "public"`, `buyerEphemeralPubkey` MUST equal
|
|
291
|
+
* {@link CANONICAL_EMPTY_BYTES32}.
|
|
292
|
+
* - For `expectedPrivacy: "encrypted"`, `buyerEphemeralPubkey` MUST NOT
|
|
293
|
+
* be {@link CANONICAL_EMPTY_BYTES32} (a zero X25519 public key is
|
|
294
|
+
* rejected by RFC 7748 §6.1 anyway, but we surface a clearer error).
|
|
295
|
+
* - `expiresInSec` (when supplied) must be a positive integer.
|
|
296
|
+
*
|
|
297
|
+
* Signing:
|
|
298
|
+
* - Uses `signer.signTypedData(domain, types, signed)` with the
|
|
299
|
+
* canonical delivery EIP-712 domain anchored to `kernelAddress`.
|
|
300
|
+
*
|
|
301
|
+
* Nonce manager:
|
|
302
|
+
* - When supplied, `getNextNonce(DELIVERY_NONCE_KEY_SETUP)` is called
|
|
303
|
+
* purely for audit / future-compat. The returned counter is NOT
|
|
304
|
+
* encoded into the signed payload (the v1 schema has no nonce
|
|
305
|
+
* field) and the caller MAY ignore `nonceManagerKey` in the result.
|
|
306
|
+
*
|
|
307
|
+
* @param params - {@link BuildSetupParams}.
|
|
308
|
+
* @returns A {@link BuildSetupResult} carrying the signed wire object
|
|
309
|
+
* and the nonce-manager key that was touched (always
|
|
310
|
+
* {@link DELIVERY_NONCE_KEY_SETUP} for v1).
|
|
311
|
+
* @throws {DeliveryEip712Error} on signer absence, signer/address
|
|
312
|
+
* mismatch, or canonical-empty rule violation.
|
|
313
|
+
*/
|
|
314
|
+
build(params: BuildSetupParams): Promise<BuildSetupResult>;
|
|
315
|
+
/**
|
|
316
|
+
* Verify a {@link DeliverySetupWireV1} received from the relay.
|
|
317
|
+
*
|
|
318
|
+
* Check order (first failure short-circuits, with a stable code):
|
|
319
|
+
*
|
|
320
|
+
* 1. `validateSetupWire(wire)` — top-level shape + all field-level
|
|
321
|
+
* invariants (positive chainId, valid addresses, bytes32 shape on
|
|
322
|
+
* `buyerEphemeralPubkey`, non-empty acceptedChannels, valid
|
|
323
|
+
* `expectedPrivacy`, positive timestamps, `expiresAt > createdAt`,
|
|
324
|
+
* valid signature shape). On failure: code = `setup_signature_invalid`,
|
|
325
|
+
* error = the validator's identifier.
|
|
326
|
+
*
|
|
327
|
+
* 2. `signed.chainId === expectedChainId` — else `setup_chain_mismatch`.
|
|
328
|
+
*
|
|
329
|
+
* 3. `signed.kernelAddress` (lowercased) === `expectedKernelAddress`
|
|
330
|
+
* (lowercased) — else `setup_kernel_mismatch`. This is the
|
|
331
|
+
* allowlist anchor: callers MUST pass the kernel address they
|
|
332
|
+
* trust on the target chain; passing the payload's own kernel
|
|
333
|
+
* would defeat the allowlist (an attacker could sign under any
|
|
334
|
+
* kernel).
|
|
335
|
+
*
|
|
336
|
+
* 4. `recoverSetupSigner(signed, requesterSig, expectedKernelAddress)`
|
|
337
|
+
* (lowercased) === `signed.signerAddress` (lowercased). NOTE:
|
|
338
|
+
* recovery uses `expectedKernelAddress`, NOT `signed.kernelAddress`
|
|
339
|
+
* — at this point we've already enforced they match in step 3,
|
|
340
|
+
* but using the trusted value defends against future code
|
|
341
|
+
* refactors that might accidentally drop step 3. On failure:
|
|
342
|
+
* `setup_signature_invalid`.
|
|
343
|
+
*
|
|
344
|
+
* 5. Timestamp skew: `|now - createdAt| <= SETUP_TIMESTAMP_SKEW_SEC`
|
|
345
|
+
* — else `setup_timestamp_skew`. Symmetric to catch both
|
|
346
|
+
* past-replays and forward-dated forgeries.
|
|
347
|
+
*
|
|
348
|
+
* 6. Expiry: `expiresAt > now` — else `setup_expired`. Strict `>`
|
|
349
|
+
* (not `>=`) so a setup exactly at its expiry second is
|
|
350
|
+
* considered expired.
|
|
351
|
+
*
|
|
352
|
+
* Smart-wallet equality between `signerAddress` and `requesterAddress`
|
|
353
|
+
* is intentionally NOT performed here — that's the verifier's
|
|
354
|
+
* responsibility (server side, V2 receipts pattern, DEC-10).
|
|
355
|
+
*
|
|
356
|
+
* @param wire - The wire object received from the relay.
|
|
357
|
+
* @param opts.expectedKernelAddress - Trusted kernel address for the
|
|
358
|
+
* target chain (from the verifier's allowlist).
|
|
359
|
+
* @param opts.expectedChainId - Trusted chainId for the target chain.
|
|
360
|
+
* @param opts.now - Override for the verifier's wall clock (Unix
|
|
361
|
+
* seconds). Tests use this to drive timestamp-skew and expiry paths
|
|
362
|
+
* deterministically; production callers SHOULD omit it.
|
|
363
|
+
* @returns `{ ok: true, signed }` on success, `{ ok: false, code, error }`
|
|
364
|
+
* on failure.
|
|
365
|
+
*/
|
|
366
|
+
static verify(wire: DeliverySetupWireV1, opts: {
|
|
367
|
+
expectedKernelAddress: string;
|
|
368
|
+
expectedChainId: number;
|
|
369
|
+
now?: number;
|
|
370
|
+
}): {
|
|
371
|
+
ok: true;
|
|
372
|
+
signed: DeliverySetupSignedV1;
|
|
373
|
+
} | {
|
|
374
|
+
ok: false;
|
|
375
|
+
code: string;
|
|
376
|
+
error: string;
|
|
377
|
+
};
|
|
378
|
+
/**
|
|
379
|
+
* Compute a stable, cross-SDK identifier for a setup wire object.
|
|
380
|
+
*
|
|
381
|
+
* The hash is `keccak256(utf8Bytes(canonicalJsonStringify(wire.signed)))`:
|
|
382
|
+
*
|
|
383
|
+
* - canonical JSON (sorted keys, no whitespace) guarantees
|
|
384
|
+
* byte-for-byte identical input across SDK languages,
|
|
385
|
+
* - `keccak256` matches the on-chain hashing convention,
|
|
386
|
+
* - hashing the SIGNED projection (not the full wire) excludes the
|
|
387
|
+
* signature and any `serverMeta` so the hash is stable across
|
|
388
|
+
* relay-side decoration. The signature is recoverable from the
|
|
389
|
+
* signed bytes; including it in the hash would make the hash
|
|
390
|
+
* depend on signature malleability.
|
|
391
|
+
*
|
|
392
|
+
* This is not part of the EIP-712 signature path — it is purely a
|
|
393
|
+
* content-addressing helper for logs, dedup sets, and cross-SDK
|
|
394
|
+
* test fixtures. The EIP-712 hash (the one the wallet signs) is
|
|
395
|
+
* computed by ethers internally and is NOT exposed here.
|
|
396
|
+
*
|
|
397
|
+
* @param wire - The wire object to hash.
|
|
398
|
+
* @returns 32-byte hex-encoded keccak256 hash (`0x` + 64 hex chars).
|
|
399
|
+
*/
|
|
400
|
+
static computeHash(wire: DeliverySetupWireV1): string;
|
|
401
|
+
}
|
|
402
|
+
export type { BuildSetupResult } from './types';
|
|
403
|
+
//# sourceMappingURL=setupBuilder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setupBuilder.d.ts","sourceRoot":"","sources":["../../src/delivery/setupBuilder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgFG;AAEH,OAAO,EAIL,KAAK,MAAM,EACZ,MAAM,QAAQ,CAAC;AAGhB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAS1D,OAAO,EAEL,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,EACzB,MAAM,SAAS,CAAC;AAOjB;;;;;;;GAOG;AACH,eAAO,MAAM,wBAAwB,OAAO,CAAC;AAE7C;;;;;;;;GAQG;AACH,eAAO,MAAM,wBAAwB,MAAM,CAAC;AAE5C;;;;;;GAMG;AACH,eAAO,MAAM,yBAAyB,EAAE,SAAS,MAAM,EAE7C,CAAC;AA2CX;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,CAAC,MAAM,MAAM,CAAC,GAAG,IAAI,GAAG,IAAI,CAMvE;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,IAAI,IAAI,CAE9C;AAMD;;;;;;;GAOG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,IAAI,EAAE,KAAK,MAAM,EAAE,CAAC;IAEpB;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB;;;OAGG;IACH,aAAa,EAAE,KAAK,MAAM,EAAE,CAAC;IAE7B;;;;OAIG;IACH,gBAAgB,EAAE,KAAK,MAAM,EAAE,CAAC;IAEhC;;;;OAIG;IACH,aAAa,EAAE,KAAK,MAAM,EAAE,CAAC;IAE7B;;;;;;;;;OASG;IACH,oBAAoB,EAAE,KAAK,MAAM,EAAE,CAAC;IAEpC;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAE5B;;;OAGG;IACH,eAAe,EAAE,eAAe,CAAC;IAEjC;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;;;;;;;;;;;OAaG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAe;IAE7C;;;;;;;;;;;OAWG;gBACS,MAAM,CAAC,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,YAAY;IASxD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA8BG;IACG,KAAK,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAkJhE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAkDG;IACH,MAAM,CAAC,MAAM,CACX,IAAI,EAAE,mBAAmB,EACzB,IAAI,EAAE;QACJ,qBAAqB,EAAE,MAAM,CAAC;QAC9B,eAAe,EAAE,MAAM,CAAC;QACxB,GAAG,CAAC,EAAE,MAAM,CAAC;KACd,GAEC;QAAE,EAAE,EAAE,IAAI,CAAC;QAAC,MAAM,EAAE,qBAAqB,CAAA;KAAE,GAC3C;QAAE,EAAE,EAAE,KAAK,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE;IA4F9C;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE,mBAAmB,GAAG,MAAM;CAGtD;AAWD,YAAY,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC"}
|