@tapforce/pod-bridge-sdk 1.2.5 → 2.1.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/README.md +132 -156
- package/dist/clients/action/pod-to-source-chain-client.d.ts +26 -21
- package/dist/clients/action/pod-to-source-chain-client.js +32 -28
- package/dist/clients/action/source-chain-to-pod-client.d.ts +13 -6
- package/dist/clients/action/source-chain-to-pod-client.js +15 -8
- package/dist/clients/tracker/client.js +2 -1
- package/dist/clients/tracker/pod-tracker.service.d.ts +9 -13
- package/dist/clients/tracker/pod-tracker.service.js +48 -32
- package/dist/clients/tracker/source-chain-tracker.service.d.ts +5 -10
- package/dist/clients/tracker/source-chain-tracker.service.js +16 -18
- package/dist/index.d.ts +2 -2
- package/dist/index.js +3 -11
- package/dist/libs/abi/bridge.abi.d.ts +13 -6
- package/dist/libs/abi/bridge.abi.js +29 -20
- package/dist/libs/helpers/bridge-claim-proof.helper.d.ts +16 -0
- package/dist/libs/helpers/bridge-claim-proof.helper.js +27 -0
- package/dist/libs/helpers/convert-certified-log.helper.d.ts +2 -6
- package/dist/libs/helpers/convert-certified-log.helper.js +4 -8
- package/dist/libs/types/pod-bridge.types.d.ts +56 -17
- package/package.json +1 -1
- package/dist/libs/helpers/signature-recovery.helper.d.ts +0 -161
- package/dist/libs/helpers/signature-recovery.helper.js +0 -447
|
@@ -2,11 +2,9 @@ import { UnsignedTransaction, PodBridgeActionsClientConfig } from "../../libs/ty
|
|
|
2
2
|
/**
|
|
3
3
|
* SourceChainToPodActionClient - Handles ETH -> Pod bridging
|
|
4
4
|
*
|
|
5
|
-
* New architecture:
|
|
6
5
|
* - User deposits ERC20 tokens on ETH (source chain)
|
|
7
|
-
* - Balance is automatically added on Pod
|
|
6
|
+
* - Balance is automatically added on Pod after finalization
|
|
8
7
|
* - NO claim transaction needed on Pod side (auto-claim)
|
|
9
|
-
* - Only ERC20 tokens supported (wrap ETH to WETH first)
|
|
10
8
|
*/
|
|
11
9
|
export declare class SourceChainToPodActionClient {
|
|
12
10
|
private readonly config;
|
|
@@ -16,15 +14,21 @@ export declare class SourceChainToPodActionClient {
|
|
|
16
14
|
* Create unsigned transaction for depositing ERC20 tokens from ETH to Pod
|
|
17
15
|
*
|
|
18
16
|
* After deposit:
|
|
19
|
-
* - Wait for block finalization
|
|
17
|
+
* - Wait for block finalization
|
|
20
18
|
* - Balance will be automatically added on Pod (no claim needed)
|
|
21
19
|
*
|
|
22
|
-
* Note: Native ETH is not supported. Wrap to WETH first.
|
|
23
20
|
* Note: Token addresses differ between ETH and Pod chains.
|
|
21
|
+
* Note: For USDC-like tokens, use the token's decimals (e.g. parseUnits('1', 6)),
|
|
22
|
+
* not parseEther which assumes 18 decimals.
|
|
24
23
|
*
|
|
25
24
|
* @param args.token Token address on source chain (ETH) to deposit
|
|
26
|
-
* @param args.amount Amount to deposit (in
|
|
25
|
+
* @param args.amount Amount to deposit (in token's smallest unit)
|
|
27
26
|
* @param args.destinationWalletAddress Recipient address on Pod
|
|
27
|
+
* @param args.callContract Optional: contract to call on Pod after deposit (default: address(0) for simple bridge)
|
|
28
|
+
* @param args.reserveBalance Optional: amount to keep as reserve when using callContract (default: 0).
|
|
29
|
+
* When callContract is address(0), reserveBalance MUST be 0.
|
|
30
|
+
* When callContract is set, amount must exceed reserveBalance; contract must be whitelisted.
|
|
31
|
+
* @param args.permit Optional permit bytes for gasless approval (default '0x')
|
|
28
32
|
* @param args.from Optional sender address
|
|
29
33
|
* @returns Unsigned transaction template with encoded deposit call
|
|
30
34
|
*/
|
|
@@ -32,6 +36,9 @@ export declare class SourceChainToPodActionClient {
|
|
|
32
36
|
token: string;
|
|
33
37
|
amount: string | bigint;
|
|
34
38
|
destinationWalletAddress: string;
|
|
39
|
+
callContract?: string;
|
|
40
|
+
reserveBalance?: string | bigint;
|
|
41
|
+
permit?: string;
|
|
35
42
|
from?: string;
|
|
36
43
|
}): UnsignedTransaction;
|
|
37
44
|
}
|
|
@@ -6,30 +6,34 @@ const bridge_abi_1 = require("../../libs/abi/bridge.abi");
|
|
|
6
6
|
/**
|
|
7
7
|
* SourceChainToPodActionClient - Handles ETH -> Pod bridging
|
|
8
8
|
*
|
|
9
|
-
* New architecture:
|
|
10
9
|
* - User deposits ERC20 tokens on ETH (source chain)
|
|
11
|
-
* - Balance is automatically added on Pod
|
|
10
|
+
* - Balance is automatically added on Pod after finalization
|
|
12
11
|
* - NO claim transaction needed on Pod side (auto-claim)
|
|
13
|
-
* - Only ERC20 tokens supported (wrap ETH to WETH first)
|
|
14
12
|
*/
|
|
15
13
|
class SourceChainToPodActionClient {
|
|
16
14
|
constructor(config) {
|
|
17
15
|
this.config = config;
|
|
18
|
-
this.iface = new ethers_1.Interface(bridge_abi_1.
|
|
16
|
+
this.iface = new ethers_1.Interface(bridge_abi_1.SOURCE_CHAIN_BRIDGE_ABI);
|
|
19
17
|
}
|
|
20
18
|
/**
|
|
21
19
|
* Create unsigned transaction for depositing ERC20 tokens from ETH to Pod
|
|
22
20
|
*
|
|
23
21
|
* After deposit:
|
|
24
|
-
* - Wait for block finalization
|
|
22
|
+
* - Wait for block finalization
|
|
25
23
|
* - Balance will be automatically added on Pod (no claim needed)
|
|
26
24
|
*
|
|
27
|
-
* Note: Native ETH is not supported. Wrap to WETH first.
|
|
28
25
|
* Note: Token addresses differ between ETH and Pod chains.
|
|
26
|
+
* Note: For USDC-like tokens, use the token's decimals (e.g. parseUnits('1', 6)),
|
|
27
|
+
* not parseEther which assumes 18 decimals.
|
|
29
28
|
*
|
|
30
29
|
* @param args.token Token address on source chain (ETH) to deposit
|
|
31
|
-
* @param args.amount Amount to deposit (in
|
|
30
|
+
* @param args.amount Amount to deposit (in token's smallest unit)
|
|
32
31
|
* @param args.destinationWalletAddress Recipient address on Pod
|
|
32
|
+
* @param args.callContract Optional: contract to call on Pod after deposit (default: address(0) for simple bridge)
|
|
33
|
+
* @param args.reserveBalance Optional: amount to keep as reserve when using callContract (default: 0).
|
|
34
|
+
* When callContract is address(0), reserveBalance MUST be 0.
|
|
35
|
+
* When callContract is set, amount must exceed reserveBalance; contract must be whitelisted.
|
|
36
|
+
* @param args.permit Optional permit bytes for gasless approval (default '0x')
|
|
33
37
|
* @param args.from Optional sender address
|
|
34
38
|
* @returns Unsigned transaction template with encoded deposit call
|
|
35
39
|
*/
|
|
@@ -37,7 +41,10 @@ class SourceChainToPodActionClient {
|
|
|
37
41
|
const data = this.iface.encodeFunctionData('deposit', [
|
|
38
42
|
args.token,
|
|
39
43
|
args.amount,
|
|
40
|
-
args.destinationWalletAddress
|
|
44
|
+
args.destinationWalletAddress,
|
|
45
|
+
args.callContract ?? ethers_1.ZeroAddress,
|
|
46
|
+
args.reserveBalance ?? 0,
|
|
47
|
+
args.permit ?? '0x',
|
|
41
48
|
]);
|
|
42
49
|
return {
|
|
43
50
|
to: this.config.sourceChain.contractAddress,
|
|
@@ -167,6 +167,7 @@ class PodBridgeTrackerClient {
|
|
|
167
167
|
}
|
|
168
168
|
else {
|
|
169
169
|
// Pod -> ETH: Check manual claim on Source Chain
|
|
170
|
+
// Claim event's txHash field = deposit's requestId (not deposit's txHash)
|
|
170
171
|
const claimInfo = sourceChainClaimEvents.get(depositData.requestId);
|
|
171
172
|
if (claimInfo) {
|
|
172
173
|
depositData.isClaimed = true;
|
|
@@ -218,7 +219,7 @@ class PodBridgeTrackerClient {
|
|
|
218
219
|
return d.isClaimed;
|
|
219
220
|
}
|
|
220
221
|
else {
|
|
221
|
-
// Pod -> ETH:
|
|
222
|
+
// Pod -> ETH: Claim event's txHash field = deposit's requestId
|
|
222
223
|
return sourceChainClaims.has(d.requestId);
|
|
223
224
|
}
|
|
224
225
|
});
|
|
@@ -2,40 +2,36 @@ import { BridgeRequest, PodBridgeChainConfig } from '../../libs/types/pod-bridge
|
|
|
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
|
-
*
|
|
10
5
|
* Responsibilities:
|
|
11
6
|
* - Fetch deposits made on POD (Pod -> ETH direction)
|
|
12
7
|
*
|
|
13
|
-
* Note: POD
|
|
14
|
-
*
|
|
8
|
+
* Note: POD returns logs with blockNumber: null which ethers.js can't parse.
|
|
9
|
+
* We use raw eth_getLogs RPC calls and parse logs manually.
|
|
15
10
|
*/
|
|
16
11
|
export declare class PodTrackerService {
|
|
17
12
|
private readonly config;
|
|
18
13
|
private readonly provider;
|
|
19
|
-
private readonly bridge;
|
|
20
14
|
private readonly iface;
|
|
15
|
+
/** Interface with uint256 id variant — Pod system contract may emit either bytes32 or uint256 id */
|
|
16
|
+
private readonly ifaceUint256Id;
|
|
21
17
|
private chainId;
|
|
22
18
|
constructor(config: PodBridgeChainConfig);
|
|
23
19
|
private initChainId;
|
|
24
20
|
ensureChainId(): Promise<void>;
|
|
25
21
|
/**
|
|
26
22
|
* Get deposits sent by an address on POD
|
|
27
|
-
* Note: POD has a single block, so blockNumber is essentially a timestamp
|
|
28
23
|
*/
|
|
29
24
|
getDepositsSentBy(address: string): Promise<BridgeRequest[]>;
|
|
30
25
|
/**
|
|
31
26
|
* Get deposits received by an address on POD
|
|
32
|
-
* Note: POD has a single block, so blockNumber is essentially a timestamp
|
|
33
27
|
*/
|
|
34
28
|
getDepositsReceivedBy(address: string): Promise<BridgeRequest[]>;
|
|
35
29
|
/**
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
30
|
+
* Fetch deposits from POD using raw eth_getLogs RPC.
|
|
31
|
+
* Pod returns logs with blockNumber: null, so we can't use ethers queryFilter.
|
|
32
|
+
*
|
|
33
|
+
* Queries both bytes32 and uint256 id event topics since Pod system contract
|
|
34
|
+
* may emit either variant.
|
|
39
35
|
*/
|
|
40
36
|
private getDeposits;
|
|
41
37
|
}
|
|
@@ -7,24 +7,19 @@ const bridge_abi_1 = require("../../libs/abi/bridge.abi");
|
|
|
7
7
|
/**
|
|
8
8
|
* PodTrackerService - Handles tracking on the POD Chain
|
|
9
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
|
-
*
|
|
15
10
|
* Responsibilities:
|
|
16
11
|
* - Fetch deposits made on POD (Pod -> ETH direction)
|
|
17
12
|
*
|
|
18
|
-
* Note: POD
|
|
19
|
-
*
|
|
13
|
+
* Note: POD returns logs with blockNumber: null which ethers.js can't parse.
|
|
14
|
+
* We use raw eth_getLogs RPC calls and parse logs manually.
|
|
20
15
|
*/
|
|
21
16
|
class PodTrackerService {
|
|
22
17
|
constructor(config) {
|
|
23
18
|
this.config = config;
|
|
24
19
|
this.chainId = null;
|
|
25
20
|
this.provider = config.provider;
|
|
26
|
-
this.
|
|
27
|
-
this.
|
|
21
|
+
this.iface = new ethers_1.Interface(bridge_abi_1.POD_BRIDGE_ABI);
|
|
22
|
+
this.ifaceUint256Id = new ethers_1.Interface(bridge_abi_1.SOURCE_CHAIN_BRIDGE_ABI);
|
|
28
23
|
this.initChainId();
|
|
29
24
|
}
|
|
30
25
|
async initChainId() {
|
|
@@ -43,43 +38,62 @@ class PodTrackerService {
|
|
|
43
38
|
}
|
|
44
39
|
/**
|
|
45
40
|
* Get deposits sent by an address on POD
|
|
46
|
-
* Note: POD has a single block, so blockNumber is essentially a timestamp
|
|
47
41
|
*/
|
|
48
42
|
async getDepositsSentBy(address) {
|
|
49
43
|
// Filter by 'from' (second indexed param): Deposit(id, from, to, token, amount)
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
});
|
|
44
|
+
const fromTopic = ethers_1.ethers.zeroPadValue(address, 32);
|
|
45
|
+
return this.getDeposits([null, fromTopic, null]);
|
|
53
46
|
}
|
|
54
47
|
/**
|
|
55
48
|
* Get deposits received by an address on POD
|
|
56
|
-
* Note: POD has a single block, so blockNumber is essentially a timestamp
|
|
57
49
|
*/
|
|
58
50
|
async getDepositsReceivedBy(address) {
|
|
59
51
|
// Filter by 'to' (third indexed param): Deposit(id, from, to, token, amount)
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
});
|
|
52
|
+
const toTopic = ethers_1.ethers.zeroPadValue(address, 32);
|
|
53
|
+
return this.getDeposits([null, null, toTopic]);
|
|
63
54
|
}
|
|
64
55
|
/**
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
56
|
+
* Fetch deposits from POD using raw eth_getLogs RPC.
|
|
57
|
+
* Pod returns logs with blockNumber: null, so we can't use ethers queryFilter.
|
|
58
|
+
*
|
|
59
|
+
* Queries both bytes32 and uint256 id event topics since Pod system contract
|
|
60
|
+
* may emit either variant.
|
|
68
61
|
*/
|
|
69
|
-
async getDeposits(
|
|
62
|
+
async getDeposits(topicFilters) {
|
|
70
63
|
const deposits = [];
|
|
71
|
-
//
|
|
72
|
-
const
|
|
73
|
-
const
|
|
74
|
-
//
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
64
|
+
// Pod may emit Deposit with bytes32 id or uint256 id — query both topics
|
|
65
|
+
const bytes32IdTopic = this.iface.getEvent('Deposit').topicHash;
|
|
66
|
+
const uint256IdTopic = this.ifaceUint256Id.getEvent('Deposit').topicHash;
|
|
67
|
+
// Use array in first topic position for OR matching (standard EVM eth_getLogs)
|
|
68
|
+
const topics = [
|
|
69
|
+
[bytes32IdTopic, uint256IdTopic],
|
|
70
|
+
...topicFilters,
|
|
71
|
+
];
|
|
72
|
+
// Use raw RPC to avoid ethers.js blockNumber validation
|
|
73
|
+
const rpcProvider = this.provider;
|
|
74
|
+
const rawLogs = await rpcProvider.send('eth_getLogs', [{
|
|
75
|
+
address: this.config.contractAddress,
|
|
76
|
+
topics,
|
|
77
|
+
fromBlock: 'earliest',
|
|
78
|
+
toBlock: 'latest',
|
|
79
|
+
}]);
|
|
80
|
+
// Log-level blockNumber is null/0x1 on Pod, but receipt-level blockNumber
|
|
81
|
+
// contains the real timestamp. Fetch receipts in parallel.
|
|
82
|
+
const receiptPromises = rawLogs.map(log => rpcProvider.send('eth_getTransactionReceipt', [log.transactionHash]));
|
|
83
|
+
const receipts = await Promise.all(receiptPromises);
|
|
84
|
+
for (let i = 0; i < rawLogs.length; i++) {
|
|
85
|
+
const log = rawLogs[i];
|
|
86
|
+
const receipt = receipts[i];
|
|
87
|
+
// Parse with the matching interface based on which topic was emitted
|
|
88
|
+
const isUint256Id = log.topics[0] === uint256IdTopic;
|
|
89
|
+
const parseIface = isUint256Id ? this.ifaceUint256Id : this.iface;
|
|
90
|
+
const parsed = parseIface.parseLog({
|
|
91
|
+
topics: log.topics,
|
|
78
92
|
data: log.data
|
|
79
93
|
});
|
|
80
94
|
if (parsed) {
|
|
81
|
-
//
|
|
82
|
-
const
|
|
95
|
+
// Receipt blockNumber on Pod is a Unix timestamp in hex (e.g. 0x69983FE1 -> 1771585505)
|
|
96
|
+
const timestamp = receipt?.blockNumber ? parseInt(receipt.blockNumber, 16) : 0;
|
|
83
97
|
deposits.push({
|
|
84
98
|
requestId: parsed.args.id.toString(),
|
|
85
99
|
deposit: {
|
|
@@ -89,9 +103,11 @@ class PodTrackerService {
|
|
|
89
103
|
destination: parsed.args.to,
|
|
90
104
|
token: parsed.args.token,
|
|
91
105
|
amount: parsed.args.amount.toString(),
|
|
106
|
+
callContract: parsed.args.callContract,
|
|
107
|
+
reserveBalance: parsed.args.reserveBalance.toString(),
|
|
92
108
|
chainId: this.chainId,
|
|
93
|
-
blockNumber:
|
|
94
|
-
timestamp
|
|
109
|
+
blockNumber: timestamp,
|
|
110
|
+
timestamp,
|
|
95
111
|
},
|
|
96
112
|
isClaimed: false,
|
|
97
113
|
isClaimable: false
|
|
@@ -1,11 +1,6 @@
|
|
|
1
1
|
import { BridgeRequest, BridgeChain, PodBridgeChainConfig } from '../../libs/types/pod-bridge.types';
|
|
2
2
|
/**
|
|
3
|
-
* SourceChainTrackerService - Handles tracking on the Source Chain (e.g.,
|
|
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)
|
|
3
|
+
* SourceChainTrackerService - Handles tracking on the Source Chain (e.g., ETH Mainnet)
|
|
9
4
|
*
|
|
10
5
|
* Responsibilities:
|
|
11
6
|
* - Fetch deposits made on Source Chain (ETH -> Pod direction)
|
|
@@ -34,13 +29,13 @@ export declare class SourceChainTrackerService {
|
|
|
34
29
|
private getDeposits;
|
|
35
30
|
/**
|
|
36
31
|
* Get claim events that occurred ON Source Chain
|
|
37
|
-
* These are claims of POD deposits (POD
|
|
38
|
-
* Event: Claim(bytes32 indexed
|
|
32
|
+
* These are claims of POD deposits (POD -> Source Chain direction)
|
|
33
|
+
* Event: Claim(bytes32 indexed txHash, address token, address mirrorToken, uint256 amount, address indexed to)
|
|
39
34
|
*
|
|
40
|
-
* Pod
|
|
35
|
+
* Pod deposit.txHash = ETH Claim.txHash - used to track if deposit was claimed
|
|
41
36
|
*
|
|
42
37
|
* @param deposits The POD deposits to check for claims
|
|
43
|
-
* @returns Map of
|
|
38
|
+
* @returns Map of deposit txHash to claim information
|
|
44
39
|
*/
|
|
45
40
|
getClaimEvents(deposits: BridgeRequest[]): Promise<Map<string, {
|
|
46
41
|
chain: BridgeChain;
|
|
@@ -5,12 +5,7 @@ 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.,
|
|
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)
|
|
8
|
+
* SourceChainTrackerService - Handles tracking on the Source Chain (e.g., ETH Mainnet)
|
|
14
9
|
*
|
|
15
10
|
* Responsibilities:
|
|
16
11
|
* - Fetch deposits made on Source Chain (ETH -> Pod direction)
|
|
@@ -21,8 +16,8 @@ class SourceChainTrackerService {
|
|
|
21
16
|
this.config = config;
|
|
22
17
|
this.chainId = null;
|
|
23
18
|
this.provider = config.provider;
|
|
24
|
-
this.bridge = new ethers_1.Contract(config.contractAddress, bridge_abi_1.
|
|
25
|
-
this.iface = new ethers_1.Interface(bridge_abi_1.
|
|
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);
|
|
26
21
|
this.initChainId();
|
|
27
22
|
}
|
|
28
23
|
async initChainId() {
|
|
@@ -61,7 +56,7 @@ class SourceChainTrackerService {
|
|
|
61
56
|
const BLOCK_BATCH_SIZE = 10000;
|
|
62
57
|
for (let start = startBlock; start <= currentBlock; start += BLOCK_BATCH_SIZE) {
|
|
63
58
|
const end = Math.min(start + BLOCK_BATCH_SIZE - 1, currentBlock);
|
|
64
|
-
// Event: Deposit(
|
|
59
|
+
// Event: Deposit(uint256 indexed id, address indexed from, address indexed to, address token, uint256 amount, address callContract, uint256 reserveBalance)
|
|
65
60
|
const depositFilter = this.bridge.filters.Deposit(...options.depositEventFilter);
|
|
66
61
|
const depositLogs = await this.bridge.queryFilter(depositFilter, start, end);
|
|
67
62
|
if (start + BLOCK_BATCH_SIZE <= currentBlock) {
|
|
@@ -85,6 +80,8 @@ class SourceChainTrackerService {
|
|
|
85
80
|
destination: parsed.args.to,
|
|
86
81
|
token: parsed.args.token,
|
|
87
82
|
amount: parsed.args.amount.toString(),
|
|
83
|
+
callContract: parsed.args.callContract,
|
|
84
|
+
reserveBalance: parsed.args.reserveBalance.toString(),
|
|
88
85
|
chainId: this.chainId,
|
|
89
86
|
blockNumber: log.blockNumber,
|
|
90
87
|
timestamp: block ? Number(block.timestamp) : 0
|
|
@@ -99,13 +96,13 @@ class SourceChainTrackerService {
|
|
|
99
96
|
}
|
|
100
97
|
/**
|
|
101
98
|
* Get claim events that occurred ON Source Chain
|
|
102
|
-
* These are claims of POD deposits (POD
|
|
103
|
-
* Event: Claim(bytes32 indexed
|
|
99
|
+
* These are claims of POD deposits (POD -> Source Chain direction)
|
|
100
|
+
* Event: Claim(bytes32 indexed txHash, address token, address mirrorToken, uint256 amount, address indexed to)
|
|
104
101
|
*
|
|
105
|
-
* Pod
|
|
102
|
+
* Pod deposit.txHash = ETH Claim.txHash - used to track if deposit was claimed
|
|
106
103
|
*
|
|
107
104
|
* @param deposits The POD deposits to check for claims
|
|
108
|
-
* @returns Map of
|
|
105
|
+
* @returns Map of deposit txHash to claim information
|
|
109
106
|
*/
|
|
110
107
|
async getClaimEvents(deposits) {
|
|
111
108
|
const uniqueRecipients = [...new Set(deposits.map(d => d.deposit.destination))];
|
|
@@ -114,8 +111,9 @@ class SourceChainTrackerService {
|
|
|
114
111
|
const currentBlock = await this.provider.getBlockNumber();
|
|
115
112
|
const BLOCK_BATCH_SIZE = 10000;
|
|
116
113
|
for (const recipient of uniqueRecipients) {
|
|
117
|
-
// Event: Claim(bytes32 indexed
|
|
118
|
-
|
|
114
|
+
// Event: Claim(bytes32 indexed txHash, address token, address mirrorToken, uint256 amount, address indexed to)
|
|
115
|
+
// Must pass null for all non-indexed params (token, mirrorToken, amount) to reach 'to'
|
|
116
|
+
const claimFilter = this.bridge.filters.Claim(null, null, null, null, recipient);
|
|
119
117
|
for (let start = startBlock; start <= currentBlock; start += BLOCK_BATCH_SIZE) {
|
|
120
118
|
const end = Math.min(start + BLOCK_BATCH_SIZE - 1, currentBlock);
|
|
121
119
|
const claimLogs = await this.bridge.queryFilter(claimFilter, start, end);
|
|
@@ -135,8 +133,8 @@ class SourceChainTrackerService {
|
|
|
135
133
|
if (parsed) {
|
|
136
134
|
// Get block for timestamp
|
|
137
135
|
const block = await this.provider.getBlock(log.blockNumber);
|
|
138
|
-
// Pod
|
|
139
|
-
claimedMap.set(parsed.args.
|
|
136
|
+
// Pod deposit.txHash = ETH Claim.txHash
|
|
137
|
+
claimedMap.set(parsed.args.txHash, {
|
|
140
138
|
chain: pod_bridge_types_1.BridgeChain.SOURCE_CHAIN,
|
|
141
139
|
txHash: log.transactionHash,
|
|
142
140
|
timestamp: block ? Number(block.timestamp) : 0,
|
|
@@ -163,7 +161,7 @@ class SourceChainTrackerService {
|
|
|
163
161
|
}
|
|
164
162
|
// Fallback: Use manual calculation if RPC doesn't support finalized tag
|
|
165
163
|
const currentBlock = await this.provider.getBlockNumber();
|
|
166
|
-
return currentBlock - 64; // 2 epochs (32 x 2 blocks) ~15 minutes
|
|
164
|
+
return currentBlock - 64; // 2 epochs (32 x 2 blocks) ~15 minutes
|
|
167
165
|
}
|
|
168
166
|
/**
|
|
169
167
|
* Check if a block is finalized
|
package/dist/index.d.ts
CHANGED
|
@@ -2,5 +2,5 @@ export { PodToSourceChainActionClient } from './clients/action/pod-to-source-cha
|
|
|
2
2
|
export { SourceChainToPodActionClient } from './clients/action/source-chain-to-pod-client';
|
|
3
3
|
export { PodBridgeTrackerClient } from './clients/tracker/client';
|
|
4
4
|
export { BRIDGE_ABI, POD_BRIDGE_ABI, SOURCE_CHAIN_BRIDGE_ABI, } from './libs/abi/bridge.abi';
|
|
5
|
-
export {
|
|
6
|
-
export { PodBridgeConfig, BridgeRequest, BridgeRequestWithType, BridgeChain, DepositType, UnsignedTransaction, ClaimProofData, PodBridgeActionsClientConfig, PodBridgeChainConfig, } from './libs/types/pod-bridge.types';
|
|
5
|
+
export { getBridgeClaimProof, } from './libs/helpers/bridge-claim-proof.helper';
|
|
6
|
+
export { PodBridgeConfig, BridgeRequest, BridgeRequestWithType, BridgeChain, DepositType, UnsignedTransaction, ClaimProofData, BridgeClaimProofResponse, 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.
|
|
3
|
+
exports.DepositType = exports.BridgeChain = exports.getBridgeClaimProof = 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");
|
|
@@ -11,16 +11,8 @@ var bridge_abi_1 = require("./libs/abi/bridge.abi");
|
|
|
11
11
|
Object.defineProperty(exports, "BRIDGE_ABI", { enumerable: true, get: function () { return bridge_abi_1.BRIDGE_ABI; } });
|
|
12
12
|
Object.defineProperty(exports, "POD_BRIDGE_ABI", { enumerable: true, get: function () { return bridge_abi_1.POD_BRIDGE_ABI; } });
|
|
13
13
|
Object.defineProperty(exports, "SOURCE_CHAIN_BRIDGE_ABI", { enumerable: true, get: function () { return bridge_abi_1.SOURCE_CHAIN_BRIDGE_ABI; } });
|
|
14
|
-
var
|
|
15
|
-
Object.defineProperty(exports, "
|
|
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, "extractSignatureInfo", { enumerable: true, get: function () { return signature_recovery_helper_1.extractSignatureInfo; } });
|
|
20
|
-
Object.defineProperty(exports, "addressFromPublicKey", { enumerable: true, get: function () { return signature_recovery_helper_1.addressFromPublicKey; } });
|
|
21
|
-
Object.defineProperty(exports, "parseDerSignature", { enumerable: true, get: function () { return signature_recovery_helper_1.parseDerSignature; } });
|
|
22
|
-
Object.defineProperty(exports, "recoverSignatureWithoutPubkey", { enumerable: true, get: function () { return signature_recovery_helper_1.recoverSignatureWithoutPubkey; } });
|
|
23
|
-
Object.defineProperty(exports, "extractAggregatedSignaturesWithValidators", { enumerable: true, get: function () { return signature_recovery_helper_1.extractAggregatedSignaturesWithValidators; } });
|
|
14
|
+
var bridge_claim_proof_helper_1 = require("./libs/helpers/bridge-claim-proof.helper");
|
|
15
|
+
Object.defineProperty(exports, "getBridgeClaimProof", { enumerable: true, get: function () { return bridge_claim_proof_helper_1.getBridgeClaimProof; } });
|
|
24
16
|
var pod_bridge_types_1 = require("./libs/types/pod-bridge.types");
|
|
25
17
|
Object.defineProperty(exports, "BridgeChain", { enumerable: true, get: function () { return pod_bridge_types_1.BridgeChain; } });
|
|
26
18
|
Object.defineProperty(exports, "DepositType", { enumerable: true, get: function () { return pod_bridge_types_1.DepositType; } });
|
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* ABI for Bridge contract on Source Chain (ETH/
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
2
|
+
* ABI for Bridge contract on Source Chain (ETH/Mainnet)
|
|
3
|
+
*
|
|
4
|
+
* ETH -> Pod: deposit on ETH (6-param with callContract, reserveBalance, permit), auto-claim on Pod
|
|
5
|
+
* Pod -> ETH: deposit on Pod, claim on ETH with proof from pod_getBridgeClaimProof RPC
|
|
6
|
+
*
|
|
7
|
+
* New deposit params (callContract, reserveBalance) enable depositing to CLOB orderbook in one TX.
|
|
8
|
+
* For simple bridge deposits: callContract=address(0), reserveBalance=0.
|
|
7
9
|
*/
|
|
8
|
-
export declare const BRIDGE_ABI: string[];
|
|
9
10
|
export declare const SOURCE_CHAIN_BRIDGE_ABI: string[];
|
|
11
|
+
/**
|
|
12
|
+
* ABI for Bridge system contract on Pod chain.
|
|
13
|
+
* Pod uses bytes32 indexed id in Deposit events (different from ETH's uint256).
|
|
14
|
+
* Same 6-param deposit as source chain.
|
|
15
|
+
*/
|
|
10
16
|
export declare const POD_BRIDGE_ABI: string[];
|
|
17
|
+
export declare const BRIDGE_ABI: string[];
|
|
@@ -1,29 +1,38 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.BRIDGE_ABI = exports.POD_BRIDGE_ABI = exports.SOURCE_CHAIN_BRIDGE_ABI = void 0;
|
|
4
4
|
/**
|
|
5
|
-
* ABI for Bridge contract on Source Chain (ETH/
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
5
|
+
* ABI for Bridge contract on Source Chain (ETH/Mainnet)
|
|
6
|
+
*
|
|
7
|
+
* ETH -> Pod: deposit on ETH (6-param with callContract, reserveBalance, permit), auto-claim on Pod
|
|
8
|
+
* Pod -> ETH: deposit on Pod, claim on ETH with proof from pod_getBridgeClaimProof RPC
|
|
9
|
+
*
|
|
10
|
+
* New deposit params (callContract, reserveBalance) enable depositing to CLOB orderbook in one TX.
|
|
11
|
+
* For simple bridge deposits: callContract=address(0), reserveBalance=0.
|
|
10
12
|
*/
|
|
11
|
-
exports.
|
|
13
|
+
exports.SOURCE_CHAIN_BRIDGE_ABI = [
|
|
12
14
|
// Events
|
|
13
|
-
"event Deposit(
|
|
14
|
-
"event Claim(bytes32 indexed
|
|
15
|
-
// Deposit function (
|
|
16
|
-
"function deposit(address token, uint256 amount, address to) returns (
|
|
17
|
-
// Claim function with
|
|
18
|
-
"function claim(address token, uint256 amount, address to,
|
|
15
|
+
"event Deposit(uint256 indexed id, address indexed from, address indexed to, address token, uint256 amount, address callContract, uint256 reserveBalance)",
|
|
16
|
+
"event Claim(bytes32 indexed txHash, address token, address mirrorToken, uint256 amount, address indexed to)",
|
|
17
|
+
// Deposit function (6-param: token, amount, to, callContract, reserveBalance, permit)
|
|
18
|
+
"function deposit(address token, uint256 amount, address to, address callContract, uint256 reserveBalance, bytes permit) returns (uint256)",
|
|
19
|
+
// Claim function with proof from pod_getBridgeClaimProof
|
|
20
|
+
"function claim(address token, uint256 amount, address to, bytes proof, bytes auxTxSuffix)",
|
|
19
21
|
// View functions
|
|
20
22
|
"function processedRequests(bytes32) view returns (bool)",
|
|
21
|
-
"function
|
|
22
|
-
"function DOMAIN_SEPARATOR() view returns (bytes32)",
|
|
23
|
-
"function tokenData(address) view returns (uint256 minAmount, uint256 depositLimit, uint256 claimLimit, tuple(uint256 consumed, uint256 lastUpdated) depositUsage, tuple(uint256 consumed, uint256 lastUpdated) claimUsage, address mirrorToken)",
|
|
24
|
-
"function whitelistedTokens(uint256) view returns (address)",
|
|
23
|
+
"function tokenData(address) view returns (uint256, uint256, uint256, tuple(uint256, uint256), tuple(uint256, uint256), address)",
|
|
25
24
|
"function depositIndex() view returns (uint256)",
|
|
26
25
|
];
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
26
|
+
/**
|
|
27
|
+
* ABI for Bridge system contract on Pod chain.
|
|
28
|
+
* Pod uses bytes32 indexed id in Deposit events (different from ETH's uint256).
|
|
29
|
+
* Same 6-param deposit as source chain.
|
|
30
|
+
*/
|
|
31
|
+
exports.POD_BRIDGE_ABI = [
|
|
32
|
+
// Events
|
|
33
|
+
"event Deposit(bytes32 indexed id, address indexed from, address indexed to, address token, uint256 amount, address callContract, uint256 reserveBalance)",
|
|
34
|
+
// Deposit function (6-param, same as source chain)
|
|
35
|
+
"function deposit(address token, uint256 amount, address to, address callContract, uint256 reserveBalance, bytes permit) returns (uint256)",
|
|
36
|
+
];
|
|
37
|
+
// Backward compatibility alias
|
|
38
|
+
exports.BRIDGE_ABI = exports.SOURCE_CHAIN_BRIDGE_ABI;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { JsonRpcProvider } from 'ethers';
|
|
2
|
+
/**
|
|
3
|
+
* Fetch bridge claim proof from Pod RPC.
|
|
4
|
+
*
|
|
5
|
+
* Calls the `pod_getBridgeClaimProof` RPC method with the deposit transaction hash
|
|
6
|
+
* and returns the proof data formatted for use with the ETH bridge claim function.
|
|
7
|
+
*
|
|
8
|
+
* @param podProvider A JsonRpcProvider connected to the Pod RPC
|
|
9
|
+
* @param depositTxHash The deposit transaction hash on Pod
|
|
10
|
+
* @returns Formatted proof data ready for the claim call
|
|
11
|
+
*/
|
|
12
|
+
export declare function getBridgeClaimProof(podProvider: JsonRpcProvider, depositTxHash: string): Promise<{
|
|
13
|
+
proof: string;
|
|
14
|
+
committeeEpoch: number;
|
|
15
|
+
auxTxSuffix: string;
|
|
16
|
+
}>;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getBridgeClaimProof = getBridgeClaimProof;
|
|
4
|
+
/**
|
|
5
|
+
* Convert a number[] byte array to a 0x-prefixed hex string.
|
|
6
|
+
*/
|
|
7
|
+
function bytesToHex(bytes) {
|
|
8
|
+
return '0x' + bytes.map(b => b.toString(16).padStart(2, '0')).join('');
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Fetch bridge claim proof from Pod RPC.
|
|
12
|
+
*
|
|
13
|
+
* Calls the `pod_getBridgeClaimProof` RPC method with the deposit transaction hash
|
|
14
|
+
* and returns the proof data formatted for use with the ETH bridge claim function.
|
|
15
|
+
*
|
|
16
|
+
* @param podProvider A JsonRpcProvider connected to the Pod RPC
|
|
17
|
+
* @param depositTxHash The deposit transaction hash on Pod
|
|
18
|
+
* @returns Formatted proof data ready for the claim call
|
|
19
|
+
*/
|
|
20
|
+
async function getBridgeClaimProof(podProvider, depositTxHash) {
|
|
21
|
+
const response = await podProvider.send('pod_getBridgeClaimProof', [depositTxHash]);
|
|
22
|
+
return {
|
|
23
|
+
proof: bytesToHex(response.proof),
|
|
24
|
+
committeeEpoch: response.committee_epoch,
|
|
25
|
+
auxTxSuffix: bytesToHex(response.aux_tx_suffix),
|
|
26
|
+
};
|
|
27
|
+
}
|
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @deprecated This helper is no longer needed in the new bridge architecture.
|
|
3
3
|
*
|
|
4
|
-
* The new bridge uses
|
|
5
|
-
* See
|
|
6
|
-
*
|
|
7
|
-
* New architecture:
|
|
8
|
-
* - ETH -> Pod: Auto-claim on Pod (no claim transaction needed)
|
|
9
|
-
* - Pod -> ETH: Claim with aggregated 65-byte ECDSA signatures
|
|
4
|
+
* The new bridge uses pod_getBridgeClaimProof RPC for claim proofs.
|
|
5
|
+
* See bridge-claim-proof.helper.ts for the new helper.
|
|
10
6
|
*/
|
|
11
7
|
export declare const convertFFICertifiedLog: (_ffi: unknown) => never;
|
|
@@ -2,18 +2,14 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* @deprecated This helper is no longer needed in the new bridge architecture.
|
|
4
4
|
*
|
|
5
|
-
* The new bridge uses
|
|
6
|
-
* See
|
|
7
|
-
*
|
|
8
|
-
* New architecture:
|
|
9
|
-
* - ETH -> Pod: Auto-claim on Pod (no claim transaction needed)
|
|
10
|
-
* - Pod -> ETH: Claim with aggregated 65-byte ECDSA signatures
|
|
5
|
+
* The new bridge uses pod_getBridgeClaimProof RPC for claim proofs.
|
|
6
|
+
* See bridge-claim-proof.helper.ts for the new helper.
|
|
11
7
|
*/
|
|
12
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
9
|
exports.convertFFICertifiedLog = void 0;
|
|
14
10
|
// Kept for backwards compatibility, but will be removed in future versions
|
|
15
11
|
const convertFFICertifiedLog = (_ffi) => {
|
|
16
|
-
console.warn('[DEPRECATED] convertFFICertifiedLog is deprecated. Use
|
|
17
|
-
throw new Error('CertifiedLog format is no longer supported. Use ClaimProofData with
|
|
12
|
+
console.warn('[DEPRECATED] convertFFICertifiedLog is deprecated. Use getBridgeClaimProof instead.');
|
|
13
|
+
throw new Error('CertifiedLog format is no longer supported. Use ClaimProofData with proof from pod_getBridgeClaimProof.');
|
|
18
14
|
};
|
|
19
15
|
exports.convertFFICertifiedLog = convertFFICertifiedLog;
|