@wopr-network/crypto-plugins 1.0.1

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 (211) hide show
  1. package/.github/workflows/ci.yml +33 -0
  2. package/.github/workflows/publish.yml +12 -0
  3. package/biome.json +23 -0
  4. package/dist/__tests__/bitcoin-encoder.test.d.ts +2 -0
  5. package/dist/__tests__/bitcoin-encoder.test.d.ts.map +1 -0
  6. package/dist/__tests__/bitcoin-encoder.test.js +97 -0
  7. package/dist/__tests__/bitcoin-encoder.test.js.map +1 -0
  8. package/dist/__tests__/dogecoin-encoder.test.d.ts +2 -0
  9. package/dist/__tests__/dogecoin-encoder.test.d.ts.map +1 -0
  10. package/dist/__tests__/dogecoin-encoder.test.js +57 -0
  11. package/dist/__tests__/dogecoin-encoder.test.js.map +1 -0
  12. package/dist/__tests__/litecoin-encoder.test.d.ts +2 -0
  13. package/dist/__tests__/litecoin-encoder.test.d.ts.map +1 -0
  14. package/dist/__tests__/litecoin-encoder.test.js +44 -0
  15. package/dist/__tests__/litecoin-encoder.test.js.map +1 -0
  16. package/dist/__tests__/registry.test.d.ts +2 -0
  17. package/dist/__tests__/registry.test.d.ts.map +1 -0
  18. package/dist/__tests__/registry.test.js +75 -0
  19. package/dist/__tests__/registry.test.js.map +1 -0
  20. package/dist/__tests__/rpc.test.d.ts +2 -0
  21. package/dist/__tests__/rpc.test.d.ts.map +1 -0
  22. package/dist/__tests__/rpc.test.js +31 -0
  23. package/dist/__tests__/rpc.test.js.map +1 -0
  24. package/dist/__tests__/solana-encoder.test.d.ts +2 -0
  25. package/dist/__tests__/solana-encoder.test.d.ts.map +1 -0
  26. package/dist/__tests__/solana-encoder.test.js +85 -0
  27. package/dist/__tests__/solana-encoder.test.js.map +1 -0
  28. package/dist/__tests__/solana-watcher.test.d.ts +2 -0
  29. package/dist/__tests__/solana-watcher.test.d.ts.map +1 -0
  30. package/dist/__tests__/solana-watcher.test.js +281 -0
  31. package/dist/__tests__/solana-watcher.test.js.map +1 -0
  32. package/dist/__tests__/sweep-key-parity.test.d.ts +2 -0
  33. package/dist/__tests__/sweep-key-parity.test.d.ts.map +1 -0
  34. package/dist/__tests__/sweep-key-parity.test.js +236 -0
  35. package/dist/__tests__/sweep-key-parity.test.js.map +1 -0
  36. package/dist/__tests__/tron-encoder.test.d.ts +2 -0
  37. package/dist/__tests__/tron-encoder.test.d.ts.map +1 -0
  38. package/dist/__tests__/tron-encoder.test.js +93 -0
  39. package/dist/__tests__/tron-encoder.test.js.map +1 -0
  40. package/dist/__tests__/utxo-watcher.test.d.ts +2 -0
  41. package/dist/__tests__/utxo-watcher.test.d.ts.map +1 -0
  42. package/dist/__tests__/utxo-watcher.test.js +218 -0
  43. package/dist/__tests__/utxo-watcher.test.js.map +1 -0
  44. package/dist/bitcoin/encoder.d.ts +15 -0
  45. package/dist/bitcoin/encoder.d.ts.map +1 -0
  46. package/dist/bitcoin/encoder.js +286 -0
  47. package/dist/bitcoin/encoder.js.map +1 -0
  48. package/dist/bitcoin/index.d.ts +4 -0
  49. package/dist/bitcoin/index.d.ts.map +1 -0
  50. package/dist/bitcoin/index.js +20 -0
  51. package/dist/bitcoin/index.js.map +1 -0
  52. package/dist/dogecoin/encoder.d.ts +19 -0
  53. package/dist/dogecoin/encoder.d.ts.map +1 -0
  54. package/dist/dogecoin/encoder.js +145 -0
  55. package/dist/dogecoin/encoder.js.map +1 -0
  56. package/dist/dogecoin/index.d.ts +4 -0
  57. package/dist/dogecoin/index.d.ts.map +1 -0
  58. package/dist/dogecoin/index.js +20 -0
  59. package/dist/dogecoin/index.js.map +1 -0
  60. package/dist/evm/encoder.d.ts +7 -0
  61. package/dist/evm/encoder.d.ts.map +1 -0
  62. package/dist/evm/encoder.js +43 -0
  63. package/dist/evm/encoder.js.map +1 -0
  64. package/dist/evm/eth-watcher.d.ts +38 -0
  65. package/dist/evm/eth-watcher.d.ts.map +1 -0
  66. package/dist/evm/eth-watcher.js +138 -0
  67. package/dist/evm/eth-watcher.js.map +1 -0
  68. package/dist/evm/index.d.ts +16 -0
  69. package/dist/evm/index.d.ts.map +1 -0
  70. package/dist/evm/index.js +34 -0
  71. package/dist/evm/index.js.map +1 -0
  72. package/dist/evm/types.d.ts +43 -0
  73. package/dist/evm/types.d.ts.map +1 -0
  74. package/dist/evm/types.js +101 -0
  75. package/dist/evm/types.js.map +1 -0
  76. package/dist/evm/watcher.d.ts +42 -0
  77. package/dist/evm/watcher.d.ts.map +1 -0
  78. package/dist/evm/watcher.js +162 -0
  79. package/dist/evm/watcher.js.map +1 -0
  80. package/dist/index.d.ts +7 -0
  81. package/dist/index.d.ts.map +1 -0
  82. package/dist/index.js +7 -0
  83. package/dist/index.js.map +1 -0
  84. package/dist/litecoin/encoder.d.ts +8 -0
  85. package/dist/litecoin/encoder.d.ts.map +1 -0
  86. package/dist/litecoin/encoder.js +16 -0
  87. package/dist/litecoin/encoder.js.map +1 -0
  88. package/dist/litecoin/index.d.ts +4 -0
  89. package/dist/litecoin/index.d.ts.map +1 -0
  90. package/dist/litecoin/index.js +20 -0
  91. package/dist/litecoin/index.js.map +1 -0
  92. package/dist/shared/test-helpers/index.d.ts +9 -0
  93. package/dist/shared/test-helpers/index.d.ts.map +1 -0
  94. package/dist/shared/test-helpers/index.js +30 -0
  95. package/dist/shared/test-helpers/index.js.map +1 -0
  96. package/dist/shared/utxo/index.d.ts +5 -0
  97. package/dist/shared/utxo/index.d.ts.map +1 -0
  98. package/dist/shared/utxo/index.js +3 -0
  99. package/dist/shared/utxo/index.js.map +1 -0
  100. package/dist/shared/utxo/rpc.d.ts +24 -0
  101. package/dist/shared/utxo/rpc.d.ts.map +1 -0
  102. package/dist/shared/utxo/rpc.js +75 -0
  103. package/dist/shared/utxo/rpc.js.map +1 -0
  104. package/dist/shared/utxo/types.d.ts +40 -0
  105. package/dist/shared/utxo/types.d.ts.map +1 -0
  106. package/dist/shared/utxo/types.js +2 -0
  107. package/dist/shared/utxo/types.js.map +1 -0
  108. package/dist/shared/utxo/watcher.d.ts +55 -0
  109. package/dist/shared/utxo/watcher.d.ts.map +1 -0
  110. package/dist/shared/utxo/watcher.js +150 -0
  111. package/dist/shared/utxo/watcher.js.map +1 -0
  112. package/dist/solana/encoder.d.ts +13 -0
  113. package/dist/solana/encoder.d.ts.map +1 -0
  114. package/dist/solana/encoder.js +62 -0
  115. package/dist/solana/encoder.js.map +1 -0
  116. package/dist/solana/index.d.ts +17 -0
  117. package/dist/solana/index.d.ts.map +1 -0
  118. package/dist/solana/index.js +32 -0
  119. package/dist/solana/index.js.map +1 -0
  120. package/dist/solana/sweeper.d.ts +47 -0
  121. package/dist/solana/sweeper.d.ts.map +1 -0
  122. package/dist/solana/sweeper.js +151 -0
  123. package/dist/solana/sweeper.js.map +1 -0
  124. package/dist/solana/types.d.ts +49 -0
  125. package/dist/solana/types.d.ts.map +1 -0
  126. package/dist/solana/types.js +2 -0
  127. package/dist/solana/types.js.map +1 -0
  128. package/dist/solana/watcher.d.ts +59 -0
  129. package/dist/solana/watcher.d.ts.map +1 -0
  130. package/dist/solana/watcher.js +251 -0
  131. package/dist/solana/watcher.js.map +1 -0
  132. package/dist/sweep/evm-sweeper.d.ts +31 -0
  133. package/dist/sweep/evm-sweeper.d.ts.map +1 -0
  134. package/dist/sweep/evm-sweeper.js +229 -0
  135. package/dist/sweep/evm-sweeper.js.map +1 -0
  136. package/dist/sweep/index.d.ts +22 -0
  137. package/dist/sweep/index.d.ts.map +1 -0
  138. package/dist/sweep/index.js +290 -0
  139. package/dist/sweep/index.js.map +1 -0
  140. package/dist/sweep/tron-sweeper.d.ts +40 -0
  141. package/dist/sweep/tron-sweeper.d.ts.map +1 -0
  142. package/dist/sweep/tron-sweeper.js +363 -0
  143. package/dist/sweep/tron-sweeper.js.map +1 -0
  144. package/dist/sweep/utxo-sweeper.d.ts +14 -0
  145. package/dist/sweep/utxo-sweeper.d.ts.map +1 -0
  146. package/dist/sweep/utxo-sweeper.js +13 -0
  147. package/dist/sweep/utxo-sweeper.js.map +1 -0
  148. package/dist/tron/address-convert.d.ts +15 -0
  149. package/dist/tron/address-convert.d.ts.map +1 -0
  150. package/dist/tron/address-convert.js +95 -0
  151. package/dist/tron/address-convert.js.map +1 -0
  152. package/dist/tron/encoder.d.ts +20 -0
  153. package/dist/tron/encoder.d.ts.map +1 -0
  154. package/dist/tron/encoder.js +67 -0
  155. package/dist/tron/encoder.js.map +1 -0
  156. package/dist/tron/index.d.ts +6 -0
  157. package/dist/tron/index.d.ts.map +1 -0
  158. package/dist/tron/index.js +20 -0
  159. package/dist/tron/index.js.map +1 -0
  160. package/dist/tron/sha256.d.ts +6 -0
  161. package/dist/tron/sha256.d.ts.map +1 -0
  162. package/dist/tron/sha256.js +90 -0
  163. package/dist/tron/sha256.js.map +1 -0
  164. package/dist/tron/watcher.d.ts +42 -0
  165. package/dist/tron/watcher.d.ts.map +1 -0
  166. package/dist/tron/watcher.js +168 -0
  167. package/dist/tron/watcher.js.map +1 -0
  168. package/package.json +47 -0
  169. package/src/__tests__/bitcoin-encoder.test.ts +115 -0
  170. package/src/__tests__/dogecoin-encoder.test.ts +66 -0
  171. package/src/__tests__/litecoin-encoder.test.ts +51 -0
  172. package/src/__tests__/registry.test.ts +91 -0
  173. package/src/__tests__/rpc.test.ts +36 -0
  174. package/src/__tests__/solana-encoder.test.ts +103 -0
  175. package/src/__tests__/solana-watcher.test.ts +316 -0
  176. package/src/__tests__/sweep-key-parity.test.ts +302 -0
  177. package/src/__tests__/tron-encoder.test.ts +108 -0
  178. package/src/__tests__/utxo-watcher.test.ts +252 -0
  179. package/src/bitcoin/encoder.ts +320 -0
  180. package/src/bitcoin/index.ts +23 -0
  181. package/src/dogecoin/encoder.ts +161 -0
  182. package/src/dogecoin/index.ts +23 -0
  183. package/src/evm/encoder.ts +49 -0
  184. package/src/evm/eth-watcher.ts +168 -0
  185. package/src/evm/index.ts +46 -0
  186. package/src/evm/types.ts +146 -0
  187. package/src/evm/watcher.ts +189 -0
  188. package/src/index.ts +21 -0
  189. package/src/litecoin/encoder.ts +18 -0
  190. package/src/litecoin/index.ts +23 -0
  191. package/src/shared/test-helpers/index.ts +36 -0
  192. package/src/shared/utxo/index.ts +12 -0
  193. package/src/shared/utxo/rpc.ts +80 -0
  194. package/src/shared/utxo/types.ts +43 -0
  195. package/src/shared/utxo/watcher.ts +195 -0
  196. package/src/solana/encoder.ts +72 -0
  197. package/src/solana/index.ts +36 -0
  198. package/src/solana/sweeper.ts +196 -0
  199. package/src/solana/types.ts +52 -0
  200. package/src/solana/watcher.ts +282 -0
  201. package/src/sweep/evm-sweeper.ts +296 -0
  202. package/src/sweep/index.ts +353 -0
  203. package/src/sweep/tron-sweeper.ts +467 -0
  204. package/src/sweep/utxo-sweeper.ts +23 -0
  205. package/src/tron/address-convert.ts +91 -0
  206. package/src/tron/encoder.ts +74 -0
  207. package/src/tron/index.ts +23 -0
  208. package/src/tron/sha256.ts +100 -0
  209. package/src/tron/watcher.ts +208 -0
  210. package/tsconfig.json +17 -0
  211. package/vitest.config.ts +8 -0
