@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.
@@ -1,49 +1,29 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.SOURCE_CHAIN_BRIDGE_ABI = exports.POD_BRIDGE_ABI = void 0;
3
+ exports.POD_BRIDGE_ABI = exports.SOURCE_CHAIN_BRIDGE_ABI = exports.BRIDGE_ABI = void 0;
4
4
  /**
5
- * ABI for BridgeMintBurn contract on POD Chain
6
- * - Deposits burn tokens
7
- * - Claims use block number verification via precompiles
5
+ * ABI for Bridge contract on Source Chain (ETH/Sepolia)
6
+ * New architecture:
7
+ * - ETH -> Pod: deposit on ETH, auto-claim on Pod (no claim needed)
8
+ * - Pod -> ETH: deposit on Pod, claim on ETH with aggregated validator signatures
9
+ * - Only ERC20 tokens supported (no native ETH - must wrap to WETH)
8
10
  */
9
- exports.POD_BRIDGE_ABI = [
11
+ exports.BRIDGE_ABI = [
10
12
  // Events
11
- "event Deposit(uint256 indexed id, address indexed from, address indexed to, address token, uint256 amount, uint256 timestamp, uint256 blockNumber)",
12
- "event DepositNative(uint256 indexed id, address indexed from, address indexed to, uint256 amount, uint256 timestamp, uint256 blockNumber)",
13
- "event Claim(uint256 indexed id, address indexed claimer, address indexed to, address mirrorToken, address token, uint256 amount, uint256 timestamp)",
14
- "event ClaimNative(uint256 indexed id, address indexed claimer, address indexed to, uint256 amount, uint256 timestamp)",
15
- "event BurnNative(address indexed from, uint256 amount)",
16
- // Deposit functions
17
- "function deposit(address token, uint256 amount, address to) returns (uint256)",
18
- "function depositNative(address to) payable returns (uint256)",
19
- // Claim functions (use block number verification)
20
- "function claim(uint256 id, address token, uint256 blockNumber)",
21
- "function claimNative(uint256 id, uint256 blockNumber)",
13
+ "event Deposit(bytes32 indexed id, address indexed from, address indexed to, address token, uint256 amount)",
14
+ "event Claim(bytes32 indexed id, address indexed to, address token, uint256 amount)",
15
+ // Deposit function (ERC20 only)
16
+ "function deposit(address token, uint256 amount, address to) returns (bytes32)",
17
+ // Claim function with aggregated validator signatures
18
+ "function claim(address token, uint256 amount, address to, uint64 committeeEpoch, bytes aggregatedSignatures, bytes proof)",
22
19
  // View functions
23
20
  "function processedRequests(bytes32) view returns (bool)",
24
- "function bridgeContract() view returns (address)",
25
- "function SOURCE_CHAIN_ID() view returns (uint96)",
26
- "function areRequestsProcessed(uint256[] ids, address[] tokens, uint256[] amounts, address[] tos) view returns (bool[])",
27
- ];
28
- /**
29
- * ABI for BridgeDepositWithdraw contract on Source Chain (e.g., Sepolia)
30
- * - Deposits lock tokens
31
- * - Claims use POD certificates with attestations and merkle proofs
32
- */
33
- exports.SOURCE_CHAIN_BRIDGE_ABI = [
34
- // Events
35
- "event Deposit(uint256 indexed id, address indexed from, address indexed to, address token, uint256 amount, uint256 timestamp, uint256 blockNumber)",
36
- "event DepositNative(uint256 indexed id, address indexed from, address indexed to, uint256 amount, uint256 timestamp, uint256 blockNumber)",
37
- "event Claim(uint256 indexed id, address indexed claimer, address indexed to, address mirrorToken, address token, uint256 amount, uint256 timestamp)",
38
- "event ClaimNative(uint256 indexed id, address indexed claimer, address indexed to, uint256 amount, uint256 timestamp)",
39
- // Deposit functions
40
- "function deposit(address token, uint256 amount, address to) returns (uint256)",
41
- "function depositNative(address to) payable returns (uint256)",
42
- // Claim functions (use PodECDSA.CertifiedLog with certificates)
43
- "function claim(tuple(tuple(address addr, bytes32[] topics, bytes data) log, uint256 logIndex, tuple(tuple(bytes32 receiptRoot, bytes aggregateSignature, uint256[] sortedAttestationTimestamps) certifiedReceipt, bytes32 leaf, tuple(bytes32[] path) proof) certificate) certifiedLog)",
44
- "function claimNative(tuple(tuple(address addr, bytes32[] topics, bytes data) log, uint256 logIndex, tuple(tuple(bytes32 receiptRoot, bytes aggregateSignature, uint256[] sortedAttestationTimestamps) certifiedReceipt, bytes32 leaf, tuple(bytes32[] path) proof) certificate) certifiedLog)",
45
- // View functions
46
- "function processedRequests(bytes32) view returns (bool)",
47
- "function bridgeContract() view returns (address)",
48
- "function areRequestsProcessed(uint256[] ids, address[] tokens, uint256[] amounts, address[] tos) view returns (bool[])",
21
+ "function BRIDGE_CONTRACT() view returns (address)",
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)",
25
+ "function depositIndex() view returns (uint256)",
49
26
  ];
