@epoch-protocol/epoch-commons-sdk 0.1.20 → 0.1.21-mainnet.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/constants/contractAddresses.js +32 -0
- package/dist/constants/dummyLending.d.ts +1 -1
- package/dist/constants/dummyLending.js +1 -0
- package/dist/data/epochgraphmainnet.json +72 -3
- package/dist/data/epochgraphtestnet.json +40 -20
- package/dist/utils/dex-pools.d.ts +24 -0
- package/dist/utils/dex-pools.js +94 -0
- package/dist/utils/external-provider.d.ts +9 -0
- package/dist/utils/external-provider.js +16 -0
- package/dist/utils/graph.d.ts +20 -0
- package/dist/utils/graph.js +34 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +1 -0
- package/dist/utils/miden-id.d.ts +9 -0
- package/dist/utils/miden-id.js +88 -0
- package/package.json +1 -1
|
@@ -97,10 +97,13 @@ export const ARBITER_ADDRESS = {
|
|
|
97
97
|
10: "0x9f1de3ca45b09c61792a6f649ae68f420aa8a43b",
|
|
98
98
|
42161: "0x9f1de3ca45b09c61792a6f649ae68f420aa8a43b",
|
|
99
99
|
8453: "0x9f1de3ca45b09c61792a6f649ae68f420aa8a43b",
|
|
100
|
+
// Robinhood placeholders — replace after deployment.
|
|
101
|
+
4663: "0x9f1de3ca45b09c61792a6f649ae68f420aa8a43b",
|
|
100
102
|
// Testnets
|
|
101
103
|
11155111: "0x2F5eA866716A04e91a55099620F2e1B423eC7011",
|
|
102
104
|
84532: "0x2F5eA866716A04e91a55099620F2e1B423eC7011",
|
|
103
105
|
11155420: "0x2F5eA866716A04e91a55099620F2e1B423eC7011",
|
|
106
|
+
46630: "0x2F5eA866716A04e91a55099620F2e1B423eC7011",
|
|
104
107
|
123456789: "0x9f1de3ca45b09c61792a6f649ae68f420aa8a43b",
|
|
105
108
|
999999999: "0x9f1de3ca45b09c61792a6f649ae68f420aa8a43b",
|
|
106
109
|
};
|
|
@@ -111,10 +114,13 @@ export const ALLOCATOR_ADDRESS = {
|
|
|
111
114
|
10: "0x444E8C0fC85BB47aBD3E97d00E2E2B0719034769",
|
|
112
115
|
42161: "0x444E8C0fC85BB47aBD3E97d00E2E2B0719034769",
|
|
113
116
|
8453: "0x444E8C0fC85BB47aBD3E97d00E2E2B0719034769",
|
|
117
|
+
// Robinhood placeholders — replace after deployment.
|
|
118
|
+
4663: "0x444E8C0fC85BB47aBD3E97d00E2E2B0719034769",
|
|
114
119
|
// Testnets
|
|
115
120
|
11155111: "0xa46827635A7d329608085401a3b2Bf14a8a2bDF9",
|
|
116
121
|
84532: "0xa46827635A7d329608085401a3b2Bf14a8a2bDF9",
|
|
117
122
|
11155420: "0xa46827635A7d329608085401a3b2Bf14a8a2bDF9",
|
|
123
|
+
46630: "0xa46827635A7d329608085401a3b2Bf14a8a2bDF9",
|
|
118
124
|
123456789: "0x444E8C0fC85BB47aBD3E97d00E2E2B0719034769",
|
|
119
125
|
999999999: "0x444E8C0fC85BB47aBD3E97d00E2E2B0719034769",
|
|
120
126
|
};
|
|
@@ -134,6 +140,32 @@ export function getArbiterAddress(chainId) {
|
|
|
134
140
|
}
|
|
135
141
|
return address;
|
|
136
142
|
}
|
|
143
|
+
// The Robinhood Testnet deployment uses the same deterministic/testnet
|
|
144
|
+
// addresses as the existing Epoch testnet configuration. Populate every
|
|
145
|
+
// shared contract map together so any consumer consulting one of these maps
|
|
146
|
+
// cannot silently treat 46630 as unsupported.
|
|
147
|
+
const TESTNET_CONTRACT_ADDRESS_MAPS = [
|
|
148
|
+
INTENT_REGISTRY_ADDRESS,
|
|
149
|
+
EPOCH_MODULE_SAFE_ADDRESS,
|
|
150
|
+
EPOCH_SAFE_INIT_SETUP,
|
|
151
|
+
SAFE_INIT_SETUP_FORWARDER,
|
|
152
|
+
SAFE_WEBAUTHN_SHARED_SIGNER,
|
|
153
|
+
SAFE_WEBAUTHN_SIGNER_FACTORY,
|
|
154
|
+
FCLP256Verifier,
|
|
155
|
+
SAFE_PROXY_FACTORY_ADDRESS,
|
|
156
|
+
SAFE_SINGLETON_ADDRESS,
|
|
157
|
+
SAFE_7702_SINGLETON_ADDRESS,
|
|
158
|
+
SAFE_7579_MODULE_ADDRESS,
|
|
159
|
+
SAFE_7579_REGISTRY_ADDRESS,
|
|
160
|
+
EIP7702_SAFE_PROXY_ADDRESS,
|
|
161
|
+
METAMASK_EXEC_MANAGER,
|
|
162
|
+
EPOCH_ESCROW_ADDRESS,
|
|
163
|
+
SAFE_MULTISEND_ADDRESS,
|
|
164
|
+
SAFE_MULTISEND_CALL_ONLY_ADDRESS,
|
|
165
|
+
];
|
|
166
|
+
for (const addresses of TESTNET_CONTRACT_ADDRESS_MAPS) {
|
|
167
|
+
addresses[46630] = addresses[11155420];
|
|
168
|
+
}
|
|
137
169
|
const CONTRACT_ADDRESSES = {
|
|
138
170
|
METAMASK_EXEC_MANAGER,
|
|
139
171
|
SAFE_PROXY_FACTORY_ADDRESS,
|
|
@@ -7,7 +7,7 @@ export declare const DUMMY_LENDING_PROTOCOL: "dummy-lending";
|
|
|
7
7
|
export declare const DUMMY_LENDING_MARKET_ADDRESS = "0xa73c1ae0e4e9116020dba0a419f91585d73459ee";
|
|
8
8
|
/** CREATE2 staking contract — same on all dummy-staking testnets. */
|
|
9
9
|
export declare const DUMMY_STAKING_CONTRACT_ADDRESS = "0xA25A981bc027E1f13aC70882a323B8B8EE880B9C";
|
|
10
|
-
export declare const DUMMY_LENDING_CHAIN_IDS: readonly [84532, 11155111, 11155420];
|
|
10
|
+
export declare const DUMMY_LENDING_CHAIN_IDS: readonly [84532, 11155111, 11155420, 46630];
|
|
11
11
|
export type DummyLendingChainId = (typeof DUMMY_LENDING_CHAIN_IDS)[number];
|
|
12
12
|
/** Unified CREATE2 token addresses — same on every dummy-lending chain. */
|
|
13
13
|
export declare const DUMMY_LENDING_TOKENS: {
|
|
@@ -11,6 +11,7 @@ export const DUMMY_LENDING_CHAIN_IDS = [
|
|
|
11
11
|
84532, // Base Sepolia
|
|
12
12
|
11155111, // Ethereum Sepolia
|
|
13
13
|
11155420, // Optimism Sepolia
|
|
14
|
+
46630, // Robinhood Testnet
|
|
14
15
|
];
|
|
15
16
|
/** Unified CREATE2 token addresses — same on every dummy-lending chain. */
|
|
16
17
|
export const DUMMY_LENDING_TOKENS = {
|
|
@@ -51,9 +51,41 @@
|
|
|
51
51
|
"*": "*"
|
|
52
52
|
},
|
|
53
53
|
"type": ["swapandbridge"]
|
|
54
|
+
},
|
|
55
|
+
"MidenBridge": {
|
|
56
|
+
"contractAddress": {
|
|
57
|
+
"*": "*"
|
|
58
|
+
},
|
|
59
|
+
"type": ["swapandbridge", "bridge"]
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
"oracles": {
|
|
63
|
+
"PragmaMidenV1": {
|
|
64
|
+
"chain": "Miden",
|
|
65
|
+
"oracleAccount": "0x8f8d747477ca171144feadc60a1137",
|
|
66
|
+
"rpcUrl": "https://rpc.cedar.miden.io",
|
|
67
|
+
"method": "get_median",
|
|
68
|
+
"defaultMaxAgeSeconds": 120,
|
|
69
|
+
"minimumPublishers": 1,
|
|
70
|
+
"feeds": {
|
|
71
|
+
"USDC/USD": {
|
|
72
|
+
"key": "0x1dfbb6c4acb913805c4df6731bfe7bfb8b6acd999bb768feb24979170807ee51",
|
|
73
|
+
"expectedDecimals": 6
|
|
74
|
+
},
|
|
75
|
+
"ETH/USD": {
|
|
76
|
+
"key": "0x9a50f4137c634e0b384a87bea3a186e578e21274af6ae752230ead4631233e1d",
|
|
77
|
+
"expectedDecimals": 8
|
|
78
|
+
}
|
|
79
|
+
}
|
|
54
80
|
}
|
|
55
81
|
},
|
|
56
82
|
"tokens": {
|
|
83
|
+
"USDCX": {
|
|
84
|
+
"contractAddress": {
|
|
85
|
+
"Miden": "mm1arnfum9xuwwlrvgvrefejwvlavn3vk24_qr7qqq9wr6w"
|
|
86
|
+
},
|
|
87
|
+
"decimals": 6
|
|
88
|
+
},
|
|
57
89
|
"DAI": {
|
|
58
90
|
"contractAddress": {
|
|
59
91
|
"Ethereum": "0x6B175474E89094C44Da98b954EedeAC495271d0F",
|
|
@@ -80,7 +112,21 @@
|
|
|
80
112
|
"Base": "0x4200000000000000000000000000000000000006",
|
|
81
113
|
"Optimism": "0x4200000000000000000000000000000000000006",
|
|
82
114
|
"Polygon": "0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619",
|
|
83
|
-
"Arbitrum": "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1"
|
|
115
|
+
"Arbitrum": "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1",
|
|
116
|
+
"Robinhood": "0x0Bd7D308f8E1639FAb988df18A8011f41EAcAD73",
|
|
117
|
+
"Miden": "mm1apqelr6tlaeftyfj4f7w59dycysmtawe_qr7qqq9wr6w"
|
|
118
|
+
},
|
|
119
|
+
"decimals": 18
|
|
120
|
+
},
|
|
121
|
+
"USDG": {
|
|
122
|
+
"contractAddress": {
|
|
123
|
+
"Robinhood": "0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168"
|
|
124
|
+
},
|
|
125
|
+
"decimals": 6
|
|
126
|
+
},
|
|
127
|
+
"USDe": {
|
|
128
|
+
"contractAddress": {
|
|
129
|
+
"Robinhood": "0x5d3a1Ff2b6BAb83B63cd9AD0787074081a52ef34"
|
|
84
130
|
},
|
|
85
131
|
"decimals": 18
|
|
86
132
|
},
|
|
@@ -114,6 +160,14 @@
|
|
|
114
160
|
"Arbitrum": {
|
|
115
161
|
"chainId": 42161,
|
|
116
162
|
"explorer": "https://arbiscan.io"
|
|
163
|
+
},
|
|
164
|
+
"Robinhood": {
|
|
165
|
+
"chainId": 4663,
|
|
166
|
+
"explorer": "https://robinhoodchain.blockscout.com"
|
|
167
|
+
},
|
|
168
|
+
"Miden": {
|
|
169
|
+
"chainId": 999999999,
|
|
170
|
+
"explorer": "https://midenscan.com"
|
|
117
171
|
}
|
|
118
172
|
},
|
|
119
173
|
"relationships": {
|
|
@@ -164,17 +218,32 @@
|
|
|
164
218
|
"*": {
|
|
165
219
|
"tokensInAndOut": ["*"]
|
|
166
220
|
}
|
|
221
|
+
},
|
|
222
|
+
"MidenBridge": {
|
|
223
|
+
"*": {
|
|
224
|
+
"tokensInAndOut": ["*"]
|
|
225
|
+
}
|
|
167
226
|
}
|
|
168
227
|
},
|
|
169
228
|
"tokenChains": {
|
|
170
229
|
"DAI": ["Ethereum", "Base", "Optimism", "Polygon", "Arbitrum"],
|
|
171
230
|
"USDC": ["Ethereum", "Base", "Optimism", "Polygon", "Arbitrum"],
|
|
172
|
-
"
|
|
231
|
+
"USDCX": ["Miden"],
|
|
232
|
+
"WETH": [
|
|
233
|
+
"Ethereum",
|
|
234
|
+
"Base",
|
|
235
|
+
"Optimism",
|
|
236
|
+
"Polygon",
|
|
237
|
+
"Arbitrum",
|
|
238
|
+
"Robinhood",
|
|
239
|
+
"Miden"
|
|
240
|
+
],
|
|
241
|
+
"USDG": ["Robinhood"],
|
|
173
242
|
"USDT": ["Ethereum", "Optimism", "Polygon", "Arbitrum"],
|
|
174
243
|
"WBTC": ["Ethereum", "Optimism", "Polygon", "Arbitrum"],
|
|
175
244
|
"wstETH": ["Ethereum", "Base", "Optimism", "Arbitrum"],
|
|
176
245
|
"GHO": ["Ethereum", "Arbitrum", "Base"],
|
|
177
|
-
"USDe": ["Ethereum", "Arbitrum"],
|
|
246
|
+
"USDe": ["Ethereum", "Arbitrum", "Robinhood"],
|
|
178
247
|
"cbBTC": ["Ethereum", "Base"],
|
|
179
248
|
"PYUSD": ["Ethereum"],
|
|
180
249
|
"LINK": ["Ethereum", "Base", "Optimism", "Polygon", "Arbitrum"],
|
|
@@ -66,12 +66,19 @@
|
|
|
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": "
|
|
74
|
-
"Optimism": "0x2BB4FfD7E2c6D432b697554Efd77fA13bdbefd69"
|
|
79
|
+
"Miden": "0x5b043dcb48d5721106f7a1ceb2b804",
|
|
80
|
+
"Optimism": "0x2BB4FfD7E2c6D432b697554Efd77fA13bdbefd69",
|
|
81
|
+
"Robinhood": "0x2BB4FfD7E2c6D432b697554Efd77fA13bdbefd69"
|
|
75
82
|
},
|
|
76
83
|
"decimals": 18,
|
|
77
84
|
"decimalsByChain": {
|
|
@@ -83,7 +90,8 @@
|
|
|
83
90
|
"Base": "0xc30f1Ce05d1434d484E9A47283aA925fc8A8699a",
|
|
84
91
|
"Mainnet": "0xc30f1Ce05d1434d484E9A47283aA925fc8A8699a",
|
|
85
92
|
"Optimism": "0xc30f1Ce05d1434d484E9A47283aA925fc8A8699a",
|
|
86
|
-
"
|
|
93
|
+
"Robinhood": "0xc30f1Ce05d1434d484E9A47283aA925fc8A8699a",
|
|
94
|
+
"Miden": "0xd41499b8f142ad9119fd9da357a3b2"
|
|
87
95
|
},
|
|
88
96
|
"decimals": 18,
|
|
89
97
|
"decimalsByChain": {
|
|
@@ -94,8 +102,9 @@
|
|
|
94
102
|
"contractAddress": {
|
|
95
103
|
"Base": "0xc04d2869665Be874881133943523723Be5782720",
|
|
96
104
|
"Mainnet": "0xc04d2869665Be874881133943523723Be5782720",
|
|
97
|
-
"Miden": "
|
|
98
|
-
"Optimism": "0xc04d2869665Be874881133943523723Be5782720"
|
|
105
|
+
"Miden": "0x0ead4362a745e7d1790d75ea779611",
|
|
106
|
+
"Optimism": "0xc04d2869665Be874881133943523723Be5782720",
|
|
107
|
+
"Robinhood": "0xc04d2869665Be874881133943523723Be5782720"
|
|
99
108
|
},
|
|
100
109
|
"decimals": 18,
|
|
101
110
|
"decimalsByChain": {
|
|
@@ -107,7 +116,8 @@
|
|
|
107
116
|
"Base": "0x7946dd86eE310D0aC16804A37787289Fa5b88A8A",
|
|
108
117
|
"Mainnet": "0x7946dd86eE310D0aC16804A37787289Fa5b88A8A",
|
|
109
118
|
"Optimism": "0x7946dd86eE310D0aC16804A37787289Fa5b88A8A",
|
|
110
|
-
"
|
|
119
|
+
"Robinhood": "0x7946dd86eE310D0aC16804A37787289Fa5b88A8A",
|
|
120
|
+
"Miden": "0x9368815c611d5d517914a2c1f0bc8d"
|
|
111
121
|
},
|
|
112
122
|
"decimals": 18,
|
|
113
123
|
"decimalsByChain": {
|
|
@@ -119,7 +129,8 @@
|
|
|
119
129
|
"Base": "0x9b2a2754a9182fD65360E23afCDf3BeFF51796E9",
|
|
120
130
|
"Mainnet": "0x9b2a2754a9182fD65360E23afCDf3BeFF51796E9",
|
|
121
131
|
"Optimism": "0x9b2a2754a9182fD65360E23afCDf3BeFF51796E9",
|
|
122
|
-
"
|
|
132
|
+
"Robinhood": "0x9b2a2754a9182fD65360E23afCDf3BeFF51796E9",
|
|
133
|
+
"Miden": "0x1b22d80328f58c5171f67a85f170a3"
|
|
123
134
|
},
|
|
124
135
|
"decimals": 18,
|
|
125
136
|
"decimalsByChain": {
|
|
@@ -130,7 +141,8 @@
|
|
|
130
141
|
"contractAddress": {
|
|
131
142
|
"Base": "0xEA7dC9849206Ce73b11c465d37b85eC06B11Cf2C",
|
|
132
143
|
"Mainnet": "0xEA7dC9849206Ce73b11c465d37b85eC06B11Cf2C",
|
|
133
|
-
"Optimism": "0xEA7dC9849206Ce73b11c465d37b85eC06B11Cf2C"
|
|
144
|
+
"Optimism": "0xEA7dC9849206Ce73b11c465d37b85eC06B11Cf2C",
|
|
145
|
+
"Robinhood": "0xEA7dC9849206Ce73b11c465d37b85eC06B11Cf2C"
|
|
134
146
|
},
|
|
135
147
|
"decimals": 18
|
|
136
148
|
},
|
|
@@ -138,7 +150,8 @@
|
|
|
138
150
|
"contractAddress": {
|
|
139
151
|
"Base": "0xB588418c0f90F07Bc9587d0050845a90C23C7502",
|
|
140
152
|
"Mainnet": "0xB588418c0f90F07Bc9587d0050845a90C23C7502",
|
|
141
|
-
"Optimism": "0xB588418c0f90F07Bc9587d0050845a90C23C7502"
|
|
153
|
+
"Optimism": "0xB588418c0f90F07Bc9587d0050845a90C23C7502",
|
|
154
|
+
"Robinhood": "0xB588418c0f90F07Bc9587d0050845a90C23C7502"
|
|
142
155
|
},
|
|
143
156
|
"decimals": 18
|
|
144
157
|
},
|
|
@@ -146,7 +159,8 @@
|
|
|
146
159
|
"contractAddress": {
|
|
147
160
|
"Base": "0x512Ee6Bd7A4be5Ba4796F15Df080c4D0F89a38eD",
|
|
148
161
|
"Mainnet": "0x512Ee6Bd7A4be5Ba4796F15Df080c4D0F89a38eD",
|
|
149
|
-
"Optimism": "0x512Ee6Bd7A4be5Ba4796F15Df080c4D0F89a38eD"
|
|
162
|
+
"Optimism": "0x512Ee6Bd7A4be5Ba4796F15Df080c4D0F89a38eD",
|
|
163
|
+
"Robinhood": "0x512Ee6Bd7A4be5Ba4796F15Df080c4D0F89a38eD"
|
|
150
164
|
},
|
|
151
165
|
"decimals": 18
|
|
152
166
|
},
|
|
@@ -154,7 +168,8 @@
|
|
|
154
168
|
"contractAddress": {
|
|
155
169
|
"Base": "0x145e03A80c19ad1b9d0429d06b6d52707de724A0",
|
|
156
170
|
"Mainnet": "0x145e03A80c19ad1b9d0429d06b6d52707de724A0",
|
|
157
|
-
"Optimism": "0x145e03A80c19ad1b9d0429d06b6d52707de724A0"
|
|
171
|
+
"Optimism": "0x145e03A80c19ad1b9d0429d06b6d52707de724A0",
|
|
172
|
+
"Robinhood": "0x145e03A80c19ad1b9d0429d06b6d52707de724A0"
|
|
158
173
|
},
|
|
159
174
|
"decimals": 18
|
|
160
175
|
}
|
|
@@ -175,6 +190,10 @@
|
|
|
175
190
|
"Optimism": {
|
|
176
191
|
"chainId": 11155420,
|
|
177
192
|
"explorer": "https://sepolia-optimistic.etherscan.io/"
|
|
193
|
+
},
|
|
194
|
+
"Robinhood": {
|
|
195
|
+
"chainId": 46630,
|
|
196
|
+
"explorer": "https://explorer.testnet.chain.robinhood.com"
|
|
178
197
|
}
|
|
179
198
|
},
|
|
180
199
|
"relationships": {
|
|
@@ -338,15 +357,16 @@
|
|
|
338
357
|
}
|
|
339
358
|
},
|
|
340
359
|
"tokenChains": {
|
|
341
|
-
"
|
|
342
|
-
"
|
|
343
|
-
"
|
|
344
|
-
"
|
|
345
|
-
"
|
|
346
|
-
"
|
|
347
|
-
"
|
|
348
|
-
"
|
|
349
|
-
"
|
|
360
|
+
"USDCX": ["Miden"],
|
|
361
|
+
"DAI": ["Base", "Mainnet", "Optimism", "Robinhood"],
|
|
362
|
+
"USDT": ["Base", "Mainnet", "Optimism", "Robinhood"],
|
|
363
|
+
"USDC": ["Base", "Optimism", "Mainnet", "Miden", "Robinhood"],
|
|
364
|
+
"WETH": ["Base", "Mainnet", "Optimism", "Robinhood"],
|
|
365
|
+
"WBTC": ["Base", "Mainnet", "Optimism", "Robinhood"],
|
|
366
|
+
"PENGU": ["Base", "Mainnet", "Optimism", "Robinhood"],
|
|
367
|
+
"OSWALD": ["Base", "Mainnet", "Optimism", "Robinhood"],
|
|
368
|
+
"KICK": ["Base", "Mainnet", "Optimism", "Robinhood"],
|
|
369
|
+
"FERB": ["Base", "Mainnet", "Optimism", "Robinhood"]
|
|
350
370
|
}
|
|
351
371
|
}
|
|
352
372
|
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { Hex } from "viem";
|
|
2
|
+
export declare const DEX_POOLS_EXTRA_TYPESTRING = "string dexPools";
|
|
3
|
+
export declare const MAX_DEX_POOL_PREFERENCES = 16;
|
|
4
|
+
export type UniswapV3PoolPreference = {
|
|
5
|
+
protocol: "uniswap-v3";
|
|
6
|
+
chainId: number;
|
|
7
|
+
address: Hex;
|
|
8
|
+
};
|
|
9
|
+
export type UniswapV4PoolKey = {
|
|
10
|
+
currency0: Hex;
|
|
11
|
+
currency1: Hex;
|
|
12
|
+
fee: number;
|
|
13
|
+
tickSpacing: number;
|
|
14
|
+
hooks: Hex;
|
|
15
|
+
};
|
|
16
|
+
export type UniswapV4PoolPreference = {
|
|
17
|
+
protocol: "uniswap-v4";
|
|
18
|
+
chainId: number;
|
|
19
|
+
poolKey: UniswapV4PoolKey;
|
|
20
|
+
hookData?: Hex;
|
|
21
|
+
};
|
|
22
|
+
export type DexPoolPreference = UniswapV3PoolPreference | UniswapV4PoolPreference;
|
|
23
|
+
export declare function decodeDexPools(value: unknown): DexPoolPreference[];
|
|
24
|
+
export declare function encodeDexPools(pools: readonly DexPoolPreference[]): string;
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
export const DEX_POOLS_EXTRA_TYPESTRING = "string dexPools";
|
|
2
|
+
export const MAX_DEX_POOL_PREFERENCES = 16;
|
|
3
|
+
const DYNAMIC_FEE_FLAG = 0x800000;
|
|
4
|
+
function invalid(message) {
|
|
5
|
+
throw new Error(`Invalid dexPools: ${message}`);
|
|
6
|
+
}
|
|
7
|
+
function isHex(value) {
|
|
8
|
+
return typeof value === "string" && /^0x(?:[0-9a-fA-F]{2})*$/.test(value);
|
|
9
|
+
}
|
|
10
|
+
function address(value, field, allowZero = false) {
|
|
11
|
+
if (typeof value !== "string" ||
|
|
12
|
+
!/^0x[0-9a-fA-F]{40}$/.test(value) ||
|
|
13
|
+
(!allowZero && /^0x0{40}$/i.test(value))) {
|
|
14
|
+
return invalid(`${field} must be a non-zero address`);
|
|
15
|
+
}
|
|
16
|
+
return value.toLowerCase();
|
|
17
|
+
}
|
|
18
|
+
function integer(value, field, minimum, maximum) {
|
|
19
|
+
if (typeof value !== "number" ||
|
|
20
|
+
!Number.isSafeInteger(value) ||
|
|
21
|
+
value < minimum ||
|
|
22
|
+
value > maximum) {
|
|
23
|
+
return invalid(`${field} must be an integer between ${minimum} and ${maximum}`);
|
|
24
|
+
}
|
|
25
|
+
return value;
|
|
26
|
+
}
|
|
27
|
+
function decodeEntry(value) {
|
|
28
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
29
|
+
return invalid("each entry must be an object");
|
|
30
|
+
}
|
|
31
|
+
const entry = value;
|
|
32
|
+
const chainId = integer(entry.chainId, "chainId", 1, Number.MAX_SAFE_INTEGER);
|
|
33
|
+
if (entry.protocol === "uniswap-v3") {
|
|
34
|
+
return {
|
|
35
|
+
protocol: "uniswap-v3",
|
|
36
|
+
chainId,
|
|
37
|
+
address: address(entry.address, "address"),
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
if (entry.protocol !== "uniswap-v4") {
|
|
41
|
+
return invalid("protocol must be uniswap-v3 or uniswap-v4");
|
|
42
|
+
}
|
|
43
|
+
if (!entry.poolKey ||
|
|
44
|
+
typeof entry.poolKey !== "object" ||
|
|
45
|
+
Array.isArray(entry.poolKey)) {
|
|
46
|
+
return invalid("poolKey must be an object");
|
|
47
|
+
}
|
|
48
|
+
const key = entry.poolKey;
|
|
49
|
+
const currency0 = address(key.currency0, "poolKey.currency0", true);
|
|
50
|
+
const currency1 = address(key.currency1, "poolKey.currency1");
|
|
51
|
+
if (currency0 >= currency1) {
|
|
52
|
+
return invalid("poolKey.currency0 must sort before poolKey.currency1");
|
|
53
|
+
}
|
|
54
|
+
const fee = integer(key.fee, "poolKey.fee", 0, 0xffffff);
|
|
55
|
+
if (fee > 1_000_000 && fee !== DYNAMIC_FEE_FLAG) {
|
|
56
|
+
return invalid("poolKey.fee is outside the v4 fee range");
|
|
57
|
+
}
|
|
58
|
+
const tickSpacing = integer(key.tickSpacing, "poolKey.tickSpacing", 1, 32767);
|
|
59
|
+
const hooks = address(key.hooks, "poolKey.hooks", true);
|
|
60
|
+
const hookData = entry.hookData === undefined ? "0x" : entry.hookData;
|
|
61
|
+
if (!isHex(hookData))
|
|
62
|
+
return invalid("hookData must be even-length hex");
|
|
63
|
+
return {
|
|
64
|
+
protocol: "uniswap-v4",
|
|
65
|
+
chainId,
|
|
66
|
+
poolKey: { currency0, currency1, fee, tickSpacing, hooks },
|
|
67
|
+
hookData: hookData.toLowerCase(),
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
export function decodeDexPools(value) {
|
|
71
|
+
if (value === undefined || value === null || value === "")
|
|
72
|
+
return [];
|
|
73
|
+
if (typeof value !== "string")
|
|
74
|
+
return invalid("must be a JSON string");
|
|
75
|
+
let decoded;
|
|
76
|
+
try {
|
|
77
|
+
decoded = JSON.parse(value);
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
return invalid("must contain valid JSON");
|
|
81
|
+
}
|
|
82
|
+
if (!Array.isArray(decoded))
|
|
83
|
+
return invalid("must contain an array");
|
|
84
|
+
if (decoded.length > MAX_DEX_POOL_PREFERENCES) {
|
|
85
|
+
return invalid(`must contain at most ${MAX_DEX_POOL_PREFERENCES} entries`);
|
|
86
|
+
}
|
|
87
|
+
return decoded.map(decodeEntry);
|
|
88
|
+
}
|
|
89
|
+
export function encodeDexPools(pools) {
|
|
90
|
+
if (!Array.isArray(pools))
|
|
91
|
+
return invalid("must be an array");
|
|
92
|
+
// Reuse the decoder so encoding and decoding accept precisely the same schema.
|
|
93
|
+
return JSON.stringify(decodeDexPools(JSON.stringify(pools)));
|
|
94
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** Compact witness declaration for selecting an external quote provider. */
|
|
2
|
+
export declare const EXTERNAL_PROVIDER_EXTRA_TYPESTRING = "string provider";
|
|
3
|
+
export declare const EXTERNAL_QUOTE_PROVIDERS: readonly ["khalani", "near", "lifi"];
|
|
4
|
+
export type ExternalQuoteProvider = (typeof EXTERNAL_QUOTE_PROVIDERS)[number];
|
|
5
|
+
/**
|
|
6
|
+
* Validates an optional signed provider field without normalizing its value.
|
|
7
|
+
* The exact string is part of the Compact witness and must remain unchanged.
|
|
8
|
+
*/
|
|
9
|
+
export declare function decodeExternalQuoteProvider(value: unknown): ExternalQuoteProvider | undefined;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/** Compact witness declaration for selecting an external quote provider. */
|
|
2
|
+
export const EXTERNAL_PROVIDER_EXTRA_TYPESTRING = "string provider";
|
|
3
|
+
export const EXTERNAL_QUOTE_PROVIDERS = ["khalani", "near", "lifi"];
|
|
4
|
+
/**
|
|
5
|
+
* Validates an optional signed provider field without normalizing its value.
|
|
6
|
+
* The exact string is part of the Compact witness and must remain unchanged.
|
|
7
|
+
*/
|
|
8
|
+
export function decodeExternalQuoteProvider(value) {
|
|
9
|
+
if (value === undefined)
|
|
10
|
+
return undefined;
|
|
11
|
+
if (typeof value !== "string" ||
|
|
12
|
+
!EXTERNAL_QUOTE_PROVIDERS.includes(value)) {
|
|
13
|
+
throw new Error(`Invalid external provider; expected one of ${EXTERNAL_QUOTE_PROVIDERS.join(", ")}`);
|
|
14
|
+
}
|
|
15
|
+
return value;
|
|
16
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Graph } from "../types/index.js";
|
|
2
|
+
/** Resolve the canonical graph name and metadata from an EVM chain id. */
|
|
3
|
+
export declare function getGraphChain(graph: Graph, chainId: number): {
|
|
4
|
+
chainId: number;
|
|
5
|
+
explorer: string;
|
|
6
|
+
nativeCurrency?: {
|
|
7
|
+
name: string;
|
|
8
|
+
symbol: string;
|
|
9
|
+
decimals: number;
|
|
10
|
+
};
|
|
11
|
+
name: string;
|
|
12
|
+
} | undefined;
|
|
13
|
+
/** Resolve an asset only when its address exists on the requested chain. */
|
|
14
|
+
export declare function getGraphToken(graph: Graph, chainId: number, symbol: string): {
|
|
15
|
+
symbol: string;
|
|
16
|
+
address: string;
|
|
17
|
+
decimals: number;
|
|
18
|
+
} | undefined;
|
|
19
|
+
/** Check graph path eligibility, including wildcard filler protocols. */
|
|
20
|
+
export declare function supportsGraphProtocol(graph: Graph, chainId: number, protocol: string, symbol: string): boolean;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/** Resolve the canonical graph name and metadata from an EVM chain id. */
|
|
2
|
+
export function getGraphChain(graph, chainId) {
|
|
3
|
+
const entry = Object.entries(graph.chains).find(([, chain]) => chain.chainId === chainId);
|
|
4
|
+
return entry ? { name: entry[0], ...entry[1] } : undefined;
|
|
5
|
+
}
|
|
6
|
+
/** Resolve an asset only when its address exists on the requested chain. */
|
|
7
|
+
export function getGraphToken(graph, chainId, symbol) {
|
|
8
|
+
const chain = getGraphChain(graph, chainId);
|
|
9
|
+
const token = graph.tokens[symbol];
|
|
10
|
+
const address = chain && token?.contractAddress[chain.name];
|
|
11
|
+
return address && chain && token
|
|
12
|
+
? {
|
|
13
|
+
symbol,
|
|
14
|
+
address,
|
|
15
|
+
decimals: token.decimalsByChain?.[chain.name] ?? token.decimals,
|
|
16
|
+
}
|
|
17
|
+
: undefined;
|
|
18
|
+
}
|
|
19
|
+
/** Check graph path eligibility, including wildcard filler protocols. */
|
|
20
|
+
export function supportsGraphProtocol(graph, chainId, protocol, symbol) {
|
|
21
|
+
const chain = getGraphChain(graph, chainId);
|
|
22
|
+
if (!chain || !getGraphToken(graph, chainId, symbol))
|
|
23
|
+
return false;
|
|
24
|
+
const addresses = graph.protocols[protocol]?.contractAddress;
|
|
25
|
+
if (!addresses?.[chain.name] && !addresses?.["*"])
|
|
26
|
+
return false;
|
|
27
|
+
const relationships = graph.relationships.protocolTokensByChain[protocol];
|
|
28
|
+
const relation = relationships?.[chain.name] ?? relationships?.["*"];
|
|
29
|
+
return [
|
|
30
|
+
relation?.tokensIn,
|
|
31
|
+
relation?.tokensOut,
|
|
32
|
+
relation?.tokensInAndOut,
|
|
33
|
+
].some((tokens) => tokens?.includes(symbol) || tokens?.includes("*"));
|
|
34
|
+
}
|
package/dist/utils/index.d.ts
CHANGED
package/dist/utils/index.js
CHANGED
|
@@ -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
|
+
}
|