@@ -0,0 +1,251 @@
1
+ /** Microdollars per cent. Used for oracle price conversion. */
2
+ const MICROS_PER_CENT = 10000n;
3
+ /** SOL has 9 decimals (lamports). */
4
+ const SOL_DECIMALS = 9;
5
+ /** Create a Solana JSON-RPC caller. */
6
+ export function createSolanaRpcCaller(rpcUrl, extraHeaders) {
7
+ let id = 0;
8
+ const headers = { "Content-Type": "application/json", ...extraHeaders };
9
+ return async (method, params) => {
10
+ const res = await fetch(rpcUrl, {
11
+ method: "POST",
12
+ headers,
13
+ body: JSON.stringify({ jsonrpc: "2.0", id: ++id, method, params }),
14
+ });
15
+ if (!res.ok) {
16
+ const body = await res.text().catch(() => "");
17
+ throw new Error(`Solana RPC ${method} failed: ${res.status} ${body.slice(0, 200)}`);
18
+ }
19
+ const data = (await res.json());
20
+ if (data.error)
21
+ throw new Error(`Solana RPC ${method} error: ${data.error.message}`);
22
+ return data.result;
23
+ };
24
+ }
25
+ /**
26
+ * Convert native SOL amount (lamports) to USD cents using oracle price in microdollars.
27
+ */
28
+ function nativeToCents(lamports, priceMicros, decimals) {
29
+ if (lamports < 0n)
30
+ throw new Error("lamports must be non-negative");
31
+ if (!Number.isInteger(priceMicros) || priceMicros <= 0) {
32
+ throw new Error(`priceMicros must be a positive integer, got ${priceMicros}`);
33
+ }
34
+ return Number((lamports * BigInt(priceMicros)) / (MICROS_PER_CENT * 10n ** BigInt(decimals)));
35
+ }
36
+ /**
37
+ * Solana chain watcher.
38
+ *
39
+ * Monitors watched addresses for incoming SOL transfers and SPL token transfers.
40
+ * Uses getSignaturesForAddress + getTransaction RPCs. Cursor is a slot number.
41
+ *
42
+ * For native SOL: detects balance increases to watched addresses.
43
+ * For SPL tokens: detects token transfer instructions to watched addresses.
44
+ */
45
+ export class SolanaWatcher {
46
+ _cursor = 0;
47
+ _stopped = false;
48
+ chain;
49
+ token;
50
+ rpc;
51
+ confirmations;
52
+ decimals;
53
+ cursorStore;
54
+ watcherId;
55
+ contractAddress;
56
+ _watchedAddresses;
57
+ constructor(opts) {
58
+ this.chain = opts.chain;
59
+ this.token = opts.token;
60
+ this.rpc = createSolanaRpcCaller(opts.rpcUrl, opts.rpcHeaders);
61
+ this._cursor = 0;
62
+ this.confirmations = opts.confirmations;
63
+ this.decimals = opts.decimals;
64
+ this.cursorStore = opts.cursorStore;
65
+ this.watcherId = `solana:${opts.chain}:${opts.token}`;
66
+ this.contractAddress = opts.contractAddress;
67
+ this._watchedAddresses = new Set();
68
+ }
69
+ async init() {
70
+ const saved = await this.cursorStore.get(this.watcherId);
71
+ if (saved !== null)
72
+ this._cursor = saved;
73
+ }
74
+ setWatchedAddresses(addresses) {
75
+ this._watchedAddresses = new Set(addresses);
76
+ }
77
+ getCursor() {
78
+ return this._cursor;
79
+ }
80
+ stop() {
81
+ this._stopped = true;
82
+ }
83
+ /**
84
+ * Poll for SOL or SPL token transfers to watched addresses.
85
+ *
86
+ * For each watched address:
87
+ * 1. Call getSignaturesForAddress to find recent transactions
88
+ * 2. Call getTransaction for each to extract transfer details
89
+ * 3. Detect native SOL transfers (balance diff) or SPL token transfers
90
+ *
91
+ * Cursor is the highest slot seen, advanced only for finalized transactions.
92
+ */
93
+ async poll() {
94
+ if (this._stopped || this._watchedAddresses.size === 0)
95
+ return [];
96
+ const events = [];
97
+ for (const address of this._watchedAddresses) {
98
+ if (this._stopped)
99
+ break;
100
+ const sigs = await this.getRecentSignatures(address);
101
+ if (sigs.length === 0)
102
+ continue;
103
+ for (const sig of sigs) {
104
+ if (this._stopped)
105
+ break;
106
+ if (sig.err)
107
+ continue;
108
+ if (sig.slot <= this._cursor)
109
+ continue;
110
+ const tx = (await this.rpc("getTransaction", [
111
+ sig.signature,
112
+ { encoding: "json", maxSupportedTransactionVersion: 0 },
113
+ ]));
114
+ if (!tx?.meta || tx.meta.err)
115
+ continue;
116
+ const txEvents = this.contractAddress
117
+ ? this.extractSplTransferEvents(tx, address, sig.signature)
118
+ : this.extractNativeTransferEvents(tx, address, sig.signature);
119
+ for (const evt of txEvents) {
120
+ // Skip if already emitted at this confirmation count
121
+ const txKey = `${sig.signature}:${evt.to}`;
122
+ const lastConf = await this.cursorStore.getConfirmationCount(this.watcherId, txKey);
123
+ if (lastConf !== null && evt.confirmations <= lastConf)
124
+ continue;
125
+ events.push(evt);
126
+ await this.cursorStore.saveConfirmationCount(this.watcherId, txKey, evt.confirmations);
127
+ }
128
+ // Advance cursor for finalized slots
129
+ if (sig.confirmationStatus === "finalized" && sig.slot > this._cursor) {
130
+ this._cursor = sig.slot;
131
+ await this.cursorStore.save(this.watcherId, this._cursor);
132
+ }
133
+ }
134
+ }
135
+ return events;
136
+ }
137
+ /** Fetch recent signatures for an address, filtering by slot > cursor. */
138
+ async getRecentSignatures(address) {
139
+ const params = { limit: 100 };
140
+ const sigs = (await this.rpc("getSignaturesForAddress", [address, params]));
141
+ // Filter to only signatures after our cursor and sort ascending by slot
142
+ return sigs.filter((s) => s.slot > this._cursor).sort((a, b) => a.slot - b.slot);
143
+ }
144
+ /**
145
+ * Extract native SOL transfer events from a transaction.
146
+ *
147
+ * Detects balance increases to the watched address by comparing
148
+ * preBalances and postBalances in the transaction metadata.
149
+ */
150
+ extractNativeTransferEvents(tx, watchedAddress, signature) {
151
+ const events = [];
152
+ const { accountKeys } = tx.transaction.message;
153
+ const meta = tx.meta;
154
+ if (!meta)
155
+ return events;
156
+ const { preBalances, postBalances } = meta;
157
+ const addrIndex = accountKeys.indexOf(watchedAddress);
158
+ if (addrIndex === -1)
159
+ return events;
160
+ const pre = BigInt(preBalances[addrIndex]);
161
+ const post = BigInt(postBalances[addrIndex]);
162
+ const diff = post - pre;
163
+ if (diff <= 0n)
164
+ return events;
165
+ // Determine sender: the first account with a balance decrease
166
+ let from = accountKeys[0]; // fee payer as fallback
167
+ for (let i = 0; i < accountKeys.length; i++) {
168
+ if (i === addrIndex)
169
+ continue;
170
+ const senderDiff = BigInt(postBalances[i]) - BigInt(preBalances[i]);
171
+ if (senderDiff < 0n) {
172
+ from = accountKeys[i];
173
+ break;
174
+ }
175
+ }
176
+ // Get current slot for confirmation count
177
+ const confs = this.confirmations; // simplified; real impl would compare against current slot
178
+ events.push({
179
+ chain: this.chain,
180
+ token: this.token,
181
+ from,
182
+ to: watchedAddress,
183
+ rawAmount: diff.toString(),
184
+ amountUsdCents: nativeToCents(diff, 1, SOL_DECIMALS), // price conversion done by caller via oracle
185
+ txHash: signature,
186
+ blockNumber: tx.slot,
187
+ confirmations: confs,
188
+ confirmationsRequired: this.confirmations,
189
+ });
190
+ return events;
191
+ }
192
+ /**
193
+ * Extract SPL token transfer events from a transaction.
194
+ *
195
+ * Compares preTokenBalances and postTokenBalances for the watched address
196
+ * filtered by the configured token mint (contractAddress).
197
+ */
198
+ extractSplTransferEvents(tx, watchedAddress, signature) {
199
+ const events = [];
200
+ const { accountKeys } = tx.transaction.message;
201
+ const mint = this.contractAddress;
202
+ if (!mint)
203
+ return events;
204
+ const pre = tx.meta?.preTokenBalances ?? [];
205
+ const post = tx.meta?.postTokenBalances ?? [];
206
+ // Find post-balances for our token mint owned by the watched address
207
+ for (const postBal of post) {
208
+ if (postBal.mint !== mint)
209
+ continue;
210
+ if (postBal.owner !== watchedAddress)
211
+ continue;
212
+ const postAmount = BigInt(postBal.uiTokenAmount.amount);
213
+ // Find matching pre-balance
214
+ const preBal = pre.find((p) => p.accountIndex === postBal.accountIndex && p.mint === mint && p.owner === watchedAddress);
215
+ const preAmount = preBal ? BigInt(preBal.uiTokenAmount.amount) : 0n;
216
+ const diff = postAmount - preAmount;
217
+ if (diff <= 0n)
218
+ continue;
219
+ // Determine sender: owner of any token account that decreased
220
+ let from = accountKeys[0];
221
+ for (const preTb of pre) {
222
+ if (preTb.mint !== mint)
223
+ continue;
224
+ if (preTb.owner === watchedAddress)
225
+ continue;
226
+ const matchingPost = post.find((p) => p.accountIndex === preTb.accountIndex && p.mint === mint);
227
+ if (matchingPost) {
228
+ const senderDiff = BigInt(matchingPost.uiTokenAmount.amount) - BigInt(preTb.uiTokenAmount.amount);
229
+ if (senderDiff < 0n && preTb.owner) {
230
+ from = preTb.owner;
231
+ break;
232
+ }
233
+ }
234
+ }
235
+ events.push({
236
+ chain: this.chain,
237
+ token: this.token,
238
+ from,
239
+ to: watchedAddress,
240
+ rawAmount: diff.toString(),
241
+ amountUsdCents: 0, // SPL stablecoins: conversion done by caller
242
+ txHash: signature,
243
+ blockNumber: tx.slot,
244
+ confirmations: this.confirmations,
245
+ confirmationsRequired: this.confirmations,
246
+ });
247
+ }
248
+ return events;
249
+ }
250
+ }
251
+ //# sourceMappingURL=watcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watcher.js","sourceRoot":"","sources":["../../src/solana/watcher.ts"],"names":[],"mappings":"AAQA,+DAA+D;AAC/D,MAAM,eAAe,GAAG,MAAO,CAAC;AAEhC,qCAAqC;AACrC,MAAM,YAAY,GAAG,CAAC,CAAC;AAEvB,uCAAuC;AACvC,MAAM,UAAU,qBAAqB,CAAC,MAAc,EAAE,YAAqC;IAC1F,IAAI,EAAE,GAAG,CAAC,CAAC;IACX,MAAM,OAAO,GAA2B,EAAE,cAAc,EAAE,kBAAkB,EAAE,GAAG,YAAY,EAAE,CAAC;IAChG,OAAO,KAAK,EAAE,MAAc,EAAE,MAAiB,EAAoB,EAAE;QACpE,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,MAAM,EAAE;YAC/B,MAAM,EAAE,MAAM;YACd,OAAO;YACP,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;SAClE,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACb,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;YAC9C,MAAM,IAAI,KAAK,CAAC,cAAc,MAAM,YAAY,GAAG,CAAC,MAAM,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;QACrF,CAAC;QACD,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAsD,CAAC;QACrF,IAAI,IAAI,CAAC,KAAK;YAAE,MAAM,IAAI,KAAK,CAAC,cAAc,MAAM,WAAW,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QACrF,OAAO,IAAI,CAAC,MAAM,CAAC;IACpB,CAAC,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,aAAa,CAAC,QAAgB,EAAE,WAAmB,EAAE,QAAgB;IAC7E,IAAI,QAAQ,GAAG,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;IACpE,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,WAAW,CAAC,IAAI,WAAW,IAAI,CAAC,EAAE,CAAC;QACxD,MAAM,IAAI,KAAK,CAAC,+CAA+C,WAAW,EAAE,CAAC,CAAC;IAC/E,CAAC;IACD,OAAO,MAAM,CAAC,CAAC,QAAQ,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,eAAe,GAAG,GAAG,IAAI,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AAC/F,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,OAAO,aAAa;IACjB,OAAO,GAAG,CAAC,CAAC;IACZ,QAAQ,GAAG,KAAK,CAAC;IACR,KAAK,CAAS;IACd,KAAK,CAAS;IACd,GAAG,CAAgB;IACnB,aAAa,CAAS;IACtB,QAAQ,CAAS;IACjB,WAAW,CAAsB;IACjC,SAAS,CAAS;IAClB,eAAe,CAAU;IAClC,iBAAiB,CAAc;IAEvC,YAAY,IAAiB;QAC5B,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;QACxB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;QACxB,IAAI,CAAC,GAAG,GAAG,qBAAqB,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;QAC/D,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC;QACjB,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,aAAa,CAAC;QACxC,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;QAC9B,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC;QACpC,IAAI,CAAC,SAAS,GAAG,UAAU,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QACtD,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,eAAe,CAAC;QAC5C,IAAI,CAAC,iBAAiB,GAAG,IAAI,GAAG,EAAU,CAAC;IAC5C,CAAC;IAED,KAAK,CAAC,IAAI;QACT,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACzD,IAAI,KAAK,KAAK,IAAI;YAAE,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;IAC1C,CAAC;IAED,mBAAmB,CAAC,SAAmB;QACtC,IAAI,CAAC,iBAAiB,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC;IAC7C,CAAC;IAED,SAAS;QACR,OAAO,IAAI,CAAC,OAAO,CAAC;IACrB,CAAC;IAED,IAAI;QACH,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;IACtB,CAAC;IAED;;;;;;;;;OASG;IACH,KAAK,CAAC,IAAI;QACT,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,iBAAiB,CAAC,IAAI,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QAElE,MAAM,MAAM,GAAmB,EAAE,CAAC;QAElC,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,iBAAiB,EAAE,CAAC;YAC9C,IAAI,IAAI,CAAC,QAAQ;gBAAE,MAAM;YAEzB,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAC;YACrD,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;gBAAE,SAAS;YAEhC,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;gBACxB,IAAI,IAAI,CAAC,QAAQ;oBAAE,MAAM;gBACzB,IAAI,GAAG,CAAC,GAAG;oBAAE,SAAS;gBACtB,IAAI,GAAG,CAAC,IAAI,IAAI,IAAI,CAAC,OAAO;oBAAE,SAAS;gBAEvC,MAAM,EAAE,GAAG,CAAC,MAAM,IAAI,CAAC,GAAG,CAAC,gBAAgB,EAAE;oBAC5C,GAAG,CAAC,SAAS;oBACb,EAAE,QAAQ,EAAE,MAAM,EAAE,8BAA8B,EAAE,CAAC,EAAE;iBACvD,CAAC,CAA6B,CAAC;gBAEhC,IAAI,CAAC,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,IAAI,CAAC,GAAG;oBAAE,SAAS;gBAEvC,MAAM,QAAQ,GAAG,IAAI,CAAC,eAAe;oBACpC,CAAC,CAAC,IAAI,CAAC,wBAAwB,CAAC,EAAE,EAAE,OAAO,EAAE,GAAG,CAAC,SAAS,CAAC;oBAC3D,CAAC,CAAC,IAAI,CAAC,2BAA2B,CAAC,EAAE,EAAE,OAAO,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC;gBAEhE,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;oBAC5B,qDAAqD;oBACrD,MAAM,KAAK,GAAG,GAAG,GAAG,CAAC,SAAS,IAAI,GAAG,CAAC,EAAE,EAAE,CAAC;oBAC3C,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,oBAAoB,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;oBACpF,IAAI,QAAQ,KAAK,IAAI,IAAI,GAAG,CAAC,aAAa,IAAI,QAAQ;wBAAE,SAAS;oBAEjE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;oBACjB,MAAM,IAAI,CAAC,WAAW,CAAC,qBAAqB,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,EAAE,GAAG,CAAC,aAAa,CAAC,CAAC;gBACxF,CAAC;gBAED,qCAAqC;gBACrC,IAAI,GAAG,CAAC,kBAAkB,KAAK,WAAW,IAAI,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;oBACvE,IAAI,CAAC,OAAO,GAAG,GAAG,CAAC,IAAI,CAAC;oBACxB,MAAM,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;gBAC3D,CAAC;YACF,CAAC;QACF,CAAC;QAED,OAAO,MAAM,CAAC;IACf,CAAC;IAED,0EAA0E;IAClE,KAAK,CAAC,mBAAmB,CAAC,OAAe;QAChD,MAAM,MAAM,GAA4B,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;QACvD,MAAM,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,GAAG,CAAC,yBAAyB,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAoB,CAAC;QAC/F,wEAAwE;QACxE,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;IAClF,CAAC;IAED;;;;;OAKG;IACK,2BAA2B,CAClC,EAAqB,EACrB,cAAsB,EACtB,SAAiB;QAEjB,MAAM,MAAM,GAAmB,EAAE,CAAC;QAClC,MAAM,EAAE,WAAW,EAAE,GAAG,EAAE,CAAC,WAAW,CAAC,OAAO,CAAC;QAC/C,MAAM,IAAI,GAAG,EAAE,CAAC,IAAI,CAAC;QACrB,IAAI,CAAC,IAAI;YAAE,OAAO,MAAM,CAAC;QACzB,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,GAAG,IAAI,CAAC;QAE3C,MAAM,SAAS,GAAG,WAAW,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;QACtD,IAAI,SAAS,KAAK,CAAC,CAAC;YAAE,OAAO,MAAM,CAAC;QAEpC,MAAM,GAAG,GAAG,MAAM,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,CAAC;QAC3C,MAAM,IAAI,GAAG,MAAM,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC,CAAC;QAC7C,MAAM,IAAI,GAAG,IAAI,GAAG,GAAG,CAAC;QAExB,IAAI,IAAI,IAAI,EAAE;YAAE,OAAO,MAAM,CAAC;QAE9B,8DAA8D;QAC9D,IAAI,IAAI,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,wBAAwB;QACnD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,WAAW,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC7C,IAAI,CAAC,KAAK,SAAS;gBAAE,SAAS;YAC9B,MAAM,UAAU,GAAG,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;YACpE,IAAI,UAAU,GAAG,EAAE,EAAE,CAAC;gBACrB,IAAI,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;gBACtB,MAAM;YACP,CAAC;QACF,CAAC;QAED,0CAA0C;QAC1C,MAAM,KAAK,GAAG,IAAI,CAAC,aAAa,CAAC,CAAC,2DAA2D;QAE7F,MAAM,CAAC,IAAI,CAAC;YACX,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,IAAI;YACJ,EAAE,EAAE,cAAc;YAClB,SAAS,EAAE,IAAI,CAAC,QAAQ,EAAE;YAC1B,cAAc,EAAE,aAAa,CAAC,IAAI,EAAE,CAAC,EAAE,YAAY,CAAC,EAAE,6CAA6C;YACnG,MAAM,EAAE,SAAS;YACjB,WAAW,EAAE,EAAE,CAAC,IAAI;YACpB,aAAa,EAAE,KAAK;YACpB,qBAAqB,EAAE,IAAI,CAAC,aAAa;SACzC,CAAC,CAAC;QAEH,OAAO,MAAM,CAAC;IACf,CAAC;IAED;;;;;OAKG;IACK,wBAAwB,CAAC,EAAqB,EAAE,cAAsB,EAAE,SAAiB;QAChG,MAAM,MAAM,GAAmB,EAAE,CAAC;QAClC,MAAM,EAAE,WAAW,EAAE,GAAG,EAAE,CAAC,WAAW,CAAC,OAAO,CAAC;QAC/C,MAAM,IAAI,GAAG,IAAI,CAAC,eAAe,CAAC;QAClC,IAAI,CAAC,IAAI;YAAE,OAAO,MAAM,CAAC;QAEzB,MAAM,GAAG,GAAG,EAAE,CAAC,IAAI,EAAE,gBAAgB,IAAI,EAAE,CAAC;QAC5C,MAAM,IAAI,GAAG,EAAE,CAAC,IAAI,EAAE,iBAAiB,IAAI,EAAE,CAAC;QAE9C,qEAAqE;QACrE,KAAK,MAAM,OAAO,IAAI,IAAI,EAAE,CAAC;YAC5B,IAAI,OAAO,CAAC,IAAI,KAAK,IAAI;gBAAE,SAAS;YACpC,IAAI,OAAO,CAAC,KAAK,KAAK,cAAc;gBAAE,SAAS;YAE/C,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;YAExD,4BAA4B;YAC5B,MAAM,MAAM,GAAG,GAAG,CAAC,IAAI,CACtB,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,KAAK,OAAO,CAAC,YAAY,IAAI,CAAC,CAAC,IAAI,KAAK,IAAI,IAAI,CAAC,CAAC,KAAK,KAAK,cAAc,CAC/F,CAAC;YACF,MAAM,SAAS,GAAG,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAEpE,MAAM,IAAI,GAAG,UAAU,GAAG,SAAS,CAAC;YACpC,IAAI,IAAI,IAAI,EAAE;gBAAE,SAAS;YAEzB,8DAA8D;YAC9D,IAAI,IAAI,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;YAC1B,KAAK,MAAM,KAAK,IAAI,GAAG,EAAE,CAAC;gBACzB,IAAI,KAAK,CAAC,IAAI,KAAK,IAAI;oBAAE,SAAS;gBAClC,IAAI,KAAK,CAAC,KAAK,KAAK,cAAc;oBAAE,SAAS;gBAC7C,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,KAAK,KAAK,CAAC,YAAY,IAAI,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;gBAChG,IAAI,YAAY,EAAE,CAAC;oBAClB,MAAM,UAAU,GAAG,MAAM,CAAC,YAAY,CAAC,aAAa,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;oBAClG,IAAI,UAAU,GAAG,EAAE,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;wBACpC,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC;wBACnB,MAAM;oBACP,CAAC;gBACF,CAAC;YACF,CAAC;YAED,MAAM,CAAC,IAAI,CAAC;gBACX,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,IAAI;gBACJ,EAAE,EAAE,cAAc;gBAClB,SAAS,EAAE,IAAI,CAAC,QAAQ,EAAE;gBAC1B,cAAc,EAAE,CAAC,EAAE,6CAA6C;gBAChE,MAAM,EAAE,SAAS;gBACjB,WAAW,EAAE,EAAE,CAAC,IAAI;gBACpB,aAAa,EAAE,IAAI,CAAC,aAAa;gBACjC,qBAAqB,EAAE,IAAI,CAAC,aAAa;aACzC,CAAC,CAAC;QACJ,CAAC;QAED,OAAO,MAAM,CAAC;IACf,CAAC;CACD"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * EVM sweep strategy -- consolidates ETH + ERC-20s from deposit addresses to treasury.
3
+ *
4
+ * 3-phase sweep:
5
+ * 1. Sweep ETH first -- deposit addresses self-fund gas, treasury receives ETH
6
+ * 2. Fund gas -- treasury sends ETH to ERC-20 deposit addresses
7
+ * 3. Sweep ERC-20s -- deposit addresses send all tokens to treasury
8
+ */
9
+ import type { DepositInfo, ISweepStrategy, KeyPair, SweepResult } from "@wopr-network/platform-core/crypto-plugin";
10
+ import { type Address } from "viem";
11
+ export interface EvmToken {
12
+ name: string;
13
+ address: Address;
14
+ decimals: number;
15
+ }
16
+ export interface EvmSweeperOpts {
17
+ rpcUrl: string;
18
+ chainName: string;
19
+ tokens: EvmToken[];
20
+ }
21
+ export declare class EvmSweeper implements ISweepStrategy {
22
+ private readonly rpcUrl;
23
+ private readonly chainName;
24
+ private readonly tokens;
25
+ private readonly chain;
26
+ private readonly publicClient;
27
+ constructor(opts: EvmSweeperOpts);
28
+ scan(keys: KeyPair[], _treasury: string): Promise<DepositInfo[]>;
29
+ sweep(keys: KeyPair[], treasury: string, dryRun: boolean): Promise<SweepResult[]>;
30
+ }
31
+ //# sourceMappingURL=evm-sweeper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evm-sweeper.d.ts","sourceRoot":"","sources":["../../src/sweep/evm-sweeper.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,2CAA2C,CAAC;AACnH,OAAO,EACN,KAAK,OAAO,EAUZ,MAAM,MAAM,CAAC;AAuBd,MAAM,WAAW,QAAQ;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,QAAQ,EAAE,CAAC;CACnB;AAED,qBAAa,UAAW,YAAW,cAAc;IAChD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAa;IACpC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAQ;IAC9B,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAiC;gBAElD,IAAI,EAAE,cAAc;IAkB1B,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAyChE,KAAK,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;CA0KvF"}
@@ -0,0 +1,229 @@
1
+ import { createPublicClient, createWalletClient, defineChain, formatEther, formatUnits, http, } from "viem";
2
+ import { privateKeyToAccount } from "viem/accounts";
3
+ const ERC20_ABI = [
4
+ {
5
+ name: "balanceOf",
6
+ type: "function",
7
+ stateMutability: "view",
8
+ inputs: [{ name: "account", type: "address" }],
9
+ outputs: [{ name: "", type: "uint256" }],
10
+ },
11
+ {
12
+ name: "transfer",
13
+ type: "function",
14
+ stateMutability: "nonpayable",
15
+ inputs: [
16
+ { name: "to", type: "address" },
17
+ { name: "amount", type: "uint256" },
18
+ ],
19
+ outputs: [{ name: "", type: "bool" }],
20
+ },
21
+ ];
22
+ export class EvmSweeper {
23
+ rpcUrl;
24
+ chainName;
25
+ tokens;
26
+ chain;
27
+ publicClient;
28
+ constructor(opts) {
29
+ this.rpcUrl = opts.rpcUrl;
30
+ this.chainName = opts.chainName;
31
+ this.tokens = opts.tokens;
32
+ this.chain = defineChain({
33
+ id: 1,
34
+ name: this.chainName,
35
+ nativeCurrency: { name: "ETH", symbol: "ETH", decimals: 18 },
36
+ rpcUrls: { default: { http: [this.rpcUrl] } },
37
+ });
38
+ this.publicClient = createPublicClient({
39
+ chain: this.chain,
40
+ transport: http(this.rpcUrl),
41
+ });
42
+ }
43
+ async scan(keys, _treasury) {
44
+ const deposits = [];
45
+ for (const key of keys) {
46
+ const addr = key.address;
47
+ const ethBalance = await this.publicClient.getBalance({ address: addr });
48
+ const tokenBalances = [];
49
+ for (const token of this.tokens) {
50
+ try {
51
+ const balance = await this.publicClient.readContract({
52
+ address: token.address,
53
+ abi: ERC20_ABI,
54
+ functionName: "balanceOf",
55
+ args: [addr],
56
+ });
57
+ if (balance > 0n) {
58
+ tokenBalances.push({
59
+ token: token.name,
60
+ balance,
61
+ decimals: token.decimals,
62
+ });
63
+ }
64
+ }
65
+ catch {
66
+ // Contract may not exist on this chain
67
+ }
68
+ }
69
+ if (ethBalance > 0n || tokenBalances.length > 0) {
70
+ deposits.push({
71
+ index: key.index,
72
+ address: key.address,
73
+ nativeBalance: ethBalance,
74
+ tokenBalances,
75
+ });
76
+ }
77
+ }
78
+ return deposits;
79
+ }
80
+ async sweep(keys, treasury, dryRun) {
81
+ const treasuryAddress = treasury;
82
+ const deposits = await this.scan(keys, treasury);
83
+ if (deposits.length === 0) {
84
+ console.log(" No EVM deposits with balances.");
85
+ return [];
86
+ }
87
+ const gasPrice = await this.publicClient.getGasPrice();
88
+ const ethTransferGas = 21000n * gasPrice;
89
+ const erc20TransferGas = 65000n * gasPrice;
90
+ const ethDeposits = deposits.filter((d) => d.nativeBalance > ethTransferGas);
91
+ const tokenDeposits = deposits.filter((d) => d.tokenBalances.length > 0);
92
+ // Print scan summary
93
+ const totalEth = ethDeposits.reduce((sum, d) => sum + d.nativeBalance, 0n);
94
+ console.log(` Found ${ethDeposits.length} ETH deposits (${formatEther(totalEth)} ETH)`);
95
+ for (const token of this.tokens) {
96
+ const total = tokenDeposits.reduce((sum, d) => sum + (d.tokenBalances.find((t) => t.token === token.name)?.balance ?? 0n), 0n);
97
+ if (total > 0n) {
98
+ console.log(` ${formatUnits(total, token.decimals)} ${token.name}`);
99
+ }
100
+ }
101
+ if (dryRun)
102
+ return [];
103
+ const results = [];
104
+ const keyMap = new Map(keys.map((k) => [k.index, k]));
105
+ // Phase 1: Sweep ETH (self-funded gas)
106
+ if (ethDeposits.length > 0) {
107
+ console.log(" Phase 1: Sweeping ETH to treasury (self-funded gas)");
108
+ for (const dep of ethDeposits) {
109
+ const key = keyMap.get(dep.index);
110
+ if (!key)
111
+ continue;
112
+ const privHex = toHexString(key.privateKey);
113
+ const depAccount = privateKeyToAccount(privHex);
114
+ const depWallet = createWalletClient({
115
+ chain: this.chain,
116
+ transport: http(this.rpcUrl),
117
+ account: depAccount,
118
+ });
119
+ const sweepAmount = dep.nativeBalance - ethTransferGas;
120
+ if (sweepAmount <= 0n) {
121
+ console.log(` [${dep.index}] Balance too low to cover gas, skipping`);
122
+ continue;
123
+ }
124
+ const hash = await depWallet.sendTransaction({
125
+ to: treasuryAddress,
126
+ value: sweepAmount,
127
+ });
128
+ console.log(` [${dep.index}] Swept ${formatEther(sweepAmount)} ETH: ${hash}`);
129
+ await this.publicClient.waitForTransactionReceipt({ hash });
130
+ results.push({
131
+ index: dep.index,
132
+ address: dep.address,
133
+ token: "ETH",
134
+ amount: formatEther(sweepAmount),
135
+ txHash: hash,
136
+ });
137
+ }
138
+ }
139
+ // Phase 2: Fund gas for ERC-20 sweeps
140
+ if (tokenDeposits.length > 0) {
141
+ const treasuryKey = keys.find((k) => k.address.toLowerCase() === treasury.toLowerCase());
142
+ if (!treasuryKey) {
143
+ // Treasury key not in the deposit keys -- derive from the first key's parent
144
+ // The caller must ensure the treasury key is passed separately or handle this
145
+ console.log(" Warning: treasury key not found in key set, using external treasury wallet");
146
+ }
147
+ console.log(" Phase 2: Funding gas for ERC-20 sweeps");
148
+ const treasuryEth = await this.publicClient.getBalance({
149
+ address: treasuryAddress,
150
+ });
151
+ const totalGasNeeded = erc20TransferGas * BigInt(tokenDeposits.reduce((n, d) => n + d.tokenBalances.length, 0));
152
+ console.log(` Treasury ETH: ${formatEther(treasuryEth)}, gas needed: ${formatEther(totalGasNeeded)}`);
153
+ if (treasuryEth < totalGasNeeded) {
154
+ console.error(` Insufficient treasury ETH for gas. Need ${formatEther(totalGasNeeded)}, have ${formatEther(treasuryEth)}.`);
155
+ return results;
156
+ }
157
+ // We need to create a treasury wallet -- derive key for chain=1, index=0
158
+ // This is handled by the caller passing treasuryPrivKey via env or key array
159
+ // For now, we assume the treasury has enough gas from the ETH sweep
160
+ const treasuryPrivHex = treasuryKey ? toHexString(treasuryKey.privateKey) : null;
161
+ if (!treasuryPrivHex) {
162
+ console.error(" Cannot fund gas: treasury private key not available");
163
+ return results;
164
+ }
165
+ const treasuryWallet = createWalletClient({
166
+ chain: this.chain,
167
+ transport: http(this.rpcUrl),
168
+ account: privateKeyToAccount(treasuryPrivHex),
169
+ });
170
+ for (const dep of tokenDeposits) {
171
+ const depEth = await this.publicClient.getBalance({
172
+ address: dep.address,
173
+ });
174
+ const needed = erc20TransferGas * BigInt(dep.tokenBalances.length);
175
+ if (depEth >= needed) {
176
+ console.log(` [${dep.index}] Already has gas, skipping`);
177
+ continue;
178
+ }
179
+ const hash = await treasuryWallet.sendTransaction({
180
+ to: dep.address,
181
+ value: needed - depEth,
182
+ });
183
+ console.log(` [${dep.index}] Funded ${formatEther(needed - depEth)} ETH: ${hash}`);
184
+ await this.publicClient.waitForTransactionReceipt({ hash });
185
+ }
186
+ // Phase 3: Sweep ERC-20s
187
+ console.log(" Phase 3: Sweeping ERC-20s to treasury");
188
+ for (const dep of tokenDeposits) {
189
+ const key = keyMap.get(dep.index);
190
+ if (!key)
191
+ continue;
192
+ const privHex = toHexString(key.privateKey);
193
+ const depAccount = privateKeyToAccount(privHex);
194
+ const depWallet = createWalletClient({
195
+ chain: this.chain,
196
+ transport: http(this.rpcUrl),
197
+ account: depAccount,
198
+ });
199
+ for (const tokenBal of dep.tokenBalances) {
200
+ const tokenDef = this.tokens.find((t) => t.name === tokenBal.token);
201
+ if (!tokenDef)
202
+ continue;
203
+ const hash = await depWallet.writeContract({
204
+ address: tokenDef.address,
205
+ abi: ERC20_ABI,
206
+ functionName: "transfer",
207
+ args: [treasuryAddress, tokenBal.balance],
208
+ });
209
+ console.log(` [${dep.index}] Swept ${formatUnits(tokenBal.balance, tokenBal.decimals)} ${tokenBal.token}: ${hash}`);
210
+ await this.publicClient.waitForTransactionReceipt({
211
+ hash,
212
+ });
213
+ results.push({
214
+ index: dep.index,
215
+ address: dep.address,
216
+ token: tokenBal.token,
217
+ amount: formatUnits(tokenBal.balance, tokenBal.decimals),
218
+ txHash: hash,
219
+ });
220
+ }
221
+ }
222
+ }
223
+ return results;
224
+ }
225
+ }
226
+ function toHexString(bytes) {
227
+ return `0x${Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("")}`;
228
+ }
229
+ //# sourceMappingURL=evm-sweeper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evm-sweeper.js","sourceRoot":"","sources":["../../src/sweep/evm-sweeper.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Unified crypto sweep CLI -- consolidates deposits from all chains to treasury.
4
+ *
5
+ * Reads mnemonic from stdin, fetches chain config from chain server,
6
+ * dispatches to per-chain sweep strategies.
7
+ *
8
+ * Usage:
9
+ * openssl enc -aes-256-cbc -pbkdf2 -iter 100000 -d -pass pass:<passphrase> \
10
+ * -in "/mnt/g/My Drive/paperclip-wallet.enc" \
11
+ * | CRYPTO_SERVICE_URL=http://167.71.118.221:3100 \
12
+ * CRYPTO_SERVICE_KEY=sk-chain-2026 \
13
+ * crypto-sweep
14
+ *
15
+ * Env vars:
16
+ * CRYPTO_SERVICE_URL -- Chain server URL (required)
17
+ * CRYPTO_SERVICE_KEY -- Chain server auth key (optional)
18
+ * SWEEP_DRY_RUN -- set to "false" to actually broadcast (default: true)
19
+ * MAX_ADDRESSES -- how many deposit addresses to scan (default: 200)
20
+ */
21
+ export {};
22
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/sweep/index.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;;;;;;;;;GAkBG"}