@tapforce/pod-bridge-sdk 1.1.17 → 1.2.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.
@@ -11,13 +11,17 @@ const pod_tracker_service_1 = require("./pod-tracker.service");
11
11
  * to provide a unified view of bridge activity across both chains.
12
12
  *
13
13
  * Bridge Architecture:
14
- * - Source Chain (e.g., Sepolia): BridgeDepositWithdraw contract
15
- * - Deposits lock tokens
16
- * - Claims use POD certificates (requires attestations)
14
+ * - ETH -> Pod: deposits on ETH, AUTO-CLAIM on Pod (no claim needed)
15
+ * - Pod -> ETH: deposits on Pod, claims on ETH with aggregated validator signatures
16
+ * - Only ERC20 tokens supported (wrap ETH to WETH)
17
17
  *
18
- * - POD Chain: BridgeMintBurn contract
19
- * - Deposits burn tokens (POD has instant finality - single block)
20
- * - Claims use block number verification via precompiles
18
+ * Source Chain (e.g., Sepolia/ETH):
19
+ * - Deposits lock ERC20 tokens (ETH -> Pod direction)
20
+ * - Claims release ERC20 tokens with validator signatures (Pod -> ETH direction)
21
+ *
22
+ * POD Chain:
23
+ * - Auto-claim for ETH -> Pod deposits (instant finality)
24
+ * - Deposits for Pod -> ETH direction
21
25
  */
