@shroud-fi/agent-runtime 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +71 -0
  3. package/dist/cjs/agent.d.ts +235 -0
  4. package/dist/cjs/agent.d.ts.map +1 -0
  5. package/dist/cjs/agent.js +594 -0
  6. package/dist/cjs/agent.js.map +1 -0
  7. package/dist/cjs/browser.d.ts +38 -0
  8. package/dist/cjs/browser.d.ts.map +1 -0
  9. package/dist/cjs/browser.js +94 -0
  10. package/dist/cjs/browser.js.map +1 -0
  11. package/dist/cjs/constants.d.ts +17 -0
  12. package/dist/cjs/constants.d.ts.map +1 -0
  13. package/dist/cjs/constants.js +20 -0
  14. package/dist/cjs/constants.js.map +1 -0
  15. package/dist/cjs/errors.d.ts +107 -0
  16. package/dist/cjs/errors.d.ts.map +1 -0
  17. package/dist/cjs/errors.js +152 -0
  18. package/dist/cjs/errors.js.map +1 -0
  19. package/dist/cjs/factory.d.ts +19 -0
  20. package/dist/cjs/factory.d.ts.map +1 -0
  21. package/dist/cjs/factory.js +46 -0
  22. package/dist/cjs/factory.js.map +1 -0
  23. package/dist/cjs/index.d.ts +6 -0
  24. package/dist/cjs/index.d.ts.map +1 -0
  25. package/dist/cjs/index.js +37 -0
  26. package/dist/cjs/index.js.map +1 -0
  27. package/dist/cjs/package.json +1 -0
  28. package/dist/cjs/types.d.ts +151 -0
  29. package/dist/cjs/types.d.ts.map +1 -0
  30. package/dist/cjs/types.js +10 -0
  31. package/dist/cjs/types.js.map +1 -0
  32. package/dist/esm/agent.d.ts +235 -0
  33. package/dist/esm/agent.d.ts.map +1 -0
  34. package/dist/esm/agent.js +557 -0
  35. package/dist/esm/agent.js.map +1 -0
  36. package/dist/esm/browser.d.ts +38 -0
  37. package/dist/esm/browser.d.ts.map +1 -0
  38. package/dist/esm/browser.js +87 -0
  39. package/dist/esm/browser.js.map +1 -0
  40. package/dist/esm/constants.d.ts +17 -0
  41. package/dist/esm/constants.d.ts.map +1 -0
  42. package/dist/esm/constants.js +17 -0
  43. package/dist/esm/constants.js.map +1 -0
  44. package/dist/esm/errors.d.ts +107 -0
  45. package/dist/esm/errors.d.ts.map +1 -0
  46. package/dist/esm/errors.js +137 -0
  47. package/dist/esm/errors.js.map +1 -0
  48. package/dist/esm/factory.d.ts +19 -0
  49. package/dist/esm/factory.d.ts.map +1 -0
  50. package/dist/esm/factory.js +43 -0
  51. package/dist/esm/factory.js.map +1 -0
  52. package/dist/esm/index.d.ts +6 -0
  53. package/dist/esm/index.d.ts.map +1 -0
  54. package/dist/esm/index.js +16 -0
  55. package/dist/esm/index.js.map +1 -0
  56. package/dist/esm/types.d.ts +151 -0
  57. package/dist/esm/types.d.ts.map +1 -0
  58. package/dist/esm/types.js +9 -0
  59. package/dist/esm/types.js.map +1 -0
  60. package/dist/tsconfig.cjs.tsbuildinfo +1 -0
  61. package/dist/tsconfig.esm.tsbuildinfo +1 -0
  62. package/dist/tsconfig.tsbuildinfo +1 -0
  63. package/package.json +72 -0
