@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.
- package/.github/workflows/ci.yml +33 -0
- package/.github/workflows/publish.yml +12 -0
- package/biome.json +23 -0
- package/dist/__tests__/bitcoin-encoder.test.d.ts +2 -0
- package/dist/__tests__/bitcoin-encoder.test.d.ts.map +1 -0
- package/dist/__tests__/bitcoin-encoder.test.js +97 -0
- package/dist/__tests__/bitcoin-encoder.test.js.map +1 -0
- package/dist/__tests__/dogecoin-encoder.test.d.ts +2 -0
- package/dist/__tests__/dogecoin-encoder.test.d.ts.map +1 -0
- package/dist/__tests__/dogecoin-encoder.test.js +57 -0
- package/dist/__tests__/dogecoin-encoder.test.js.map +1 -0
- package/dist/__tests__/litecoin-encoder.test.d.ts +2 -0
- package/dist/__tests__/litecoin-encoder.test.d.ts.map +1 -0
- package/dist/__tests__/litecoin-encoder.test.js +44 -0
- package/dist/__tests__/litecoin-encoder.test.js.map +1 -0
- package/dist/__tests__/registry.test.d.ts +2 -0
- package/dist/__tests__/registry.test.d.ts.map +1 -0
- package/dist/__tests__/registry.test.js +75 -0
- package/dist/__tests__/registry.test.js.map +1 -0
- package/dist/__tests__/rpc.test.d.ts +2 -0
- package/dist/__tests__/rpc.test.d.ts.map +1 -0
- package/dist/__tests__/rpc.test.js +31 -0
- package/dist/__tests__/rpc.test.js.map +1 -0
- package/dist/__tests__/solana-encoder.test.d.ts +2 -0
- package/dist/__tests__/solana-encoder.test.d.ts.map +1 -0
- package/dist/__tests__/solana-encoder.test.js +85 -0
- package/dist/__tests__/solana-encoder.test.js.map +1 -0
- package/dist/__tests__/solana-watcher.test.d.ts +2 -0
- package/dist/__tests__/solana-watcher.test.d.ts.map +1 -0
- package/dist/__tests__/solana-watcher.test.js +281 -0
- package/dist/__tests__/solana-watcher.test.js.map +1 -0
- package/dist/__tests__/sweep-key-parity.test.d.ts +2 -0
- package/dist/__tests__/sweep-key-parity.test.d.ts.map +1 -0
- package/dist/__tests__/sweep-key-parity.test.js +236 -0
- package/dist/__tests__/sweep-key-parity.test.js.map +1 -0
- package/dist/__tests__/tron-encoder.test.d.ts +2 -0
- package/dist/__tests__/tron-encoder.test.d.ts.map +1 -0
- package/dist/__tests__/tron-encoder.test.js +93 -0
- package/dist/__tests__/tron-encoder.test.js.map +1 -0
- package/dist/__tests__/utxo-watcher.test.d.ts +2 -0
- package/dist/__tests__/utxo-watcher.test.d.ts.map +1 -0
- package/dist/__tests__/utxo-watcher.test.js +218 -0
- package/dist/__tests__/utxo-watcher.test.js.map +1 -0
- package/dist/bitcoin/encoder.d.ts +15 -0
- package/dist/bitcoin/encoder.d.ts.map +1 -0
- package/dist/bitcoin/encoder.js +286 -0
- package/dist/bitcoin/encoder.js.map +1 -0
- package/dist/bitcoin/index.d.ts +4 -0
- package/dist/bitcoin/index.d.ts.map +1 -0
- package/dist/bitcoin/index.js +20 -0
- package/dist/bitcoin/index.js.map +1 -0
- package/dist/dogecoin/encoder.d.ts +19 -0
- package/dist/dogecoin/encoder.d.ts.map +1 -0
- package/dist/dogecoin/encoder.js +145 -0
- package/dist/dogecoin/encoder.js.map +1 -0
- package/dist/dogecoin/index.d.ts +4 -0
- package/dist/dogecoin/index.d.ts.map +1 -0
- package/dist/dogecoin/index.js +20 -0
- package/dist/dogecoin/index.js.map +1 -0
- package/dist/evm/encoder.d.ts +7 -0
- package/dist/evm/encoder.d.ts.map +1 -0
- package/dist/evm/encoder.js +43 -0
- package/dist/evm/encoder.js.map +1 -0
- package/dist/evm/eth-watcher.d.ts +38 -0
- package/dist/evm/eth-watcher.d.ts.map +1 -0
- package/dist/evm/eth-watcher.js +138 -0
- package/dist/evm/eth-watcher.js.map +1 -0
- package/dist/evm/index.d.ts +16 -0
- package/dist/evm/index.d.ts.map +1 -0
- package/dist/evm/index.js +34 -0
- package/dist/evm/index.js.map +1 -0
- package/dist/evm/types.d.ts +43 -0
- package/dist/evm/types.d.ts.map +1 -0
- package/dist/evm/types.js +101 -0
- package/dist/evm/types.js.map +1 -0
- package/dist/evm/watcher.d.ts +42 -0
- package/dist/evm/watcher.d.ts.map +1 -0
- package/dist/evm/watcher.js +162 -0
- package/dist/evm/watcher.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/litecoin/encoder.d.ts +8 -0
- package/dist/litecoin/encoder.d.ts.map +1 -0
- package/dist/litecoin/encoder.js +16 -0
- package/dist/litecoin/encoder.js.map +1 -0
- package/dist/litecoin/index.d.ts +4 -0
- package/dist/litecoin/index.d.ts.map +1 -0
- package/dist/litecoin/index.js +20 -0
- package/dist/litecoin/index.js.map +1 -0
- package/dist/shared/test-helpers/index.d.ts +9 -0
- package/dist/shared/test-helpers/index.d.ts.map +1 -0
- package/dist/shared/test-helpers/index.js +30 -0
- package/dist/shared/test-helpers/index.js.map +1 -0
- package/dist/shared/utxo/index.d.ts +5 -0
- package/dist/shared/utxo/index.d.ts.map +1 -0
- package/dist/shared/utxo/index.js +3 -0
- package/dist/shared/utxo/index.js.map +1 -0
- package/dist/shared/utxo/rpc.d.ts +24 -0
- package/dist/shared/utxo/rpc.d.ts.map +1 -0
- package/dist/shared/utxo/rpc.js +75 -0
- package/dist/shared/utxo/rpc.js.map +1 -0
- package/dist/shared/utxo/types.d.ts +40 -0
- package/dist/shared/utxo/types.d.ts.map +1 -0
- package/dist/shared/utxo/types.js +2 -0
- package/dist/shared/utxo/types.js.map +1 -0
- package/dist/shared/utxo/watcher.d.ts +55 -0
- package/dist/shared/utxo/watcher.d.ts.map +1 -0
- package/dist/shared/utxo/watcher.js +150 -0
- package/dist/shared/utxo/watcher.js.map +1 -0
- package/dist/solana/encoder.d.ts +13 -0
- package/dist/solana/encoder.d.ts.map +1 -0
- package/dist/solana/encoder.js +62 -0
- package/dist/solana/encoder.js.map +1 -0
- package/dist/solana/index.d.ts +17 -0
- package/dist/solana/index.d.ts.map +1 -0
- package/dist/solana/index.js +32 -0
- package/dist/solana/index.js.map +1 -0
- package/dist/solana/sweeper.d.ts +47 -0
- package/dist/solana/sweeper.d.ts.map +1 -0
- package/dist/solana/sweeper.js +151 -0
- package/dist/solana/sweeper.js.map +1 -0
- package/dist/solana/types.d.ts +49 -0
- package/dist/solana/types.d.ts.map +1 -0
- package/dist/solana/types.js +2 -0
- package/dist/solana/types.js.map +1 -0
- package/dist/solana/watcher.d.ts +59 -0
- package/dist/solana/watcher.d.ts.map +1 -0
- package/dist/solana/watcher.js +251 -0
- package/dist/solana/watcher.js.map +1 -0
- package/dist/sweep/evm-sweeper.d.ts +31 -0
- package/dist/sweep/evm-sweeper.d.ts.map +1 -0
- package/dist/sweep/evm-sweeper.js +229 -0
- package/dist/sweep/evm-sweeper.js.map +1 -0
- package/dist/sweep/index.d.ts +22 -0
- package/dist/sweep/index.d.ts.map +1 -0
- package/dist/sweep/index.js +290 -0
- package/dist/sweep/index.js.map +1 -0
- package/dist/sweep/tron-sweeper.d.ts +40 -0
- package/dist/sweep/tron-sweeper.d.ts.map +1 -0
- package/dist/sweep/tron-sweeper.js +363 -0
- package/dist/sweep/tron-sweeper.js.map +1 -0
- package/dist/sweep/utxo-sweeper.d.ts +14 -0
- package/dist/sweep/utxo-sweeper.d.ts.map +1 -0
- package/dist/sweep/utxo-sweeper.js +13 -0
- package/dist/sweep/utxo-sweeper.js.map +1 -0
- package/dist/tron/address-convert.d.ts +15 -0
- package/dist/tron/address-convert.d.ts.map +1 -0
- package/dist/tron/address-convert.js +95 -0
- package/dist/tron/address-convert.js.map +1 -0
- package/dist/tron/encoder.d.ts +20 -0
- package/dist/tron/encoder.d.ts.map +1 -0
- package/dist/tron/encoder.js +67 -0
- package/dist/tron/encoder.js.map +1 -0
- package/dist/tron/index.d.ts +6 -0
- package/dist/tron/index.d.ts.map +1 -0
- package/dist/tron/index.js +20 -0
- package/dist/tron/index.js.map +1 -0
- package/dist/tron/sha256.d.ts +6 -0
- package/dist/tron/sha256.d.ts.map +1 -0
- package/dist/tron/sha256.js +90 -0
- package/dist/tron/sha256.js.map +1 -0
- package/dist/tron/watcher.d.ts +42 -0
- package/dist/tron/watcher.d.ts.map +1 -0
- package/dist/tron/watcher.js +168 -0
- package/dist/tron/watcher.js.map +1 -0
- package/package.json +47 -0
- package/src/__tests__/bitcoin-encoder.test.ts +115 -0
- package/src/__tests__/dogecoin-encoder.test.ts +66 -0
- package/src/__tests__/litecoin-encoder.test.ts +51 -0
- package/src/__tests__/registry.test.ts +91 -0
- package/src/__tests__/rpc.test.ts +36 -0
- package/src/__tests__/solana-encoder.test.ts +103 -0
- package/src/__tests__/solana-watcher.test.ts +316 -0
- package/src/__tests__/sweep-key-parity.test.ts +302 -0
- package/src/__tests__/tron-encoder.test.ts +108 -0
- package/src/__tests__/utxo-watcher.test.ts +252 -0
- package/src/bitcoin/encoder.ts +320 -0
- package/src/bitcoin/index.ts +23 -0
- package/src/dogecoin/encoder.ts +161 -0
- package/src/dogecoin/index.ts +23 -0
- package/src/evm/encoder.ts +49 -0
- package/src/evm/eth-watcher.ts +168 -0
- package/src/evm/index.ts +46 -0
- package/src/evm/types.ts +146 -0
- package/src/evm/watcher.ts +189 -0
- package/src/index.ts +21 -0
- package/src/litecoin/encoder.ts +18 -0
- package/src/litecoin/index.ts +23 -0
- package/src/shared/test-helpers/index.ts +36 -0
- package/src/shared/utxo/index.ts +12 -0
- package/src/shared/utxo/rpc.ts +80 -0
- package/src/shared/utxo/types.ts +43 -0
- package/src/shared/utxo/watcher.ts +195 -0
- package/src/solana/encoder.ts +72 -0
- package/src/solana/index.ts +36 -0
- package/src/solana/sweeper.ts +196 -0
- package/src/solana/types.ts +52 -0
- package/src/solana/watcher.ts +282 -0
- package/src/sweep/evm-sweeper.ts +296 -0
- package/src/sweep/index.ts +353 -0
- package/src/sweep/tron-sweeper.ts +467 -0
- package/src/sweep/utxo-sweeper.ts +23 -0
- package/src/tron/address-convert.ts +91 -0
- package/src/tron/encoder.ts +74 -0
- package/src/tron/index.ts +23 -0
- package/src/tron/sha256.ts +100 -0
- package/src/tron/watcher.ts +208 -0
- package/tsconfig.json +17 -0
- 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":"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"}
|
|
@@ -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"}
|