22
26
  class PodBridgeTrackerClient {
23
27
  constructor(config) {
@@ -101,24 +105,34 @@ class PodBridgeTrackerClient {
101
105
  .sort((a, b) => b.deposit.timestamp - a.deposit.timestamp);
102
106
  }
103
107
  /**
104
- * Check if deposits can be claimed (block finalized on source chain)
108
+ * Check if deposits can be claimed
109
+ *
110
+ * New architecture:
111
+ * - ETH -> Pod: AUTO-CLAIM on Pod, no manual claim needed (always returns false)
112
+ * - Pod -> ETH: Manual claim needed on ETH with aggregated signatures
113
+ *
105
114
  * @param deposit The bridge request to check
106
- * @returns True if the deposit can be claimed
115
+ * @returns True if the deposit can be manually claimed (only Pod -> ETH direction)
107
116
  */
108
117
  async canBeClaimed(deposit) {
109
- // For source chain deposits, check if block is finalized
118
+ // ETH -> Pod deposits have AUTO-CLAIM on Pod, no manual claim needed
110
119
  if (deposit.deposit.chain === pod_bridge_types_1.BridgeChain.SOURCE_CHAIN) {
111
- const isFinalized = await this.sourceChainTracker.isBlockFinalized(deposit.deposit.blockNumber);
112
- return isFinalized && !deposit.isClaimed;
120
+ // Auto-claim on Pod - nothing to claim manually
121
+ return false;
113
122
  }
114
123
  else {
115
- // POD deposits have instant finality
124
+ // POD -> ETH deposits need manual claim on ETH
125
+ // POD has instant finality, so always claimable if not already claimed
116
126
  return !deposit.isClaimed;
117
127
  }
118
128
  }
119
129
  /**
120
130
  * Batch check claim status for multiple deposits
121
- * Claims are checked on the opposite chain from where the deposit was made
131
+ *
132
+ * New architecture:
133
+ * - ETH -> Pod: AUTO-CLAIM on Pod (mark as claimed after finalization)
134
+ * - Pod -> ETH: Check claim events on Source Chain
135
+ *
122
136
  * @private
123
137
  */
124
138
  async updateClaimStatus(deposits) {
@@ -127,82 +141,93 @@ class PodBridgeTrackerClient {
127
141
  }
128
142
  console.log('[TrackerClient] Updating claim status for', deposits.length, 'deposits');
129
143
  try {
130
- // Separate deposits by their origin chain
131
- const sourceChainDeposits = deposits.filter(d => d.deposit.chain === pod_bridge_types_1.BridgeChain.SOURCE_CHAIN);
132
144
  const podDeposits = deposits.filter(d => d.deposit.chain === pod_bridge_types_1.BridgeChain.POD);
133
- // Fetch claim events from both chains in parallel
134
- // Source chain deposits are claimed on POD, POD deposits are claimed on Source chain
135
- const [podClaimEvents, sourceChainClaimEvents] = await Promise.all([
136
- sourceChainDeposits.length > 0 ? this.podTracker.getClaimEvents(sourceChainDeposits) : Promise.resolve(new Map()),
137
- podDeposits.length > 0 ? this.sourceChainTracker.getClaimEvents(podDeposits) : Promise.resolve(new Map())
138
- ]);
139
- // Combine both claim maps
140
- const claimedMap = new Map([...podClaimEvents, ...sourceChainClaimEvents]);
145
+ // For Pod -> ETH deposits, check claim events on Source Chain
146
+ const sourceChainClaimEvents = podDeposits.length > 0
147
+ ? await this.sourceChainTracker.getClaimEvents(podDeposits)
148
+ : new Map();
141
149
  // Get finalized block for source chain
142
150
  const finalizedBlock = await this.sourceChainTracker.getFinalizedBlockNumber();
143
151
  // Update deposit status
144
- for (const deposit of deposits) {
145
- const claimInfo = claimedMap.get(deposit.requestId);
146
- if (claimInfo) {
147
- deposit.isClaimed = true;
148
- deposit.claim = {
149
- chain: claimInfo.chain,
150
- txHash: claimInfo.txHash,
151
- claimer: claimInfo.claimer,
152
- chainId: claimInfo.chainId,
153
- blockNumber: claimInfo.blockNumber,
154
- timestamp: claimInfo.timestamp
155
- };
156
- }
157
- // Check if deposit is claimable (finalized and not claimed)
158
- // For source chain deposits, check if source chain block is finalized
159
- // For POD deposits, POD has instant finality (single block)
160
- if (deposit.deposit.chain === pod_bridge_types_1.BridgeChain.SOURCE_CHAIN) {
161
- deposit.isClaimable = deposit.deposit.blockNumber <= finalizedBlock && !deposit.isClaimed;
152
+ for (const depositData of deposits) {
153
+ if (depositData.deposit.chain === pod_bridge_types_1.BridgeChain.SOURCE_CHAIN) {
154
+ // ETH -> Pod: AUTO-CLAIM on Pod
155
+ // Mark as "claimed" (auto-claimed) once the deposit is finalized
156
+ const isFinalized = depositData.deposit.blockNumber <= finalizedBlock;
157
+ depositData.isClaimed = isFinalized; // Auto-claimed after finalization
158
+ depositData.isClaimable = false; // No manual claim needed
159
+ if (isFinalized) {
160
+ // Auto-claim doesn't have a separate claim tx, so we mark it as such
161
+ depositData.claim = {
162
+ chain: pod_bridge_types_1.BridgeChain.POD,
163
+ txHash: 'auto-claim', // No separate claim TX
164
+ claimer: depositData.deposit.destination,
165
+ chainId: 1293, // Pod chain ID
166
+ blockNumber: 0,
167
+ timestamp: depositData.deposit.timestamp
168
+ };
169
+ }
162
170
  }
163
171
  else {
172
+ // Pod -> ETH: Check manual claim on Source Chain
173
+ const claimInfo = sourceChainClaimEvents.get(depositData.requestId);
174
+ if (claimInfo) {
175
+ depositData.isClaimed = true;
176
+ depositData.claim = {
177
+ chain: claimInfo.chain,
178
+ txHash: claimInfo.txHash,
179
+ claimer: claimInfo.claimer,
180
+ chainId: claimInfo.chainId,
181
+ blockNumber: claimInfo.blockNumber,
182
+ timestamp: claimInfo.timestamp
183
+ };
184
+ }
164
185
  // POD deposits are immediately claimable (instant finality)
165
- deposit.isClaimable = !deposit.isClaimed;
186
+ depositData.isClaimable = !depositData.isClaimed;
166
187
  }
167
188
  }
168
189
  }
169
190
  catch (error) {
170
191
  console.error('[TrackerClient] Error checking claim status:', error);
171
- // Fallback: Still calculate isClaimable based on finalization even if claim check fails
172
- try {
173
- const finalizedBlock = await this.sourceChainTracker.getFinalizedBlockNumber();
174
- for (const deposit of deposits) {
175
- if (deposit.deposit.chain === pod_bridge_types_1.BridgeChain.SOURCE_CHAIN) {
176
- deposit.isClaimable = deposit.deposit.blockNumber <= finalizedBlock && !deposit.isClaimed;
177
- }
178
- else {
179
- deposit.isClaimable = !deposit.isClaimed;
180
- }
192
+ // Fallback: Mark Pod deposits as claimable
193
+ for (const deposit of deposits) {
194
+ if (deposit.deposit.chain === pod_bridge_types_1.BridgeChain.POD) {
195
+ deposit.isClaimable = !deposit.isClaimed;
181
196
  }
182
197
  }
183
- catch (fallbackError) {
184
- console.error('[TrackerClient] Error calculating isClaimable:', fallbackError);
185
- }
186
198
  }
187
199
  }
188
200
  /**
189
201
  * Batch check if multiple requests have been processed on-chain
202
+ *
203
+ * New architecture:
204
+ * - ETH -> Pod: Auto-claimed after finalization
205
+ * - Pod -> ETH: Check claim events on Source Chain
206
+ *
190
207
  * @param deposits Array of deposits to check
191
208
  * @returns Array of boolean values
192
209
  */
193
210
  async areRequestsProcessed(deposits) {
194
211
  if (deposits.length === 0)
195
212
  return [];
196
- // Group deposits by destination chain (where they would be claimed)
197
- const sourceChainDeposits = deposits.filter(d => d.deposit.chain === pod_bridge_types_1.BridgeChain.SOURCE_CHAIN);
213
+ // Get finalized block for ETH -> Pod auto-claim check
214
+ const finalizedBlock = await this.sourceChainTracker.getFinalizedBlockNumber();
215
+ // Group deposits by origin chain
198
216
  const podDeposits = deposits.filter(d => d.deposit.chain === pod_bridge_types_1.BridgeChain.POD);
199
- // Check claims on both chains
200
- const [podClaims, sourceChainClaims] = await Promise.all([
201
- sourceChainDeposits.length > 0 ? this.podTracker.getClaimEvents(sourceChainDeposits) : Promise.resolve(new Map()),
202
- podDeposits.length > 0 ? this.sourceChainTracker.getClaimEvents(podDeposits) : Promise.resolve(new Map())
203
- ]);
204
- const allClaims = new Map([...podClaims, ...sourceChainClaims]);
205
- return deposits.map(d => allClaims.has(d.requestId));
217
+ // Check claims on Source Chain for Pod -> ETH deposits
218
+ const sourceChainClaims = podDeposits.length > 0
219
+ ? await this.sourceChainTracker.getClaimEvents(podDeposits)
220
+ : new Map();
221
+ return deposits.map(d => {
222
+ if (d.deposit.chain === pod_bridge_types_1.BridgeChain.SOURCE_CHAIN) {
223
+ // ETH -> Pod: Auto-claimed once finalized
224
+ return d.deposit.blockNumber <= finalizedBlock;
225
+ }
226
+ else {
227
+ // Pod -> ETH: Check claim event on Source Chain
228
+ return sourceChainClaims.has(d.requestId);
229
+ }
230
+ });
206
231
  }
207
232
  }
208
233
  exports.PodBridgeTrackerClient = PodBridgeTrackerClient;
@@ -1,11 +1,14 @@
1
- import { BridgeRequest, BridgeChain, PodBridgeChainConfig } from '../../libs/types/pod-bridge.types';
1
+ import { BridgeRequest, PodBridgeChainConfig } from '../../libs/types/pod-bridge.types';
2
2
  /**
3
3
  * PodTrackerService - Handles tracking on the POD Chain
4
4
  *
5
+ * New architecture:
6
+ * - ETH -> Pod: auto-claim on Pod (no claim tracking needed on Pod)
7
+ * - Pod -> ETH: deposits are made here, claimed on ETH
8
+ * - Only ERC20 tokens supported (no native)
9
+ *
5
10
  * Responsibilities:
6
- * - Fetch deposits made on POD
7
- * - Fetch claims made on POD (from Source Chain deposits)
8
- * - Generate certified logs for claiming on Source Chain
11
+ * - Fetch deposits made on POD (Pod -> ETH direction)
9
12
  *
10
13
  * Note: POD uses a single-block architecture where blocks are essentially
11
14
  * timestamps. The chain has instant finality.
@@ -32,21 +35,7 @@ export declare class PodTrackerService {
32
35
  /**
33
36
  * Private method to fetch deposits from POD
34
37
  * POD uses a single-block architecture where blocks are essentially timestamps
38
+ * Event: Deposit(bytes32 indexed id, address indexed from, address indexed to, address token, uint256 amount)
35
39
  */
36
40
  private getDeposits;
37
- /**
38
- * Get claim events that occurred ON POD
39
- * These are claims of Source Chain deposits (Source Chain → POD direction)
40
- *
41
- * @param deposits The Source Chain deposits to check for claims
42
- * @returns Map of requestId to claim information
43
- */
44
- getClaimEvents(deposits: BridgeRequest[]): Promise<Map<string, {
45
- chain: BridgeChain;
46
- txHash: string;
47
- timestamp: number;
48
- claimer: string;
49
- chainId: number;
50
- blockNumber: number;
51
- }>>;
52
41
  }
@@ -4,14 +4,16 @@ exports.PodTrackerService = void 0;
4
4
  const ethers_1 = require("ethers");
5
5
  const pod_bridge_types_1 = require("../../libs/types/pod-bridge.types");
6
6
  const bridge_abi_1 = require("../../libs/abi/bridge.abi");
7
- const provider_builder_1 = require("../../libs/pod-sdk/src/provider/provider-builder");
8
7
  /**
9
8
  * PodTrackerService - Handles tracking on the POD Chain
10
9
  *
10
+ * New architecture:
11
+ * - ETH -> Pod: auto-claim on Pod (no claim tracking needed on Pod)
12
+ * - Pod -> ETH: deposits are made here, claimed on ETH
13
+ * - Only ERC20 tokens supported (no native)
14
+ *
11
15
  * Responsibilities:
12
- * - Fetch deposits made on POD
13
- * - Fetch claims made on POD (from Source Chain deposits)
14
- * - Generate certified logs for claiming on Source Chain
16
+ * - Fetch deposits made on POD (Pod -> ETH direction)
15
17
  *
16
18
  * Note: POD uses a single-block architecture where blocks are essentially
17
19
  * timestamps. The chain has instant finality.
@@ -20,9 +22,9 @@ class PodTrackerService {
20
22
  constructor(config) {
21
23
  this.config = config;
22
24
  this.chainId = null;
23
- this.provider = new provider_builder_1.PodProvider(config.rpcUrl);
24
- this.bridge = new ethers_1.Contract(config.contractAddress, bridge_abi_1.POD_BRIDGE_ABI, this.provider);
25
- this.iface = new ethers_1.Interface(bridge_abi_1.POD_BRIDGE_ABI);
25
+ this.provider = config.provider;
26
+ this.bridge = new ethers_1.Contract(config.contractAddress, bridge_abi_1.BRIDGE_ABI, this.provider);
27
+ this.iface = new ethers_1.Interface(bridge_abi_1.BRIDGE_ABI);
26
28
  this.initChainId();
27
29
  }
28
30
  async initChainId() {
@@ -44,6 +46,7 @@ class PodTrackerService {
44
46
  * Note: POD has a single block, so blockNumber is essentially a timestamp
45
47
  */
46
48
  async getDepositsSentBy(address) {
49
+ // Filter by 'from' (second indexed param): Deposit(id, from, to, token, amount)
47
50
  return this.getDeposits({
48
51
  depositEventFilter: [null, address, null]
49
52
  });
@@ -53,6 +56,7 @@ class PodTrackerService {
53
56
  * Note: POD has a single block, so blockNumber is essentially a timestamp
54
57
  */
55
58
  async getDepositsReceivedBy(address) {
59
+ // Filter by 'to' (third indexed param): Deposit(id, from, to, token, amount)
56
60
  return this.getDeposits({
57
61
  depositEventFilter: [null, null, address]
58
62
  });
@@ -60,23 +64,22 @@ class PodTrackerService {
60
64
  /**
61
65
  * Private method to fetch deposits from POD
62
66
  * POD uses a single-block architecture where blocks are essentially timestamps
67
+ * Event: Deposit(bytes32 indexed id, address indexed from, address indexed to, address token, uint256 amount)
63
68
  */
64
69
  async getDeposits(options) {
65
70
  const deposits = [];
71
+ // Event: Deposit(bytes32 indexed id, address indexed from, address indexed to, address token, uint256 amount)
66
72
  const depositFilter = this.bridge.filters.Deposit(...options.depositEventFilter);
67
- const depositNativeFilter = this.bridge.filters.DepositNative(...options.depositEventFilter);
68
- const [depositLogs, depositNativeLogs] = await Promise.all([
69
- this.bridge.queryFilter(depositFilter),
70
- this.bridge.queryFilter(depositNativeFilter)
71
- ]);
73
+ const depositLogs = await this.bridge.queryFilter(depositFilter);
72
74
  // Process deposits
73
- for (const log of [...depositLogs, ...depositNativeLogs]) {
75
+ for (const log of depositLogs) {
74
76
  const parsed = this.iface.parseLog({
75
77
  topics: [...log.topics],
76
78
  data: log.data
77
79
  });
78
80
  if (parsed) {
79
- const isNative = log.topics[0] === ethers_1.ethers.id('DepositNative(uint256,address,address,uint256,uint256,uint256)');
81
+ // Get block for timestamp
82
+ const block = await this.provider.getBlock(log.blockNumber);
80
83
  deposits.push({
81
84
  requestId: parsed.args.id.toString(),
82
85
  deposit: {
@@ -84,11 +87,11 @@ class PodTrackerService {
84
87
  txHash: log.transactionHash,
85
88
  depositor: parsed.args.from,
86
89
  destination: parsed.args.to,
87
- token: isNative ? ethers_1.ethers.ZeroAddress : parsed.args.token,
90
+ token: parsed.args.token,
88
91
  amount: parsed.args.amount.toString(),
89
92
  chainId: this.chainId,
90
- blockNumber: Number(parsed.args.blockNumber), // On POD, this is essentially a timestamp
91
- timestamp: Number(parsed.args.timestamp)
93
+ blockNumber: log.blockNumber, // On POD, this is essentially a timestamp
94
+ timestamp: block ? Number(block.timestamp) : 0
92
95
  },
93
96
  isClaimed: false,
94
97
  isClaimable: false
@@ -97,47 +100,5 @@ class PodTrackerService {
97
100
  }
98
101
  return deposits;
99
102
  }
100
- /**
101
- * Get claim events that occurred ON POD
102
- * These are claims of Source Chain deposits (Source Chain → POD direction)
103
- *
104
- * @param deposits The Source Chain deposits to check for claims
105
- * @returns Map of requestId to claim information
106
- */
107
- async getClaimEvents(deposits) {
108
- await this.ensureChainId();
109
- const uniqueRecipients = [...new Set(deposits.map(d => d.deposit.destination))];
110
- const allClaimLogs = [];
111
- const allClaimNativeLogs = [];
112
- for (const recipient of uniqueRecipients) {
113
- const claimFilter = this.bridge.filters.Claim(null, null, recipient);
114
- const claimNativeFilter = this.bridge.filters.ClaimNative(null, null, recipient);
115
- const [claimLogs, claimNativeLogs] = await Promise.all([
116
- this.bridge.queryFilter(claimFilter),
117
- this.bridge.queryFilter(claimNativeFilter)
118
- ]);
119
- allClaimLogs.push(...claimLogs);
120
- allClaimNativeLogs.push(...claimNativeLogs);
121
- }
122
- console.log(`[POD] Found ${allClaimLogs.length} claims, ${allClaimNativeLogs.length} native claims`);
123
- const claimedMap = new Map();
124
- for (const log of [...allClaimLogs, ...allClaimNativeLogs]) {
125
- const parsed = this.iface.parseLog({
126
- topics: [...log.topics],
127
- data: log.data
128
- });
129
- if (parsed) {
130
- claimedMap.set(parsed.args.id.toString(), {
131
- chain: pod_bridge_types_1.BridgeChain.POD,
132
- txHash: log.transactionHash,
133
- timestamp: Number(parsed.args.timestamp),
134
- claimer: parsed.args.claimer,
135
- chainId: this.chainId,
136
- blockNumber: log.blockNumber
137
- });
138
- }
139
- }
140
- return claimedMap;
141
- }
142
103
  }
143
104
  exports.PodTrackerService = PodTrackerService;
@@ -1,10 +1,15 @@
1
1
  import { BridgeRequest, BridgeChain, PodBridgeChainConfig } from '../../libs/types/pod-bridge.types';
2
2
  /**
3
- * SourceChainTrackerService - Handles tracking on the Source Chain (e.g., Sepolia)
3
+ * SourceChainTrackerService - Handles tracking on the Source Chain (e.g., Sepolia/ETH)
4
+ *
5
+ * New architecture:
6
+ * - ETH -> Pod: deposits are made here, auto-claimed on Pod
7
+ * - Pod -> ETH: claims are made here with aggregated validator signatures
8
+ * - Only ERC20 tokens supported (no native)
4
9
  *
5
10
  * Responsibilities:
6
- * - Fetch deposits made on Source Chain
7
- * - Fetch claims made on Source Chain (from POD deposits)
11
+ * - Fetch deposits made on Source Chain (ETH -> Pod direction)
12
+ * - Fetch claims made on Source Chain (Pod -> ETH direction)
8
13
  */
9
14
  export declare class SourceChainTrackerService {
10
15
  private readonly config;
@@ -30,6 +35,9 @@ export declare class SourceChainTrackerService {
30
35
  /**
31
36
  * Get claim events that occurred ON Source Chain
32
37
  * These are claims of POD deposits (POD → Source Chain direction)
38
+ * Event: Claim(bytes32 indexed id, address indexed to, address token, uint256 amount)
39
+ *
40
+ * Pod Deposit.id = ETH Claim.id - used to track if deposit was claimed
33
41
  *
34
42
  * @param deposits The POD deposits to check for claims
35
43
  * @returns Map of requestId to claim information
@@ -5,19 +5,24 @@ const ethers_1 = require("ethers");
5
5
  const pod_bridge_types_1 = require("../../libs/types/pod-bridge.types");
6
6
  const bridge_abi_1 = require("../../libs/abi/bridge.abi");
7
7
  /**
8
- * SourceChainTrackerService - Handles tracking on the Source Chain (e.g., Sepolia)
8
+ * SourceChainTrackerService - Handles tracking on the Source Chain (e.g., Sepolia/ETH)
9
+ *
10
+ * New architecture:
11
+ * - ETH -> Pod: deposits are made here, auto-claimed on Pod
12
+ * - Pod -> ETH: claims are made here with aggregated validator signatures
13
+ * - Only ERC20 tokens supported (no native)
9
14
  *
10
15
  * Responsibilities:
11
- * - Fetch deposits made on Source Chain
12
- * - Fetch claims made on Source Chain (from POD deposits)
16
+ * - Fetch deposits made on Source Chain (ETH -> Pod direction)
17
+ * - Fetch claims made on Source Chain (Pod -> ETH direction)
13
18
  */
14
19
  class SourceChainTrackerService {
15
20
  constructor(config) {
16
21
  this.config = config;
17
22
  this.chainId = null;
18
- this.provider = new ethers_1.ethers.JsonRpcProvider(config.rpcUrl);
19
- this.bridge = new ethers_1.Contract(config.contractAddress, bridge_abi_1.SOURCE_CHAIN_BRIDGE_ABI, this.provider);
20
- this.iface = new ethers_1.Interface(bridge_abi_1.SOURCE_CHAIN_BRIDGE_ABI);
23
+ this.provider = config.provider;
24
+ this.bridge = new ethers_1.Contract(config.contractAddress, bridge_abi_1.BRIDGE_ABI, this.provider);
25
+ this.iface = new ethers_1.Interface(bridge_abi_1.BRIDGE_ABI);
21
26
  this.initChainId();
22
27
  }
23
28
  async initChainId() {
@@ -33,8 +38,9 @@ class SourceChainTrackerService {
33
38
  * Get deposits sent by an address on Source Chain
34
39
  */
35
40
  async getDepositsSentBy(address, options) {
41
+ // Filter by 'from' (second indexed param): Deposit(id, from, to, token, amount)
36
42
  return this.getDeposits({
37
- fromBlock: options === null || options === void 0 ? void 0 : options.fromBlock,
43
+ fromBlock: options?.fromBlock,
38
44
  depositEventFilter: [null, address, null]
39
45
  });
40
46
  }
@@ -42,36 +48,34 @@ class SourceChainTrackerService {
42
48
  * Get deposits received by an address on Source Chain
43
49
  */
44
50
  async getDepositsReceivedBy(address, options) {
51
+ // Filter by 'to' (third indexed param): Deposit(id, from, to, token, amount)
45
52
  return this.getDeposits({
46
- fromBlock: options === null || options === void 0 ? void 0 : options.fromBlock,
53
+ fromBlock: options?.fromBlock,
47
54
  depositEventFilter: [null, null, address]
48
55
  });
49
56
  }
50
57
  async getDeposits(options) {
51
- var _a, _b;
52
- const startBlock = (_b = (_a = options === null || options === void 0 ? void 0 : options.fromBlock) !== null && _a !== void 0 ? _a : this.config.deploymentBlock) !== null && _b !== void 0 ? _b : 0;
58
+ const startBlock = options?.fromBlock ?? this.config.deploymentBlock ?? 0;
53
59
  const deposits = [];
54
60
  const currentBlock = await this.provider.getBlockNumber();
55
61
  const BLOCK_BATCH_SIZE = 10000;
56
62
  for (let start = startBlock; start <= currentBlock; start += BLOCK_BATCH_SIZE) {
57
63
  const end = Math.min(start + BLOCK_BATCH_SIZE - 1, currentBlock);
64
+ // Event: Deposit(bytes32 indexed id, address indexed from, address indexed to, address token, uint256 amount)
58
65
  const depositFilter = this.bridge.filters.Deposit(...options.depositEventFilter);
59
- const depositNativeFilter = this.bridge.filters.DepositNative(...options.depositEventFilter);
60
- const [depositLogs, depositNativeLogs] = await Promise.all([
61
- this.bridge.queryFilter(depositFilter, start, end),
62
- this.bridge.queryFilter(depositNativeFilter, start, end)
63
- ]);
66
+ const depositLogs = await this.bridge.queryFilter(depositFilter, start, end);
64
67
  if (start + BLOCK_BATCH_SIZE <= currentBlock) {
65
68
  await new Promise(resolve => setTimeout(resolve, 100));
66
69
  }
67
70
  // Process deposits
68
- for (const log of [...depositLogs, ...depositNativeLogs]) {
71
+ for (const log of depositLogs) {
69
72
  const parsed = this.iface.parseLog({
70
73
  topics: [...log.topics],
71
74
  data: log.data
72
75
  });
73
76
  if (parsed) {
74
- const isNative = log.topics[0] === ethers_1.ethers.id('DepositNative(uint256,address,address,uint256,uint256,uint256)');
77
+ // Get block for timestamp
78
+ const block = await this.provider.getBlock(log.blockNumber);
75
79
  deposits.push({
76
80
  requestId: parsed.args.id.toString(),
77
81
  deposit: {
@@ -79,11 +83,11 @@ class SourceChainTrackerService {
79
83
  txHash: log.transactionHash,
80
84
  depositor: parsed.args.from,
81
85
  destination: parsed.args.to,
82
- token: isNative ? ethers_1.ethers.ZeroAddress : parsed.args.token,
86
+ token: parsed.args.token,
83
87
  amount: parsed.args.amount.toString(),
84
88
  chainId: this.chainId,
85
- blockNumber: Number(parsed.args.blockNumber),
86
- timestamp: Number(parsed.args.timestamp)
89
+ blockNumber: log.blockNumber,
90
+ timestamp: block ? Number(block.timestamp) : 0
87
91
  },
88
92
  isClaimed: false,
89
93
  isClaimable: false
@@ -96,6 +100,9 @@ class SourceChainTrackerService {
96
100
  /**
97
101
  * Get claim events that occurred ON Source Chain
98
102
  * These are claims of POD deposits (POD → Source Chain direction)
103
+ * Event: Claim(bytes32 indexed id, address indexed to, address token, uint256 amount)
104
+ *
105
+ * Pod Deposit.id = ETH Claim.id - used to track if deposit was claimed
99
106
  *
100
107
  * @param deposits The POD deposits to check for claims
101
108
  * @returns Map of requestId to claim information
@@ -103,30 +110,28 @@ class SourceChainTrackerService {
103
110
  async getClaimEvents(deposits) {
104
111
  const uniqueRecipients = [...new Set(deposits.map(d => d.deposit.destination))];
105
112
  const allClaimLogs = [];
106
- const allClaimNativeLogs = [];
107
113
  for (const recipient of uniqueRecipients) {
108
- const claimFilter = this.bridge.filters.Claim(null, null, recipient);
109
- const claimNativeFilter = this.bridge.filters.ClaimNative(null, null, recipient);
110
- const [claimLogs, claimNativeLogs] = await Promise.all([
111
- this.bridge.queryFilter(claimFilter),
112
- this.bridge.queryFilter(claimNativeFilter)
113
- ]);
114
+ // Event: Claim(bytes32 indexed id, address indexed to, address token, uint256 amount)
115
+ const claimFilter = this.bridge.filters.Claim(null, recipient);
116
+ const claimLogs = await this.bridge.queryFilter(claimFilter);
114
117
  allClaimLogs.push(...claimLogs);
115
- allClaimNativeLogs.push(...claimNativeLogs);
116
118
  }
117
- console.log(`[SourceChain] Found ${allClaimLogs.length} claims, ${allClaimNativeLogs.length} native claims`);
119
+ console.log(`[SourceChain] Found ${allClaimLogs.length} claims`);
118
120
  const claimedMap = new Map();
119
- for (const log of [...allClaimLogs, ...allClaimNativeLogs]) {
121
+ for (const log of allClaimLogs) {
120
122
  const parsed = this.iface.parseLog({
121
123
  topics: [...log.topics],
122
124
  data: log.data
123
125
  });
124
126
  if (parsed) {
127
+ // Get block for timestamp
128
+ const block = await this.provider.getBlock(log.blockNumber);
129
+ // Pod Deposit.id = ETH Claim.id
125
130
  claimedMap.set(parsed.args.id.toString(), {
126
131
  chain: pod_bridge_types_1.BridgeChain.SOURCE_CHAIN,
127
132
  txHash: log.transactionHash,
128
- timestamp: Number(parsed.args.timestamp),
129
- claimer: parsed.args.claimer,
133
+ timestamp: block ? Number(block.timestamp) : 0,
134
+ claimer: parsed.args.to,
130
135
  chainId: this.chainId,
131
136
  blockNumber: log.blockNumber
132
137
  });
package/dist/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  export { PodToSourceChainActionClient } from './clients/action/pod-to-source-chain-client';
2
2
  export { SourceChainToPodActionClient } from './clients/action/source-chain-to-pod-client';
3
3
  export { PodBridgeTrackerClient } from './clients/tracker/client';
4
- export { POD_BRIDGE_ABI } from './libs/abi/bridge.abi';
5
- export { PodBridgeConfig, BridgeRequest, BridgeRequestWithType, BridgeChain, DepositType, UnsignedTransaction, CertifiedLog, PodBridgeActionsClientConfig, PodBridgeChainConfig, } from './libs/types/pod-bridge.types';
4
+ export { BRIDGE_ABI, POD_BRIDGE_ABI, SOURCE_CHAIN_BRIDGE_ABI, } from './libs/abi/bridge.abi';
5
+ export { recoverSignature65B, recoverAggregatedSignatures65B, computeDepositTxHash, extractAggregatedSignatures, extractAttestationInfo, addressFromPublicKey, } from './libs/helpers/signature-recovery.helper';
6
+ export { PodBridgeConfig, BridgeRequest, BridgeRequestWithType, BridgeChain, DepositType, UnsignedTransaction, ClaimProofData, PodBridgeActionsClientConfig, PodBridgeChainConfig, } from './libs/types/pod-bridge.types';
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.DepositType = exports.BridgeChain = exports.POD_BRIDGE_ABI = exports.PodBridgeTrackerClient = exports.SourceChainToPodActionClient = exports.PodToSourceChainActionClient = void 0;
3
+ exports.DepositType = exports.BridgeChain = exports.addressFromPublicKey = exports.extractAttestationInfo = exports.extractAggregatedSignatures = exports.computeDepositTxHash = exports.recoverAggregatedSignatures65B = exports.recoverSignature65B = exports.SOURCE_CHAIN_BRIDGE_ABI = exports.POD_BRIDGE_ABI = exports.BRIDGE_ABI = exports.PodBridgeTrackerClient = exports.SourceChainToPodActionClient = exports.PodToSourceChainActionClient = void 0;
4
4
  var pod_to_source_chain_client_1 = require("./clients/action/pod-to-source-chain-client");
5
5
  Object.defineProperty(exports, "PodToSourceChainActionClient", { enumerable: true, get: function () { return pod_to_source_chain_client_1.PodToSourceChainActionClient; } });
6
6
  var source_chain_to_pod_client_1 = require("./clients/action/source-chain-to-pod-client");
@@ -8,7 +8,16 @@ Object.defineProperty(exports, "SourceChainToPodActionClient", { enumerable: tru
8
8
  var client_1 = require("./clients/tracker/client");
9
9
  Object.defineProperty(exports, "PodBridgeTrackerClient", { enumerable: true, get: function () { return client_1.PodBridgeTrackerClient; } });
10
10
  var bridge_abi_1 = require("./libs/abi/bridge.abi");
11
+ Object.defineProperty(exports, "BRIDGE_ABI", { enumerable: true, get: function () { return bridge_abi_1.BRIDGE_ABI; } });
11
12
  Object.defineProperty(exports, "POD_BRIDGE_ABI", { enumerable: true, get: function () { return bridge_abi_1.POD_BRIDGE_ABI; } });
13
+ Object.defineProperty(exports, "SOURCE_CHAIN_BRIDGE_ABI", { enumerable: true, get: function () { return bridge_abi_1.SOURCE_CHAIN_BRIDGE_ABI; } });
14
+ var signature_recovery_helper_1 = require("./libs/helpers/signature-recovery.helper");
15
+ Object.defineProperty(exports, "recoverSignature65B", { enumerable: true, get: function () { return signature_recovery_helper_1.recoverSignature65B; } });
16
+ Object.defineProperty(exports, "recoverAggregatedSignatures65B", { enumerable: true, get: function () { return signature_recovery_helper_1.recoverAggregatedSignatures65B; } });
17
+ Object.defineProperty(exports, "computeDepositTxHash", { enumerable: true, get: function () { return signature_recovery_helper_1.computeDepositTxHash; } });
18
+ Object.defineProperty(exports, "extractAggregatedSignatures", { enumerable: true, get: function () { return signature_recovery_helper_1.extractAggregatedSignatures; } });
19
+ Object.defineProperty(exports, "extractAttestationInfo", { enumerable: true, get: function () { return signature_recovery_helper_1.extractAttestationInfo; } });
20
+ Object.defineProperty(exports, "addressFromPublicKey", { enumerable: true, get: function () { return signature_recovery_helper_1.addressFromPublicKey; } });
12
21
  var pod_bridge_types_1 = require("./libs/types/pod-bridge.types");
13
22
  Object.defineProperty(exports, "BridgeChain", { enumerable: true, get: function () { return pod_bridge_types_1.BridgeChain; } });
14
23
  Object.defineProperty(exports, "DepositType", { enumerable: true, get: function () { return pod_bridge_types_1.DepositType; } });
@@ -1,12 +1,10 @@
1
1
  /**
2
- * ABI for BridgeMintBurn contract on POD Chain
3
- * - Deposits burn tokens
4
- * - Claims use block number verification via precompiles
5
- */
6
- export declare const POD_BRIDGE_ABI: string[];
7
- /**
8
- * ABI for BridgeDepositWithdraw contract on Source Chain (e.g., Sepolia)
9
- * - Deposits lock tokens
10
- * - Claims use POD certificates with attestations and merkle proofs
2
+ * ABI for Bridge contract on Source Chain (ETH/Sepolia)
3
+ * New architecture:
4
+ * - ETH -> Pod: deposit on ETH, auto-claim on Pod (no claim needed)
5
+ * - Pod -> ETH: deposit on Pod, claim on ETH with aggregated validator signatures
6
+ * - Only ERC20 tokens supported (no native ETH - must wrap to WETH)
11
7
  */
8
+ export declare const BRIDGE_ABI: string[];
12
9
  export declare const SOURCE_CHAIN_BRIDGE_ABI: string[];
10
+ export declare const POD_BRIDGE_ABI: string[];