27
+ // Legacy alias for backwards compatibility
28
+ exports.SOURCE_CHAIN_BRIDGE_ABI = exports.BRIDGE_ABI;
29
+ exports.POD_BRIDGE_ABI = exports.BRIDGE_ABI;
@@ -1,23 +1,11 @@
1
- import { CertifiedLog } from "../types/pod-bridge.types";
2
1
  /**
3
- * Convert FFI CertifiedLog to the TypeScript CertifiedLog format
2
+ * @deprecated This helper is no longer needed in the new bridge architecture.
3
+ *
4
+ * The new bridge uses aggregated validator signatures instead of certified logs.
5
+ * See signature-recovery.helper.ts for the new signature recovery utilities.
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
10
  */
5
- export declare const convertFFICertifiedLog: (ffi: CertifiedLog) => {
6
- log: {
7
- addr: string;
8
- topics: string[];
9
- data: string;
10
- };
11
- logIndex: bigint;
12
- certificate: {
13
- certifiedReceipt: {
14
- receiptRoot: string;
15
- aggregateSignature: string;
16
- sortedAttestationTimestamps: bigint[];
17
- };
18
- leaf: string;
19
- proof: {
20
- path: string[];
21
- };
22
- };
23
- };
11
+ export declare const convertFFICertifiedLog: (_ffi: unknown) => never;
@@ -1,28 +1,19 @@
1
1
  "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.convertFFICertifiedLog = void 0;
4
2
  /**
5
- * Convert FFI CertifiedLog to the TypeScript CertifiedLog format
3
+ * @deprecated This helper is no longer needed in the new bridge architecture.
4
+ *
5
+ * The new bridge uses aggregated validator signatures instead of certified logs.
6
+ * See signature-recovery.helper.ts for the new signature recovery utilities.
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
6
11
  */
