@shroud-fi/relayer 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 (71) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +57 -0
  3. package/dist/cjs/constants.d.ts +41 -0
  4. package/dist/cjs/constants.d.ts.map +1 -0
  5. package/dist/cjs/constants.js +49 -0
  6. package/dist/cjs/constants.js.map +1 -0
  7. package/dist/cjs/errors.d.ts +56 -0
  8. package/dist/cjs/errors.d.ts.map +1 -0
  9. package/dist/cjs/errors.js +85 -0
  10. package/dist/cjs/errors.js.map +1 -0
  11. package/dist/cjs/eth-sweep.d.ts +36 -0
  12. package/dist/cjs/eth-sweep.d.ts.map +1 -0
  13. package/dist/cjs/eth-sweep.js +193 -0
  14. package/dist/cjs/eth-sweep.js.map +1 -0
  15. package/dist/cjs/gelato-adapter.d.ts +69 -0
  16. package/dist/cjs/gelato-adapter.d.ts.map +1 -0
  17. package/dist/cjs/gelato-adapter.js +209 -0
  18. package/dist/cjs/gelato-adapter.js.map +1 -0
  19. package/dist/cjs/index.d.ts +7 -0
  20. package/dist/cjs/index.d.ts.map +1 -0
  21. package/dist/cjs/index.js +26 -0
  22. package/dist/cjs/index.js.map +1 -0
  23. package/dist/cjs/package.json +1 -0
  24. package/dist/cjs/relayer.d.ts +23 -0
  25. package/dist/cjs/relayer.d.ts.map +1 -0
  26. package/dist/cjs/relayer.js +149 -0
  27. package/dist/cjs/relayer.js.map +1 -0
  28. package/dist/cjs/signing.d.ts +24 -0
  29. package/dist/cjs/signing.d.ts.map +1 -0
  30. package/dist/cjs/signing.js +155 -0
  31. package/dist/cjs/signing.js.map +1 -0
  32. package/dist/cjs/types.d.ts +88 -0
  33. package/dist/cjs/types.d.ts.map +1 -0
  34. package/dist/cjs/types.js +3 -0
  35. package/dist/cjs/types.js.map +1 -0
  36. package/dist/esm/constants.d.ts +41 -0
  37. package/dist/esm/constants.d.ts.map +1 -0
  38. package/dist/esm/constants.js +46 -0
  39. package/dist/esm/constants.js.map +1 -0
  40. package/dist/esm/errors.d.ts +56 -0
  41. package/dist/esm/errors.d.ts.map +1 -0
  42. package/dist/esm/errors.js +74 -0
  43. package/dist/esm/errors.js.map +1 -0
  44. package/dist/esm/eth-sweep.d.ts +36 -0
  45. package/dist/esm/eth-sweep.d.ts.map +1 -0
  46. package/dist/esm/eth-sweep.js +190 -0
  47. package/dist/esm/eth-sweep.js.map +1 -0
  48. package/dist/esm/gelato-adapter.d.ts +69 -0
  49. package/dist/esm/gelato-adapter.d.ts.map +1 -0
  50. package/dist/esm/gelato-adapter.js +205 -0
  51. package/dist/esm/gelato-adapter.js.map +1 -0
  52. package/dist/esm/index.d.ts +7 -0
  53. package/dist/esm/index.d.ts.map +1 -0
  54. package/dist/esm/index.js +6 -0
  55. package/dist/esm/index.js.map +1 -0
  56. package/dist/esm/relayer.d.ts +23 -0
  57. package/dist/esm/relayer.d.ts.map +1 -0
  58. package/dist/esm/relayer.js +146 -0
  59. package/dist/esm/relayer.js.map +1 -0
  60. package/dist/esm/signing.d.ts +24 -0
  61. package/dist/esm/signing.d.ts.map +1 -0
  62. package/dist/esm/signing.js +152 -0
  63. package/dist/esm/signing.js.map +1 -0
  64. package/dist/esm/types.d.ts +88 -0
  65. package/dist/esm/types.d.ts.map +1 -0
  66. package/dist/esm/types.js +2 -0
  67. package/dist/esm/types.js.map +1 -0
  68. package/dist/tsconfig.cjs.tsbuildinfo +1 -0
  69. package/dist/tsconfig.esm.tsbuildinfo +1 -0
  70. package/dist/tsconfig.tsbuildinfo +1 -0
  71. package/package.json +64 -0