@@ -0,0 +1,594 @@
1
+ "use strict";
2
+ /**
3
+ * ShroudAgent — the ergonomic runtime that composes core + payments + scanning
4
+ * + transport into a single class.
5
+ *
6
+ * Privacy invariants (binding — code-reviewer will check):
7
+ * - No console.* anywhere in this file.
8
+ * - No JSON.stringify of keys, identity, detection, signature, or masterSeed.
9
+ * - No key bytes / signature bytes in error messages.
10
+ * - No amount values in error messages.
11
+ * - The spend key never leaves runtime; the scanning module needs it for
12
+ * ECDH derivation only.
13
+ */
14
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
15
+ if (k2 === undefined) k2 = k;
16
+ var desc = Object.getOwnPropertyDescriptor(m, k);
17
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
18
+ desc = { enumerable: true, get: function() { return m[k]; } };
19
+ }
20
+ Object.defineProperty(o, k2, desc);
21
+ }) : (function(o, m, k, k2) {
22
+ if (k2 === undefined) k2 = k;
23
+ o[k2] = m[k];
24
+ }));
25
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
26
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
27
+ }) : function(o, v) {
28
+ o["default"] = v;
29
+ });
30
+ var __importStar = (this && this.__importStar) || (function () {
31
+ var ownKeys = function(o) {
32
+ ownKeys = Object.getOwnPropertyNames || function (o) {
33
+ var ar = [];
34
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
35
+ return ar;
36
+ };
37
+ return ownKeys(o);
38
+ };
39
+ return function (mod) {
40
+ if (mod && mod.__esModule) return mod;
41
+ var result = {};
42
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
43
+ __setModuleDefault(result, mod);
44
+ return result;
45
+ };
46
+ })();
47
+ Object.defineProperty(exports, "__esModule", { value: true });
48
+ exports.ShroudAgent = void 0;
49
+ const viem_1 = require("viem");
50
+ const core_1 = require("@shroud-fi/core");
51
+ const payments_1 = require("@shroud-fi/payments");
52
+ const scanning_1 = require("@shroud-fi/scanning");
53
+ const transport_1 = require("@shroud-fi/transport");
54
+ const errors_js_1 = require("./errors.js");
55
+ /**
56
+ * ETH zero-address sentinel — some callers may pass this to indicate "ETH" on
57
+ * the sweep dispatch. Kept beside the canonical ETH_SENTINEL constant.
58
+ */
59
+ const ZERO_ADDRESS_ETH = '0x0000000000000000000000000000000000000000';
60
+ /**
61
+ * The ShroudAgent class. Wraps an EIP-5564 identity + the four ShroudFi
62
+ * packages behind a single ergonomic surface.
63
+ *
64
+ * Constructor is exported but typically reached through `createShroudAgent` or
65
+ * `createShroudAgentFromBrowserWallet`. Direct construction is supported for
66
+ * tests that need to inject a mock scanner backend.
67
+ */
68
+ class ShroudAgent {
69
+ identity;
70
+ metaAddress;
71
+ metaAddressEncoded;
72
+ transport;
73
+ stealthContract;
74
+ finality;
75
+ startBlock;
76
+ announcer;
77
+ backendOverride;
78
+ autoRegister;
79
+ scanner;
80
+ isStarted = false;
81
+ controller;
82
+ constructor(opts) {
83
+ this.identity = opts.identity;
84
+ this.metaAddress = opts.identity.metaAddress;
85
+ this.metaAddressEncoded = (0, core_1.encodeMetaAddress)(opts.identity.metaAddress);
86
+ this.transport = opts.transport;
87
+ this.stealthContract = opts.stealthContract;
88
+ this.startBlock = opts.startBlock;
89
+ this.finality = opts.finality ?? 'safe';
90
+ this.announcer = opts.announcer;
91
+ this.backendOverride = opts.backend;
92
+ this.autoRegister = opts.autoRegister ?? false;
93
+ // Scanner is built lazily in start() — see H8 in docs/debug/P4-STEP3-STALL.md.
94
+ // Reusing one Scanner across start/stop/start cycles silently dropped events
95
+ // because Scanner.close() permanently sets its `closed` flag.
96
+ }
97
+ /**
98
+ * Build a fresh Scanner with this agent's config. Called from start() so
99
+ * each lifecycle gets its own scanner instance (a closed scanner can't be
100
+ * reopened — see H8).
101
+ */
102
+ buildScanner() {
103
+ return (0, scanning_1.createScanner)({
104
+ transport: this.transport,
105
+ scanningKey: this.identity.keys.scanningKey,
106
+ spendingKey: this.identity.keys.spendingKey,
107
+ startBlock: this.startBlock,
108
+ finality: this.finality,
109
+ ...(this.announcer !== undefined ? { contractAddress: this.announcer } : {}),
110
+ ...(this.backendOverride !== undefined ? { backend: this.backendOverride } : {}),
111
+ });
112
+ }
113
+ /**
114
+ * Start receiving detected payments.
115
+ *
116
+ * Returns an AsyncIterable; consumer drives via `for await`. If
117
+ * `opts.backfillFrom` is set, the first phase yields scanRange results,
118
+ * then transitions to live watch().
119
+ *
120
+ * @throws AgentAlreadyStartedError if called twice without stop().
121
+ */
122
+ start(opts) {
123
+ if (this.isStarted) {
124
+ throw new errors_js_1.AgentAlreadyStartedError();
125
+ }
126
+ this.isStarted = true;
127
+ const controller = new AbortController();
128
+ this.controller = controller;
129
+ // Forward external signal to internal controller.
130
+ const externalSignal = opts?.signal;
131
+ if (externalSignal !== undefined) {
132
+ if (externalSignal.aborted) {
133
+ controller.abort();
134
+ }
135
+ else {
136
+ externalSignal.addEventListener('abort', () => controller.abort(), { once: true });
137
+ }
138
+ }
139
+ // Build a fresh scanner for THIS start() cycle. Reusing the same scanner
140
+ // across start/stop/start would silently drop events because Scanner.close()
141
+ // sets a permanent `closed` flag inside detector.ts. See H8.
142
+ const scanner = this.buildScanner();
143
+ this.scanner = scanner;
144
+ const finality = this.finality;
145
+ const transport = this.transport;
146
+ const backfillFrom = opts?.backfillFrom;
147
+ const resetStarted = () => {
148
+ this.isStarted = false;
149
+ };
150
+ // EAGERLY open the live watch subscription before this method returns.
151
+ // `scanner.watch()` is lazy — the backend.watchAnnouncements registration
152
+ // only fires when [Symbol.asyncIterator]() is called. If we left this to
153
+ // the generator body below (which runs on first iter.next()), a caller
154
+ // pattern like:
155
+ // const iter = agent.start();
156
+ // await agent.send(...) // tx mines before we subscribe
157
+ // for await (const d of iter) ... // never sees the event
158
+ // would race and miss the announcement. Subscribing here closes the gap.
159
+ const watchIterator = scanner.watch(controller.signal)[Symbol.asyncIterator]();
160
+ return {
161
+ [Symbol.asyncIterator]: async function* () {
162
+ try {
163
+ if (backfillFrom !== undefined) {
164
+ // Determine the latest block we can backfill to. The tag mirrors
165
+ // the configured finality so unfinalized history is not yielded
166
+ // for 'safe' / 'finalized' callers. 'unsafe' callers (and chains
167
+ // that don't track 'safe'/'finalized' — e.g. Anvil) use 'latest'
168
+ // so the backfill reaches the actual head.
169
+ const tag = finality === 'finalized'
170
+ ? 'finalized'
171
+ : finality === 'safe'
172
+ ? 'safe'
173
+ : 'latest';
174
+ const latestBlock = await transport.publicClient.getBlock({
175
+ blockTag: tag,
176
+ });
177
+ const latestSafe = latestBlock.number ?? backfillFrom;
178
+ if (latestSafe >= backfillFrom) {
179
+ for await (const detection of scanner.scanRange(backfillFrom, latestSafe, controller.signal)) {
180
+ if (controller.signal.aborted)
181
+ return;
182
+ yield detection;
183
+ }
184
+ }
185
+ }
186
+ // Drain the live watch iterator we eagerly opened above.
187
+ while (true) {
188
+ if (controller.signal.aborted)
189
+ return;
190
+ const r = await watchIterator.next();
191
+ if (r.done)
192
+ return;
193
+ yield r.value;
194
+ }
195
+ }
196
+ finally {
197
+ // Tear down the eagerly-opened watch iterator so scanner.watchActive
198
+ // resets and a follow-up start() can resubscribe.
199
+ try {
200
+ await watchIterator.return?.({
201
+ value: undefined,
202
+ done: true,
203
+ });
204
+ }
205
+ catch {
206
+ // close path must never throw out of finally.
207
+ }
208
+ resetStarted();
209
+ }
210
+ },
211
+ };
212
+ }
213
+ /**
214
+ * Stop the agent. Aborts the internal signal, closes the current scanner,
215
+ * and clears the reference so the next start() builds a fresh one.
216
+ * Idempotent — safe to call multiple times or before start().
217
+ */
218
+ stop() {
219
+ if (this.controller !== undefined) {
220
+ try {
221
+ this.controller.abort();
222
+ }
223
+ catch {
224
+ // Swallow — stop must not throw.
225
+ }
226
+ this.controller = undefined;
227
+ }
228
+ if (this.scanner !== undefined) {
229
+ try {
230
+ this.scanner.close();
231
+ }
232
+ catch {
233
+ // Swallow — stop must not throw.
234
+ }
235
+ this.scanner = undefined;
236
+ }
237
+ this.isStarted = false;
238
+ }
239
+ /**
240
+ * Send native ETH to a recipient stealth meta-address.
241
+ *
242
+ * Accepts either a parsed StealthMetaAddress or the encoded string form
243
+ * (`st:base:0x...`). String form is decoded via decodeMetaAddress before use.
244
+ */
245
+ async send(to, valueWei) {
246
+ const meta = typeof to === 'string' ? (0, core_1.decodeMetaAddress)(to) : to;
247
+ return (0, payments_1.sendETHPayment)(this.transport, this.stealthContract, meta, valueWei);
248
+ }
249
+ /**
250
+ * Send an ERC-20 token to a recipient stealth meta-address.
251
+ *
252
+ * Caller MUST have already approved the stealth contract to spend the token
253
+ * — v1 does not include an approve flow.
254
+ */
255
+ async sendERC20(to, token, amount) {
256
+ const meta = typeof to === 'string' ? (0, core_1.decodeMetaAddress)(to) : to;
257
+ return (0, payments_1.sendERC20Payment)(this.transport, this.stealthContract, meta, token, amount);
258
+ }
259
+ /**
260
+ * M3 — read the canonical ERC-6538 registry and return whether the agent's
261
+ * registrant wallet has a non-empty stealth meta-address on file for
262
+ * scheme 1 (the ShroudFi default).
263
+ *
264
+ * The registrant is keyed by `transport.walletClient.account.address` —
265
+ * the EOA that would sign the `registerKeys` transaction. Read-only
266
+ * transports (no walletClient or no account) cannot be registered and
267
+ * therefore return `false`.
268
+ *
269
+ * No side effects, no gas. Safe to call before every send.
270
+ */
271
+ async isRegistered() {
272
+ const walletClient = this.transport.walletClient;
273
+ if (walletClient === undefined)
274
+ return false;
275
+ const account = walletClient.account;
276
+ if (account === undefined)
277
+ return false;
278
+ const registrant = account.address;
279
+ const raw = (await this.transport.publicClient.readContract({
280
+ address: transport_1.ERC6538_REGISTRY,
281
+ abi: transport_1.ERC6538RegistryAbi,
282
+ functionName: 'stealthMetaAddressOf',
283
+ args: [registrant, REGISTRY_SCHEME_ID],
284
+ }));
285
+ // viem returns '0x' for empty bytes. Anything longer is a registration.
286
+ return raw !== '0x' && raw.length > 2;
287
+ }
288
+ /**
289
+ * M3 — publish the agent's stealth meta-address (33-byte spending pubkey
290
+ * concatenated with 33-byte viewing pubkey) into the canonical ERC-6538
291
+ * registry under scheme 1.
292
+ *
293
+ * Throws `AlreadyRegisteredError` if the registrant wallet already has a
294
+ * non-empty entry. Throws `RegistrationRequiresWalletError` if the
295
+ * transport has no walletClient with an account.
296
+ *
297
+ * Privacy: only the agent's PUBLIC keys cross the wire (these are the
298
+ * same bytes that already live in `metaAddressEncoded`). The spending
299
+ * private key is never touched by this path.
300
+ *
301
+ * @returns the transaction hash of the `registerKeys` call.
302
+ */
303
+ async register() {
304
+ const walletClient = this.transport.walletClient;
305
+ if (walletClient === undefined) {
306
+ throw new errors_js_1.RegistrationRequiresWalletError();
307
+ }
308
+ const account = walletClient.account;
309
+ if (account === undefined) {
310
+ throw new errors_js_1.RegistrationRequiresWalletError();
311
+ }
312
+ // Fail fast if already registered. This both saves the operator a gas
313
+ // payment and keeps `register()` honest: the only way to overwrite an
314
+ // existing entry on the canonical registry is to bump the per-scheme
315
+ // nonce, which is out of scope for v1.
316
+ if (await this.isRegistered()) {
317
+ throw new errors_js_1.AlreadyRegisteredError();
318
+ }
319
+ // Build the 66-byte payload: 33 spending pubkey || 33 viewing pubkey.
320
+ // The registrar contract layout is confirmed by
321
+ // contracts/src/ShroudFiRegistrar.sol (each pubkey is a compressed
322
+ // secp256k1 point — 33 bytes, prefix 0x02 / 0x03).
323
+ const payload = (0, viem_1.concatBytes)([
324
+ this.metaAddress.spendingPubKey,
325
+ this.metaAddress.viewingPubKey,
326
+ ]);
327
+ const stealthMetaAddress = (0, viem_1.bytesToHex)(payload);
328
+ const writeArgs = {
329
+ address: transport_1.ERC6538_REGISTRY,
330
+ abi: transport_1.ERC6538RegistryAbi,
331
+ functionName: 'registerKeys',
332
+ args: [REGISTRY_SCHEME_ID, stealthMetaAddress],
333
+ account,
334
+ chain: this.transport.chain,
335
+ };
336
+ // viem's writeContract has a complex union signature — cast at the
337
+ // boundary, mirroring the pattern used in @shroud-fi/payments.
338
+ const txHash = (await walletClient.writeContract(writeArgs));
339
+ return txHash;
340
+ }
341
+ /**
342
+ * M3 — composite, idempotent registration helper.
343
+ *
344
+ * Returns `{ registered: false }` if the agent is already registered
345
+ * (no tx broadcast). Otherwise returns `{ registered: true, txHash }`
346
+ * with the registration tx hash.
347
+ *
348
+ * Safe to call before every send — the check is a single eth_call.
349
+ */
350
+ async ensureRegistered() {
351
+ if (await this.isRegistered()) {
352
+ return { registered: false };
353
+ }
354
+ const txHash = await this.register();
355
+ return { registered: true, txHash };
356
+ }
357
+ /**
358
+ * M4 — ergonomic helper: pay an EVM wallet by its plain address, no
359
+ * meta-address handling on the caller side.
360
+ *
361
+ * Delegates to `sendToWallet` from `@shroud-fi/payments` which does the
362
+ * ERC-6538 registry lookup, decodes the recipient's stealth meta-address,
363
+ * and dispatches `sendETHPayment` or `sendERC20Payment` as appropriate.
364
+ *
365
+ * If the agent was constructed with `autoRegister: true`, this method
366
+ * calls `ensureRegistered` BEFORE dispatching the payment so the agent
367
+ * itself becomes reachable as a stealth-payment recipient the first time
368
+ * it pays someone. A failure inside `ensureRegistered` is wrapped in
369
+ * `AutoRegistrationFailedError` so callers can distinguish setup failures
370
+ * from payment failures via the `cause` chain.
371
+ *
372
+ * Privacy: the recipient wallet address never appears in error messages
373
+ * — `RecipientNotOnboardedError.wallet` exposes it on a structured field
374
+ * for callers that need to show a UI hint.
375
+ */
376
+ async sendToWallet(recipientWallet, asset, amount, options) {
377
+ if (this.autoRegister) {
378
+ try {
379
+ await this.ensureRegistered();
380
+ }
381
+ catch (err) {
382
+ // Preserve the underlying cause so callers can introspect (e.g.,
383
+ // tell apart a missing walletClient from an RPC error). The wrapper
384
+ // message itself is privacy-safe — see AutoRegistrationFailedError.
385
+ throw new errors_js_1.AutoRegistrationFailedError(err);
386
+ }
387
+ }
388
+ return (0, payments_1.sendToWallet)(this.transport, recipientWallet, asset, amount, options);
389
+ }
390
+ /**
391
+ * Sweep funds from a detected stealth address to a destination.
392
+ *
393
+ * If `opts.token` is undefined or matches the ETH sentinel (or zero address)
394
+ * the agent dispatches to sweepETH; otherwise it dispatches to sweepERC20
395
+ * with the given token.
396
+ *
397
+ * Direct sweep (the default path) requires the stealth address to hold
398
+ * enough ETH to pay its own gas. When the stealth holds zero ETH set
399
+ * `opts.viaRelayer = true`:
400
+ * - ERC-20 → routed to {@link sweepViaRelayer} (Gelato or self-host).
401
+ * - ETH → routed to {@link sweepEthViaRelayer} via EIP-7702 (P5.1).
402
+ * Requires `opts.ethRelayerOptions.selfHostEndpoint` since there's no
403
+ * third-party fallback for the 7702 path.
404
+ */
405
+ async sweep(detection, destination, opts) {
406
+ const token = opts?.token;
407
+ const isEth = token === undefined ||
408
+ token === ZERO_ADDRESS_ETH ||
409
+ token.toLowerCase() === payments_1.ETH_SENTINEL.toLowerCase();
410
+ if (opts?.viaRelayer === true) {
411
+ if (isEth) {
412
+ if (opts.ethRelayerOptions === undefined) {
413
+ throw new errors_js_1.EthRelayerEndpointRequiredError();
414
+ }
415
+ return this.sweepEthViaRelayer(detection, destination, {
416
+ ...(opts.ethRelayerContract !== undefined
417
+ ? { ethRelayerContract: opts.ethRelayerContract }
418
+ : {}),
419
+ relayerOptions: opts.ethRelayerOptions,
420
+ });
421
+ }
422
+ return this.sweepViaRelayer(detection, destination, {
423
+ token,
424
+ ...(opts.relayerContract !== undefined ? { relayerContract: opts.relayerContract } : {}),
425
+ ...(opts.relayerOptions !== undefined ? { relayerOptions: opts.relayerOptions } : {}),
426
+ });
427
+ }
428
+ if (isEth) {
429
+ const swept = await (0, payments_1.sweepETH)(this.transport, detection.stealthPrivateKey, destination);
430
+ return { swept, detection };
431
+ }
432
+ const swept = await (0, payments_1.sweepERC20)(this.transport, detection.stealthPrivateKey, token, destination);
433
+ return { swept, detection };
434
+ }
435
+ /**
436
+ * Gasless ERC-20 sweep via the ShroudFiRelayer + Gelato 1Balance.
437
+ *
438
+ * Lazy-imports `@shroud-fi/relayer` so the agent-runtime bundle stays small
439
+ * for callers that never use the relayer path. The Gelato SDK + axios + ws
440
+ * deps only land in the bundle when this method is actually called.
441
+ *
442
+ * Relayer contract resolution order:
443
+ * 1. `opts.relayerContract` if provided
444
+ * 2. `getRelayer(transport.chain.id)` lookup from `@shroud-fi/transport`
445
+ * 3. Throw `RelayerContractNotConfiguredError`
446
+ *
447
+ * @throws RelayerContractNotConfiguredError if no relayer is resolvable.
448
+ * @throws RelayerNotAvailableForETHError if the agent itself ever invokes
449
+ * this with an ETH-like token (the dispatch in `sweep()` already
450
+ * guards, this guards direct callers too).
451
+ */
452
+ async sweepViaRelayer(detection, destination, opts) {
453
+ const { token } = opts;
454
+ const isEth = token === ZERO_ADDRESS_ETH ||
455
+ token.toLowerCase() === payments_1.ETH_SENTINEL.toLowerCase();
456
+ if (isEth) {
457
+ // Direct callers asking for ERC-20 relayer with the ETH sentinel need
458
+ // to use sweepEthViaRelayer instead.
459
+ throw new errors_js_1.EthRelayerEndpointRequiredError();
460
+ }
461
+ const chainId = this.transport.chain.id;
462
+ const relayerContract = opts.relayerContract ?? (0, transport_1.getRelayer)(chainId);
463
+ if (relayerContract === undefined) {
464
+ throw new errors_js_1.RelayerContractNotConfiguredError();
465
+ }
466
+ // Lazy dynamic import — keeps the agent-runtime ESM bundle small for
467
+ // consumers that never call sweepViaRelayer. The Gelato SDK + transitive
468
+ // deps (axios, ws, isomorphic-ws) only enter the bundle on demand.
469
+ const relayerMod = await Promise.resolve().then(() => __importStar(require('@shroud-fi/relayer')));
470
+ // Self-host path: skip Gelato. Sign the permit locally, POST the request
471
+ // to the operator-controlled relayer service, return a receipt shaped
472
+ // like the Gelato one.
473
+ const selfHostEndpoint = opts.relayerOptions?.selfHostEndpoint;
474
+ if (typeof selfHostEndpoint === 'string' && selfHostEndpoint.length > 0) {
475
+ const swept = await this.sweepViaSelfHost(relayerMod.signEip2612Permit, detection, destination, token, relayerContract, selfHostEndpoint, opts.relayerOptions);
476
+ return { swept, detection };
477
+ }
478
+ const swept = await relayerMod.relayedSweepERC20(this.transport, detection.stealthPrivateKey, token, destination, relayerContract, opts.relayerOptions);
479
+ return { swept, detection };
480
+ }
481
+ /**
482
+ * Self-host dispatch: sign the EIP-2612 permit, POST to the operator's
483
+ * service, return a Gelato-shaped receipt.
484
+ *
485
+ * Privacy: only the (public) permit signature + stealth address + token
486
+ * + destination cross the wire. The stealth private key never leaves the
487
+ * client.
488
+ */
489
+ async sweepViaSelfHost(signEip2612Permit, detection, destination, token, relayerContract, endpoint, options) {
490
+ // 1. Read the stealth balance.
491
+ const stealthAddress = detection.stealthAddress;
492
+ const balance = (await this.transport.publicClient.readContract({
493
+ address: token,
494
+ abi: BALANCE_OF_ABI,
495
+ functionName: 'balanceOf',
496
+ args: [stealthAddress],
497
+ }));
498
+ // 2. Compute the permit deadline.
499
+ const lifetime = options?.deadlineSecs ?? 1800n;
500
+ const latestBlock = await this.transport.publicClient.getBlock();
501
+ const deadline = latestBlock.timestamp + lifetime;
502
+ // 3. Sign the permit (the only place the stealth private key is consumed).
503
+ const permit = await signEip2612Permit(this.transport, detection.stealthPrivateKey, token, relayerContract, balance, deadline);
504
+ // 4. POST to the self-host service.
505
+ const body = {
506
+ token,
507
+ destination,
508
+ stealthAddress,
509
+ deadline: permit.deadline.toString(),
510
+ v: permit.v,
511
+ r: permit.r,
512
+ s: permit.s,
513
+ };
514
+ const fetchInit = {
515
+ method: 'POST',
516
+ headers: { 'content-type': 'application/json' },
517
+ body: JSON.stringify(body),
518
+ };
519
+ if (options?.signal !== undefined) {
520
+ fetchInit.signal = options.signal;
521
+ }
522
+ const response = await fetch(`${endpoint.replace(/\/$/, '')}/relay`, fetchInit);
523
+ const json = (await response.json());
524
+ if (!json.ok) {
525
+ throw new Error(json.error);
526
+ }
527
+ return {
528
+ taskId: `self-host:${json.txHash}`,
529
+ txHash: json.txHash,
530
+ status: 'success',
531
+ relayerContract,
532
+ token,
533
+ destination,
534
+ blockNumber: BigInt(json.blockNumber),
535
+ };
536
+ }
537
+ /**
538
+ * P5.1 — gasless ETH sweep via EIP-7702 + self-host relayer service.
539
+ *
540
+ * Dispatch order for the ShroudFiEthRelayer contract address:
541
+ * 1. `opts.ethRelayerContract` if provided
542
+ * 2. `getEthRelayer(transport.chain.id)` lookup
543
+ * 3. Throw EthRelayerContractNotConfiguredError
544
+ *
545
+ * Lazy-imports @shroud-fi/relayer so the agent-runtime bundle stays small
546
+ * for callers that never touch the gasless path.
547
+ *
548
+ * @throws EthRelayerContractNotConfiguredError if no contract is resolvable.
549
+ * @throws EthRelayerEndpointRequiredError if no self-host endpoint is provided.
550
+ */
551
+ async sweepEthViaRelayer(detection, destination, opts) {
552
+ const chainId = this.transport.chain.id;
553
+ const ethRelayerContract = opts.ethRelayerContract ?? (0, transport_1.getEthRelayer)(chainId);
554
+ if (ethRelayerContract === undefined) {
555
+ throw new errors_js_1.EthRelayerContractNotConfiguredError();
556
+ }
557
+ const endpoint = opts.relayerOptions.selfHostEndpoint;
558
+ if (typeof endpoint !== 'string' || endpoint.length === 0) {
559
+ throw new errors_js_1.EthRelayerEndpointRequiredError();
560
+ }
561
+ // Lazy dynamic import keeps the agent-runtime ESM bundle small.
562
+ const relayerMod = await Promise.resolve().then(() => __importStar(require('@shroud-fi/relayer')));
563
+ const passOptions = {};
564
+ if (opts.relayerOptions.deadlineSecs !== undefined) {
565
+ passOptions.deadlineSecs = opts.relayerOptions.deadlineSecs;
566
+ }
567
+ if (opts.relayerOptions.pollTimeoutMs !== undefined) {
568
+ passOptions.pollTimeoutMs = opts.relayerOptions.pollTimeoutMs;
569
+ }
570
+ if (opts.relayerOptions.signal !== undefined) {
571
+ passOptions.signal = opts.relayerOptions.signal;
572
+ }
573
+ const swept = await relayerMod.relayedSweepETH(this.transport, detection.stealthPrivateKey, destination, ethRelayerContract, endpoint, passOptions);
574
+ return { swept, detection };
575
+ }
576
+ }
577
+ exports.ShroudAgent = ShroudAgent;
578
+ // Minimal balanceOf ABI for the self-host pre-flight balance read.
579
+ const BALANCE_OF_ABI = [
580
+ {
581
+ type: 'function',
582
+ name: 'balanceOf',
583
+ stateMutability: 'view',
584
+ inputs: [{ name: 'account', type: 'address' }],
585
+ outputs: [{ name: '', type: 'uint256' }],
586
+ },
587
+ ];
588
+ /**
589
+ * ERC-6538 scheme identifier for secp256k1 stealth addresses with view-tag
590
+ * filtering (per EIP-5564). Kept as a `bigint` because the registry signature
591
+ * is `uint256 schemeId`. Mirrors `SCHEME_ID` in @shroud-fi/payments.
592
+ */
593
+ const REGISTRY_SCHEME_ID = 1n;
594
+ //# sourceMappingURL=agent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent.js","sourceRoot":"","sources":["../../src/agent.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * createShroudAgentFromBrowserWallet — browser / EIP-1193 wallet entry point.
3
+ *
4
+ * Flow:
5
+ * 1. Ask the wallet to sign BROWSER_KEY_MESSAGE via personal_sign.
6
+ * 2. HKDF the signature bytes to a deterministic 32-byte master seed.
7
+ * 3. Delegate to createShroudAgent.
8
+ *
9
+ * The same wallet always produces the same agent identity — no localStorage,
10
+ * no persistence. Bumping BROWSER_KEY_MESSAGE forks the identity space.
11
+ *
12
+ * Privacy invariants:
13
+ * - No console.* anywhere.
14
+ * - The signature bytes never appear in error messages or stack frames.
15
+ * - The derived master seed is passed to createShroudAgent and immediately
16
+ * consumed by createAgentIdentity; no caller-visible reference is retained.
17
+ */
18
+ import type { Address } from 'viem';
19
+ import type { FinalityLevel } from '@shroud-fi/scanning';
20
+ import type { ShroudFiTransport } from '@shroud-fi/transport';
21
+ import type { ShroudAgent } from './agent.js';
22
+ import type { BrowserWalletAdapter } from './types.js';
23
+ export { BROWSER_KEY_MESSAGE, HKDF_BROWSER_SALT, HKDF_BROWSER_INFO, } from './constants.js';
24
+ export interface CreateShroudAgentFromBrowserWalletArgs {
25
+ readonly wallet: BrowserWalletAdapter;
26
+ readonly transport: ShroudFiTransport;
27
+ readonly stealthContract?: Address;
28
+ readonly startBlock: bigint;
29
+ readonly finality?: FinalityLevel;
30
+ }
31
+ /**
32
+ * Build a ShroudAgent from a browser wallet adapter (e.g. MetaMask).
33
+ *
34
+ * @throws MissingBrowserWalletError if the adapter is missing required fields.
35
+ * @throws BrowserWalletSignatureRejectedError if the signature request is rejected.
36
+ */
37
+ export declare function createShroudAgentFromBrowserWallet(args: CreateShroudAgentFromBrowserWalletArgs): Promise<ShroudAgent>;
38
+ //# sourceMappingURL=browser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../../src/browser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAGpC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAE9D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAW9C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAEvD,OAAO,EACL,mBAAmB,EACnB,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,gBAAgB,CAAC;AAExB,MAAM,WAAW,sCAAsC;IACrD,QAAQ,CAAC,MAAM,EAAE,oBAAoB,CAAC;IACtC,QAAQ,CAAC,SAAS,EAAE,iBAAiB,CAAC;IACtC,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,CAAC;IACnC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,QAAQ,CAAC,EAAE,aAAa,CAAC;CACnC;AAoBD;;;;;GAKG;AACH,wBAAsB,kCAAkC,CACtD,IAAI,EAAE,sCAAsC,GAC3C,OAAO,CAAC,WAAW,CAAC,CAgDtB"}