@epoch-protocol/epoch-commons-sdk 0.2.3 → 2.0.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/README.md +0 -19
- package/dist/constants/contractAddresses.js +0 -7
- package/dist/data/epochgraphmainnet.json +37 -88
- package/dist/data/epochgraphtestnet.json +12 -5
- package/dist/data/index.d.ts +3 -7
- package/dist/data/index.js +3 -4
- package/dist/types/index.d.ts +0 -24
- package/dist/utils/index.d.ts +1 -3
- package/dist/utils/index.js +1 -3
- package/dist/utils/miden-id.d.ts +9 -0
- package/dist/utils/miden-id.js +88 -0
- package/package.json +2 -5
- package/dist/constants/chains.d.ts +0 -21
- package/dist/constants/chains.js +0 -21
- package/dist/utils/address.d.ts +0 -23
- package/dist/utils/address.js +0 -39
- package/dist/utils/chain-kind.d.ts +0 -6
- package/dist/utils/chain-kind.js +0 -18
- package/dist/utils/intent-route.d.ts +0 -19
- package/dist/utils/intent-route.js +0 -84
- package/dist/utils/solana-intent.d.ts +0 -31
- package/dist/utils/solana-intent.js +0 -75
- package/dist/utils/value-validation.d.ts +0 -1
- package/dist/utils/value-validation.js +0 -18
package/README.md
CHANGED
|
@@ -1,20 +1 @@
|
|
|
1
1
|
# Epoch Commons SDK
|
|
2
|
-
|
|
3
|
-
### Ethereum and Robinhood mainnet graph
|
|
4
|
-
|
|
5
|
-
`mainnetGraph` is the canonical source for Ethereum (1) and Robinhood Chain
|
|
6
|
-
(4663) network, token, and protocol relationships. `getGraphChain`,
|
|
7
|
-
`getGraphToken`, and `supportsGraphProtocol` resolve chain ids and validate
|
|
8
|
-
path eligibility without treating a token on one network as available on another.
|
|
9
|
-
|
|
10
|
-
Native ETH uses the zero-address sentinel and 18 decimals. Generic filler and
|
|
11
|
-
external routes can select ETH; `uniswap-v3` relationships expose WETH instead,
|
|
12
|
-
because that solver currently requires ERC20 input. Ethereum USDG and USDe use
|
|
13
|
-
the issuer addresses documented by [Paxos](https://docs.paxos.com/guides/stablecoin/usdg/mainnet)
|
|
14
|
-
and [Ethena](https://docs.ethena.fi/api-documentation/overview). WBTC uses its
|
|
15
|
-
Ethereum token address and 8 decimals, distinct from the 18-decimal testnet mock.
|
|
16
|
-
|
|
17
|
-
Protocol router and custom Epoch/Safe address maps retain deployment
|
|
18
|
-
placeholders as requested. A graph relationship describes configured routing
|
|
19
|
-
eligibility; it does not verify deployment or pool liquidity. Replace placeholder
|
|
20
|
-
addresses with verified deployments before executing production operations.
|
|
@@ -166,13 +166,6 @@ const TESTNET_CONTRACT_ADDRESS_MAPS = [
|
|
|
166
166
|
for (const addresses of TESTNET_CONTRACT_ADDRESS_MAPS) {
|
|
167
167
|
addresses[46630] = addresses[11155420];
|
|
168
168
|
}
|
|
169
|
-
// Ethereum and Robinhood mainnet deployment placeholders. These preserve the
|
|
170
|
-
// deterministic address configuration used by testnets; replace each entry
|
|
171
|
-
// with its verified mainnet deployment before executing production operations.
|
|
172
|
-
for (const addresses of TESTNET_CONTRACT_ADDRESS_MAPS) {
|
|
173
|
-
addresses[1] = addresses[11155420];
|
|
174
|
-
addresses[4663] = addresses[1];
|
|
175
|
-
}
|
|
176
169
|
const CONTRACT_ADDRESSES = {
|
|
177
170
|
METAMASK_EXEC_MANAGER,
|
|
178
171
|
SAFE_PROXY_FACTORY_ADDRESS,
|
|
@@ -5,9 +5,7 @@
|
|
|
5
5
|
"Base": "0xMorphoBaseAddress",
|
|
6
6
|
"Optimism": "0xMorphoOptimismAddress",
|
|
7
7
|
"Polygon": "0xMorphoPolygonAddress",
|
|
8
|
-
"Arbitrum": "0xMorphoArbitrumAddress"
|
|
9
|
-
"Ethereum": "0xrafflesEthereumAddress",
|
|
10
|
-
"Robinhood": "0xrafflesRobinhoodAddress"
|
|
8
|
+
"Arbitrum": "0xMorphoArbitrumAddress"
|
|
11
9
|
},
|
|
12
10
|
"type": ["protocol-interaction"]
|
|
13
11
|
},
|
|
@@ -17,8 +15,7 @@
|
|
|
17
15
|
"Base": "0x1deltaBaseAddress",
|
|
18
16
|
"Optimism": "0x1deltaOptimismAddress",
|
|
19
17
|
"Polygon": "0x1deltaPolygonAddress",
|
|
20
|
-
"Arbitrum": "0x1deltaArbitrumAddress"
|
|
21
|
-
"Robinhood": "0xOnedeltaRobinhoodAddress"
|
|
18
|
+
"Arbitrum": "0x1deltaArbitrumAddress"
|
|
22
19
|
},
|
|
23
20
|
"type": ["protocol-interaction"]
|
|
24
21
|
},
|
|
@@ -27,9 +24,7 @@
|
|
|
27
24
|
"Base": "0xMorphoBaseAddress",
|
|
28
25
|
"Optimism": "0xMorphoOptimismAddress",
|
|
29
26
|
"Polygon": "0xMorphoPolygonAddress",
|
|
30
|
-
"Arbitrum": "0xMorphoArbitrumAddress"
|
|
31
|
-
"Ethereum": "0xuniswapv3EthereumAddress",
|
|
32
|
-
"Robinhood": "0xuniswapv3RobinhoodAddress"
|
|
27
|
+
"Arbitrum": "0xMorphoArbitrumAddress"
|
|
33
28
|
},
|
|
34
29
|
"type": ["swap"]
|
|
35
30
|
},
|
|
@@ -56,9 +51,21 @@
|
|
|
56
51
|
"*": "*"
|
|
57
52
|
},
|
|
58
53
|
"type": ["swapandbridge"]
|
|
54
|
+
},
|
|
55
|
+
"MidenBridge": {
|
|
56
|
+
"contractAddress": {
|
|
57
|
+
"*": "*"
|
|
58
|
+
},
|
|
59
|
+
"type": ["swapandbridge", "bridge"]
|
|
59
60
|
}
|
|
60
61
|
},
|
|
61
62
|
"tokens": {
|
|
63
|
+
"USDCX": {
|
|
64
|
+
"contractAddress": {
|
|
65
|
+
"Miden": "mm1arnfum9xuwwlrvgvrefejwvlavn3vk24_qr7qqq9wr6w"
|
|
66
|
+
},
|
|
67
|
+
"decimals": 6
|
|
68
|
+
},
|
|
62
69
|
"DAI": {
|
|
63
70
|
"contractAddress": {
|
|
64
71
|
"Ethereum": "0x6B175474E89094C44Da98b954EedeAC495271d0F",
|
|
@@ -86,21 +93,20 @@
|
|
|
86
93
|
"Optimism": "0x4200000000000000000000000000000000000006",
|
|
87
94
|
"Polygon": "0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619",
|
|
88
95
|
"Arbitrum": "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1",
|
|
89
|
-
"Robinhood": "0x0Bd7D308f8E1639FAb988df18A8011f41EAcAD73"
|
|
96
|
+
"Robinhood": "0x0Bd7D308f8E1639FAb988df18A8011f41EAcAD73",
|
|
97
|
+
"Miden": "mm1apqelr6tlaeftyfj4f7w59dycysmtawe_qr7qqq9wr6w"
|
|
90
98
|
},
|
|
91
99
|
"decimals": 18
|
|
92
100
|
},
|
|
93
101
|
"USDG": {
|
|
94
102
|
"contractAddress": {
|
|
95
|
-
"Robinhood": "0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168"
|
|
96
|
-
"Ethereum": "0xe343167631d89B6Ffc58B88d6b7fB0228795491D"
|
|
103
|
+
"Robinhood": "0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168"
|
|
97
104
|
},
|
|
98
105
|
"decimals": 6
|
|
99
106
|
},
|
|
100
107
|
"USDe": {
|
|
101
108
|
"contractAddress": {
|
|
102
|
-
"Robinhood": "0x5d3a1Ff2b6BAb83B63cd9AD0787074081a52ef34"
|
|
103
|
-
"Ethereum": "0x4c9EDD5852cd905f086C759E8383e09bff1E68B3"
|
|
109
|
+
"Robinhood": "0x5d3a1Ff2b6BAb83B63cd9AD0787074081a52ef34"
|
|
104
110
|
},
|
|
105
111
|
"decimals": 18
|
|
106
112
|
},
|
|
@@ -112,30 +118,12 @@
|
|
|
112
118
|
"Arbitrum": "0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9"
|
|
113
119
|
},
|
|
114
120
|
"decimals": 6
|
|
115
|
-
},
|
|
116
|
-
"ETH": {
|
|
117
|
-
"contractAddress": {
|
|
118
|
-
"Ethereum": "0x0000000000000000000000000000000000000000",
|
|
119
|
-
"Robinhood": "0x0000000000000000000000000000000000000000"
|
|
120
|
-
},
|
|
121
|
-
"decimals": 18
|
|
122
|
-
},
|
|
123
|
-
"WBTC": {
|
|
124
|
-
"contractAddress": {
|
|
125
|
-
"Ethereum": "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599"
|
|
126
|
-
},
|
|
127
|
-
"decimals": 8
|
|
128
121
|
}
|
|
129
122
|
},
|
|
130
123
|
"chains": {
|
|
131
124
|
"Ethereum": {
|
|
132
125
|
"chainId": 1,
|
|
133
|
-
"explorer": "https://etherscan.io"
|
|
134
|
-
"nativeCurrency": {
|
|
135
|
-
"name": "Ether",
|
|
136
|
-
"symbol": "ETH",
|
|
137
|
-
"decimals": 18
|
|
138
|
-
}
|
|
126
|
+
"explorer": "https://etherscan.io"
|
|
139
127
|
},
|
|
140
128
|
"Base": {
|
|
141
129
|
"chainId": 8453,
|
|
@@ -155,12 +143,11 @@
|
|
|
155
143
|
},
|
|
156
144
|
"Robinhood": {
|
|
157
145
|
"chainId": 4663,
|
|
158
|
-
"explorer": "https://robinhoodchain.blockscout.com"
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
}
|
|
146
|
+
"explorer": "https://robinhoodchain.blockscout.com"
|
|
147
|
+
},
|
|
148
|
+
"Miden": {
|
|
149
|
+
"chainId": 999999999,
|
|
150
|
+
"explorer": "https://midenscan.com"
|
|
164
151
|
}
|
|
165
152
|
},
|
|
166
153
|
"relationships": {
|
|
@@ -171,21 +158,6 @@
|
|
|
171
158
|
},
|
|
172
159
|
"Optimism": {
|
|
173
160
|
"tokensInAndOut": ["WETH", "USDC", "DAI", "USDT"]
|
|
174
|
-
},
|
|
175
|
-
"Ethereum": {
|
|
176
|
-
"tokensInAndOut": [
|
|
177
|
-
"DAI",
|
|
178
|
-
"USDC",
|
|
179
|
-
"WETH",
|
|
180
|
-
"USDG",
|
|
181
|
-
"USDe",
|
|
182
|
-
"USDT",
|
|
183
|
-
"ETH",
|
|
184
|
-
"WBTC"
|
|
185
|
-
]
|
|
186
|
-
},
|
|
187
|
-
"Robinhood": {
|
|
188
|
-
"tokensInAndOut": ["WETH", "USDG", "USDe", "ETH"]
|
|
189
161
|
}
|
|
190
162
|
},
|
|
191
163
|
"uniswap-v3": {
|
|
@@ -200,20 +172,6 @@
|
|
|
200
172
|
},
|
|
201
173
|
"Arbitrum": {
|
|
202
174
|
"tokensInAndOut": ["WETH", "USDC", "DAI", "USDT"]
|
|
203
|
-
},
|
|
204
|
-
"Ethereum": {
|
|
205
|
-
"tokensInAndOut": [
|
|
206
|
-
"DAI",
|
|
207
|
-
"USDC",
|
|
208
|
-
"WETH",
|
|
209
|
-
"USDG",
|
|
210
|
-
"USDe",
|
|
211
|
-
"USDT",
|
|
212
|
-
"WBTC"
|
|
213
|
-
]
|
|
214
|
-
},
|
|
215
|
-
"Robinhood": {
|
|
216
|
-
"tokensInAndOut": ["WETH", "USDG", "USDe"]
|
|
217
175
|
}
|
|
218
176
|
},
|
|
219
177
|
"FillerCrossChain": {
|
|
@@ -234,51 +192,42 @@
|
|
|
234
192
|
"1delta": {
|
|
235
193
|
"*": {
|
|
236
194
|
"tokensInAndOut": ["*"]
|
|
237
|
-
},
|
|
238
|
-
"Ethereum": {
|
|
239
|
-
"tokensInAndOut": [
|
|
240
|
-
"DAI",
|
|
241
|
-
"USDC",
|
|
242
|
-
"WETH",
|
|
243
|
-
"USDG",
|
|
244
|
-
"USDe",
|
|
245
|
-
"USDT",
|
|
246
|
-
"ETH",
|
|
247
|
-
"WBTC"
|
|
248
|
-
]
|
|
249
|
-
},
|
|
250
|
-
"Robinhood": {
|
|
251
|
-
"tokensInAndOut": ["WETH", "USDG", "USDe", "ETH"]
|
|
252
195
|
}
|
|
253
196
|
},
|
|
254
197
|
"ExternalSwapBridge": {
|
|
255
198
|
"*": {
|
|
256
199
|
"tokensInAndOut": ["*"]
|
|
257
200
|
}
|
|
201
|
+
},
|
|
202
|
+
"MidenBridge": {
|
|
203
|
+
"*": {
|
|
204
|
+
"tokensInAndOut": ["*"]
|
|
205
|
+
}
|
|
258
206
|
}
|
|
259
207
|
},
|
|
260
208
|
"tokenChains": {
|
|
261
209
|
"DAI": ["Ethereum", "Base", "Optimism", "Polygon", "Arbitrum"],
|
|
262
210
|
"USDC": ["Ethereum", "Base", "Optimism", "Polygon", "Arbitrum"],
|
|
211
|
+
"USDCX": ["Miden"],
|
|
263
212
|
"WETH": [
|
|
264
213
|
"Ethereum",
|
|
265
214
|
"Base",
|
|
266
215
|
"Optimism",
|
|
267
216
|
"Polygon",
|
|
268
217
|
"Arbitrum",
|
|
269
|
-
"Robinhood"
|
|
218
|
+
"Robinhood",
|
|
219
|
+
"Miden"
|
|
270
220
|
],
|
|
271
|
-
"USDG": ["
|
|
221
|
+
"USDG": ["Robinhood"],
|
|
272
222
|
"USDT": ["Ethereum", "Optimism", "Polygon", "Arbitrum"],
|
|
273
|
-
"WBTC": ["Ethereum"],
|
|
223
|
+
"WBTC": ["Ethereum", "Optimism", "Polygon", "Arbitrum"],
|
|
274
224
|
"wstETH": ["Ethereum", "Base", "Optimism", "Arbitrum"],
|
|
275
225
|
"GHO": ["Ethereum", "Arbitrum", "Base"],
|
|
276
|
-
"USDe": ["Ethereum", "Robinhood"],
|
|
226
|
+
"USDe": ["Ethereum", "Arbitrum", "Robinhood"],
|
|
277
227
|
"cbBTC": ["Ethereum", "Base"],
|
|
278
228
|
"PYUSD": ["Ethereum"],
|
|
279
229
|
"LINK": ["Ethereum", "Base", "Optimism", "Polygon", "Arbitrum"],
|
|
280
|
-
"weETH": ["Ethereum", "Base", "Arbitrum"]
|
|
281
|
-
"ETH": ["Ethereum", "Robinhood"]
|
|
230
|
+
"weETH": ["Ethereum", "Base", "Arbitrum"]
|
|
282
231
|
}
|
|
283
232
|
}
|
|
284
233
|
}
|
|
@@ -66,11 +66,17 @@
|
|
|
66
66
|
}
|
|
67
67
|
},
|
|
68
68
|
"tokens": {
|
|
69
|
+
"USDCX": {
|
|
70
|
+
"contractAddress": {
|
|
71
|
+
"Miden": "0x4cbdcaffe75f0a317482224dae6436"
|
|
72
|
+
},
|
|
73
|
+
"decimals": 6
|
|
74
|
+
},
|
|
69
75
|
"USDC": {
|
|
70
76
|
"contractAddress": {
|
|
71
77
|
"Base": "0x2BB4FfD7E2c6D432b697554Efd77fA13bdbefd69",
|
|
72
78
|
"Mainnet": "0x2BB4FfD7E2c6D432b697554Efd77fA13bdbefd69",
|
|
73
|
-
"Miden": "
|
|
79
|
+
"Miden": "0x5b043dcb48d5721106f7a1ceb2b804",
|
|
74
80
|
"Optimism": "0x2BB4FfD7E2c6D432b697554Efd77fA13bdbefd69",
|
|
75
81
|
"Robinhood": "0x2BB4FfD7E2c6D432b697554Efd77fA13bdbefd69"
|
|
76
82
|
},
|
|
@@ -85,7 +91,7 @@
|
|
|
85
91
|
"Mainnet": "0xc30f1Ce05d1434d484E9A47283aA925fc8A8699a",
|
|
86
92
|
"Optimism": "0xc30f1Ce05d1434d484E9A47283aA925fc8A8699a",
|
|
87
93
|
"Robinhood": "0xc30f1Ce05d1434d484E9A47283aA925fc8A8699a",
|
|
88
|
-
"Miden": "
|
|
94
|
+
"Miden": "0xd41499b8f142ad9119fd9da357a3b2"
|
|
89
95
|
},
|
|
90
96
|
"decimals": 18,
|
|
91
97
|
"decimalsByChain": {
|
|
@@ -96,7 +102,7 @@
|
|
|
96
102
|
"contractAddress": {
|
|
97
103
|
"Base": "0xc04d2869665Be874881133943523723Be5782720",
|
|
98
104
|
"Mainnet": "0xc04d2869665Be874881133943523723Be5782720",
|
|
99
|
-
"Miden": "
|
|
105
|
+
"Miden": "0x0ead4362a745e7d1790d75ea779611",
|
|
100
106
|
"Optimism": "0xc04d2869665Be874881133943523723Be5782720",
|
|
101
107
|
"Robinhood": "0xc04d2869665Be874881133943523723Be5782720"
|
|
102
108
|
},
|
|
@@ -111,7 +117,7 @@
|
|
|
111
117
|
"Mainnet": "0x7946dd86eE310D0aC16804A37787289Fa5b88A8A",
|
|
112
118
|
"Optimism": "0x7946dd86eE310D0aC16804A37787289Fa5b88A8A",
|
|
113
119
|
"Robinhood": "0x7946dd86eE310D0aC16804A37787289Fa5b88A8A",
|
|
114
|
-
"Miden": "
|
|
120
|
+
"Miden": "0x9368815c611d5d517914a2c1f0bc8d"
|
|
115
121
|
},
|
|
116
122
|
"decimals": 18,
|
|
117
123
|
"decimalsByChain": {
|
|
@@ -124,7 +130,7 @@
|
|
|
124
130
|
"Mainnet": "0x9b2a2754a9182fD65360E23afCDf3BeFF51796E9",
|
|
125
131
|
"Optimism": "0x9b2a2754a9182fD65360E23afCDf3BeFF51796E9",
|
|
126
132
|
"Robinhood": "0x9b2a2754a9182fD65360E23afCDf3BeFF51796E9",
|
|
127
|
-
"Miden": "
|
|
133
|
+
"Miden": "0x1b22d80328f58c5171f67a85f170a3"
|
|
128
134
|
},
|
|
129
135
|
"decimals": 18,
|
|
130
136
|
"decimalsByChain": {
|
|
@@ -351,6 +357,7 @@
|
|
|
351
357
|
}
|
|
352
358
|
},
|
|
353
359
|
"tokenChains": {
|
|
360
|
+
"USDCX": ["Miden"],
|
|
354
361
|
"DAI": ["Base", "Mainnet", "Optimism", "Robinhood"],
|
|
355
362
|
"USDT": ["Base", "Mainnet", "Optimism", "Robinhood"],
|
|
356
363
|
"USDC": ["Base", "Optimism", "Mainnet", "Miden", "Robinhood"],
|
package/dist/data/index.d.ts
CHANGED
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
type ConcreteGraph<T> = T & Graph;
|
|
5
|
-
export declare const mainnetGraph: ConcreteGraph<typeof mainnetGraphData>;
|
|
6
|
-
export declare const testnetGraph: ConcreteGraph<typeof testnetGraphData>;
|
|
7
|
-
export {};
|
|
1
|
+
import mainnetGraph from "./epochgraphmainnet.json";
|
|
2
|
+
import testnetGraph from "./epochgraphtestnet.json";
|
|
3
|
+
export { mainnetGraph, testnetGraph };
|
package/dist/data/index.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
export
|
|
4
|
-
export const testnetGraph = testnetGraphData;
|
|
1
|
+
import mainnetGraph from "./epochgraphmainnet.json" with { type: "json" };
|
|
2
|
+
import testnetGraph from "./epochgraphtestnet.json" with { type: "json" };
|
|
3
|
+
export { mainnetGraph, testnetGraph };
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { ethers } from "ethers";
|
|
2
2
|
import { Address, WalletClient } from "viem";
|
|
3
|
-
export type { DexPoolPreference, UniswapV3PoolPreference, UniswapV4PoolKey, UniswapV4PoolPreference, } from "../utils/dex-pools.js";
|
|
4
3
|
export type ApiResponse<T> = {
|
|
5
4
|
data: T;
|
|
6
5
|
status: number;
|
|
@@ -111,14 +110,8 @@ export type Token = {
|
|
|
111
110
|
export type Chain = {
|
|
112
111
|
chainId: number;
|
|
113
112
|
explorer: string;
|
|
114
|
-
nativeCurrency?: {
|
|
115
|
-
name: string;
|
|
116
|
-
symbol: string;
|
|
117
|
-
decimals: number;
|
|
118
|
-
};
|
|
119
113
|
};
|
|
120
114
|
export type Relationships = {
|
|
121
|
-
tokenChains?: Record<string, string[]>;
|
|
122
115
|
protocolTokensByChain: {
|
|
123
116
|
[protocolName: string]: {
|
|
124
117
|
[chainName: string]: {
|
|
@@ -190,8 +183,6 @@ export type PathItem = {
|
|
|
190
183
|
};
|
|
191
184
|
calldata?: CalldataReturnInterface;
|
|
192
185
|
fillerData?: FillerTokenData;
|
|
193
|
-
/** Client-side execution metadata retained when quote-only paths strip calldata. */
|
|
194
|
-
externalExecution?: ExternalExecutionPlan;
|
|
195
186
|
};
|
|
196
187
|
export type Path = PathItem[][][];
|
|
197
188
|
export interface QuoteReturnInterface {
|
|
@@ -214,21 +205,6 @@ export type ExecutionTransaction = {
|
|
|
214
205
|
value: string;
|
|
215
206
|
callData: string;
|
|
216
207
|
};
|
|
217
|
-
/** LI.FI's source bridge may be followed by an SDK-refreshed destination v4 swap. */
|
|
218
|
-
export type LifiExternalExecutionPlan = {
|
|
219
|
-
provider: "lifi";
|
|
220
|
-
sourceChainId: number;
|
|
221
|
-
externalSolverUrl: string;
|
|
222
|
-
sourceTransactions: ExecutionTransaction[];
|
|
223
|
-
submitTransactionIndex: number;
|
|
224
|
-
requiresSequentialReceipts: true;
|
|
225
|
-
lifi: {
|
|
226
|
-
destinationChainId: number;
|
|
227
|
-
bridgeToken: string;
|
|
228
|
-
};
|
|
229
|
-
destinationSwap?: Record<string, unknown>;
|
|
230
|
-
};
|
|
231
|
-
export type ExternalExecutionPlan = LifiExternalExecutionPlan;
|
|
232
208
|
export type IntermediaryApprovals = {
|
|
233
209
|
tokenAddress: string;
|
|
234
210
|
spenderAddress: string;
|
package/dist/utils/index.d.ts
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
export * from "./compact.js";
|
|
2
|
-
export * from "./
|
|
3
|
-
export * from "./external-provider.js";
|
|
2
|
+
export * from "./miden-id.js";
|
|
4
3
|
export * from "./miden-intent.js";
|
|
5
4
|
export * from "./path.js";
|
|
6
5
|
export * from "./witness-typestring.js";
|
|
7
|
-
export * from "./graph.js";
|
package/dist/utils/index.js
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
export * from "./compact.js";
|
|
2
|
-
export * from "./
|
|
3
|
-
export * from "./external-provider.js";
|
|
2
|
+
export * from "./miden-id.js";
|
|
4
3
|
export * from "./miden-intent.js";
|
|
5
4
|
export * from "./path.js";
|
|
6
5
|
export * from "./witness-typestring.js";
|
|
7
|
-
export * from "./graph.js";
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Convert a Miden account or faucet identifier to canonical 0x-prefixed hex.
|
|
3
|
+
*
|
|
4
|
+
* Hex identifiers pass through with their body case preserved. Valid Miden
|
|
5
|
+
* Bech32/Bech32m addresses (including an optional interface suffix) are decoded.
|
|
6
|
+
* Invalid non-hex input is returned trimmed so callers can apply their own
|
|
7
|
+
* validation and surface the original value in error messages.
|
|
8
|
+
*/
|
|
9
|
+
export declare function normalizeMidenId(id: string): string;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
const BECH32_CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l";
|
|
2
|
+
const BECH32_CHECKSUM = 1;
|
|
3
|
+
const BECH32M_CHECKSUM = 0x2bc830a3;
|
|
4
|
+
const MIDEN_ACCOUNT_ID_BYTES = 15;
|
|
5
|
+
function bech32Polymod(values) {
|
|
6
|
+
const generator = [
|
|
7
|
+
0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3,
|
|
8
|
+
];
|
|
9
|
+
let checksum = 1;
|
|
10
|
+
for (const value of values) {
|
|
11
|
+
const top = checksum >>> 25;
|
|
12
|
+
checksum = ((checksum & 0x1ffffff) << 5) ^ value;
|
|
13
|
+
for (let index = 0; index < generator.length; index += 1) {
|
|
14
|
+
if ((top >>> index) & 1)
|
|
15
|
+
checksum ^= generator[index];
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return checksum >>> 0;
|
|
19
|
+
}
|
|
20
|
+
function bech32HrpExpand(hrp) {
|
|
21
|
+
const output = [];
|
|
22
|
+
for (let index = 0; index < hrp.length; index += 1) {
|
|
23
|
+
output.push(hrp.charCodeAt(index) >> 5);
|
|
24
|
+
}
|
|
25
|
+
output.push(0);
|
|
26
|
+
for (let index = 0; index < hrp.length; index += 1) {
|
|
27
|
+
output.push(hrp.charCodeAt(index) & 31);
|
|
28
|
+
}
|
|
29
|
+
return output;
|
|
30
|
+
}
|
|
31
|
+
function decodeMidenBech32(input) {
|
|
32
|
+
const address = input.split("_")[0].toLowerCase();
|
|
33
|
+
const separator = address.lastIndexOf("1");
|
|
34
|
+
if (separator < 1 || separator + 7 > address.length)
|
|
35
|
+
return null;
|
|
36
|
+
const words = [];
|
|
37
|
+
for (const character of address.slice(separator + 1)) {
|
|
38
|
+
const value = BECH32_CHARSET.indexOf(character);
|
|
39
|
+
if (value < 0)
|
|
40
|
+
return null;
|
|
41
|
+
words.push(value);
|
|
42
|
+
}
|
|
43
|
+
const checksum = bech32Polymod([
|
|
44
|
+
...bech32HrpExpand(address.slice(0, separator)),
|
|
45
|
+
...words,
|
|
46
|
+
]);
|
|
47
|
+
if (checksum !== BECH32_CHECKSUM && checksum !== BECH32M_CHECKSUM) {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
let accumulator = 0;
|
|
51
|
+
let bits = 0;
|
|
52
|
+
const bytes = [];
|
|
53
|
+
for (const word of words.slice(0, -6)) {
|
|
54
|
+
accumulator = (accumulator << 5) | word;
|
|
55
|
+
bits += 5;
|
|
56
|
+
while (bits >= 8) {
|
|
57
|
+
bits -= 8;
|
|
58
|
+
bytes.push((accumulator >> bits) & 0xff);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
if (bytes.length < MIDEN_ACCOUNT_ID_BYTES + 1)
|
|
62
|
+
return null;
|
|
63
|
+
return ("0x" +
|
|
64
|
+
bytes
|
|
65
|
+
.slice(1, 1 + MIDEN_ACCOUNT_ID_BYTES)
|
|
66
|
+
.map((byte) => byte.toString(16).padStart(2, "0"))
|
|
67
|
+
.join(""));
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Convert a Miden account or faucet identifier to canonical 0x-prefixed hex.
|
|
71
|
+
*
|
|
72
|
+
* Hex identifiers pass through with their body case preserved. Valid Miden
|
|
73
|
+
* Bech32/Bech32m addresses (including an optional interface suffix) are decoded.
|
|
74
|
+
* Invalid non-hex input is returned trimmed so callers can apply their own
|
|
75
|
+
* validation and surface the original value in error messages.
|
|
76
|
+
*/
|
|
77
|
+
export function normalizeMidenId(id) {
|
|
78
|
+
const raw = (id ?? "").trim();
|
|
79
|
+
if (!raw)
|
|
80
|
+
return raw;
|
|
81
|
+
if (raw.startsWith("0x") || raw.startsWith("0X")) {
|
|
82
|
+
return "0x" + raw.slice(2);
|
|
83
|
+
}
|
|
84
|
+
if (/^[0-9a-fA-F]+$/.test(raw) && raw.length % 2 === 0) {
|
|
85
|
+
return "0x" + raw;
|
|
86
|
+
}
|
|
87
|
+
return decodeMidenBech32(raw) ?? raw;
|
|
88
|
+
}
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@epoch-protocol/epoch-commons-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "SDK for interacting with Epoch Commons Protocol",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
8
8
|
"scripts": {
|
|
9
|
-
"build": "tsc
|
|
9
|
+
"build": "tsc",
|
|
10
10
|
"test": "jest",
|
|
11
11
|
"lint": "eslint . --ext .ts",
|
|
12
12
|
"format": "prettier --write \"src/**/*.ts\"",
|
|
@@ -24,9 +24,6 @@
|
|
|
24
24
|
],
|
|
25
25
|
"author": "",
|
|
26
26
|
"license": "MIT",
|
|
27
|
-
"publishConfig": {
|
|
28
|
-
"access": "public"
|
|
29
|
-
},
|
|
30
27
|
"dependencies": {
|
|
31
28
|
"ethers": "^6.0.0",
|
|
32
29
|
"viem": "2.42.0"
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Canonical chain ids. Define new ones HERE and import them — `MIDEN_CHAIN_ID`
|
|
3
|
-
* is currently redefined in seven places across the monorepo.
|
|
4
|
-
*
|
|
5
|
-
* Ids MUST fit in uint32: `getEncodedIntent` and the deployed IntentRegistry
|
|
6
|
-
* both declare `uint32[] chainIds`, so anything larger throws at ABI encode
|
|
7
|
-
* time. That rules out Solana's CAIP-2 id (1151111081099710).
|
|
8
|
-
*/
|
|
9
|
-
/**
|
|
10
|
-
* Solana mainnet-beta. Leading digits of the CAIP-2 id, so it stays traceable.
|
|
11
|
-
* PROVISIONAL — check chainlist for collisions before mainnet.
|
|
12
|
-
*/
|
|
13
|
-
export declare const SOLANA_MAINNET_CHAIN_ID = 1151111;
|
|
14
|
-
/**
|
|
15
|
-
* Solana devnet. Separate id rather than one shared with mainnet, so devnet can
|
|
16
|
-
* pass the testnet-gated checks in dex-solver's candidate-evaluator and mainnet
|
|
17
|
-
* still can't skip them.
|
|
18
|
-
*/
|
|
19
|
-
export declare const SOLANA_DEVNET_CHAIN_ID = 1151112;
|
|
20
|
-
/** Graph chain name. Load-bearing: `chains` and `token.contractAddress` key off it. */
|
|
21
|
-
export declare const SOLANA_CHAIN_NAME = "Solana";
|
package/dist/constants/chains.js
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Canonical chain ids. Define new ones HERE and import them — `MIDEN_CHAIN_ID`
|
|
3
|
-
* is currently redefined in seven places across the monorepo.
|
|
4
|
-
*
|
|
5
|
-
* Ids MUST fit in uint32: `getEncodedIntent` and the deployed IntentRegistry
|
|
6
|
-
* both declare `uint32[] chainIds`, so anything larger throws at ABI encode
|
|
7
|
-
* time. That rules out Solana's CAIP-2 id (1151111081099710).
|
|
8
|
-
*/
|
|
9
|
-
/**
|
|
10
|
-
* Solana mainnet-beta. Leading digits of the CAIP-2 id, so it stays traceable.
|
|
11
|
-
* PROVISIONAL — check chainlist for collisions before mainnet.
|
|
12
|
-
*/
|
|
13
|
-
export const SOLANA_MAINNET_CHAIN_ID = 1151111;
|
|
14
|
-
/**
|
|
15
|
-
* Solana devnet. Separate id rather than one shared with mainnet, so devnet can
|
|
16
|
-
* pass the testnet-gated checks in dex-solver's candidate-evaluator and mainnet
|
|
17
|
-
* still can't skip them.
|
|
18
|
-
*/
|
|
19
|
-
export const SOLANA_DEVNET_CHAIN_ID = 1151112;
|
|
20
|
-
/** Graph chain name. Load-bearing: `chains` and `token.contractAddress` key off it. */
|
|
21
|
-
export const SOLANA_CHAIN_NAME = "Solana";
|
package/dist/utils/address.d.ts
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Chain-aware address handling. Never call `.toLowerCase()` on an address.
|
|
3
|
-
*
|
|
4
|
-
* Lowercasing is safe for hex (EVM addresses, Miden faucet ids) and destroys
|
|
5
|
-
* base58 (Solana), where `A` and `a` are different characters. The failure is
|
|
6
|
-
* silent — graph lookups still match, because both sides get lowercased — and
|
|
7
|
-
* only surfaces once the value is used as a real address, by which point a
|
|
8
|
-
* solver has been told to deliver there.
|
|
9
|
-
*/
|
|
10
|
-
/** Exactly 20-byte `0x` hex — a strict EVM address. */
|
|
11
|
-
export declare function isEvmAddress(value: string): boolean;
|
|
12
|
-
/** Solana's base58 alphabet (no `0`, `O`, `I`, `l`), 32-44 chars = 32-byte pubkey. */
|
|
13
|
-
export declare function isBase58Address(value: string): boolean;
|
|
14
|
-
/** Any identifier the protocol can route: EVM, Miden faucet, or Solana mint. */
|
|
15
|
-
export declare function isTokenIdentifier(value: string): boolean;
|
|
16
|
-
/** Canonical form for lookups and map keys. Hex is lowercased, base58 is not. */
|
|
17
|
-
export declare function normalizeTokenAddress(address: string): string;
|
|
18
|
-
/**
|
|
19
|
-
* Equality that respects each family's case rules. Replaces
|
|
20
|
-
* `a.toLowerCase() === b.toLowerCase()`, which returns true for two base58
|
|
21
|
-
* strings differing only in case — i.e. two different accounts.
|
|
22
|
-
*/
|
|
23
|
-
export declare function sameTokenAddress(a?: string | null, b?: string | null): boolean;
|
package/dist/utils/address.js
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Chain-aware address handling. Never call `.toLowerCase()` on an address.
|
|
3
|
-
*
|
|
4
|
-
* Lowercasing is safe for hex (EVM addresses, Miden faucet ids) and destroys
|
|
5
|
-
* base58 (Solana), where `A` and `a` are different characters. The failure is
|
|
6
|
-
* silent — graph lookups still match, because both sides get lowercased — and
|
|
7
|
-
* only surfaces once the value is used as a real address, by which point a
|
|
8
|
-
* solver has been told to deliver there.
|
|
9
|
-
*/
|
|
10
|
-
/** `0x`-prefixed hex of any length: EVM addresses and Miden faucet ids. */
|
|
11
|
-
function isHexIdentifier(value) {
|
|
12
|
-
return /^0x[a-fA-F0-9]+$/.test(value);
|
|
13
|
-
}
|
|
14
|
-
/** Exactly 20-byte `0x` hex — a strict EVM address. */
|
|
15
|
-
export function isEvmAddress(value) {
|
|
16
|
-
return /^0x[a-fA-F0-9]{40}$/.test(value);
|
|
17
|
-
}
|
|
18
|
-
/** Solana's base58 alphabet (no `0`, `O`, `I`, `l`), 32-44 chars = 32-byte pubkey. */
|
|
19
|
-
export function isBase58Address(value) {
|
|
20
|
-
return /^[1-9A-HJ-NP-Za-km-z]{32,44}$/.test(value);
|
|
21
|
-
}
|
|
22
|
-
/** Any identifier the protocol can route: EVM, Miden faucet, or Solana mint. */
|
|
23
|
-
export function isTokenIdentifier(value) {
|
|
24
|
-
return isHexIdentifier(value) || isBase58Address(value);
|
|
25
|
-
}
|
|
26
|
-
/** Canonical form for lookups and map keys. Hex is lowercased, base58 is not. */
|
|
27
|
-
export function normalizeTokenAddress(address) {
|
|
28
|
-
return isHexIdentifier(address) ? address.toLowerCase() : address;
|
|
29
|
-
}
|
|
30
|
-
/**
|
|
31
|
-
* Equality that respects each family's case rules. Replaces
|
|
32
|
-
* `a.toLowerCase() === b.toLowerCase()`, which returns true for two base58
|
|
33
|
-
* strings differing only in case — i.e. two different accounts.
|
|
34
|
-
*/
|
|
35
|
-
export function sameTokenAddress(a, b) {
|
|
36
|
-
if (!a || !b)
|
|
37
|
-
return false;
|
|
38
|
-
return normalizeTokenAddress(a) === normalizeTokenAddress(b);
|
|
39
|
-
}
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import type { ChainKind, Graph } from "../types/index.js";
|
|
2
|
-
/**
|
|
3
|
-
* `undefined` for an unknown chain — treat that as unsupported, never as EVM.
|
|
4
|
-
* Defaulting to EVM is how a Solana mint ends up in `ethers.getAddress()`.
|
|
5
|
-
*/
|
|
6
|
-
export declare function getChainKind(graph: Graph | undefined | null, chainId: number): ChainKind | undefined;
|
package/dist/utils/chain-kind.js
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* `undefined` when the chain is not in the graph. Tolerates a missing or
|
|
3
|
-
* malformed graph rather than throwing — several suites stub the graph module
|
|
4
|
-
* out, and throwing there surfaces as a TypeError far from the cause.
|
|
5
|
-
*/
|
|
6
|
-
function findChainById(graph, chainId) {
|
|
7
|
-
if (!graph?.chains)
|
|
8
|
-
return undefined;
|
|
9
|
-
const entry = Object.entries(graph.chains).find(([, chain]) => chain?.chainId === chainId);
|
|
10
|
-
return entry ? { name: entry[0], chain: entry[1] } : undefined;
|
|
11
|
-
}
|
|
12
|
-
/**
|
|
13
|
-
* `undefined` for an unknown chain — treat that as unsupported, never as EVM.
|
|
14
|
-
* Defaulting to EVM is how a Solana mint ends up in `ethers.getAddress()`.
|
|
15
|
-
*/
|
|
16
|
-
export function getChainKind(graph, chainId) {
|
|
17
|
-
return findChainById(graph, chainId)?.chain.kind;
|
|
18
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
/** Origin and destination are resolved independently and returned as a pair. */
|
|
2
|
-
export type IntentOrigin = "evm" | "miden" | "solana";
|
|
3
|
-
export type IntentDestination = "evm" | "miden" | "solana";
|
|
4
|
-
export interface IntentRoute {
|
|
5
|
-
origin: IntentOrigin;
|
|
6
|
-
destination: IntentDestination;
|
|
7
|
-
}
|
|
8
|
-
/** Table-dispatch key, e.g. `"miden->solana"`. */
|
|
9
|
-
export type RouteKey = `${IntentOrigin}->${IntentDestination}`;
|
|
10
|
-
export type IntentRouteResult = {
|
|
11
|
-
valid: true;
|
|
12
|
-
route: IntentRoute;
|
|
13
|
-
} | {
|
|
14
|
-
valid: false;
|
|
15
|
-
error: string;
|
|
16
|
-
};
|
|
17
|
-
export declare function routeKey(route: IntentRoute): RouteKey;
|
|
18
|
-
/** Resolve from witness markers; callers validate chain-ID consistency. */
|
|
19
|
-
export declare function resolveIntentRoute(data?: Record<string, unknown>): IntentRouteResult;
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
import { MIDEN_RECIPIENT_ACCOUNT_FIELD_NAME, MIDEN_SOURCE_ACCOUNT_FIELD_NAME, SOLANA_MINT_FIELD_NAME, SOLANA_RECIPIENT_ACCOUNT_FIELD_NAME, SOLANA_SOURCE_ACCOUNT_FIELD_NAME, SOLANA_SOURCE_MINT_FIELD_NAME, } from "./witness-typestring.js";
|
|
2
|
-
function hasTruthyField(data, fieldName) {
|
|
3
|
-
if (!data)
|
|
4
|
-
return false;
|
|
5
|
-
const value = data[fieldName];
|
|
6
|
-
return typeof value === "string" && value.trim() !== "";
|
|
7
|
-
}
|
|
8
|
-
export function routeKey(route) {
|
|
9
|
-
return `${route.origin}->${route.destination}`;
|
|
10
|
-
}
|
|
11
|
-
/** Resolve from witness markers; callers validate chain-ID consistency. */
|
|
12
|
-
export function resolveIntentRoute(data) {
|
|
13
|
-
for (const fieldName of [
|
|
14
|
-
MIDEN_SOURCE_ACCOUNT_FIELD_NAME,
|
|
15
|
-
MIDEN_RECIPIENT_ACCOUNT_FIELD_NAME,
|
|
16
|
-
SOLANA_RECIPIENT_ACCOUNT_FIELD_NAME,
|
|
17
|
-
SOLANA_MINT_FIELD_NAME,
|
|
18
|
-
SOLANA_SOURCE_ACCOUNT_FIELD_NAME,
|
|
19
|
-
SOLANA_SOURCE_MINT_FIELD_NAME,
|
|
20
|
-
]) {
|
|
21
|
-
const value = data?.[fieldName];
|
|
22
|
-
if (value !== undefined &&
|
|
23
|
-
value !== null &&
|
|
24
|
-
(typeof value !== "string" || value.trim() === "")) {
|
|
25
|
-
return {
|
|
26
|
-
valid: false,
|
|
27
|
-
error: `Intent route marker "${fieldName}" must be a non-empty string`,
|
|
28
|
-
};
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
const hasMidenSource = hasTruthyField(data, MIDEN_SOURCE_ACCOUNT_FIELD_NAME);
|
|
32
|
-
const hasMidenRecipient = hasTruthyField(data, MIDEN_RECIPIENT_ACCOUNT_FIELD_NAME);
|
|
33
|
-
const hasSolanaRecipient = hasTruthyField(data, SOLANA_RECIPIENT_ACCOUNT_FIELD_NAME);
|
|
34
|
-
const hasSolanaMint = hasTruthyField(data, SOLANA_MINT_FIELD_NAME);
|
|
35
|
-
const hasSolanaSource = hasTruthyField(data, SOLANA_SOURCE_ACCOUNT_FIELD_NAME);
|
|
36
|
-
const hasSolanaSourceMint = hasTruthyField(data, SOLANA_SOURCE_MINT_FIELD_NAME);
|
|
37
|
-
if (hasMidenSource && hasMidenRecipient) {
|
|
38
|
-
return {
|
|
39
|
-
valid: false,
|
|
40
|
-
error: "Intent cannot include both midenSourceAccount and midenRecipientAccount",
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
if (hasSolanaRecipient !== hasSolanaMint) {
|
|
44
|
-
return {
|
|
45
|
-
valid: false,
|
|
46
|
-
error: "Solana intent must carry both solanaRecipientAccount and solanaMint",
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
if (hasSolanaSource !== hasSolanaSourceMint) {
|
|
50
|
-
return {
|
|
51
|
-
valid: false,
|
|
52
|
-
error: "Solana-origin intent must carry both solanaSourceAccount and solanaSourceMint",
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
if (hasMidenSource && hasSolanaSource) {
|
|
56
|
-
return {
|
|
57
|
-
valid: false,
|
|
58
|
-
error: "Intent declares two origins (midenSourceAccount and solanaSourceAccount)",
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
if (hasSolanaSource && hasSolanaRecipient) {
|
|
62
|
-
return {
|
|
63
|
-
valid: false,
|
|
64
|
-
error: "Solana→Solana intents are not supported",
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
if (hasMidenRecipient && hasSolanaRecipient) {
|
|
68
|
-
return {
|
|
69
|
-
valid: false,
|
|
70
|
-
error: "Intent declares two destinations (midenRecipientAccount and solanaRecipientAccount)",
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
const origin = hasMidenSource
|
|
74
|
-
? "miden"
|
|
75
|
-
: hasSolanaSource
|
|
76
|
-
? "solana"
|
|
77
|
-
: "evm";
|
|
78
|
-
const destination = hasSolanaRecipient
|
|
79
|
-
? "solana"
|
|
80
|
-
: hasMidenRecipient
|
|
81
|
-
? "miden"
|
|
82
|
-
: "evm";
|
|
83
|
-
return { valid: true, route: { origin, destination } };
|
|
84
|
-
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { EVM_TO_SOLANA_EXTRA_TYPESTRING, EVM_TO_SOLANA_FIELD_NAMES, SOLANA_MARKER_FIELD_NAMES, SOLANA_TO_EVM_EXTRA_TYPESTRING } from "./witness-typestring.js";
|
|
2
|
-
/** Detect Solana markers by exact field name in typestrings or mandate data. */
|
|
3
|
-
export interface SolanaExtraData {
|
|
4
|
-
/** Base58 account that receives the payout. Case-significant. */
|
|
5
|
-
solanaRecipientAccount?: string;
|
|
6
|
-
/** Base58 SPL mint being delivered. Case-significant. */
|
|
7
|
-
solanaMint?: string;
|
|
8
|
-
}
|
|
9
|
-
/** Solana-origin collateral: where the escrow deposit came from. */
|
|
10
|
-
export interface SolanaSourceData {
|
|
11
|
-
/** Base58 account that opened the escrow. Seeds its PDA. Case-significant. */
|
|
12
|
-
solanaSourceAccount: string;
|
|
13
|
-
/** Base58 SPL mint locked in the escrow. Case-significant. */
|
|
14
|
-
solanaSourceMint: string;
|
|
15
|
-
/** Nonce bound into the escrow PDA, preserved in its input representation. */
|
|
16
|
-
intentNonce: string | number | bigint;
|
|
17
|
-
}
|
|
18
|
-
/**
|
|
19
|
-
* True iff the intent is a Solana bridge intent.
|
|
20
|
-
* At least one of `typestring` or `data` must be provided.
|
|
21
|
-
*/
|
|
22
|
-
export declare function isSolanaIntent(typestring?: string, data?: Record<string, unknown>): boolean;
|
|
23
|
-
/** True when both Solana destination identifiers are present. */
|
|
24
|
-
export declare function isEVMToSolanaIntent(data?: Record<string, unknown>): boolean;
|
|
25
|
-
/** True when both Solana source identifiers are present. */
|
|
26
|
-
export declare function isSolanaToEVMIntent(data?: Record<string, unknown>): boolean;
|
|
27
|
-
/** Extract complete Solana source metadata or return `null`. */
|
|
28
|
-
export declare function getSolanaSourceMetadata(data?: Record<string, unknown>): SolanaSourceData | null;
|
|
29
|
-
/** Extract Solana identifiers, or `null` when this is not a Solana intent. */
|
|
30
|
-
export declare function getSolanaMetadata(data?: Record<string, unknown>, typestring?: string): SolanaExtraData | null;
|
|
31
|
-
export { EVM_TO_SOLANA_EXTRA_TYPESTRING, EVM_TO_SOLANA_FIELD_NAMES, SOLANA_MARKER_FIELD_NAMES, SOLANA_TO_EVM_EXTRA_TYPESTRING, };
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import { EVM_TO_SOLANA_EXTRA_TYPESTRING, EVM_TO_SOLANA_FIELD_NAMES, SOLANA_MARKER_FIELD_NAMES, SOLANA_MINT_FIELD_NAME, SOLANA_RECIPIENT_ACCOUNT_FIELD_NAME, SOLANA_SOURCE_ACCOUNT_FIELD_NAME, SOLANA_SOURCE_MINT_FIELD_NAME, SOLANA_SOURCE_NONCE_FIELD_NAME, SOLANA_TO_EVM_EXTRA_TYPESTRING, fieldNamesFromExtraTypestring, } from "./witness-typestring.js";
|
|
2
|
-
import { isUint256Value } from "./value-validation.js";
|
|
3
|
-
function hasTruthyField(data, fieldName) {
|
|
4
|
-
if (!data)
|
|
5
|
-
return false;
|
|
6
|
-
const value = data[fieldName];
|
|
7
|
-
return typeof value === "string" && value.trim() !== "";
|
|
8
|
-
}
|
|
9
|
-
/** True when a typestring DECLARES a field with exactly this name. */
|
|
10
|
-
function declaresField(typestring, fieldName) {
|
|
11
|
-
if (!typestring.trim())
|
|
12
|
-
return false;
|
|
13
|
-
try {
|
|
14
|
-
return fieldNamesFromExtraTypestring(typestring).includes(fieldName);
|
|
15
|
-
}
|
|
16
|
-
catch {
|
|
17
|
-
// Malformed typestring declares nothing. The caller's own typestring
|
|
18
|
-
// validation is responsible for rejecting it.
|
|
19
|
-
return false;
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
/** True when mandate/extra data carries any Solana bridge marker field. */
|
|
23
|
-
function hasSolanaMarkersInData(data) {
|
|
24
|
-
return SOLANA_MARKER_FIELD_NAMES.some((name) => hasTruthyField(data, name));
|
|
25
|
-
}
|
|
26
|
-
/** True when a witness/extra typestring declares any Solana bridge marker field. */
|
|
27
|
-
function hasSolanaMarkersInTypestring(typestring) {
|
|
28
|
-
return SOLANA_MARKER_FIELD_NAMES.some((name) => declaresField(typestring, name));
|
|
29
|
-
}
|
|
30
|
-
/**
|
|
31
|
-
* True iff the intent is a Solana bridge intent.
|
|
32
|
-
* At least one of `typestring` or `data` must be provided.
|
|
33
|
-
*/
|
|
34
|
-
export function isSolanaIntent(typestring, data) {
|
|
35
|
-
const hasTypestring = typestring !== undefined && typestring.trim() !== "";
|
|
36
|
-
const hasData = data !== undefined;
|
|
37
|
-
if (!hasTypestring && !hasData) {
|
|
38
|
-
throw new Error("isSolanaIntent requires typestring and/or data");
|
|
39
|
-
}
|
|
40
|
-
return ((hasTypestring && hasSolanaMarkersInTypestring(typestring)) ||
|
|
41
|
-
hasSolanaMarkersInData(data));
|
|
42
|
-
}
|
|
43
|
-
/** True when both Solana destination identifiers are present. */
|
|
44
|
-
export function isEVMToSolanaIntent(data) {
|
|
45
|
-
return (hasTruthyField(data, SOLANA_RECIPIENT_ACCOUNT_FIELD_NAME) &&
|
|
46
|
-
hasTruthyField(data, SOLANA_MINT_FIELD_NAME));
|
|
47
|
-
}
|
|
48
|
-
/** True when both Solana source identifiers are present. */
|
|
49
|
-
export function isSolanaToEVMIntent(data) {
|
|
50
|
-
return (hasTruthyField(data, SOLANA_SOURCE_ACCOUNT_FIELD_NAME) &&
|
|
51
|
-
hasTruthyField(data, SOLANA_SOURCE_MINT_FIELD_NAME));
|
|
52
|
-
}
|
|
53
|
-
/** Extract complete Solana source metadata or return `null`. */
|
|
54
|
-
export function getSolanaSourceMetadata(data) {
|
|
55
|
-
if (!isSolanaToEVMIntent(data))
|
|
56
|
-
return null;
|
|
57
|
-
const intentNonce = data?.[SOLANA_SOURCE_NONCE_FIELD_NAME];
|
|
58
|
-
if (!isUint256Value(intentNonce))
|
|
59
|
-
return null;
|
|
60
|
-
return {
|
|
61
|
-
solanaSourceAccount: data[SOLANA_SOURCE_ACCOUNT_FIELD_NAME],
|
|
62
|
-
solanaSourceMint: data[SOLANA_SOURCE_MINT_FIELD_NAME],
|
|
63
|
-
intentNonce: intentNonce,
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
/** Extract Solana identifiers, or `null` when this is not a Solana intent. */
|
|
67
|
-
export function getSolanaMetadata(data, typestring) {
|
|
68
|
-
if (!data || !isSolanaIntent(typestring, data))
|
|
69
|
-
return null;
|
|
70
|
-
return {
|
|
71
|
-
solanaRecipientAccount: data[SOLANA_RECIPIENT_ACCOUNT_FIELD_NAME],
|
|
72
|
-
solanaMint: data[SOLANA_MINT_FIELD_NAME],
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
export { EVM_TO_SOLANA_EXTRA_TYPESTRING, EVM_TO_SOLANA_FIELD_NAMES, SOLANA_MARKER_FIELD_NAMES, SOLANA_TO_EVM_EXTRA_TYPESTRING, };
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function isUint256Value(value: unknown): value is string | number | bigint;
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
export function isUint256Value(value) {
|
|
2
|
-
if (typeof value !== "string" &&
|
|
3
|
-
typeof value !== "number" &&
|
|
4
|
-
typeof value !== "bigint") {
|
|
5
|
-
return false;
|
|
6
|
-
}
|
|
7
|
-
if (typeof value === "string" && value.trim() === "")
|
|
8
|
-
return false;
|
|
9
|
-
if (typeof value === "number" && !Number.isSafeInteger(value))
|
|
10
|
-
return false;
|
|
11
|
-
try {
|
|
12
|
-
const parsed = BigInt(value);
|
|
13
|
-
return parsed >= 0n && parsed < 1n << 256n;
|
|
14
|
-
}
|
|
15
|
-
catch {
|
|
16
|
-
return false;
|
|
17
|
-
}
|
|
18
|
-
}
|