@waiaas/adapter-evm 2.5.0 → 2.6.0-rc

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.
@@ -0,0 +1,36 @@
1
+ /**
2
+ * EvmIncomingSubscriber -- IChainSubscriber implementation for EVM chains.
3
+ *
4
+ * Detection strategy: polling-first (design decision D-06).
5
+ * - ERC-20 transfers: getLogs with parseAbiItem Transfer event filter
6
+ * - Native ETH transfers: getBlock(includeTransactions:true) scanning tx.to
7
+ * - 10-block cap per poll cycle to stay within RPC provider limits (pitfall 4)
8
+ *
9
+ * Lifecycle:
10
+ * - connect() is no-op (no WebSocket needed)
11
+ * - waitForDisconnect() returns a never-resolving Promise (EVM stays in WS_ACTIVE permanently)
12
+ * - pollAll() is called externally by BackgroundWorkers in Phase 226
13
+ *
14
+ * Phase 225-02: Initial implementation.
15
+ */
16
+ import type { IChainSubscriber, IncomingTransaction, ChainType } from '@waiaas/core';
17
+ export declare class EvmIncomingSubscriber implements IChainSubscriber {
18
+ readonly chain: ChainType;
19
+ private client;
20
+ private subscriptions;
21
+ private generateId;
22
+ constructor(config: {
23
+ rpcUrl: string;
24
+ generateId?: () => string;
25
+ });
26
+ subscribe(walletId: string, address: string, network: string, onTransaction: (tx: IncomingTransaction) => void): Promise<void>;
27
+ unsubscribe(walletId: string): Promise<void>;
28
+ subscribedWallets(): string[];
29
+ connect(): Promise<void>;
30
+ waitForDisconnect(): Promise<void>;
31
+ destroy(): Promise<void>;
32
+ pollAll(): Promise<void>;
33
+ private pollERC20;
34
+ private pollNativeETH;
35
+ }
36
+ //# sourceMappingURL=evm-incoming-subscriber.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evm-incoming-subscriber.d.ts","sourceRoot":"","sources":["../src/evm-incoming-subscriber.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AASH,OAAO,KAAK,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAiBrF,qBAAa,qBAAsB,YAAW,gBAAgB;IAC5D,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAc;IAEvC,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,aAAa,CAAsC;IAC3D,OAAO,CAAC,UAAU,CAAe;gBAErB,MAAM,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,MAAM,CAAA;KAAE;IAO3D,SAAS,CACb,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,aAAa,EAAE,CAAC,EAAE,EAAE,mBAAmB,KAAK,IAAI,GAC/C,OAAO,CAAC,IAAI,CAAC;IAYV,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMlD,iBAAiB,IAAI,MAAM,EAAE;IAMvB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAIxB,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC;IAQlC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAMxB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;YA0ChB,SAAS;YA8BT,aAAa;CA4C5B"}
@@ -0,0 +1,144 @@
1
+ /**
2
+ * EvmIncomingSubscriber -- IChainSubscriber implementation for EVM chains.
3
+ *
4
+ * Detection strategy: polling-first (design decision D-06).
5
+ * - ERC-20 transfers: getLogs with parseAbiItem Transfer event filter
6
+ * - Native ETH transfers: getBlock(includeTransactions:true) scanning tx.to
7
+ * - 10-block cap per poll cycle to stay within RPC provider limits (pitfall 4)
8
+ *
9
+ * Lifecycle:
10
+ * - connect() is no-op (no WebSocket needed)
11
+ * - waitForDisconnect() returns a never-resolving Promise (EVM stays in WS_ACTIVE permanently)
12
+ * - pollAll() is called externally by BackgroundWorkers in Phase 226
13
+ *
14
+ * Phase 225-02: Initial implementation.
15
+ */
16
+ import { createPublicClient, http, parseAbiItem, } from 'viem';
17
+ /** ERC-20 Transfer event signature for getLogs filtering. */
18
+ const TRANSFER_EVENT = parseAbiItem('event Transfer(address indexed from, address indexed to, uint256 value)');
19
+ /** Maximum blocks per poll cycle (pitfall 4: RPC provider limits). */
20
+ const MAX_BLOCK_RANGE = 10n;
21
+ export class EvmIncomingSubscriber {
22
+ chain = 'ethereum';
23
+ client;
24
+ subscriptions = new Map();
25
+ generateId;
26
+ constructor(config) {
27
+ this.client = createPublicClient({ transport: http(config.rpcUrl) });
28
+ this.generateId = config.generateId ?? (() => crypto.randomUUID());
29
+ }
30
+ // -- Subscription management (2) --
31
+ async subscribe(walletId, address, network, onTransaction) {
32
+ if (this.subscriptions.has(walletId))
33
+ return; // idempotent
34
+ const currentBlock = await this.client.getBlockNumber();
35
+ this.subscriptions.set(walletId, {
36
+ address,
37
+ network,
38
+ onTransaction,
39
+ lastBlock: currentBlock,
40
+ });
41
+ }
42
+ async unsubscribe(walletId) {
43
+ this.subscriptions.delete(walletId);
44
+ }
45
+ // -- Query (1) --
46
+ subscribedWallets() {
47
+ return Array.from(this.subscriptions.keys());
48
+ }
49
+ // -- Lifecycle (3) --
50
+ async connect() {
51
+ // No-op: EVM uses polling-first strategy (design decision D-06).
52
+ }
53
+ async waitForDisconnect() {
54
+ // Never-resolving Promise: EVM polling mode has no WebSocket to disconnect.
55
+ // The reconnectLoop in Phase 226 will call connect() (succeeds instantly)
56
+ // then waitForDisconnect() (blocks forever), meaning EVM stays in
57
+ // WS_ACTIVE state permanently and polling workers handle the actual work.
58
+ return new Promise(() => { });
59
+ }
60
+ async destroy() {
61
+ this.subscriptions.clear();
62
+ }
63
+ // -- Polling (called by BackgroundWorkers in Phase 226) --
64
+ async pollAll() {
65
+ const currentBlock = await this.client.getBlockNumber();
66
+ for (const [walletId, sub] of this.subscriptions) {
67
+ try {
68
+ if (sub.lastBlock >= currentBlock)
69
+ continue; // no new blocks
70
+ const toBlock = sub.lastBlock + MAX_BLOCK_RANGE < currentBlock
71
+ ? sub.lastBlock + MAX_BLOCK_RANGE
72
+ : currentBlock;
73
+ const erc20Txs = await this.pollERC20(sub.address, sub.lastBlock + 1n, toBlock, walletId, sub.network);
74
+ const nativeTxs = await this.pollNativeETH(sub.address, sub.lastBlock + 1n, toBlock, walletId, sub.network);
75
+ const allTxs = [...erc20Txs, ...nativeTxs];
76
+ for (const tx of allTxs) {
77
+ sub.onTransaction(tx);
78
+ }
79
+ sub.lastBlock = toBlock;
80
+ }
81
+ catch (err) {
82
+ console.warn(`EVM poll failed for wallet ${walletId}:`, err);
83
+ }
84
+ }
85
+ }
86
+ // -- Private helpers --
87
+ async pollERC20(walletAddress, fromBlock, toBlock, walletId, network) {
88
+ const logs = await this.client.getLogs({
89
+ event: TRANSFER_EVENT,
90
+ args: { to: walletAddress },
91
+ fromBlock,
92
+ toBlock,
93
+ });
94
+ return logs.map((log) => ({
95
+ id: this.generateId(),
96
+ txHash: log.transactionHash,
97
+ walletId,
98
+ fromAddress: log.args.from,
99
+ amount: log.args.value.toString(),
100
+ tokenAddress: log.address,
101
+ chain: 'ethereum',
102
+ network,
103
+ status: 'DETECTED',
104
+ blockNumber: Number(log.blockNumber),
105
+ detectedAt: Math.floor(Date.now() / 1000),
106
+ confirmedAt: null,
107
+ }));
108
+ }
109
+ async pollNativeETH(walletAddress, fromBlock, toBlock, walletId, network) {
110
+ const results = [];
111
+ for (let blockNum = fromBlock; blockNum <= toBlock; blockNum++) {
112
+ const block = await this.client.getBlock({
113
+ blockNumber: blockNum,
114
+ includeTransactions: true,
115
+ });
116
+ for (const tx of block.transactions) {
117
+ // Guard: hash-only without includeTransactions (pitfall 2)
118
+ if (typeof tx === 'string')
119
+ continue;
120
+ if (typeof tx !== 'object' || !tx.to)
121
+ continue;
122
+ if (tx.to.toLowerCase() === walletAddress.toLowerCase() &&
123
+ tx.value > 0n) {
124
+ results.push({
125
+ id: this.generateId(),
126
+ txHash: tx.hash,
127
+ walletId,
128
+ fromAddress: tx.from,
129
+ amount: tx.value.toString(),
130
+ tokenAddress: null, // native ETH
131
+ chain: 'ethereum',
132
+ network,
133
+ status: 'DETECTED',
134
+ blockNumber: Number(blockNum),
135
+ detectedAt: Math.floor(Date.now() / 1000),
136
+ confirmedAt: null,
137
+ });
138
+ }
139
+ }
140
+ }
141
+ return results;
142
+ }
143
+ }
144
+ //# sourceMappingURL=evm-incoming-subscriber.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evm-incoming-subscriber.js","sourceRoot":"","sources":["../src/evm-incoming-subscriber.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export { EvmAdapter } from './adapter.js';
2
+ export { EvmIncomingSubscriber } from './evm-incoming-subscriber.js';
2
3
  export { ERC20_ABI } from './abi/erc20.js';
3
4
  export { EVM_CHAIN_MAP, type EvmChainEntry } from './evm-chain-map.js';
4
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC"}
package/dist/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  // @waiaas/adapter-evm
2
2
  export { EvmAdapter } from './adapter.js';
3
+ export { EvmIncomingSubscriber } from './evm-incoming-subscriber.js';
3
4
  export { ERC20_ABI } from './abi/erc20.js';
4
5
  export { EVM_CHAIN_MAP } from './evm-chain-map.js';
5
6
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,sBAAsB;AACtB,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAsB,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,sBAAsB;AACtB,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAsB,MAAM,oBAAoB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@waiaas/adapter-evm",
3
- "version": "2.5.0",
3
+ "version": "2.6.0-rc",
4
4
  "description": "WAIaaS EVM chain adapter - Ethereum/ERC-20 support via viem",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -29,7 +29,7 @@
29
29
  ],
30
30
  "dependencies": {
31
31
  "viem": "^2.21.0",
32
- "@waiaas/core": "2.5.0"
32
+ "@waiaas/core": "2.6.0-rc"
33
33
  },
34
34
  "devDependencies": {
35
35
  "@types/node": "^25.2.3"