@bananapus/nana-sdk-core 1.2.0 → 1.4.0
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/dist/cjs/utils/hook.d.ts +15 -0
- package/dist/cjs/utils/hook.d.ts.map +1 -1
- package/dist/cjs/utils/hook.js +20 -0
- package/dist/cjs/utils/hook.js.map +1 -1
- package/dist/cjs/utils/index.d.ts +1 -0
- package/dist/cjs/utils/index.d.ts.map +1 -1
- package/dist/cjs/utils/index.js +1 -0
- package/dist/cjs/utils/index.js.map +1 -1
- package/dist/cjs/utils/ipfs.d.ts +33 -1
- package/dist/cjs/utils/ipfs.d.ts.map +1 -1
- package/dist/cjs/utils/ipfs.js +212 -8
- package/dist/cjs/utils/ipfs.js.map +1 -1
- package/dist/cjs/utils/ipfs.test.js +34 -0
- package/dist/cjs/utils/ipfs.test.js.map +1 -1
- package/dist/cjs/v6/cashOut.d.ts +23 -0
- package/dist/cjs/v6/cashOut.d.ts.map +1 -1
- package/dist/cjs/v6/cashOut.js +35 -0
- package/dist/cjs/v6/cashOut.js.map +1 -1
- package/dist/cjs/v6/cashOut.test.js +20 -0
- package/dist/cjs/v6/cashOut.test.js.map +1 -1
- package/dist/cjs/v6/index.d.ts +3 -0
- package/dist/cjs/v6/index.d.ts.map +1 -1
- package/dist/cjs/v6/index.js +3 -0
- package/dist/cjs/v6/index.js.map +1 -1
- package/dist/cjs/v6/launch.d.ts +23 -2
- package/dist/cjs/v6/launch.d.ts.map +1 -1
- package/dist/cjs/v6/launch.js +40 -1
- package/dist/cjs/v6/launch.js.map +1 -1
- package/dist/cjs/v6/launch.test.js +25 -0
- package/dist/cjs/v6/launch.test.js.map +1 -1
- package/dist/cjs/v6/nft.d.ts +165 -0
- package/dist/cjs/v6/nft.d.ts.map +1 -0
- package/dist/cjs/v6/nft.js +356 -0
- package/dist/cjs/v6/nft.js.map +1 -0
- package/dist/cjs/v6/nft.test.d.ts +2 -0
- package/dist/cjs/v6/nft.test.d.ts.map +1 -0
- package/dist/cjs/v6/nft.test.js +279 -0
- package/dist/cjs/v6/nft.test.js.map +1 -0
- package/dist/cjs/v6/pay.d.ts +13 -5
- package/dist/cjs/v6/pay.d.ts.map +1 -1
- package/dist/cjs/v6/pay.js +15 -18
- package/dist/cjs/v6/pay.js.map +1 -1
- package/dist/cjs/v6/pay.test.js +7 -0
- package/dist/cjs/v6/pay.test.js.map +1 -1
- package/dist/cjs/v6/permissions.d.ts +21 -0
- package/dist/cjs/v6/permissions.d.ts.map +1 -1
- package/dist/cjs/v6/permissions.js +44 -1
- package/dist/cjs/v6/permissions.js.map +1 -1
- package/dist/cjs/v6/permissions.test.js +25 -0
- package/dist/cjs/v6/permissions.test.js.map +1 -1
- package/dist/cjs/v6/projectPayers.d.ts +178 -0
- package/dist/cjs/v6/projectPayers.d.ts.map +1 -0
- package/dist/cjs/v6/projectPayers.js +108 -0
- package/dist/cjs/v6/projectPayers.js.map +1 -0
- package/dist/cjs/v6/projectPayers.test.d.ts +2 -0
- package/dist/cjs/v6/projectPayers.test.d.ts.map +1 -0
- package/dist/cjs/v6/projectPayers.test.js +85 -0
- package/dist/cjs/v6/projectPayers.test.js.map +1 -0
- package/dist/cjs/v6/revnets.d.ts +3 -2
- package/dist/cjs/v6/revnets.d.ts.map +1 -1
- package/dist/cjs/v6/revnets.js +3 -2
- package/dist/cjs/v6/revnets.js.map +1 -1
- package/dist/cjs/v6/rulesets.d.ts +42 -0
- package/dist/cjs/v6/rulesets.d.ts.map +1 -1
- package/dist/cjs/v6/rulesets.js +87 -0
- package/dist/cjs/v6/rulesets.js.map +1 -1
- package/dist/cjs/v6/rulesets.test.js +54 -0
- package/dist/cjs/v6/rulesets.test.js.map +1 -1
- package/dist/cjs/v6/suckers.d.ts +740 -2
- package/dist/cjs/v6/suckers.d.ts.map +1 -1
- package/dist/cjs/v6/suckers.js +647 -8
- package/dist/cjs/v6/suckers.js.map +1 -1
- package/dist/cjs/v6/suckers.test.js +228 -0
- package/dist/cjs/v6/suckers.test.js.map +1 -1
- package/dist/cjs/v6/uniswapV4.d.ts +82 -0
- package/dist/cjs/v6/uniswapV4.d.ts.map +1 -0
- package/dist/cjs/v6/uniswapV4.js +336 -0
- package/dist/cjs/v6/uniswapV4.js.map +1 -0
- package/dist/cjs/v6/uniswapV4.test.d.ts +2 -0
- package/dist/cjs/v6/uniswapV4.test.d.ts.map +1 -0
- package/dist/cjs/v6/uniswapV4.test.js +128 -0
- package/dist/cjs/v6/uniswapV4.test.js.map +1 -0
- package/dist/esm/utils/hook.d.ts +15 -0
- package/dist/esm/utils/hook.d.ts.map +1 -1
- package/dist/esm/utils/hook.js +20 -1
- package/dist/esm/utils/hook.js.map +1 -1
- package/dist/esm/utils/index.d.ts +1 -0
- package/dist/esm/utils/index.d.ts.map +1 -1
- package/dist/esm/utils/index.js +1 -0
- package/dist/esm/utils/index.js.map +1 -1
- package/dist/esm/utils/ipfs.d.ts +33 -1
- package/dist/esm/utils/ipfs.d.ts.map +1 -1
- package/dist/esm/utils/ipfs.js +204 -8
- package/dist/esm/utils/ipfs.js.map +1 -1
- package/dist/esm/utils/ipfs.test.js +35 -1
- package/dist/esm/utils/ipfs.test.js.map +1 -1
- package/dist/esm/v6/cashOut.d.ts +23 -0
- package/dist/esm/v6/cashOut.d.ts.map +1 -1
- package/dist/esm/v6/cashOut.js +34 -0
- package/dist/esm/v6/cashOut.js.map +1 -1
- package/dist/esm/v6/cashOut.test.js +22 -2
- package/dist/esm/v6/cashOut.test.js.map +1 -1
- package/dist/esm/v6/index.d.ts +3 -0
- package/dist/esm/v6/index.d.ts.map +1 -1
- package/dist/esm/v6/index.js +3 -0
- package/dist/esm/v6/index.js.map +1 -1
- package/dist/esm/v6/launch.d.ts +23 -2
- package/dist/esm/v6/launch.d.ts.map +1 -1
- package/dist/esm/v6/launch.js +39 -2
- package/dist/esm/v6/launch.js.map +1 -1
- package/dist/esm/v6/launch.test.js +27 -2
- package/dist/esm/v6/launch.test.js.map +1 -1
- package/dist/esm/v6/nft.d.ts +165 -0
- package/dist/esm/v6/nft.d.ts.map +1 -0
- package/dist/esm/v6/nft.js +342 -0
- package/dist/esm/v6/nft.js.map +1 -0
- package/dist/esm/v6/nft.test.d.ts +2 -0
- package/dist/esm/v6/nft.test.d.ts.map +1 -0
- package/dist/esm/v6/nft.test.js +277 -0
- package/dist/esm/v6/nft.test.js.map +1 -0
- package/dist/esm/v6/pay.d.ts +13 -5
- package/dist/esm/v6/pay.d.ts.map +1 -1
- package/dist/esm/v6/pay.js +17 -20
- package/dist/esm/v6/pay.js.map +1 -1
- package/dist/esm/v6/pay.test.js +7 -0
- package/dist/esm/v6/pay.test.js.map +1 -1
- package/dist/esm/v6/permissions.d.ts +21 -0
- package/dist/esm/v6/permissions.d.ts.map +1 -1
- package/dist/esm/v6/permissions.js +40 -0
- package/dist/esm/v6/permissions.js.map +1 -1
- package/dist/esm/v6/permissions.test.js +26 -1
- package/dist/esm/v6/permissions.test.js.map +1 -1
- package/dist/esm/v6/projectPayers.d.ts +178 -0
- package/dist/esm/v6/projectPayers.d.ts.map +1 -0
- package/dist/esm/v6/projectPayers.js +101 -0
- package/dist/esm/v6/projectPayers.js.map +1 -0
- package/dist/esm/v6/projectPayers.test.d.ts +2 -0
- package/dist/esm/v6/projectPayers.test.d.ts.map +1 -0
- package/dist/esm/v6/projectPayers.test.js +83 -0
- package/dist/esm/v6/projectPayers.test.js.map +1 -0
- package/dist/esm/v6/revnets.d.ts +3 -2
- package/dist/esm/v6/revnets.d.ts.map +1 -1
- package/dist/esm/v6/revnets.js +3 -2
- package/dist/esm/v6/revnets.js.map +1 -1
- package/dist/esm/v6/rulesets.d.ts +42 -0
- package/dist/esm/v6/rulesets.d.ts.map +1 -1
- package/dist/esm/v6/rulesets.js +83 -0
- package/dist/esm/v6/rulesets.js.map +1 -1
- package/dist/esm/v6/rulesets.test.js +55 -1
- package/dist/esm/v6/rulesets.test.js.map +1 -1
- package/dist/esm/v6/suckers.d.ts +740 -2
- package/dist/esm/v6/suckers.d.ts.map +1 -1
- package/dist/esm/v6/suckers.js +630 -8
- package/dist/esm/v6/suckers.js.map +1 -1
- package/dist/esm/v6/suckers.test.js +230 -2
- package/dist/esm/v6/suckers.test.js.map +1 -1
- package/dist/esm/v6/uniswapV4.d.ts +82 -0
- package/dist/esm/v6/uniswapV4.d.ts.map +1 -0
- package/dist/esm/v6/uniswapV4.js +318 -0
- package/dist/esm/v6/uniswapV4.js.map +1 -0
- package/dist/esm/v6/uniswapV4.test.d.ts +2 -0
- package/dist/esm/v6/uniswapV4.test.d.ts.map +1 -0
- package/dist/esm/v6/uniswapV4.test.js +126 -0
- package/dist/esm/v6/uniswapV4.test.js.map +1 -0
- package/dist/tsconfig.cjs.tsbuildinfo +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
package/dist/cjs/v6/suckers.js
CHANGED
|
@@ -1,18 +1,31 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.jbSuckerV6Abi = void 0;
|
|
3
|
+
exports.NATIVE_SUCKER_TRANSPORT_VALUES = exports.CCIP_SUCKER_TRANSPORT_VALUES = exports.SUCKER_EMPTY_TREE_ROOT = exports.SUCKER_MERKLE_DEPTH = exports.jbSuckerV6Abi = exports.jbNativeSuckerV6ProbeAbi = exports.jbCcipSuckerV6Abi = exports.insertToSuckerOutboxEvent = exports.jbSuckerV6ViewAbi = void 0;
|
|
4
|
+
exports.suckerLeafHash = suckerLeafHash;
|
|
5
|
+
exports.suckerHashPair = suckerHashPair;
|
|
6
|
+
exports.suckerZeroHashes = suckerZeroHashes;
|
|
7
|
+
exports.suckerLeafProof = suckerLeafProof;
|
|
8
|
+
exports.suckerBranchRoot = suckerBranchRoot;
|
|
9
|
+
exports.suckerBytes32ToAddress = suckerBytes32ToAddress;
|
|
10
|
+
exports.getSuckerOutboxLeaves = getSuckerOutboxLeaves;
|
|
11
|
+
exports.classifySuckerMovement = classifySuckerMovement;
|
|
12
|
+
exports.getSuckerMovements = getSuckerMovements;
|
|
13
|
+
exports.claimFromSuckerMovement = claimFromSuckerMovement;
|
|
14
|
+
exports.findSuckerTransportValue = findSuckerTransportValue;
|
|
15
|
+
exports.assertSuckerTransportValue = assertSuckerTransportValue;
|
|
16
|
+
exports.classifySuckerTransport = classifySuckerTransport;
|
|
17
|
+
exports.buildSyncAccountingDataTx = buildSyncAccountingDataTx;
|
|
18
|
+
exports.relativeSuckerDrift = relativeSuckerDrift;
|
|
19
|
+
exports.suckerTimestampSeconds = suckerTimestampSeconds;
|
|
4
20
|
exports.buildBridgePrepareTx = buildBridgePrepareTx;
|
|
5
21
|
exports.buildBridgeClaimTx = buildBridgeClaimTx;
|
|
6
22
|
exports.buildToRemoteTx = buildToRemoteTx;
|
|
7
23
|
exports.getV6SuckerPairs = getV6SuckerPairs;
|
|
24
|
+
exports.getAllV6SuckerPairs = getAllV6SuckerPairs;
|
|
8
25
|
const viem_1 = require("viem");
|
|
9
26
|
const juicebox_js_1 = require("../generated/juicebox.js");
|
|
10
27
|
const types_js_1 = require("./types.js");
|
|
11
|
-
|
|
12
|
-
* Minimal v6 JBSucker ABI. v6 identifies remote beneficiaries as bytes32 (for cross-VM
|
|
13
|
-
* compatibility) and adds an opaque `metadata` attribution payload to prepared leaves.
|
|
14
|
-
*/
|
|
15
|
-
exports.jbSuckerV6Abi = [
|
|
28
|
+
const jbSuckerV6WriteAbi = [
|
|
16
29
|
{
|
|
17
30
|
type: "function",
|
|
18
31
|
name: "prepare",
|
|
@@ -50,8 +63,16 @@ exports.jbSuckerV6Abi = [
|
|
|
50
63
|
components: [
|
|
51
64
|
{ name: "index", type: "uint256", internalType: "uint256" },
|
|
52
65
|
{ name: "beneficiary", type: "bytes32", internalType: "bytes32" },
|
|
53
|
-
{
|
|
54
|
-
|
|
66
|
+
{
|
|
67
|
+
name: "projectTokenCount",
|
|
68
|
+
type: "uint256",
|
|
69
|
+
internalType: "uint256",
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
name: "terminalTokenAmount",
|
|
73
|
+
type: "uint256",
|
|
74
|
+
internalType: "uint256",
|
|
75
|
+
},
|
|
55
76
|
{ name: "metadata", type: "bytes32", internalType: "bytes32" },
|
|
56
77
|
],
|
|
57
78
|
},
|
|
@@ -63,6 +84,593 @@ exports.jbSuckerV6Abi = [
|
|
|
63
84
|
stateMutability: "nonpayable",
|
|
64
85
|
},
|
|
65
86
|
];
|
|
87
|
+
/** Common v6 sucker view surface used to reconstruct and verify bridge state. */
|
|
88
|
+
exports.jbSuckerV6ViewAbi = [
|
|
89
|
+
{
|
|
90
|
+
type: "function",
|
|
91
|
+
name: "peer",
|
|
92
|
+
stateMutability: "view",
|
|
93
|
+
inputs: [],
|
|
94
|
+
outputs: [{ name: "", type: "bytes32" }],
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
type: "function",
|
|
98
|
+
name: "peerChainId",
|
|
99
|
+
stateMutability: "view",
|
|
100
|
+
inputs: [],
|
|
101
|
+
outputs: [{ name: "", type: "uint256" }],
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
type: "function",
|
|
105
|
+
name: "projectId",
|
|
106
|
+
stateMutability: "view",
|
|
107
|
+
inputs: [],
|
|
108
|
+
outputs: [{ name: "", type: "uint256" }],
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
type: "function",
|
|
112
|
+
name: "outboxOf",
|
|
113
|
+
stateMutability: "view",
|
|
114
|
+
inputs: [{ name: "token", type: "address" }],
|
|
115
|
+
outputs: [
|
|
116
|
+
{
|
|
117
|
+
name: "outbox",
|
|
118
|
+
type: "tuple",
|
|
119
|
+
components: [
|
|
120
|
+
{ name: "nonce", type: "uint64" },
|
|
121
|
+
{ name: "numberOfClaimsSent", type: "uint192" },
|
|
122
|
+
{ name: "balance", type: "uint256" },
|
|
123
|
+
{
|
|
124
|
+
name: "tree",
|
|
125
|
+
type: "tuple",
|
|
126
|
+
components: [
|
|
127
|
+
{ name: "branch", type: "bytes32[32]" },
|
|
128
|
+
{ name: "count", type: "uint256" },
|
|
129
|
+
],
|
|
130
|
+
},
|
|
131
|
+
],
|
|
132
|
+
},
|
|
133
|
+
],
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
type: "function",
|
|
137
|
+
name: "inboxOf",
|
|
138
|
+
stateMutability: "view",
|
|
139
|
+
inputs: [{ name: "token", type: "address" }],
|
|
140
|
+
outputs: [
|
|
141
|
+
{
|
|
142
|
+
name: "inbox",
|
|
143
|
+
type: "tuple",
|
|
144
|
+
components: [
|
|
145
|
+
{ name: "nonce", type: "uint64" },
|
|
146
|
+
{ name: "root", type: "bytes32" },
|
|
147
|
+
],
|
|
148
|
+
},
|
|
149
|
+
],
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
type: "function",
|
|
153
|
+
name: "executedLeafHashOf",
|
|
154
|
+
stateMutability: "view",
|
|
155
|
+
inputs: [
|
|
156
|
+
{ name: "token", type: "address" },
|
|
157
|
+
{ name: "index", type: "uint256" },
|
|
158
|
+
],
|
|
159
|
+
outputs: [{ name: "hash", type: "bytes32" }],
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
type: "function",
|
|
163
|
+
name: "remoteTokenFor",
|
|
164
|
+
stateMutability: "view",
|
|
165
|
+
inputs: [{ name: "token", type: "address" }],
|
|
166
|
+
outputs: [
|
|
167
|
+
{
|
|
168
|
+
name: "remoteToken",
|
|
169
|
+
type: "tuple",
|
|
170
|
+
components: [
|
|
171
|
+
{ name: "enabled", type: "bool" },
|
|
172
|
+
{ name: "emergencyHatch", type: "bool" },
|
|
173
|
+
{ name: "minGas", type: "uint32" },
|
|
174
|
+
{ name: "addr", type: "bytes32" },
|
|
175
|
+
],
|
|
176
|
+
},
|
|
177
|
+
],
|
|
178
|
+
},
|
|
179
|
+
];
|
|
180
|
+
/** Event carrying the complete v6 outbox leaf preimage and resulting root. */
|
|
181
|
+
exports.insertToSuckerOutboxEvent = {
|
|
182
|
+
type: "event",
|
|
183
|
+
name: "InsertToOutboxTree",
|
|
184
|
+
inputs: [
|
|
185
|
+
{ name: "beneficiary", type: "bytes32", indexed: true },
|
|
186
|
+
{ name: "token", type: "address", indexed: true },
|
|
187
|
+
{ name: "hashed", type: "bytes32", indexed: false },
|
|
188
|
+
{ name: "index", type: "uint256", indexed: false },
|
|
189
|
+
{ name: "root", type: "bytes32", indexed: false },
|
|
190
|
+
{ name: "projectTokenCount", type: "uint256", indexed: false },
|
|
191
|
+
{ name: "terminalTokenAmount", type: "uint256", indexed: false },
|
|
192
|
+
{ name: "metadata", type: "bytes32", indexed: false },
|
|
193
|
+
{ name: "caller", type: "address", indexed: false },
|
|
194
|
+
],
|
|
195
|
+
};
|
|
196
|
+
/** CCIP-only probe used to distinguish fee-bearing sucker transports. */
|
|
197
|
+
exports.jbCcipSuckerV6Abi = [
|
|
198
|
+
{
|
|
199
|
+
type: "function",
|
|
200
|
+
name: "CCIP_ROUTER",
|
|
201
|
+
stateMutability: "view",
|
|
202
|
+
inputs: [],
|
|
203
|
+
outputs: [{ name: "", type: "address" }],
|
|
204
|
+
},
|
|
205
|
+
];
|
|
206
|
+
/** Native-bridge-only probes used to positively identify sucker transports. */
|
|
207
|
+
exports.jbNativeSuckerV6ProbeAbi = [
|
|
208
|
+
{
|
|
209
|
+
type: "function",
|
|
210
|
+
name: "OPMESSENGER",
|
|
211
|
+
stateMutability: "view",
|
|
212
|
+
inputs: [],
|
|
213
|
+
outputs: [{ name: "", type: "address" }],
|
|
214
|
+
},
|
|
215
|
+
{
|
|
216
|
+
type: "function",
|
|
217
|
+
name: "ARBINBOX",
|
|
218
|
+
stateMutability: "view",
|
|
219
|
+
inputs: [],
|
|
220
|
+
outputs: [{ name: "", type: "address" }],
|
|
221
|
+
},
|
|
222
|
+
];
|
|
223
|
+
/**
|
|
224
|
+
* Reusable v6 JBSucker ABI: transaction builders, bridge-state views, the
|
|
225
|
+
* outbox event, and the permissionless accounting-sync entrypoint.
|
|
226
|
+
*/
|
|
227
|
+
exports.jbSuckerV6Abi = [
|
|
228
|
+
...exports.jbSuckerV6ViewAbi,
|
|
229
|
+
exports.insertToSuckerOutboxEvent,
|
|
230
|
+
...jbSuckerV6WriteAbi,
|
|
231
|
+
{
|
|
232
|
+
type: "function",
|
|
233
|
+
name: "syncAccountingData",
|
|
234
|
+
stateMutability: "payable",
|
|
235
|
+
inputs: [],
|
|
236
|
+
outputs: [],
|
|
237
|
+
},
|
|
238
|
+
];
|
|
239
|
+
/** Reproduce the exact leaf hash committed by a v6 sucker. */
|
|
240
|
+
function suckerLeafHash({ projectTokenCount, terminalTokenAmount, beneficiary, metadata, }) {
|
|
241
|
+
return (0, viem_1.keccak256)((0, viem_1.encodeAbiParameters)([
|
|
242
|
+
{ type: "uint256" },
|
|
243
|
+
{ type: "uint256" },
|
|
244
|
+
{ type: "bytes32" },
|
|
245
|
+
{ type: "bytes32" },
|
|
246
|
+
], [projectTokenCount, terminalTokenAmount, beneficiary, metadata]));
|
|
247
|
+
}
|
|
248
|
+
/** Fixed depth used by the v6 suckers' incremental Merkle trees. */
|
|
249
|
+
exports.SUCKER_MERKLE_DEPTH = 32;
|
|
250
|
+
/** MerkleLib's root for an empty depth-32 tree. */
|
|
251
|
+
exports.SUCKER_EMPTY_TREE_ROOT = "0x27ae5ba08d7291c96c8cbddcc148bf48a6d68c7974b94356f53754ef6171d757";
|
|
252
|
+
/** Hash a MerkleLib node pair (`keccak256(abi.encode(bytes32, bytes32))`). */
|
|
253
|
+
function suckerHashPair(left, right) {
|
|
254
|
+
return (0, viem_1.keccak256)((0, viem_1.encodeAbiParameters)([{ type: "bytes32" }, { type: "bytes32" }], [left, right]));
|
|
255
|
+
}
|
|
256
|
+
let suckerZeroHashesCache = null;
|
|
257
|
+
/** Empty-subtree hashes for depths 0 through 32, self-checked at depth 32. */
|
|
258
|
+
function suckerZeroHashes() {
|
|
259
|
+
if (suckerZeroHashesCache)
|
|
260
|
+
return suckerZeroHashesCache;
|
|
261
|
+
const hashes = [viem_1.zeroHash];
|
|
262
|
+
for (let depth = 0; depth < exports.SUCKER_MERKLE_DEPTH; depth++) {
|
|
263
|
+
hashes.push(suckerHashPair(hashes[depth], hashes[depth]));
|
|
264
|
+
}
|
|
265
|
+
if (hashes[exports.SUCKER_MERKLE_DEPTH] !== exports.SUCKER_EMPTY_TREE_ROOT) {
|
|
266
|
+
throw new Error("The sucker Merkle zero-hash self-check failed.");
|
|
267
|
+
}
|
|
268
|
+
suckerZeroHashesCache = hashes;
|
|
269
|
+
return hashes;
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Build the fixed 32-sibling inclusion path for a dense outbox leaf array.
|
|
273
|
+
* Missing right-hand subtrees are filled with MerkleLib's canonical zero hash.
|
|
274
|
+
*/
|
|
275
|
+
function suckerLeafProof(leafHashes, index) {
|
|
276
|
+
if (!Number.isSafeInteger(index) || index < 0 || index >= leafHashes.length) {
|
|
277
|
+
throw new Error("The requested sucker leaf is outside the outbox.");
|
|
278
|
+
}
|
|
279
|
+
const zeroHashes = suckerZeroHashes();
|
|
280
|
+
let level = leafHashes.slice();
|
|
281
|
+
const proof = [];
|
|
282
|
+
let position = index;
|
|
283
|
+
for (let depth = 0; depth < exports.SUCKER_MERKLE_DEPTH; depth++) {
|
|
284
|
+
const sibling = position ^ 1;
|
|
285
|
+
proof.push(sibling < level.length ? level[sibling] : zeroHashes[depth]);
|
|
286
|
+
const next = [];
|
|
287
|
+
for (let offset = 0; offset < level.length; offset += 2) {
|
|
288
|
+
next.push(suckerHashPair(level[offset], offset + 1 < level.length ? level[offset + 1] : zeroHashes[depth]));
|
|
289
|
+
}
|
|
290
|
+
level = next;
|
|
291
|
+
position = Math.floor(position / 2);
|
|
292
|
+
}
|
|
293
|
+
return proof;
|
|
294
|
+
}
|
|
295
|
+
/** Recompute a sucker root from one leaf hash and its inclusion proof. */
|
|
296
|
+
function suckerBranchRoot(leafHash, proof, index) {
|
|
297
|
+
if (!Number.isSafeInteger(index) || index < 0) {
|
|
298
|
+
throw new Error("A sucker leaf index must be a non-negative safe integer.");
|
|
299
|
+
}
|
|
300
|
+
if (proof.length !== exports.SUCKER_MERKLE_DEPTH) {
|
|
301
|
+
throw new Error(`A sucker proof must contain ${exports.SUCKER_MERKLE_DEPTH} sibling hashes.`);
|
|
302
|
+
}
|
|
303
|
+
let current = leafHash;
|
|
304
|
+
let position = index;
|
|
305
|
+
for (let depth = 0; depth < exports.SUCKER_MERKLE_DEPTH; depth++) {
|
|
306
|
+
current =
|
|
307
|
+
position & 1
|
|
308
|
+
? suckerHashPair(proof[depth], current)
|
|
309
|
+
: suckerHashPair(current, proof[depth]);
|
|
310
|
+
position = Math.floor(position / 2);
|
|
311
|
+
}
|
|
312
|
+
return current;
|
|
313
|
+
}
|
|
314
|
+
function safeSuckerCount(value, label) {
|
|
315
|
+
const count = Number(value);
|
|
316
|
+
if (!Number.isSafeInteger(count) || count < 0) {
|
|
317
|
+
throw new Error(`The sucker returned an invalid ${label}.`);
|
|
318
|
+
}
|
|
319
|
+
return count;
|
|
320
|
+
}
|
|
321
|
+
/** Convert a low-20-byte EVM address stored in bytes32 into a checksum address. */
|
|
322
|
+
function suckerBytes32ToAddress(value) {
|
|
323
|
+
if (value.toLowerCase() === viem_1.zeroHash) {
|
|
324
|
+
throw new Error("The sucker bytes32 value does not contain an address.");
|
|
325
|
+
}
|
|
326
|
+
if (!/^0x0{24}[0-9a-fA-F]{40}$/.test(value)) {
|
|
327
|
+
throw new Error("The sucker bytes32 value is not an EVM address.");
|
|
328
|
+
}
|
|
329
|
+
return (0, viem_1.getAddress)((0, viem_1.sliceHex)(value, 12));
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Read every dense outbox leaf for a sucker/token and verify the reconstructed
|
|
333
|
+
* latest root against the root emitted on-chain.
|
|
334
|
+
*
|
|
335
|
+
* A wide log request is attempted first. Providers that reject it fall back to
|
|
336
|
+
* bounded reverse scans, avoiding the subtly truncated histories which would
|
|
337
|
+
* otherwise produce invalid claim proofs.
|
|
338
|
+
*/
|
|
339
|
+
async function getSuckerOutboxLeaves(client, { sucker, token, count: requestedCount, fromBlock = 0n, toBlock, blockRange = 45000n, maxBlockRanges = 512, }) {
|
|
340
|
+
if (fromBlock < 0n)
|
|
341
|
+
throw new Error("fromBlock cannot be negative.");
|
|
342
|
+
if (blockRange <= 0n)
|
|
343
|
+
throw new Error("blockRange must be positive.");
|
|
344
|
+
if (!Number.isSafeInteger(maxBlockRanges) || maxBlockRanges < 1) {
|
|
345
|
+
throw new Error("maxBlockRanges must be a positive safe integer.");
|
|
346
|
+
}
|
|
347
|
+
const count = requestedCount ??
|
|
348
|
+
safeSuckerCount((await client.readContract({
|
|
349
|
+
address: sucker,
|
|
350
|
+
abi: exports.jbSuckerV6ViewAbi,
|
|
351
|
+
functionName: "outboxOf",
|
|
352
|
+
args: [token],
|
|
353
|
+
})).tree.count, "outbox count");
|
|
354
|
+
if (!Number.isSafeInteger(count) || count < 0) {
|
|
355
|
+
throw new Error("count must be a non-negative safe integer.");
|
|
356
|
+
}
|
|
357
|
+
if (count === 0)
|
|
358
|
+
return [];
|
|
359
|
+
const latest = toBlock ?? (await client.getBlockNumber());
|
|
360
|
+
if (latest < fromBlock)
|
|
361
|
+
throw new Error("toBlock cannot precede fromBlock.");
|
|
362
|
+
const byIndex = new Map();
|
|
363
|
+
const collect = (logs) => {
|
|
364
|
+
for (const log of logs) {
|
|
365
|
+
const index = safeSuckerCount(log.args.index, "outbox leaf index");
|
|
366
|
+
if (index >= count)
|
|
367
|
+
continue;
|
|
368
|
+
const hashed = suckerLeafHash({
|
|
369
|
+
beneficiary: log.args.beneficiary,
|
|
370
|
+
projectTokenCount: log.args.projectTokenCount,
|
|
371
|
+
terminalTokenAmount: log.args.terminalTokenAmount,
|
|
372
|
+
metadata: log.args.metadata,
|
|
373
|
+
});
|
|
374
|
+
if (hashed.toLowerCase() !== log.args.hashed.toLowerCase()) {
|
|
375
|
+
throw new Error(`The sucker outbox event's leaf preimage does not match leaf ${index}.`);
|
|
376
|
+
}
|
|
377
|
+
byIndex.set(index, {
|
|
378
|
+
index,
|
|
379
|
+
hashed,
|
|
380
|
+
root: log.args.root,
|
|
381
|
+
beneficiary: log.args.beneficiary,
|
|
382
|
+
projectTokenCount: log.args.projectTokenCount,
|
|
383
|
+
terminalTokenAmount: log.args.terminalTokenAmount,
|
|
384
|
+
metadata: log.args.metadata,
|
|
385
|
+
blockNumber: log.blockNumber,
|
|
386
|
+
});
|
|
387
|
+
}
|
|
388
|
+
};
|
|
389
|
+
let wideScanFailed = false;
|
|
390
|
+
try {
|
|
391
|
+
collect((await client.getLogs({
|
|
392
|
+
address: sucker,
|
|
393
|
+
event: exports.insertToSuckerOutboxEvent,
|
|
394
|
+
args: { token },
|
|
395
|
+
fromBlock,
|
|
396
|
+
toBlock: latest,
|
|
397
|
+
strict: true,
|
|
398
|
+
})));
|
|
399
|
+
}
|
|
400
|
+
catch {
|
|
401
|
+
wideScanFailed = true;
|
|
402
|
+
}
|
|
403
|
+
if (wideScanFailed || byIndex.size !== count) {
|
|
404
|
+
byIndex.clear();
|
|
405
|
+
let cursor = latest;
|
|
406
|
+
let ranges = 0;
|
|
407
|
+
while (cursor >= fromBlock &&
|
|
408
|
+
byIndex.size < count &&
|
|
409
|
+
ranges < maxBlockRanges) {
|
|
410
|
+
const rangeStart = cursor - fromBlock + 1n > blockRange
|
|
411
|
+
? cursor - blockRange + 1n
|
|
412
|
+
: fromBlock;
|
|
413
|
+
collect((await client.getLogs({
|
|
414
|
+
address: sucker,
|
|
415
|
+
event: exports.insertToSuckerOutboxEvent,
|
|
416
|
+
args: { token },
|
|
417
|
+
fromBlock: rangeStart,
|
|
418
|
+
toBlock: cursor,
|
|
419
|
+
strict: true,
|
|
420
|
+
})));
|
|
421
|
+
ranges += 1;
|
|
422
|
+
if (rangeStart === fromBlock)
|
|
423
|
+
break;
|
|
424
|
+
cursor = rangeStart - 1n;
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
const leaves = [];
|
|
428
|
+
for (let index = 0; index < count; index++) {
|
|
429
|
+
const leaf = byIndex.get(index);
|
|
430
|
+
if (!leaf) {
|
|
431
|
+
throw new Error(`The RPC did not return the complete sucker outbox history (missing leaf ${index}).`);
|
|
432
|
+
}
|
|
433
|
+
leaves.push(leaf);
|
|
434
|
+
}
|
|
435
|
+
const last = leaves[count - 1];
|
|
436
|
+
const latestRoot = suckerBranchRoot(last.hashed, suckerLeafProof(leaves.map((leaf) => leaf.hashed), count - 1), count - 1);
|
|
437
|
+
if (latestRoot.toLowerCase() !== last.root.toLowerCase()) {
|
|
438
|
+
throw new Error("The reconstructed sucker outbox does not match its latest emitted root.");
|
|
439
|
+
}
|
|
440
|
+
return leaves;
|
|
441
|
+
}
|
|
442
|
+
/** Pure status classification shared by bridge movement lists. */
|
|
443
|
+
function classifySuckerMovement({ executed, index, deliveredCount, sentCount, }) {
|
|
444
|
+
if (executed)
|
|
445
|
+
return { status: "claimed", canExecute: false };
|
|
446
|
+
if (index < deliveredCount) {
|
|
447
|
+
return { status: "claimable", canExecute: false };
|
|
448
|
+
}
|
|
449
|
+
return { status: "pending", canExecute: index >= sentCount };
|
|
450
|
+
}
|
|
451
|
+
/**
|
|
452
|
+
* Reconstruct all movements for one source sucker/token, verify the outbox and
|
|
453
|
+
* destination inbox roots, and attach a claim proof only to claimable leaves.
|
|
454
|
+
*/
|
|
455
|
+
async function getSuckerMovements(sourceClient, destinationClient, { sourceSucker, destinationSucker, sourceToken, remoteToken: requestedRemoteToken, ...scanOptions }) {
|
|
456
|
+
const [outbox, remoteMapping] = await Promise.all([
|
|
457
|
+
sourceClient.readContract({
|
|
458
|
+
address: sourceSucker,
|
|
459
|
+
abi: exports.jbSuckerV6ViewAbi,
|
|
460
|
+
functionName: "outboxOf",
|
|
461
|
+
args: [sourceToken],
|
|
462
|
+
}),
|
|
463
|
+
sourceClient.readContract({
|
|
464
|
+
address: sourceSucker,
|
|
465
|
+
abi: exports.jbSuckerV6ViewAbi,
|
|
466
|
+
functionName: "remoteTokenFor",
|
|
467
|
+
args: [sourceToken],
|
|
468
|
+
}),
|
|
469
|
+
]);
|
|
470
|
+
const count = safeSuckerCount(outbox.tree.count, "outbox count");
|
|
471
|
+
const sentCount = safeSuckerCount(outbox.numberOfClaimsSent, "sent-claims count");
|
|
472
|
+
if (sentCount > count) {
|
|
473
|
+
throw new Error("The sucker sent-claims count exceeds its outbox count.");
|
|
474
|
+
}
|
|
475
|
+
if (count === 0)
|
|
476
|
+
return [];
|
|
477
|
+
const mappedRemoteToken = remoteMapping.addr.toLowerCase() === viem_1.zeroHash
|
|
478
|
+
? null
|
|
479
|
+
: suckerBytes32ToAddress(remoteMapping.addr);
|
|
480
|
+
if (mappedRemoteToken &&
|
|
481
|
+
requestedRemoteToken &&
|
|
482
|
+
mappedRemoteToken.toLowerCase() !== requestedRemoteToken.toLowerCase()) {
|
|
483
|
+
throw new Error("The supplied historical token does not match the sucker's live mapping.");
|
|
484
|
+
}
|
|
485
|
+
const remoteToken = mappedRemoteToken ?? requestedRemoteToken;
|
|
486
|
+
if (!remoteToken) {
|
|
487
|
+
throw new Error("The sucker's historical remote token mapping must be supplied explicitly.");
|
|
488
|
+
}
|
|
489
|
+
const leaves = await getSuckerOutboxLeaves(sourceClient, {
|
|
490
|
+
sucker: sourceSucker,
|
|
491
|
+
token: sourceToken,
|
|
492
|
+
count,
|
|
493
|
+
...scanOptions,
|
|
494
|
+
});
|
|
495
|
+
const leafHashes = leaves.map((leaf) => leaf.hashed);
|
|
496
|
+
const [inbox, executedHashes] = await Promise.all([
|
|
497
|
+
destinationClient.readContract({
|
|
498
|
+
address: destinationSucker,
|
|
499
|
+
abi: exports.jbSuckerV6ViewAbi,
|
|
500
|
+
functionName: "inboxOf",
|
|
501
|
+
args: [remoteToken],
|
|
502
|
+
}),
|
|
503
|
+
Promise.all(leaves.map((leaf) => destinationClient.readContract({
|
|
504
|
+
address: destinationSucker,
|
|
505
|
+
abi: exports.jbSuckerV6ViewAbi,
|
|
506
|
+
functionName: "executedLeafHashOf",
|
|
507
|
+
args: [remoteToken, BigInt(leaf.index)],
|
|
508
|
+
}))),
|
|
509
|
+
]);
|
|
510
|
+
let deliveredCount = 0;
|
|
511
|
+
if (inbox.root.toLowerCase() !== viem_1.zeroHash) {
|
|
512
|
+
for (let index = leaves.length - 1; index >= 0; index--) {
|
|
513
|
+
if (leaves[index].root.toLowerCase() === inbox.root.toLowerCase()) {
|
|
514
|
+
deliveredCount = index + 1;
|
|
515
|
+
break;
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
if (deliveredCount === 0) {
|
|
519
|
+
throw new Error("The destination sucker inbox root is absent from the reconstructed outbox.");
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
return leaves.map((outboxLeaf, index) => {
|
|
523
|
+
const executedHash = executedHashes[index];
|
|
524
|
+
if (executedHash.toLowerCase() !== viem_1.zeroHash &&
|
|
525
|
+
executedHash.toLowerCase() !== outboxLeaf.hashed.toLowerCase()) {
|
|
526
|
+
throw new Error("The destination sucker's executed leaf does not match the reconstructed outbox.");
|
|
527
|
+
}
|
|
528
|
+
const { status, canExecute } = classifySuckerMovement({
|
|
529
|
+
executed: executedHash.toLowerCase() !== viem_1.zeroHash,
|
|
530
|
+
index,
|
|
531
|
+
deliveredCount,
|
|
532
|
+
sentCount,
|
|
533
|
+
});
|
|
534
|
+
const proof = status === "claimable"
|
|
535
|
+
? suckerLeafProof(leafHashes.slice(0, deliveredCount), index)
|
|
536
|
+
: null;
|
|
537
|
+
if (proof &&
|
|
538
|
+
suckerBranchRoot(outboxLeaf.hashed, proof, index).toLowerCase() !==
|
|
539
|
+
inbox.root.toLowerCase()) {
|
|
540
|
+
throw new Error("The reconstructed sucker proof does not match the destination inbox.");
|
|
541
|
+
}
|
|
542
|
+
return {
|
|
543
|
+
sourceToken,
|
|
544
|
+
remoteToken,
|
|
545
|
+
leaf: {
|
|
546
|
+
index: BigInt(index),
|
|
547
|
+
beneficiary: outboxLeaf.beneficiary,
|
|
548
|
+
projectTokenCount: outboxLeaf.projectTokenCount,
|
|
549
|
+
terminalTokenAmount: outboxLeaf.terminalTokenAmount,
|
|
550
|
+
metadata: outboxLeaf.metadata,
|
|
551
|
+
},
|
|
552
|
+
leafHash: outboxLeaf.hashed,
|
|
553
|
+
outboxRoot: outboxLeaf.root,
|
|
554
|
+
blockNumber: outboxLeaf.blockNumber,
|
|
555
|
+
status,
|
|
556
|
+
canExecute,
|
|
557
|
+
proof,
|
|
558
|
+
};
|
|
559
|
+
});
|
|
560
|
+
}
|
|
561
|
+
/** Build a claim object from a movement whose proof was verified by the SDK. */
|
|
562
|
+
function claimFromSuckerMovement(movement) {
|
|
563
|
+
if (movement.status !== "claimable" || !movement.proof) {
|
|
564
|
+
throw new Error("Only a claimable sucker movement has a verified proof.");
|
|
565
|
+
}
|
|
566
|
+
return {
|
|
567
|
+
token: movement.remoteToken,
|
|
568
|
+
leaf: movement.leaf,
|
|
569
|
+
proof: movement.proof,
|
|
570
|
+
};
|
|
571
|
+
}
|
|
572
|
+
/** Common escalating native-value candidates for CCIP sucker simulations. */
|
|
573
|
+
exports.CCIP_SUCKER_TRANSPORT_VALUES = [
|
|
574
|
+
1000000000000000n,
|
|
575
|
+
5000000000000000n,
|
|
576
|
+
20000000000000000n,
|
|
577
|
+
50000000000000000n,
|
|
578
|
+
200000000000000000n,
|
|
579
|
+
500000000000000000n,
|
|
580
|
+
];
|
|
581
|
+
/** Common escalating native-value candidates for native bridge simulations. */
|
|
582
|
+
exports.NATIVE_SUCKER_TRANSPORT_VALUES = [
|
|
583
|
+
0n,
|
|
584
|
+
1000000000000000n,
|
|
585
|
+
10000000000000000n,
|
|
586
|
+
50000000000000000n,
|
|
587
|
+
];
|
|
588
|
+
/** Return the first value whose exact transaction simulation succeeds. */
|
|
589
|
+
async function findSuckerTransportValue(values, simulate) {
|
|
590
|
+
for (const value of values) {
|
|
591
|
+
try {
|
|
592
|
+
await simulate(value);
|
|
593
|
+
return value;
|
|
594
|
+
}
|
|
595
|
+
catch {
|
|
596
|
+
// Try the next fee tier.
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
return null;
|
|
600
|
+
}
|
|
601
|
+
/** Refuse the CCIP zero-transport path, which would switch fees to LINK. */
|
|
602
|
+
function assertSuckerTransportValue(transport, value, baseFee = 0n) {
|
|
603
|
+
if (transport === "unknown") {
|
|
604
|
+
throw new Error("The sucker transport could not be verified.");
|
|
605
|
+
}
|
|
606
|
+
if (transport === "ccip" && value - baseFee <= 0n) {
|
|
607
|
+
throw new Error("A CCIP sucker message requires a positive native transport budget.");
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
/**
|
|
611
|
+
* Positively identify a sucker's bridge family. RPC failures and unfamiliar
|
|
612
|
+
* implementations return `unknown`; callers must not assume they are native.
|
|
613
|
+
*/
|
|
614
|
+
async function classifySuckerTransport(client, sucker) {
|
|
615
|
+
try {
|
|
616
|
+
const router = await client.readContract({
|
|
617
|
+
address: sucker,
|
|
618
|
+
abi: exports.jbCcipSuckerV6Abi,
|
|
619
|
+
functionName: "CCIP_ROUTER",
|
|
620
|
+
});
|
|
621
|
+
if (router.toLowerCase() !== "0x0000000000000000000000000000000000000000") {
|
|
622
|
+
return "ccip";
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
catch {
|
|
626
|
+
// Probe the native bridge families below.
|
|
627
|
+
}
|
|
628
|
+
for (const functionName of ["OPMESSENGER", "ARBINBOX"]) {
|
|
629
|
+
try {
|
|
630
|
+
const bridge = await client.readContract({
|
|
631
|
+
address: sucker,
|
|
632
|
+
abi: exports.jbNativeSuckerV6ProbeAbi,
|
|
633
|
+
functionName,
|
|
634
|
+
});
|
|
635
|
+
if (bridge.toLowerCase() !== viem_1.zeroAddress)
|
|
636
|
+
return "native";
|
|
637
|
+
}
|
|
638
|
+
catch {
|
|
639
|
+
// Keep probing; an RPC error must not be treated as a positive match.
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
return "unknown";
|
|
643
|
+
}
|
|
644
|
+
/** Build a payable JBSucker.syncAccountingData transaction request. */
|
|
645
|
+
function buildSyncAccountingDataTx(args) {
|
|
646
|
+
return {
|
|
647
|
+
chainId: args.chainId,
|
|
648
|
+
address: args.sucker,
|
|
649
|
+
abi: exports.jbSuckerV6Abi,
|
|
650
|
+
functionName: "syncAccountingData",
|
|
651
|
+
args: [],
|
|
652
|
+
value: args.value ?? 0n,
|
|
653
|
+
};
|
|
654
|
+
}
|
|
655
|
+
/** Relative absolute drift between two unsigned bigint values, from 0 to 1. */
|
|
656
|
+
function relativeSuckerDrift(left, right) {
|
|
657
|
+
if (left < 0n || right < 0n) {
|
|
658
|
+
throw new Error("Sucker accounting values cannot be negative.");
|
|
659
|
+
}
|
|
660
|
+
const larger = left > right ? left : right;
|
|
661
|
+
if (larger === 0n)
|
|
662
|
+
return 0;
|
|
663
|
+
const difference = left > right ? left - right : right - left;
|
|
664
|
+
return Number((difference * 1000000n) / larger) / 1_000_000;
|
|
665
|
+
}
|
|
666
|
+
/** Unpack a sucker freshness key (`timestamp << 128 | sequence`). */
|
|
667
|
+
function suckerTimestampSeconds(value) {
|
|
668
|
+
const timestamp = Number(value >> 128n);
|
|
669
|
+
if (!Number.isSafeInteger(timestamp) || timestamp < 0) {
|
|
670
|
+
throw new Error("The sucker timestamp is outside JavaScript's safe range.");
|
|
671
|
+
}
|
|
672
|
+
return timestamp;
|
|
673
|
+
}
|
|
66
674
|
/**
|
|
67
675
|
* Builds a `prepare` transaction on a v6 sucker, locking project tokens into an outbox
|
|
68
676
|
* leaf destined for the remote chain.
|
|
@@ -160,4 +768,35 @@ async function getV6SuckerPairs(client, { chainId, projectId }) {
|
|
|
160
768
|
remoteChainId: pair.remoteChainId,
|
|
161
769
|
}));
|
|
162
770
|
}
|
|
771
|
+
/**
|
|
772
|
+
* Read active and deprecated suckers for a project. Historical suckers remain
|
|
773
|
+
* relevant because their already-delivered leaves can still be claimed.
|
|
774
|
+
*/
|
|
775
|
+
async function getAllV6SuckerPairs(client, { chainId, projectId }) {
|
|
776
|
+
const suckers = await client.readContract({
|
|
777
|
+
address: (0, types_js_1.v6Address)("JBSuckerRegistry", chainId),
|
|
778
|
+
abi: juicebox_js_1.jbSuckerRegistryAbi,
|
|
779
|
+
functionName: "allSuckersOf",
|
|
780
|
+
args: [projectId],
|
|
781
|
+
});
|
|
782
|
+
return Promise.all(suckers.map(async (local) => {
|
|
783
|
+
const [remote, remoteChainId] = await Promise.all([
|
|
784
|
+
client.readContract({
|
|
785
|
+
address: local,
|
|
786
|
+
abi: exports.jbSuckerV6ViewAbi,
|
|
787
|
+
functionName: "peer",
|
|
788
|
+
}),
|
|
789
|
+
client.readContract({
|
|
790
|
+
address: local,
|
|
791
|
+
abi: exports.jbSuckerV6ViewAbi,
|
|
792
|
+
functionName: "peerChainId",
|
|
793
|
+
}),
|
|
794
|
+
]);
|
|
795
|
+
return {
|
|
796
|
+
local,
|
|
797
|
+
remote: suckerBytes32ToAddress(remote),
|
|
798
|
+
remoteChainId,
|
|
799
|
+
};
|
|
800
|
+
}));
|
|
801
|
+
}
|
|
163
802
|
//# sourceMappingURL=suckers.js.map
|