7
- const convertFFICertifiedLog = (ffi) => {
8
- return {
9
- log: {
10
- addr: ffi.log.addr,
11
- topics: ffi.log.topics,
12
- data: ffi.log.data,
13
- },
14
- logIndex: BigInt(ffi.log_index),
15
- certificate: {
16
- certifiedReceipt: {
17
- receiptRoot: ffi.certificate.certified_receipt.receipt_root,
18
- aggregateSignature: ffi.certificate.certified_receipt.aggregate_signature,
19
- sortedAttestationTimestamps: ffi.certificate.certified_receipt.sorted_attestation_timestamps.map(t => BigInt(t)),
20
- },
21
- leaf: ffi.certificate.leaf,
22
- proof: {
23
- path: ffi.certificate.proof.path,
24
- },
25
- },
26
- };
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.convertFFICertifiedLog = void 0;
14
+ // Kept for backwards compatibility, but will be removed in future versions
15
+ const convertFFICertifiedLog = (_ffi) => {
16
+ console.warn('[DEPRECATED] convertFFICertifiedLog is deprecated. Use signature-recovery.helper.ts instead.');
17
+ throw new Error('CertifiedLog format is no longer supported. Use ClaimProofData with aggregated signatures.');
27
18
  };
28
19
  exports.convertFFICertifiedLog = convertFFICertifiedLog;
@@ -0,0 +1,91 @@
1
+ import { PodTransactionReceipt } from '../pod-sdk/src/types/responses';
2
+ /**
3
+ * Derive Ethereum address from a public key.
4
+ *
5
+ * @param publicKey The public key (uncompressed 65 bytes with 04 prefix, or 64 bytes x||y)
6
+ * @returns The Ethereum address
7
+ */
8
+ export declare function addressFromPublicKey(publicKey: string): string;
9
+ /**
10
+ * Recover a 65-byte ECDSA signature (r,s,v) from a 64-byte compact signature.
11
+ *
12
+ * Exactly matches the Rust implementation:
13
+ * ```rust
14
+ * pub fn recover_65b_signature(
15
+ * sig: &Signature,
16
+ * msg_hash: [u8; 32],
17
+ * pubkey: &PublicKey,
18
+ * ) -> anyhow::Result<[u8; 65]> {
19
+ * let secp = Secp256k1::new();
20
+ * let msg = Message::from_digest(msg_hash);
21
+ * let sig_bytes = sig.serialize_compact();
22
+ *
23
+ * for recovery_id in [RecoveryId::Zero, RecoveryId::One] {
24
+ * let recoverable_sig = RecoverableSignature::from_compact(&sig_bytes, recovery_id)?;
25
+ * match secp.recover_ecdsa(msg, &recoverable_sig) {
26
+ * Ok(recovered_key) => {
27
+ * if recovered_key == *pubkey {
28
+ * return Ok(recoverable_sig.to_alloy().as_bytes());
29
+ * }
30
+ * }
31
+ * Err(e) => { ... }
32
+ * }
33
+ * }
34
+ * Err(anyhow!("Could not find valid recovery ID for signature"))
35
+ * }
36
+ * ```
37
+ *
38
+ * @param r The r component of the signature (32 bytes hex)
39
+ * @param s The s component of the signature (32 bytes hex)
40
+ * @param msgHash The 32-byte message hash that was signed
41
+ * @param publicKey The expected signer's public key
42
+ * @returns The 65-byte signature (r || s || v) or null if recovery fails
43
+ */
44
+ export declare function recoverSignature65B(r: string, s: string, msgHash: string, publicKey: string): string | null;
45
+ /**
46
+ * Recover multiple 65-byte signatures from concatenated 64-byte signatures.
47
+ *
48
+ * @param aggregatedSig64 Concatenated 64-byte signatures (r || s for each)
49
+ * @param msgHash The message hash that was signed
50
+ * @param publicKeys Array of expected signer public keys in order
51
+ * @returns Concatenated 65-byte signatures or null if any recovery fails
52
+ */
53
+ export declare function recoverAggregatedSignatures65B(aggregatedSig64: string | Uint8Array, msgHash: string, publicKeys: string[]): string | null;
54
+ /**
55
+ * Compute the transaction hash for a bridge deposit that needs to be signed.
56
+ * This matches the depositTxHash function in the Bridge.sol contract.
57
+ *
58
+ * @param domainSeparator The domain separator from the bridge contract
59
+ * @param bridgeContract The address of the bridge contract on the other chain
60
+ * @param token The token address
61
+ * @param amount The amount
62
+ * @param to The recipient address
63
+ * @param proof The proof (deposit TX hash)
64
+ * @returns The transaction hash to be signed
65
+ */
66
+ export declare function computeDepositTxHash(domainSeparator: string, bridgeContract: string, token: string, amount: bigint | string, to: string, proof: string): string;
67
+ /**
68
+ * Extract aggregated 65-byte signatures from Pod transaction receipt attestations.
69
+ *
70
+ * Exactly matches the Rust implementation - recovers the v (parity bit) by trying
71
+ * both recovery IDs and checking which one recovers to the correct public key.
72
+ *
73
+ * @param receipt The Pod transaction receipt
74
+ * @param msgHash The message hash that validators signed (transaction hash)
75
+ * @returns Concatenated 65-byte signatures (r || s || v for each attestation)
76
+ */
77
+ export declare function extractAggregatedSignatures(receipt: PodTransactionReceipt, msgHash?: string): string;
78
+ /**
79
+ * Extract attestation data from Pod receipt for debugging/verification.
80
+ * Uses recoverSignature65B to properly recover v value.
81
+ *
82
+ * @param receipt The Pod transaction receipt
83
+ * @param msgHash The message hash that validators signed
84
+ * @returns Array of attestation info with public keys and recovered signatures
85
+ */
86
+ export declare function extractAttestationInfo(receipt: PodTransactionReceipt, msgHash?: string): Array<{
87
+ publicKey: string;
88
+ address: string;
89
+ signature: string;
90
+ timestamp: number;
91
+ }>;
@@ -0,0 +1,218 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.addressFromPublicKey = addressFromPublicKey;
4
+ exports.recoverSignature65B = recoverSignature65B;
5
+ exports.recoverAggregatedSignatures65B = recoverAggregatedSignatures65B;
6
+ exports.computeDepositTxHash = computeDepositTxHash;
7
+ exports.extractAggregatedSignatures = extractAggregatedSignatures;
8
+ exports.extractAttestationInfo = extractAttestationInfo;
9
+ const ethers_1 = require("ethers");
10
+ /**
11
+ * Derive Ethereum address from a public key.
12
+ *
13
+ * @param publicKey The public key (uncompressed 65 bytes with 04 prefix, or 64 bytes x||y)
14
+ * @returns The Ethereum address
15
+ */
16
+ function addressFromPublicKey(publicKey) {
17
+ const pubKeyHex = publicKey.replace('0x', '');
18
+ // Handle different public key formats
19
+ let xyBytes;
20
+ if (pubKeyHex.length === 130 && pubKeyHex.startsWith('04')) {
21
+ // Uncompressed: 04 + x (32 bytes) + y (32 bytes)
22
+ xyBytes = pubKeyHex.slice(2);
23
+ }
24
+ else if (pubKeyHex.length === 128) {
25
+ // Already x || y without prefix
26
+ xyBytes = pubKeyHex;
27
+ }
28
+ else {
29
+ throw new Error(`Invalid public key length: ${pubKeyHex.length}. Expected 128 or 130 hex chars.`);
30
+ }
31
+ // Address = keccak256(x || y)[12:] = last 20 bytes
32
+ const hash = (0, ethers_1.keccak256)('0x' + xyBytes);
33
+ return '0x' + hash.slice(-40);
34
+ }
35
+ /**
36
+ * Recover a 65-byte ECDSA signature (r,s,v) from a 64-byte compact signature.
37
+ *
38
+ * Exactly matches the Rust implementation:
39
+ * ```rust
40
+ * pub fn recover_65b_signature(
41
+ * sig: &Signature,
42
+ * msg_hash: [u8; 32],
43
+ * pubkey: &PublicKey,
44
+ * ) -> anyhow::Result<[u8; 65]> {
45
+ * let secp = Secp256k1::new();
46
+ * let msg = Message::from_digest(msg_hash);
47
+ * let sig_bytes = sig.serialize_compact();
48
+ *
49
+ * for recovery_id in [RecoveryId::Zero, RecoveryId::One] {
50
+ * let recoverable_sig = RecoverableSignature::from_compact(&sig_bytes, recovery_id)?;
51
+ * match secp.recover_ecdsa(msg, &recoverable_sig) {
52
+ * Ok(recovered_key) => {
53
+ * if recovered_key == *pubkey {
54
+ * return Ok(recoverable_sig.to_alloy().as_bytes());
55
+ * }
56
+ * }
57
+ * Err(e) => { ... }
58
+ * }
59
+ * }
60
+ * Err(anyhow!("Could not find valid recovery ID for signature"))
61
+ * }
62
+ * ```
63
+ *
64
+ * @param r The r component of the signature (32 bytes hex)
65
+ * @param s The s component of the signature (32 bytes hex)
66
+ * @param msgHash The 32-byte message hash that was signed
67
+ * @param publicKey The expected signer's public key
68
+ * @returns The 65-byte signature (r || s || v) or null if recovery fails
69
+ */
70
+ function recoverSignature65B(r, s, msgHash, publicKey) {
71
+ // Normalize r and s
72
+ const rHex = r.replace('0x', '').padStart(64, '0');
73
+ const sHex = s.replace('0x', '').padStart(64, '0');
74
+ // Derive expected address from public key
75
+ let expectedAddress;
76
+ try {
77
+ expectedAddress = addressFromPublicKey(publicKey);
78
+ }
79
+ catch (e) {
80
+ console.error('Failed to derive address from public key:', e);
81
+ return null;
82
+ }
83
+ // Try both recovery IDs (27 and 28 in Ethereum, corresponding to RecoveryId::Zero and RecoveryId::One)
84
+ for (const v of [27, 28]) {
85
+ try {
86
+ const signature = { r: '0x' + rHex, s: '0x' + sHex, v };
87
+ const recoveredAddress = (0, ethers_1.recoverAddress)(msgHash, signature);
88
+ if (recoveredAddress.toLowerCase() === expectedAddress.toLowerCase()) {
89
+ // Found the correct v value - matches Rust: "if recovered_key == *pubkey"
90
+ const vHex = v.toString(16).padStart(2, '0');
91
+ return '0x' + rHex + sHex + vHex;
92
+ }
93
+ }
94
+ catch (e) {
95
+ // Recovery failed with this v, try the other
96
+ continue;
97
+ }
98
+ }
99
+ return null;
100
+ }
101
+ /**
102
+ * Recover multiple 65-byte signatures from concatenated 64-byte signatures.
103
+ *
104
+ * @param aggregatedSig64 Concatenated 64-byte signatures (r || s for each)
105
+ * @param msgHash The message hash that was signed
106
+ * @param publicKeys Array of expected signer public keys in order
107
+ * @returns Concatenated 65-byte signatures or null if any recovery fails
108
+ */
109
+ function recoverAggregatedSignatures65B(aggregatedSig64, msgHash, publicKeys) {
110
+ const sigBytes = typeof aggregatedSig64 === 'string'
111
+ ? Uint8Array.from(Buffer.from(aggregatedSig64.replace('0x', ''), 'hex'))
112
+ : aggregatedSig64;
113
+ const sigCount = sigBytes.length / 64;
114
+ if (sigCount !== publicKeys.length) {
115
+ throw new Error(`Signature count (${sigCount}) doesn't match expected public keys count (${publicKeys.length})`);
116
+ }
117
+ const recovered65BSigs = [];
118
+ for (let i = 0; i < sigCount; i++) {
119
+ const offset = i * 64;
120
+ const r = '0x' + Buffer.from(sigBytes.slice(offset, offset + 32)).toString('hex');
121
+ const s = '0x' + Buffer.from(sigBytes.slice(offset + 32, offset + 64)).toString('hex');
122
+ const sig65 = recoverSignature65B(r, s, msgHash, publicKeys[i]);
123
+ if (!sig65) {
124
+ console.error(`Failed to recover signature ${i} for public key ${publicKeys[i]}`);
125
+ return null;
126
+ }
127
+ recovered65BSigs.push(sig65.replace('0x', ''));
128
+ }
129
+ return '0x' + recovered65BSigs.join('');
130
+ }
131
+ /**
132
+ * Compute the transaction hash for a bridge deposit that needs to be signed.
133
+ * This matches the depositTxHash function in the Bridge.sol contract.
134
+ *
135
+ * @param domainSeparator The domain separator from the bridge contract
136
+ * @param bridgeContract The address of the bridge contract on the other chain
137
+ * @param token The token address
138
+ * @param amount The amount
139
+ * @param to The recipient address
140
+ * @param proof The proof (deposit TX hash)
141
+ * @returns The transaction hash to be signed
142
+ */
143
+ function computeDepositTxHash(domainSeparator, bridgeContract, token, amount, to, proof) {
144
+ const { AbiCoder, solidityPackedKeccak256 } = require('ethers');
145
+ const abiCoder = new AbiCoder();
146
+ // DEPOSIT_SELECTOR = keccak256("deposit(address,uint256,address)")[:4]
147
+ const DEPOSIT_SELECTOR = '0x47e7ef24';
148
+ // Compute dataHash = keccak256(selector || token || amount || to)
149
+ const dataHash = solidityPackedKeccak256(['bytes4', 'address', 'uint256', 'address'], [DEPOSIT_SELECTOR, token, amount, to]);
150
+ // Compute final hash = keccak256(domainSeparator || bridgeContract || dataHash || proof)
151
+ const txHash = (0, ethers_1.keccak256)(abiCoder.encode(['bytes32', 'address', 'bytes32', 'bytes'], [domainSeparator, bridgeContract, dataHash, proof]));
152
+ return txHash;
153
+ }
154
+ /**
155
+ * Extract aggregated 65-byte signatures from Pod transaction receipt attestations.
156
+ *
157
+ * Exactly matches the Rust implementation - recovers the v (parity bit) by trying
158
+ * both recovery IDs and checking which one recovers to the correct public key.
159
+ *
160
+ * @param receipt The Pod transaction receipt
161
+ * @param msgHash The message hash that validators signed (transaction hash)
162
+ * @returns Concatenated 65-byte signatures (r || s || v for each attestation)
163
+ */
164
+ function extractAggregatedSignatures(receipt, msgHash) {
165
+ const attestations = receipt.pod_metadata?.attestations;
166
+ if (!attestations || attestations.length === 0) {
167
+ throw new Error('No attestations found in receipt');
168
+ }
169
+ // Use provided msgHash or fall back to transaction hash
170
+ const hashToSign = msgHash || receipt.transactionHash;
171
+ const signatures = [];
172
+ for (const attestation of attestations) {
173
+ const { r, s } = attestation.signature;
174
+ const publicKey = attestation.public_key;
175
+ // Use recoverSignature65B to find correct v value - exactly like Rust code
176
+ const sig65 = recoverSignature65B(r, s, hashToSign, publicKey);
177
+ if (!sig65) {
178
+ throw new Error(`Failed to recover signature for public key ${publicKey}`);
179
+ }
180
+ signatures.push(sig65.replace('0x', ''));
181
+ }
182
+ return '0x' + signatures.join('');
183
+ }
184
+ /**
185
+ * Extract attestation data from Pod receipt for debugging/verification.
186
+ * Uses recoverSignature65B to properly recover v value.
187
+ *
188
+ * @param receipt The Pod transaction receipt
189
+ * @param msgHash The message hash that validators signed
190
+ * @returns Array of attestation info with public keys and recovered signatures
191
+ */
192
+ function extractAttestationInfo(receipt, msgHash) {
193
+ const attestations = receipt.pod_metadata?.attestations;
194
+ if (!attestations || attestations.length === 0) {
195
+ return [];
196
+ }
197
+ const hashToSign = msgHash || receipt.transactionHash;
198
+ return attestations.map(att => {
199
+ const { r, s } = att.signature;
200
+ const publicKey = att.public_key;
201
+ // Recover signature with correct v value
202
+ const sig65 = recoverSignature65B(r, s, hashToSign, publicKey);
203
+ // Derive address from public key
204
+ let address = '';
205
+ try {
206
+ address = addressFromPublicKey(publicKey);
207
+ }
208
+ catch (e) {
209
+ // Ignore
210
+ }
211
+ return {
212
+ publicKey,
213
+ address,
214
+ signature: sig65 || 'recovery_failed',
215
+ timestamp: att.timestamp
216
+ };
217
+ });
218
+ }
@@ -7,11 +7,10 @@ class PodProvider extends ethers_1.ethers.JsonRpcProvider {
7
7
  return await this.send('pod_getCommittee', {});
8
8
  }
9
9
  async getListReceipts(params) {
10
- var _a;
11
10
  return await this.send('pod_listReceipts', [
12
- (_a = params === null || params === void 0 ? void 0 : params.address) !== null && _a !== void 0 ? _a : null,
11
+ params?.address ?? null,
13
12
  params.since,
14
- params === null || params === void 0 ? void 0 : params.pagination
13
+ params?.pagination
15
14
  ]);
16
15
  }
17
16
  async getMetrics() {
@@ -1,5 +1,6 @@
1
+ import { Provider } from 'ethers';
1
2
  export interface PodBridgeChainConfig {
2
- rpcUrl: string;
3
+ provider: Provider;
3
4
  contractAddress: string;
4
5
  deploymentBlock?: number;
5
6
  }
@@ -63,22 +64,37 @@ export interface UnsignedTransaction {
63
64
  chainId?: number;
64
65
  gasLimit?: bigint;
65
66
  }
66
- export interface CertifiedLog {
67
- log: {
68
- addr: string;
69
- topics: string[];
70
- data: string;
71
- };
72
- log_index: bigint | string;
73
- certificate: {
74
- leaf: string;
75
- certified_receipt: {
76
- receipt_root: string;
77
- aggregate_signature: string;
78
- sorted_attestation_timestamps: bigint[] | string[];
79
- };
80
- proof: {
81
- path: string[];
82
- };
83
- };
67
+ /**
68
+ * Claim proof data for claiming tokens on source chain (Pod -> ETH direction)
69
+ *
70
+ * Flow:
71
+ * 1. User deposits on Pod: pod_bridge.deposit(pod_token, amount, recipient)
72
+ * 2. User waits for TX receipt
73
+ * 3. User claims on ETH: eth_bridge.claim(eth_token, amount, recipient, epoch, signatures, txHash)
74
+ *
75
+ * Important:
76
+ * - Token addresses differ between Pod and ETH (deposit AAAA on Pod, claim BBBB on ETH)
77
+ * - Signatures must be 65-byte format (r,s,v) - use recoverSignature65B helper
78
+ * - Proof is the deposit transaction hash from Pod
79
+ */
80
+ export interface ClaimProofData {
81
+ /** Token address on ETH to claim (different from Pod token address) */
82
+ ethTokenAddress: string;
83
+ /** Amount of tokens deposited/to claim (same as deposit amount) */
84
+ amount: string | bigint;
85
+ /** Recipient address (same as deposit recipient) */
86
+ to: string;
87
+ /** Committee epoch - hardcoded to 0 for now */
88
+ committeeEpoch: number;
89
+ /**
90
+ * Concatenated 65-byte ECDSA signatures (r,s,v) from validators.
91
+ * Pod uses 64-byte signatures, so use recoverSignature65B/recoverAggregatedSignatures65B
92
+ * to convert to 65-byte format required by the contract.
93
+ */
94
+ aggregatedSignatures: string;
95
+ /**
96
+ * The deposit transaction hash from Pod.
97
+ * This is used as proof that the deposit occurred.
98
+ */
99
+ depositTxHash: string;
84
100
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tapforce/pod-bridge-sdk",
3
- "version": "1.1.17",
3
+ "version": "1.2.1",
4
4
  "description": "SDK for interacting with Bridges between pod and other chains",
5
5
  "keywords": [
6
6
  "pod",