@@ -0,0 +1,209 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.submitSponsoredCallErc2771 = submitSponsoredCallErc2771;
4
+ exports.pollGelatoTaskUntilTerminal = pollGelatoTaskUntilTerminal;
5
+ const viem_1 = require("viem");
6
+ const accounts_1 = require("viem/accounts");
7
+ const relay_sdk_viem_1 = require("@gelatonetwork/relay-sdk-viem");
8
+ const constants_js_1 = require("./constants.js");
9
+ const errors_js_1 = require("./errors.js");
10
+ // Lazily instantiate a single relay client per process. Stateless wrt
11
+ // chain/key so safe to share.
12
+ let _relay;
13
+ function relay() {
14
+ if (_relay === undefined) {
15
+ _relay = new relay_sdk_viem_1.GelatoRelay();
16
+ }
17
+ return _relay;
18
+ }
19
+ /**
20
+ * Submit a sponsored ERC-2771 metaTx via Gelato 1Balance.
21
+ *
22
+ * Returns the Gelato `taskId`. Caller is responsible for polling.
23
+ */
24
+ async function submitSponsoredCallErc2771(p) {
25
+ const account = (0, accounts_1.privateKeyToAccount)(p.userPrivateKey);
26
+ // Build an ephemeral walletClient. The Gelato SDK uses it to sign the
27
+ // ERC-2771 typed data. We deliberately avoid persisting it.
28
+ const wallet = (0, viem_1.createWalletClient)({
29
+ account,
30
+ chain: p.chain,
31
+ transport: p.rpcUrl !== undefined ? (0, viem_1.http)(p.rpcUrl) : (0, viem_1.http)(),
32
+ });
33
+ const request = {
34
+ chainId: BigInt(p.chainId),
35
+ target: p.target,
36
+ data: p.data,
37
+ user: p.user,
38
+ isConcurrent: false,
39
+ };
40
+ try {
41
+ const response = await relay().sponsoredCallERC2771(request, wallet, p.apiKey ?? '');
42
+ return response.taskId;
43
+ }
44
+ catch (err) {
45
+ // Surface only the upstream error class name; never the message
46
+ // (may contain calldata bytes, addresses, or RPC quoting).
47
+ const tag = err instanceof Error ? err.name : 'unknown';
48
+ throw new errors_js_1.RelayerSubmissionError(tag);
49
+ }
50
+ }
51
+ function mapTaskState(state) {
52
+ switch (state) {
53
+ case relay_sdk_viem_1.TaskState.ExecSuccess:
54
+ case 'ExecSuccess':
55
+ return 'success';
56
+ case relay_sdk_viem_1.TaskState.ExecReverted:
57
+ case 'ExecReverted':
58
+ return 'failed';
59
+ case relay_sdk_viem_1.TaskState.Cancelled:
60
+ case 'Cancelled':
61
+ return 'cancelled';
62
+ case relay_sdk_viem_1.TaskState.CheckPending:
63
+ case relay_sdk_viem_1.TaskState.ExecPending:
64
+ case relay_sdk_viem_1.TaskState.WaitingForConfirmation:
65
+ case 'CheckPending':
66
+ case 'ExecPending':
67
+ case 'WaitingForConfirmation':
68
+ return 'pending';
69
+ default:
70
+ // Treat unknown lifecycle states (e.g. "Blacklisted") as failure.
71
+ return 'failed';
72
+ }
73
+ }
74
+ /**
75
+ * Fetch a single task-status snapshot via the public Gelato HTTP endpoint.
76
+ * Used as fallback if the SDK's getTaskStatus returns undefined.
77
+ */
78
+ async function fetchTaskStatusFallback(taskId, signal) {
79
+ // `fetch` is globally available in Node 18+.
80
+ let resp;
81
+ try {
82
+ const init = signal !== undefined ? { signal } : {};
83
+ resp = await fetch(`${constants_js_1.GELATO_TASK_STATUS_URL}${taskId}`, init);
84
+ }
85
+ catch {
86
+ return undefined;
87
+ }
88
+ if (!resp.ok)
89
+ return undefined;
90
+ let body;
91
+ try {
92
+ body = await resp.json();
93
+ }
94
+ catch {
95
+ return undefined;
96
+ }
97
+ // Endpoint returns either { task: {...} } or the bare task object.
98
+ const taskUnknown = body !== null && typeof body === 'object' && 'task' in body
99
+ ? body.task
100
+ : body;
101
+ if (taskUnknown === null || typeof taskUnknown !== 'object')
102
+ return undefined;
103
+ const task = taskUnknown;
104
+ const rawState = task['taskState'];
105
+ if (typeof rawState !== 'string')
106
+ return undefined;
107
+ const state = mapTaskState(rawState);
108
+ const result = {
109
+ taskId,
110
+ state,
111
+ };
112
+ const txHash = task['transactionHash'];
113
+ if (typeof txHash === 'string' && txHash.startsWith('0x')) {
114
+ result.txHash = txHash;
115
+ }
116
+ const blockNumber = task['blockNumber'];
117
+ if (typeof blockNumber === 'number') {
118
+ result.blockNumber = BigInt(blockNumber);
119
+ }
120
+ else if (typeof blockNumber === 'string' && /^\d+$/.test(blockNumber)) {
121
+ result.blockNumber = BigInt(blockNumber);
122
+ }
123
+ const lastErr = task['lastCheckMessage'];
124
+ if (typeof lastErr === 'string' && lastErr.length > 0) {
125
+ result.lastErrorMsg = lastErr;
126
+ }
127
+ return result;
128
+ }
129
+ /**
130
+ * Poll Gelato task status until terminal (success / failed / cancelled) or
131
+ * until the timeout expires / the abort signal fires.
132
+ *
133
+ * Strategy:
134
+ * 1. Try the SDK's `getTaskStatus` first (it shares websocket cache).
135
+ * 2. Fall back to direct HTTP if the SDK returns undefined.
136
+ *
137
+ * Errors:
138
+ * - RelayerTimeoutError on timeout / abort
139
+ * - RelayerExecutionFailedError on `failed`/`cancelled` terminal state
140
+ */
141
+ async function pollGelatoTaskUntilTerminal(taskId, opts) {
142
+ const deadline = Date.now() + opts.pollTimeoutMs;
143
+ const r = relay();
144
+ while (Date.now() < deadline) {
145
+ if (opts.signal?.aborted === true) {
146
+ throw new errors_js_1.RelayerTimeoutError();
147
+ }
148
+ let status;
149
+ try {
150
+ const upstream = await r.getTaskStatus(taskId);
151
+ if (upstream !== undefined) {
152
+ const built = {
153
+ taskId,
154
+ state: mapTaskState(upstream.taskState),
155
+ };
156
+ if (typeof upstream.transactionHash === 'string' &&
157
+ upstream.transactionHash.startsWith('0x')) {
158
+ built.txHash = upstream.transactionHash;
159
+ }
160
+ if (typeof upstream.blockNumber === 'number') {
161
+ built.blockNumber = BigInt(upstream.blockNumber);
162
+ }
163
+ if (typeof upstream.lastCheckMessage === 'string' &&
164
+ upstream.lastCheckMessage.length > 0) {
165
+ built.lastErrorMsg = upstream.lastCheckMessage;
166
+ }
167
+ status = built;
168
+ }
169
+ }
170
+ catch {
171
+ // swallow; we'll try the HTTP fallback or retry next tick
172
+ }
173
+ if (status === undefined) {
174
+ status = await fetchTaskStatusFallback(taskId, opts.signal);
175
+ }
176
+ if (status !== undefined) {
177
+ if (status.state === 'success')
178
+ return status;
179
+ if (status.state === 'failed' || status.state === 'cancelled') {
180
+ throw new errors_js_1.RelayerExecutionFailedError(status.state);
181
+ }
182
+ // pending / submitted: keep polling
183
+ }
184
+ await sleep(opts.pollIntervalMs, opts.signal);
185
+ }
186
+ throw new errors_js_1.RelayerTimeoutError();
187
+ }
188
+ async function sleep(ms, signal) {
189
+ return new Promise((resolve, reject) => {
190
+ if (signal?.aborted === true) {
191
+ reject(new errors_js_1.RelayerTimeoutError());
192
+ return;
193
+ }
194
+ const t = setTimeout(() => {
195
+ if (signal !== undefined) {
196
+ signal.removeEventListener('abort', onAbort);
197
+ }
198
+ resolve();
199
+ }, ms);
200
+ const onAbort = () => {
201
+ clearTimeout(t);
202
+ reject(new errors_js_1.RelayerTimeoutError());
203
+ };
204
+ if (signal !== undefined) {
205
+ signal.addEventListener('abort', onAbort, { once: true });
206
+ }
207
+ });
208
+ }
209
+ //# sourceMappingURL=gelato-adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gelato-adapter.js","sourceRoot":"","sources":["../../src/gelato-adapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export { relayedSweepERC20 } from './relayer.js';
2
+ export { relayedSweepETH } from './eth-sweep.js';
3
+ export { signEip2612Permit } from './signing.js';
4
+ export type { RelayerSweepOptions, RelayerSweepReceipt, RelayerSweepStatus, GelatoTaskId, Eip2612PermitSignature, RelayedEthSweepOptions, RelayedEthSweepReceipt, } from './types.js';
5
+ export { RelayerError, RelayerSignatureError, RelayerSubmissionError, RelayerExecutionFailedError, RelayerTimeoutError, RelayerForwarderMismatchError, StealthAddressEmptyError, RelayerInvalidChainError, } from './errors.js';
6
+ export { DEFAULT_PERMIT_DEADLINE_SECS, DEFAULT_POLL_INTERVAL_MS, DEFAULT_POLL_TIMEOUT_MS, GELATO_FORWARDER_BY_CHAIN, DEFAULT_ETH_SWEEP_DEADLINE_SECS, ETH_RELAYER_SUPPORTED_CHAINS, } from './constants.js';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEjD,YAAY,EACV,mBAAmB,EACnB,mBAAmB,EACnB,kBAAkB,EAClB,YAAY,EACZ,sBAAsB,EACtB,sBAAsB,EACtB,sBAAsB,GACvB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,YAAY,EACZ,qBAAqB,EACrB,sBAAsB,EACtB,2BAA2B,EAC3B,mBAAmB,EACnB,6BAA6B,EAC7B,wBAAwB,EACxB,wBAAwB,GACzB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,4BAA4B,EAC5B,wBAAwB,EACxB,uBAAuB,EACvB,yBAAyB,EACzB,+BAA+B,EAC/B,4BAA4B,GAC7B,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ETH_RELAYER_SUPPORTED_CHAINS = exports.DEFAULT_ETH_SWEEP_DEADLINE_SECS = exports.GELATO_FORWARDER_BY_CHAIN = exports.DEFAULT_POLL_TIMEOUT_MS = exports.DEFAULT_POLL_INTERVAL_MS = exports.DEFAULT_PERMIT_DEADLINE_SECS = exports.RelayerInvalidChainError = exports.StealthAddressEmptyError = exports.RelayerForwarderMismatchError = exports.RelayerTimeoutError = exports.RelayerExecutionFailedError = exports.RelayerSubmissionError = exports.RelayerSignatureError = exports.RelayerError = exports.signEip2612Permit = exports.relayedSweepETH = exports.relayedSweepERC20 = void 0;
4
+ var relayer_js_1 = require("./relayer.js");
5
+ Object.defineProperty(exports, "relayedSweepERC20", { enumerable: true, get: function () { return relayer_js_1.relayedSweepERC20; } });
6
+ var eth_sweep_js_1 = require("./eth-sweep.js");
7
+ Object.defineProperty(exports, "relayedSweepETH", { enumerable: true, get: function () { return eth_sweep_js_1.relayedSweepETH; } });
8
+ var signing_js_1 = require("./signing.js");
9
+ Object.defineProperty(exports, "signEip2612Permit", { enumerable: true, get: function () { return signing_js_1.signEip2612Permit; } });
10
+ var errors_js_1 = require("./errors.js");
11
+ Object.defineProperty(exports, "RelayerError", { enumerable: true, get: function () { return errors_js_1.RelayerError; } });
12
+ Object.defineProperty(exports, "RelayerSignatureError", { enumerable: true, get: function () { return errors_js_1.RelayerSignatureError; } });
13
+ Object.defineProperty(exports, "RelayerSubmissionError", { enumerable: true, get: function () { return errors_js_1.RelayerSubmissionError; } });
14
+ Object.defineProperty(exports, "RelayerExecutionFailedError", { enumerable: true, get: function () { return errors_js_1.RelayerExecutionFailedError; } });
15
+ Object.defineProperty(exports, "RelayerTimeoutError", { enumerable: true, get: function () { return errors_js_1.RelayerTimeoutError; } });
16
+ Object.defineProperty(exports, "RelayerForwarderMismatchError", { enumerable: true, get: function () { return errors_js_1.RelayerForwarderMismatchError; } });
17
+ Object.defineProperty(exports, "StealthAddressEmptyError", { enumerable: true, get: function () { return errors_js_1.StealthAddressEmptyError; } });
18
+ Object.defineProperty(exports, "RelayerInvalidChainError", { enumerable: true, get: function () { return errors_js_1.RelayerInvalidChainError; } });
19
+ var constants_js_1 = require("./constants.js");
20
+ Object.defineProperty(exports, "DEFAULT_PERMIT_DEADLINE_SECS", { enumerable: true, get: function () { return constants_js_1.DEFAULT_PERMIT_DEADLINE_SECS; } });
21
+ Object.defineProperty(exports, "DEFAULT_POLL_INTERVAL_MS", { enumerable: true, get: function () { return constants_js_1.DEFAULT_POLL_INTERVAL_MS; } });
22
+ Object.defineProperty(exports, "DEFAULT_POLL_TIMEOUT_MS", { enumerable: true, get: function () { return constants_js_1.DEFAULT_POLL_TIMEOUT_MS; } });
23
+ Object.defineProperty(exports, "GELATO_FORWARDER_BY_CHAIN", { enumerable: true, get: function () { return constants_js_1.GELATO_FORWARDER_BY_CHAIN; } });
24
+ Object.defineProperty(exports, "DEFAULT_ETH_SWEEP_DEADLINE_SECS", { enumerable: true, get: function () { return constants_js_1.DEFAULT_ETH_SWEEP_DEADLINE_SECS; } });
25
+ Object.defineProperty(exports, "ETH_RELAYER_SUPPORTED_CHAINS", { enumerable: true, get: function () { return constants_js_1.ETH_RELAYER_SUPPORTED_CHAINS; } });
26
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;AAAA,2CAAiD;AAAxC,+GAAA,iBAAiB,OAAA;AAC1B,+CAAiD;AAAxC,+GAAA,eAAe,OAAA;AACxB,2CAAiD;AAAxC,+GAAA,iBAAiB,OAAA;AAY1B,yCASqB;AARnB,yGAAA,YAAY,OAAA;AACZ,kHAAA,qBAAqB,OAAA;AACrB,mHAAA,sBAAsB,OAAA;AACtB,wHAAA,2BAA2B,OAAA;AAC3B,gHAAA,mBAAmB,OAAA;AACnB,0HAAA,6BAA6B,OAAA;AAC7B,qHAAA,wBAAwB,OAAA;AACxB,qHAAA,wBAAwB,OAAA;AAG1B,+CAOwB;AANtB,4HAAA,4BAA4B,OAAA;AAC5B,wHAAA,wBAAwB,OAAA;AACxB,uHAAA,uBAAuB,OAAA;AACvB,yHAAA,yBAAyB,OAAA;AACzB,+HAAA,+BAA+B,OAAA;AAC/B,4HAAA,4BAA4B,OAAA"}
@@ -0,0 +1 @@
1
+ {"type":"commonjs"}
@@ -0,0 +1,23 @@
1
+ import type { Address, Hex } from 'viem';
2
+ import type { ShroudFiTransport } from '@shroud-fi/transport';
3
+ import type { RelayerSweepOptions, RelayerSweepReceipt } from './types.js';
4
+ /**
5
+ * Gasless ERC-20 sweep via the deployed `ShroudFiRelayer` + Gelato.
6
+ *
7
+ * Flow:
8
+ * 1. Validate chain is in the supported Gelato forwarder table.
9
+ * 2. Read the relayer's on-chain trustedForwarder and assert match.
10
+ * 3. Read the stealth address ERC-20 balance (= permit `value`).
11
+ * 4. Sign an EIP-2612 permit { owner=stealth, spender=relayer, value, deadline }.
12
+ * 5. Encode `sweepERC20WithPermit(token, destination, deadline, v, r, s)`.
13
+ * 6. Submit via `sponsoredCallERC2771` (1Balance sponsored).
14
+ * 7. Poll until terminal — return receipt with txHash + blockNumber.
15
+ *
16
+ * Privacy invariants enforced here:
17
+ * - `stealthPrivateKey` is never logged, serialized, or attached to errors.
18
+ * - The receipt contains NO amount fields (balance is read but discarded
19
+ * after permit signing).
20
+ * - Error messages contain no addresses, amounts, signature bytes, or chain ids.
21
+ */
22
+ export declare function relayedSweepERC20(transport: ShroudFiTransport, stealthPrivateKey: Hex, token: Address, destination: Address, relayerContract: Address, options?: RelayerSweepOptions): Promise<RelayerSweepReceipt>;
23
+ //# sourceMappingURL=relayer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relayer.d.ts","sourceRoot":"","sources":["../../src/relayer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,MAAM,CAAC;AAGzC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAO9D,OAAO,KAAK,EACV,mBAAmB,EACnB,mBAAmB,EACpB,MAAM,YAAY,CAAC;AAuDpB;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,iBAAiB,CACrC,SAAS,EAAE,iBAAiB,EAC5B,iBAAiB,EAAE,GAAG,EACtB,KAAK,EAAE,OAAO,EACd,WAAW,EAAE,OAAO,EACpB,eAAe,EAAE,OAAO,EACxB,OAAO,CAAC,EAAE,mBAAmB,GAC5B,OAAO,CAAC,mBAAmB,CAAC,CAqH9B"}
@@ -0,0 +1,149 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.relayedSweepERC20 = relayedSweepERC20;
4
+ const viem_1 = require("viem");
5
+ const accounts_1 = require("viem/accounts");
6
+ const constants_js_1 = require("./constants.js");
7
+ const errors_js_1 = require("./errors.js");
8
+ const signing_js_1 = require("./signing.js");
9
+ const gelato_adapter_js_1 = require("./gelato-adapter.js");
10
+ /**
11
+ * Minimal inline ABI for `ShroudFiRelayer` — only the surface we call from
12
+ * the SDK. Kept here (not in a shared `abi.ts`) because no other module needs
13
+ * these entries today.
14
+ */
15
+ const SHROUDFI_RELAYER_ABI = [
16
+ {
17
+ type: 'function',
18
+ name: 'sweepERC20WithPermit',
19
+ stateMutability: 'nonpayable',
20
+ inputs: [
21
+ { name: 'token', type: 'address' },
22
+ { name: 'destination', type: 'address' },
23
+ { name: 'deadline', type: 'uint256' },
24
+ { name: 'v', type: 'uint8' },
25
+ { name: 'r', type: 'bytes32' },
26
+ { name: 's', type: 'bytes32' },
27
+ ],
28
+ outputs: [],
29
+ },
30
+ {
31
+ type: 'function',
32
+ name: 'trustedForwarder',
33
+ stateMutability: 'view',
34
+ inputs: [],
35
+ outputs: [{ name: '', type: 'address' }],
36
+ },
37
+ ];
38
+ /**
39
+ * Minimal balanceOf ABI for the pre-flight balance read. Inlined so this file
40
+ * has no dependency on `@shroud-fi/transport`'s ERC20Abi shape.
41
+ */
42
+ const ERC20_BALANCE_OF_ABI = [
43
+ {
44
+ type: 'function',
45
+ name: 'balanceOf',
46
+ stateMutability: 'view',
47
+ inputs: [{ name: 'account', type: 'address' }],
48
+ outputs: [{ name: '', type: 'uint256' }],
49
+ },
50
+ ];
51
+ /**
52
+ * Gasless ERC-20 sweep via the deployed `ShroudFiRelayer` + Gelato.
53
+ *
54
+ * Flow:
55
+ * 1. Validate chain is in the supported Gelato forwarder table.
56
+ * 2. Read the relayer's on-chain trustedForwarder and assert match.
57
+ * 3. Read the stealth address ERC-20 balance (= permit `value`).
58
+ * 4. Sign an EIP-2612 permit { owner=stealth, spender=relayer, value, deadline }.
59
+ * 5. Encode `sweepERC20WithPermit(token, destination, deadline, v, r, s)`.
60
+ * 6. Submit via `sponsoredCallERC2771` (1Balance sponsored).
61
+ * 7. Poll until terminal — return receipt with txHash + blockNumber.
62
+ *
63
+ * Privacy invariants enforced here:
64
+ * - `stealthPrivateKey` is never logged, serialized, or attached to errors.
65
+ * - The receipt contains NO amount fields (balance is read but discarded
66
+ * after permit signing).
67
+ * - Error messages contain no addresses, amounts, signature bytes, or chain ids.
68
+ */
69
+ async function relayedSweepERC20(transport, stealthPrivateKey, token, destination, relayerContract, options) {
70
+ const chainId = transport.chain.id;
71
+ // 1. Chain support check.
72
+ const expectedForwarder = constants_js_1.GELATO_FORWARDER_BY_CHAIN[chainId];
73
+ if (expectedForwarder === undefined) {
74
+ throw new errors_js_1.RelayerInvalidChainError();
75
+ }
76
+ // 2. Forwarder match check (defense-in-depth).
77
+ const onChainForwarder = (await transport.publicClient.readContract({
78
+ address: relayerContract,
79
+ abi: SHROUDFI_RELAYER_ABI,
80
+ functionName: 'trustedForwarder',
81
+ }));
82
+ if ((0, viem_1.getAddress)(onChainForwarder) !== (0, viem_1.getAddress)(expectedForwarder)) {
83
+ throw new errors_js_1.RelayerForwarderMismatchError();
84
+ }
85
+ // 3. Balance read. Note: `account` is derived inside a tight scope; we
86
+ // never persist or log the privateKey-derived account beyond this.
87
+ const stealthAddress = (0, accounts_1.privateKeyToAccount)(stealthPrivateKey).address;
88
+ const balance = (await transport.publicClient.readContract({
89
+ address: token,
90
+ abi: ERC20_BALANCE_OF_ABI,
91
+ functionName: 'balanceOf',
92
+ args: [stealthAddress],
93
+ }));
94
+ if (balance === 0n) {
95
+ throw new errors_js_1.StealthAddressEmptyError();
96
+ }
97
+ // 4. Compute permit deadline. Use block.timestamp + lifetime so the
98
+ // deadline aligns with the chain's clock rather than the host's.
99
+ const lifetime = options?.deadlineSecs ?? constants_js_1.DEFAULT_PERMIT_DEADLINE_SECS;
100
+ const latestBlock = await transport.publicClient.getBlock();
101
+ const deadline = latestBlock.timestamp + lifetime;
102
+ // 5. Sign the EIP-2612 permit.
103
+ const permit = await (0, signing_js_1.signEip2612Permit)(transport, stealthPrivateKey, token, relayerContract, balance, deadline);
104
+ // 6. Encode sweepERC20WithPermit calldata.
105
+ const calldata = (0, viem_1.encodeFunctionData)({
106
+ abi: SHROUDFI_RELAYER_ABI,
107
+ functionName: 'sweepERC20WithPermit',
108
+ args: [token, destination, permit.deadline, permit.v, permit.r, permit.s],
109
+ });
110
+ // 7. Submit via Gelato 1Balance sponsored call.
111
+ const submitParams = {
112
+ chainId,
113
+ target: relayerContract,
114
+ data: calldata,
115
+ user: stealthAddress,
116
+ userPrivateKey: stealthPrivateKey,
117
+ chain: transport.chain,
118
+ };
119
+ if (options?.gelatoApiKey !== undefined) {
120
+ submitParams.apiKey = options.gelatoApiKey;
121
+ }
122
+ if (options?.signal !== undefined) {
123
+ submitParams.signal = options.signal;
124
+ }
125
+ const taskId = await (0, gelato_adapter_js_1.submitSponsoredCallErc2771)(submitParams);
126
+ // 8. Poll until terminal.
127
+ const pollOpts = {
128
+ pollIntervalMs: options?.pollIntervalMs ?? constants_js_1.DEFAULT_POLL_INTERVAL_MS,
129
+ pollTimeoutMs: options?.pollTimeoutMs ?? constants_js_1.DEFAULT_POLL_TIMEOUT_MS,
130
+ };
131
+ if (options?.signal !== undefined) {
132
+ pollOpts.signal = options.signal;
133
+ }
134
+ const status = await (0, gelato_adapter_js_1.pollGelatoTaskUntilTerminal)(taskId, pollOpts);
135
+ // Build the receipt. NOTE: no amount fields by design.
136
+ const receipt = {
137
+ taskId,
138
+ txHash: status.txHash ?? '0x',
139
+ status: status.state,
140
+ relayerContract,
141
+ token,
142
+ destination,
143
+ };
144
+ if (status.blockNumber !== undefined) {
145
+ receipt.blockNumber = status.blockNumber;
146
+ }
147
+ return receipt;
148
+ }
149
+ //# sourceMappingURL=relayer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relayer.js","sourceRoot":"","sources":["../../src/relayer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ import type { Address, Hex } from 'viem';
2
+ import type { ShroudFiTransport } from '@shroud-fi/transport';
3
+ import type { Eip2612PermitSignature } from './types.js';
4
+ /**
5
+ * Sign an EIP-2612 permit for {token, spender, value, deadline} from the
6
+ * stealth address keyed by `stealthPrivateKey`.
7
+ *
8
+ * Privacy:
9
+ * - The privateKey is consumed once to derive a viem `account` and is not
10
+ * stored, logged, serialized, or attached to thrown errors.
11
+ * - On failure we throw a structured `RelayerSignatureError` with no key
12
+ * material, no signature bytes, no nonce.
13
+ * - Token `version()` is probed with a try/catch fallback to "1" — the
14
+ * dominant default across permit-compatible ERC-20s.
15
+ *
16
+ * @param transport - ShroudFi transport (publicClient for reads)
17
+ * @param stealthPrivateKey - 0x-prefixed 32-byte private key (treated as secret)
18
+ * @param token - ERC-20 contract
19
+ * @param spender - relayer contract address (= `ShroudFiRelayer`)
20
+ * @param value - permit value (= full balance at time of sign)
21
+ * @param deadline - unix-seconds deadline (caller computes from `block.timestamp + lifetime`)
22
+ */
23
+ export declare function signEip2612Permit(transport: ShroudFiTransport, stealthPrivateKey: Hex, token: Address, spender: Address, value: bigint, deadline: bigint): Promise<Eip2612PermitSignature>;
24
+ //# sourceMappingURL=signing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signing.d.ts","sourceRoot":"","sources":["../../src/signing.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,MAAM,CAAC;AAGzC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AA2CzD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,iBAAiB,CACrC,SAAS,EAAE,iBAAiB,EAC5B,iBAAiB,EAAE,GAAG,EACtB,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,sBAAsB,CAAC,CA2FjC"}
@@ -0,0 +1,155 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.signEip2612Permit = signEip2612Permit;
4
+ const viem_1 = require("viem");
5
+ const accounts_1 = require("viem/accounts");
6
+ const errors_js_1 = require("./errors.js");
7
+ /**
8
+ * Minimal ABI for the read paths we use. Inlined rather than imported from
9
+ * `@shroud-fi/transport`'s ERC20Abi so this file has zero coupling to
10
+ * non-permit fields. Direct two-call reads (no multicall3 dependency) so the
11
+ * SDK runs against forks/local Anvils where multicall may not be configured.
12
+ */
13
+ const PERMIT_READ_ABI = [
14
+ {
15
+ type: 'function',
16
+ name: 'name',
17
+ stateMutability: 'view',
18
+ inputs: [],
19
+ outputs: [{ name: '', type: 'string' }],
20
+ },
21
+ {
22
+ type: 'function',
23
+ name: 'version',
24
+ stateMutability: 'view',
25
+ inputs: [],
26
+ outputs: [{ name: '', type: 'string' }],
27
+ },
28
+ {
29
+ type: 'function',
30
+ name: 'nonces',
31
+ stateMutability: 'view',
32
+ inputs: [{ name: 'owner', type: 'address' }],
33
+ outputs: [{ name: '', type: 'uint256' }],
34
+ },
35
+ ];
36
+ const PERMIT_TYPES = {
37
+ Permit: [
38
+ { name: 'owner', type: 'address' },
39
+ { name: 'spender', type: 'address' },
40
+ { name: 'value', type: 'uint256' },
41
+ { name: 'nonce', type: 'uint256' },
42
+ { name: 'deadline', type: 'uint256' },
43
+ ],
44
+ };
45
+ /**
46
+ * Sign an EIP-2612 permit for {token, spender, value, deadline} from the
47
+ * stealth address keyed by `stealthPrivateKey`.
48
+ *
49
+ * Privacy:
50
+ * - The privateKey is consumed once to derive a viem `account` and is not
51
+ * stored, logged, serialized, or attached to thrown errors.
52
+ * - On failure we throw a structured `RelayerSignatureError` with no key
53
+ * material, no signature bytes, no nonce.
54
+ * - Token `version()` is probed with a try/catch fallback to "1" — the
55
+ * dominant default across permit-compatible ERC-20s.
56
+ *
57
+ * @param transport - ShroudFi transport (publicClient for reads)
58
+ * @param stealthPrivateKey - 0x-prefixed 32-byte private key (treated as secret)
59
+ * @param token - ERC-20 contract
60
+ * @param spender - relayer contract address (= `ShroudFiRelayer`)
61
+ * @param value - permit value (= full balance at time of sign)
62
+ * @param deadline - unix-seconds deadline (caller computes from `block.timestamp + lifetime`)
63
+ */
64
+ async function signEip2612Permit(transport, stealthPrivateKey, token, spender, value, deadline) {
65
+ const account = (0, accounts_1.privateKeyToAccount)(stealthPrivateKey);
66
+ const owner = account.address;
67
+ const chainId = transport.chain.id;
68
+ // Read token name (required for the domain separator). If a token doesn't
69
+ // expose `name()` it isn't ERC-2612 compatible — propagate as signature error.
70
+ let tokenName;
71
+ try {
72
+ tokenName = (await transport.publicClient.readContract({
73
+ address: token,
74
+ abi: PERMIT_READ_ABI,
75
+ functionName: 'name',
76
+ }));
77
+ }
78
+ catch {
79
+ throw new errors_js_1.RelayerSignatureError();
80
+ }
81
+ // Token version: most permit ERC-20s use "1". Probe with a try/catch.
82
+ let tokenVersion = '1';
83
+ try {
84
+ const v = (await transport.publicClient.readContract({
85
+ address: token,
86
+ abi: PERMIT_READ_ABI,
87
+ functionName: 'version',
88
+ }));
89
+ if (typeof v === 'string' && v.length > 0) {
90
+ tokenVersion = v;
91
+ }
92
+ }
93
+ catch {
94
+ // intentional: fall back to "1"
95
+ }
96
+ // Read the current permit nonce for `owner`.
97
+ let nonce;
98
+ try {
99
+ nonce = (await transport.publicClient.readContract({
100
+ address: token,
101
+ abi: PERMIT_READ_ABI,
102
+ functionName: 'nonces',
103
+ args: [owner],
104
+ }));
105
+ }
106
+ catch {
107
+ throw new errors_js_1.RelayerSignatureError();
108
+ }
109
+ const domain = {
110
+ name: tokenName,
111
+ version: tokenVersion,
112
+ chainId,
113
+ verifyingContract: token,
114
+ };
115
+ let signatureHex;
116
+ try {
117
+ signatureHex = await account.signTypedData({
118
+ domain,
119
+ types: PERMIT_TYPES,
120
+ primaryType: 'Permit',
121
+ message: {
122
+ owner,
123
+ spender,
124
+ value,
125
+ nonce,
126
+ deadline,
127
+ },
128
+ });
129
+ }
130
+ catch {
131
+ throw new errors_js_1.RelayerSignatureError();
132
+ }
133
+ // viem returns the 65-byte signature; split into v/r/s.
134
+ // `parseSignature` returns either {r,s,v,yParity} or {r,s,yParity} (v?: never).
135
+ // Standard EIP-2612 needs `v ∈ {27, 28}`: derive from yParity if v is absent.
136
+ let v;
137
+ let r;
138
+ let s;
139
+ try {
140
+ const split = (0, viem_1.parseSignature)(signatureHex);
141
+ r = split.r;
142
+ s = split.s;
143
+ if (split.v !== undefined) {
144
+ v = Number(split.v);
145
+ }
146
+ else {
147
+ v = split.yParity === 0 ? 27 : 28;
148
+ }
149
+ }
150
+ catch {
151
+ throw new errors_js_1.RelayerSignatureError();
152
+ }
153
+ return { v, r, s, deadline };
154
+ }
155
+ //# sourceMappingURL=signing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signing.js","sourceRoot":"","sources":["../../src/signing.ts"],"names":[],"mappings":"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"}