@gibs/bridge-sdk 1.19.0 → 1.20.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/abis.js +0 -2
- package/dist/bridge-limits.js +0 -38
- package/dist/chain-info.js +0 -116
- package/dist/chain-names.js +0 -151
- package/dist/chains.js +0 -198
- package/dist/cjs/abis.js +0 -2
- package/dist/cjs/bridge-limits.js +0 -38
- package/dist/cjs/chain-info.js +0 -116
- package/dist/cjs/chain-names.js +0 -151
- package/dist/cjs/chains.js +0 -198
- package/dist/cjs/claims.js +0 -60
- package/dist/cjs/config.js +1 -208
- package/dist/cjs/consolidated-quote.js +0 -465
- package/dist/cjs/destination-calldata.js +0 -71
- package/dist/cjs/ecosystems.js +0 -183
- package/dist/cjs/execution.js +0 -92
- package/dist/cjs/fee-type.js +0 -1
- package/dist/cjs/hyperliquid-execution.js +0 -98
- package/dist/cjs/image-links.js +0 -108
- package/dist/cjs/lifi-execution-guard.js +65 -172
- package/dist/cjs/near-intents-conformance.js +0 -110
- package/dist/cjs/near-intents-route.js +0 -149
- package/dist/cjs/near-intents.js +0 -562
- package/dist/cjs/origin-deposit.js +0 -56
- package/dist/cjs/pre-quote.js +0 -80
- package/dist/cjs/prices.js +0 -113
- package/dist/cjs/providers.js +0 -83
- package/dist/cjs/quote-fees.js +0 -80
- package/dist/cjs/referral.js +0 -75
- package/dist/cjs/relay-currencies.js +0 -31
- package/dist/cjs/relay-depository.js +52 -77
- package/dist/cjs/relay-quote.js +0 -394
- package/dist/cjs/route-steps.js +0 -100
- package/dist/cjs/routing/amounts.js +0 -83
- package/dist/cjs/routing/candidate-route.js +0 -73
- package/dist/cjs/routing/candidate.js +0 -46
- package/dist/cjs/routing/carrier-provider-key.js +0 -27
- package/dist/cjs/routing/carriers/omnibridge.js +0 -120
- package/dist/cjs/routing/carriers/pulsex-paths.js +0 -57
- package/dist/cjs/routing/carriers/pulsex-split.js +0 -92
- package/dist/cjs/routing/carriers/pulsex.js +0 -279
- package/dist/cjs/routing/carriers/wrap.js +0 -57
- package/dist/cjs/routing/composed-route-quality.js +0 -95
- package/dist/cjs/routing/entry-chain-anchor.js +0 -27
- package/dist/cjs/routing/format.js +0 -50
- package/dist/cjs/routing/index.js +0 -28
- package/dist/cjs/routing/producers.js +0 -854
- package/dist/cjs/routing/providers.js +0 -27
- package/dist/cjs/routing/search/compose.js +0 -56
- package/dist/cjs/routing/search/graph.js +0 -364
- package/dist/cjs/routing/search/plan-route-data.js +0 -508
- package/dist/cjs/routing/search/score.js +0 -344
- package/dist/cjs/routing/swap-transactions.js +0 -74
- package/dist/cjs/routing/usd-value.js +0 -12
- package/dist/cjs/settings.js +1 -456
- package/dist/cjs/swap-venues.js +0 -17
- package/dist/cjs/ton-connect.js +0 -82
- package/dist/cjs/ton-execution.js +0 -6
- package/dist/cjs/ton.js +0 -42
- package/dist/cjs/tron-execution.js +0 -145
- package/dist/claims.js +0 -60
- package/dist/config.js +1 -211
- package/dist/consolidated-quote.js +0 -465
- package/dist/destination-calldata.js +0 -71
- package/dist/ecosystems.js +0 -183
- package/dist/execution.js +0 -92
- package/dist/fee-type.js +0 -2
- package/dist/hyperliquid-execution.js +0 -98
- package/dist/image-links.js +0 -108
- package/dist/lifi-execution-guard.js +65 -172
- package/dist/near-intents-conformance.js +0 -110
- package/dist/near-intents-route.js +0 -149
- package/dist/near-intents.js +0 -562
- package/dist/origin-deposit.js +0 -56
- package/dist/pre-quote.js +0 -80
- package/dist/prices.js +0 -113
- package/dist/providers.js +0 -83
- package/dist/quote-fees.js +0 -80
- package/dist/referral.js +0 -75
- package/dist/relay-currencies.js +0 -31
- package/dist/relay-depository.js +52 -77
- package/dist/relay-quote.js +0 -394
- package/dist/route-steps.js +0 -100
- package/dist/routing/amounts.js +0 -83
- package/dist/routing/candidate-route.js +0 -73
- package/dist/routing/candidate.js +0 -46
- package/dist/routing/carrier-provider-key.js +0 -27
- package/dist/routing/carriers/omnibridge.js +0 -120
- package/dist/routing/carriers/pulsex-paths.js +0 -57
- package/dist/routing/carriers/pulsex-split.js +0 -92
- package/dist/routing/carriers/pulsex.js +0 -279
- package/dist/routing/carriers/wrap.js +0 -57
- package/dist/routing/composed-route-quality.js +0 -95
- package/dist/routing/entry-chain-anchor.js +0 -27
- package/dist/routing/format.js +0 -50
- package/dist/routing/index.js +0 -28
- package/dist/routing/producers.js +0 -854
- package/dist/routing/providers.js +0 -27
- package/dist/routing/search/compose.js +0 -56
- package/dist/routing/search/graph.js +0 -364
- package/dist/routing/search/plan-route-data.js +0 -508
- package/dist/routing/search/score.js +0 -344
- package/dist/routing/swap-transactions.js +0 -74
- package/dist/routing/usd-value.js +0 -12
- package/dist/settings.js +1 -456
- package/dist/swap-venues.js +0 -17
- package/dist/ton-connect.js +0 -82
- package/dist/ton-execution.js +0 -6
- package/dist/ton.js +0 -42
- package/dist/tron-execution.js +0 -145
- package/package.json +3 -3
package/dist/chains.js
CHANGED
|
@@ -1,99 +1,8 @@
|
|
|
1
|
-
// Relative, not through this package's own name. A self-reference resolves
|
|
2
|
-
// through the `exports` map, which now points at the compiled `dist` — so the
|
|
3
|
-
// same module would be loaded twice, once as source and once as build output,
|
|
4
|
-
// and `Chains.PLS` from one would not be the same object as from the other.
|
|
5
1
|
import { chainDisplayName } from './chain-names.js';
|
|
6
2
|
import { Chains, toChain } from './config.js';
|
|
7
3
|
import * as imageLinks from './image-links.js';
|
|
8
|
-
// Chain definitions come from viem, not from a wallet-connection library. These
|
|
9
|
-
// five objects are identical in `@reown/appkit/networks`, which is where they used
|
|
10
|
-
// to be imported from — but that made a package with no user interface depend on a
|
|
11
|
-
// wallet modal, and it was never declared in `dependencies`, so the root entry
|
|
12
|
-
// point of this package could not be loaded by anyone outside this repository.
|
|
13
4
|
import { bsc, mainnet, pulsechain, pulsechainV4, sepolia } from 'viem/chains';
|
|
14
|
-
/**
|
|
15
|
-
* Builds an endpoint on valve.city, which proxies four of this dapp's chains.
|
|
16
|
-
*
|
|
17
|
-
* DEMO ONLY. These endpoints live in {@link demoRpcUrls}, never in
|
|
18
|
-
* {@link chainsMetadata}. A third party that hands `chainsMetadata` to viem with
|
|
19
|
-
* a bare `http()` gets the public endpoints below, not this shared key. The Gibs
|
|
20
|
-
* interface asks for the demo list by name (`@gibs/bridge-client`'s
|
|
21
|
-
* `clientFromChain`). Any other caller should pass its own clients.
|
|
22
|
-
*
|
|
23
|
-
* The key in this URL is `vk_demo`, and it is MEANT to be here. It is the
|
|
24
|
-
* proxy's published demo key — it is already listed on chainlist.org, so it is
|
|
25
|
-
* public knowledge and shipping it in a browser bundle discloses nothing. The
|
|
26
|
-
* proxy reflects any `Origin` back, which is what makes it usable at all from
|
|
27
|
-
* an IPFS build: the same bundle is served from gib.show, from ipfs.io, from
|
|
28
|
-
* dweb.link, and from a local node, so an origin-locked key would break every
|
|
29
|
-
* gateway but one.
|
|
30
|
-
*
|
|
31
|
-
* NEVER replace this with the unlimited key from 1Password. That one is a
|
|
32
|
-
* bearer credential, this file compiles into the public bundle, and the two
|
|
33
|
-
* facts together would hand an unmetered proxy to every visitor.
|
|
34
|
-
*
|
|
35
|
-
* Only chains 1, 369, 943 and 11155111 are proxied; the service lists them at
|
|
36
|
-
* its root. Binance Smart Chain is not, which is why it keeps a public endpoint
|
|
37
|
-
* alone. Every chain below keeps its previous endpoints after this one, so a
|
|
38
|
-
* valve.city outage falls through to where it used to go rather than breaking.
|
|
39
|
-
*
|
|
40
|
-
* IT LEADS EVERY LIST IT APPEARS IN, and the measurement that says it may is
|
|
41
|
-
* not a burst — it is the shape this interface actually produces.
|
|
42
|
-
*
|
|
43
|
-
* MEASURED 2026-08-29, against the real cadence rather than a synthetic flood:
|
|
44
|
-
*
|
|
45
|
-
* steady, 1 request per 4 seconds for 3 minutes 45 of 45 answered 200
|
|
46
|
-
* bursts, 8 concurrent, four rounds 30 of 32 answered 200
|
|
47
|
-
* 20 requests at concurrency 1, 2, 4, 6 and 8 20 of 20 every time
|
|
48
|
-
* 20 requests at concurrency 12 19 of 20
|
|
49
|
-
*
|
|
50
|
-
* Four seconds is not arbitrary: `watchBlocks` runs on viem's default poll, one
|
|
51
|
-
* per watched chain, and `clientFromChain` coalesces up to 32 JSON-RPC calls
|
|
52
|
-
* made within 10ms into ONE HTTP POST. So the interface's request rate is about
|
|
53
|
-
* a quarter of a request per second per chain, and the key handles four times
|
|
54
|
-
* that without a single refusal.
|
|
55
|
-
*
|
|
56
|
-
* AN EARLIER READING SAID THE OPPOSITE AND WAS MEASURING SOMETHING ELSE. On
|
|
57
|
-
* 2026-08-27 this key answered 429 for four requests in five — from 40 requests
|
|
58
|
-
* at 12 concurrent, fired four times back to back across four chains, roughly
|
|
59
|
-
* 160 requests with no pause. That exhausts a windowed budget. No browser does
|
|
60
|
-
* it. The reading before THAT one was 40 CONSECUTIVE requests, which cannot see
|
|
61
|
-
* a rate limit at all because it paces itself. Both were honest measurements of
|
|
62
|
-
* the wrong thing.
|
|
63
|
-
*
|
|
64
|
-
* THE PROBE STORM WAS THE REAL CULPRIT. `fallback` used to run `rank: true`,
|
|
65
|
-
* which pings every url on every chain every few seconds forever — on an idle
|
|
66
|
-
* page, every outbound request was one of those. That is what spent the key's
|
|
67
|
-
* budget. It is off now (see `packages/common/src/client.ts`), and the
|
|
68
|
-
* demotion that shipped alongside turning it off was treating the symptom.
|
|
69
|
-
*
|
|
70
|
-
* THE SPARE BEHIND IT IS STILL LOAD-BEARING. `vk_demo` is shared — published on
|
|
71
|
-
* chainlist.org — so the budget is not ours alone and the headroom moves with
|
|
72
|
-
* other people's use. About one burst request in sixteen still meets a 429, and
|
|
73
|
-
* a 429 is an HTTP error, so `fallback` moves to the next entry at once. The
|
|
74
|
-
* cost is one wasted round trip on a small fraction of burst requests, not a
|
|
75
|
-
* failed read. Never leave a proxied chain with valve.city alone.
|
|
76
|
-
*
|
|
77
|
-
* @param chainId - the numeric chain id to proxy
|
|
78
|
-
* @returns the fully qualified JSON-RPC endpoint
|
|
79
|
-
*/
|
|
80
5
|
const valveCity = (chainId) => `https://one.valve.city/rpc/vk_demo/evm/${chainId}`;
|
|
81
|
-
/**
|
|
82
|
-
* all of the chains that are enabled in this dapp
|
|
83
|
-
* and their corresponding useful metadata
|
|
84
|
-
*
|
|
85
|
-
* Every entry below sets `name` explicitly to `chainDisplayName(...)` rather
|
|
86
|
-
* than trusting the spread-in viem chain object or typing a string here. Two
|
|
87
|
-
* hand-typed copies of the same name is exactly how chain 943 once read as
|
|
88
|
-
* "PulseChain Testnet V4" in the resolver and "Pulsechain V4" here — one
|
|
89
|
-
* string, two spellings, and only one of them got fixed. Routing every name
|
|
90
|
-
* through `chainDisplayName` leaves nothing to drift a second time.
|
|
91
|
-
*
|
|
92
|
-
* Each `logoURI` is a getter, not a string fixed at import time, so a later
|
|
93
|
-
* `setImageRoot` call (from `image-links.ts`) changes every chain logo. Spread
|
|
94
|
-
* an entry (`{ ...chainsMetadata[chain] }`) and the copy holds the URL as it
|
|
95
|
-
* was at that moment.
|
|
96
|
-
*/
|
|
97
6
|
export const chainsMetadata = {
|
|
98
7
|
[Chains.PLS]: {
|
|
99
8
|
...pulsechain,
|
|
@@ -129,12 +38,6 @@ export const chainsMetadata = {
|
|
|
129
38
|
alt: 'two pyramids joined on one side',
|
|
130
39
|
rpcUrls: {
|
|
131
40
|
default: {
|
|
132
|
-
// TWO PUBLIC ENDPOINTS, and {@link demoRpcUrls} puts valve.city in
|
|
133
|
-
// front of them. Both are needed behind it. On 2026-08-25 g4mm4
|
|
134
|
-
// answered nothing at all for hours, and the list was g4mm4 then
|
|
135
|
-
// valve.city — so every read fell through a dead host onto a key that
|
|
136
|
-
// rejects four requests in five. publicnode measured 40 of 40 on
|
|
137
|
-
// 2026-08-27 and costs nothing to carry.
|
|
138
41
|
http: [
|
|
139
42
|
'https://rpc-ethereum.g4mm4.io',
|
|
140
43
|
'https://ethereum-rpc.publicnode.com',
|
|
@@ -144,9 +47,6 @@ export const chainsMetadata = {
|
|
|
144
47
|
},
|
|
145
48
|
[Chains.BNB]: {
|
|
146
49
|
...bsc,
|
|
147
|
-
// viem's own default is "BNB Smart Chain" — deferring to the resolver
|
|
148
|
-
// keeps this the product's chosen "Binance Smart Chain" without a second
|
|
149
|
-
// hand-typed copy of that decision living here.
|
|
150
50
|
name: chainDisplayName(bsc.id),
|
|
151
51
|
chainId: Chains.BNB,
|
|
152
52
|
get logoURI() {
|
|
@@ -155,11 +55,6 @@ export const chainsMetadata = {
|
|
|
155
55
|
alt: 'a gold cube with slits in the middle of each side',
|
|
156
56
|
rpcUrls: {
|
|
157
57
|
default: {
|
|
158
|
-
// valve.city does not proxy chain 56 — it answers "Unsupported
|
|
159
|
-
// chain" — so this is the one chain with no entry of ours, which
|
|
160
|
-
// makes a second PUBLIC endpoint the only fallback available. A
|
|
161
|
-
// one-entry list is what took Sepolia down outright (see below).
|
|
162
|
-
// Both measured 40 of 40 on 2026-08-27.
|
|
163
58
|
http: ['https://bsc-rpc.publicnode.com', 'https://bsc-dataseed.binance.org'],
|
|
164
59
|
},
|
|
165
60
|
},
|
|
@@ -172,31 +67,8 @@ export const chainsMetadata = {
|
|
|
172
67
|
return imageLinks.network(sepolia.id);
|
|
173
68
|
},
|
|
174
69
|
alt: 'two pyramids joined on one side',
|
|
175
|
-
// FOUR endpoints, not one, and the reason is specific: a public endpoint
|
|
176
|
-
// answers a single curl perfectly well and returns 403 under a browser's
|
|
177
|
-
// load — five times on one page render. A rate limit, not a dead host.
|
|
178
|
-
//
|
|
179
|
-
// The transport wraps this list in viem's `fallback()`, which moves on for
|
|
180
|
-
// an HTTP error, and 403 is one. With a single entry there was nowhere to
|
|
181
|
-
// move to, so the whole testnet side simply failed. All three were checked
|
|
182
|
-
// for a correct chain id AND for an allow-origin header, because answering
|
|
183
|
-
// curl is not the same as being reachable from a page.
|
|
184
70
|
rpcUrls: {
|
|
185
71
|
default: {
|
|
186
|
-
// Ordered deliberately, by the operational rule that the most reliable
|
|
187
|
-
// endpoint goes FIRST.
|
|
188
|
-
//
|
|
189
|
-
// valve.city is not here. It sits in front of these three only in
|
|
190
|
-
// {@link demoRpcUrls}. Being ours does not buy it a budget: the SHARED
|
|
191
|
-
// DEMO KEY answered 429 for 32 of 40 burst requests against Sepolia on
|
|
192
|
-
// 2026-08-27, which is why nothing may depend on it alone.
|
|
193
|
-
//
|
|
194
|
-
// These three keep the order an earlier browser measurement earned
|
|
195
|
-
// them. publicnode stays last of the public three because it is the one
|
|
196
|
-
// observed returning 403 under a browser's load — five times on one
|
|
197
|
-
// page render — which a `curl` burst does not reproduce and therefore
|
|
198
|
-
// cannot overturn. It answers fine when the others are busy, so it is
|
|
199
|
-
// demoted rather than dropped.
|
|
200
72
|
http: [
|
|
201
73
|
'https://sepolia.gateway.tenderly.co',
|
|
202
74
|
'https://1rpc.io/sepolia',
|
|
@@ -215,10 +87,6 @@ export const chainsMetadata = {
|
|
|
215
87
|
alt: 'a pink blue and purple hexagon with an ekg line running horizontally',
|
|
216
88
|
rpcUrls: {
|
|
217
89
|
default: {
|
|
218
|
-
// Two, for the reason Ethereum has two: g4mm4 is a single host that
|
|
219
|
-
// has gone away before, and valve.city ({@link demoRpcUrls}) alone in
|
|
220
|
-
// front of it is not a fallback. The official testnet node measured 40
|
|
221
|
-
// of 40 on 2026-08-27.
|
|
222
90
|
http: [
|
|
223
91
|
'https://rpc-testnet-pulsechain.g4mm4.io',
|
|
224
92
|
'https://rpc.v4.testnet.pulsechain.com',
|
|
@@ -236,22 +104,6 @@ export const chainsMetadata = {
|
|
|
236
104
|
},
|
|
237
105
|
},
|
|
238
106
|
};
|
|
239
|
-
/**
|
|
240
|
-
* The RPC endpoints the Gibs interface uses, FOR DEMOS ONLY.
|
|
241
|
-
*
|
|
242
|
-
* Each proxied chain's list starts with valve.city's shared `vk_demo` key and
|
|
243
|
-
* falls through to that chain's public endpoints in {@link chainsMetadata}.
|
|
244
|
-
* Binance Smart Chain has no valve.city entry, so its list is the public one.
|
|
245
|
-
*
|
|
246
|
-
* WHY IT IS A SEPARATE, NAMED LIST. The key is public, so shipping it discloses
|
|
247
|
-
* nothing. But its rate budget is shared by everybody who uses it, and the proxy
|
|
248
|
-
* belongs to the Gibs Finance operator. A wallet that inherits it without
|
|
249
|
-
* choosing it puts its users' reads on somebody else's budget and uptime. So no
|
|
250
|
-
* reader in this package uses it, and `chainsMetadata` does not carry it. A
|
|
251
|
-
* caller who wants it asks for it by this name.
|
|
252
|
-
*
|
|
253
|
-
* Production callers: pass your own viem clients to every reader.
|
|
254
|
-
*/
|
|
255
107
|
export const demoRpcUrls = Object.freeze({
|
|
256
108
|
[Chains.PLS]: [valveCity(pulsechain.id), ...chainsMetadata[Chains.PLS].rpcUrls.default.http],
|
|
257
109
|
[Chains.ETH]: [valveCity(mainnet.id), ...chainsMetadata[Chains.ETH].rpcUrls.default.http],
|
|
@@ -259,61 +111,11 @@ export const demoRpcUrls = Object.freeze({
|
|
|
259
111
|
[Chains.SEP]: [valveCity(sepolia.id), ...chainsMetadata[Chains.SEP].rpcUrls.default.http],
|
|
260
112
|
[Chains.V4PLS]: [valveCity(pulsechainV4.id), ...chainsMetadata[Chains.V4PLS].rpcUrls.default.http],
|
|
261
113
|
});
|
|
262
|
-
/**
|
|
263
|
-
* The demo endpoints for one chain, FOR DEMOS ONLY. See {@link demoRpcUrls}.
|
|
264
|
-
*
|
|
265
|
-
* @param chainId - a decimal chain id
|
|
266
|
-
* @returns a copy of the chain's demo endpoints, or an empty list for a chain the bridge does not cross
|
|
267
|
-
*/
|
|
268
114
|
export const demoRpcUrlsFor = (chainId) => [
|
|
269
115
|
...(demoRpcUrls[toChain(chainId)] ?? []),
|
|
270
116
|
];
|
|
271
|
-
/**
|
|
272
|
-
* Every chain this bridge itself carries funds across, in the order the
|
|
273
|
-
* metadata declares them.
|
|
274
|
-
*
|
|
275
|
-
* Read from {@link chainsMetadata} rather than typed out, for the reason the
|
|
276
|
-
* whole table above gives: a second hand-written list is how one chain ends up
|
|
277
|
-
* present in one place and missing from another. A control that offers the
|
|
278
|
-
* reader a network to add or remove reads this, so a chain added to the
|
|
279
|
-
* metadata appears in that control without anybody remembering to add it.
|
|
280
|
-
*
|
|
281
|
-
* This is NOT every chain a route can traverse. An aggregator reaches dozens
|
|
282
|
-
* more, and `chain-names.ts` can name them. These five are the ones the
|
|
283
|
-
* transfers archive holds records for.
|
|
284
|
-
*/
|
|
285
117
|
export const bridgeNetworkChainIds = Object.values(chainsMetadata).map((metadata) => Number(metadata.id));
|
|
286
|
-
/**
|
|
287
|
-
* The chain identifiers this product treats as TEST networks.
|
|
288
|
-
*
|
|
289
|
-
* THE FLAG IS VIEM'S AND IT IS CHECKED FOR `true`, NOT FOR TRUTHINESS. Each
|
|
290
|
-
* entry above spreads a viem chain definition, and viem sets `testnet: true` on
|
|
291
|
-
* Sepolia and on PulseChain Testnet V4, `testnet: false` on PulseChain, and
|
|
292
|
-
* omits the key entirely on Ethereum and on Binance Smart Chain. So the value
|
|
293
|
-
* has three states, and only one of them is a claim. Testing for `=== true`
|
|
294
|
-
* means a chain whose definition says nothing is treated as a real network —
|
|
295
|
-
* which is the safe direction, because the cost of failing to hide a test
|
|
296
|
-
* network is an extra row and the cost of hiding a real one is a reader who
|
|
297
|
-
* cannot find their money.
|
|
298
|
-
*
|
|
299
|
-
* WHY NOT DERIVE IT FROM THE BRIDGE KEYS. `validBridgeKeys(isProd)` in
|
|
300
|
-
* `config.ts` splits the same five chains into a mainnet set and a testnet set,
|
|
301
|
-
* and subtracting one from the other would give the same two identifiers today.
|
|
302
|
-
* It would also give the wrong answer the moment a real chain gains a pathway
|
|
303
|
-
* that is still behind the testnet switch — the key list records what is
|
|
304
|
-
* ENABLED, and this records what a chain IS. Two different questions.
|
|
305
|
-
*
|
|
306
|
-
* `buildFullChainIdSet` in the interface already gates the pickers on the same
|
|
307
|
-
* flag, and `tokenLists.ts` gates the synthesized native assets on it. This is
|
|
308
|
-
* that decision written down once so a third reader does not restate it.
|
|
309
|
-
*/
|
|
310
118
|
export const testNetworkChainIds = new Set(Object.values(chainsMetadata)
|
|
311
119
|
.filter((metadata) => metadata.testnet === true)
|
|
312
120
|
.map((metadata) => Number(metadata.id)));
|
|
313
|
-
/**
|
|
314
|
-
* Whether one chain is a test network.
|
|
315
|
-
*
|
|
316
|
-
* @param chainId - a decimal chain id
|
|
317
|
-
* @returns true only when the chain's own definition claims it is a test network
|
|
318
|
-
*/
|
|
319
121
|
export const isTestNetwork = (chainId) => testNetworkChainIds.has(chainId);
|
package/dist/cjs/abis.js
CHANGED
|
@@ -14,6 +14,4 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
// All ABIs have moved to the standalone @gibs/abis package.
|
|
18
|
-
// This module re-exports everything for backwards compatibility.
|
|
19
17
|
__exportStar(require("@gibs/abis"), exports);
|
|
@@ -2,27 +2,10 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.checkEntryAmount = exports.bridgeEntryLimits = exports.entryLimitsAbi = void 0;
|
|
4
4
|
const viem_1 = require("viem");
|
|
5
|
-
/**
|
|
6
|
-
* Exported so a batched reader (`routing/carriers/omnibridge.ts`'s `prepare`)
|
|
7
|
-
* can multicall the same two functions across many tokens in one call rather
|
|
8
|
-
* than duplicating this ABI.
|
|
9
|
-
*/
|
|
10
5
|
exports.entryLimitsAbi = (0, viem_1.parseAbi)([
|
|
11
6
|
'function minPerTx(address token) external view returns(uint256)',
|
|
12
7
|
'function maxAvailablePerTx(address token) external view returns(uint256)',
|
|
13
8
|
]);
|
|
14
|
-
/**
|
|
15
|
-
* Reads the bounds the entry mediator will enforce on this exact call.
|
|
16
|
-
*
|
|
17
|
-
* IT TAKES THE CALL, NOT A MEDIATOR AND A TOKEN. The two travel together on the
|
|
18
|
-
* destination call precisely so a caller cannot pair one route's mediator with
|
|
19
|
-
* another route's token and get a plausible number back — the reads would
|
|
20
|
-
* succeed and the answer would be about a transfer nobody is making.
|
|
21
|
-
*
|
|
22
|
-
* @param destinationCall - the entry call, or null when none could be built
|
|
23
|
-
* @param entryChainClient - a client on the chain the funds leave
|
|
24
|
-
* @returns the two bounds, or null when there is no call to measure
|
|
25
|
-
*/
|
|
26
9
|
const bridgeEntryLimits = async ({ destinationCall, entryChainClient, }) => {
|
|
27
10
|
if (!destinationCall) {
|
|
28
11
|
return null;
|
|
@@ -45,28 +28,7 @@ const bridgeEntryLimits = async ({ destinationCall, entryChainClient, }) => {
|
|
|
45
28
|
return { minimumPerTransaction, availablePerTransaction };
|
|
46
29
|
};
|
|
47
30
|
exports.bridgeEntryLimits = bridgeEntryLimits;
|
|
48
|
-
/**
|
|
49
|
-
* Decides whether an amount can enter the bridge.
|
|
50
|
-
*
|
|
51
|
-
* WHY THIS IS WORTH CHECKING BEFORE A ROUTE IS OFFERED: on a consolidated
|
|
52
|
-
* route the entry call is made by an aggregator's executor, not by the user.
|
|
53
|
-
* When the mediator rejects the amount the executor's call reverts, the
|
|
54
|
-
* aggregator has already delivered the funds, and they stop at the fallback
|
|
55
|
-
* address on the entry chain. The user is left holding an entry-chain token
|
|
56
|
-
* and a second transfer to make. Refusing the quote costs them nothing.
|
|
57
|
-
*
|
|
58
|
-
* The bounds are inclusive: the mediator accepts an amount equal to either.
|
|
59
|
-
*
|
|
60
|
-
* @param amount - the transfer, in the token's base units
|
|
61
|
-
* @param limits - the bounds from {@link bridgeEntryLimits}, or null when they
|
|
62
|
-
* could not be read
|
|
63
|
-
* @returns a verdict naming the bound that was missed
|
|
64
|
-
*/
|
|
65
31
|
const checkEntryAmount = ({ amount, limits, }) => {
|
|
66
|
-
// An unread limit is not a failed one. A network hiccup must not block a
|
|
67
|
-
// route that the mediator would accept — the transaction still gets the
|
|
68
|
-
// mediator's own answer, and this guard exists to save the user a wasted
|
|
69
|
-
// crossing, not to be the only thing standing between them and a revert.
|
|
70
32
|
if (!limits) {
|
|
71
33
|
return { fits: true };
|
|
72
34
|
}
|
package/dist/cjs/chain-info.js
CHANGED
|
@@ -40,34 +40,8 @@ const viem_1 = require("viem");
|
|
|
40
40
|
const abis = __importStar(require("./abis.js"));
|
|
41
41
|
const chains_js_1 = require("./chains.js");
|
|
42
42
|
const config_js_1 = require("./config.js");
|
|
43
|
-
/** Cache key for the links memoize: one entry per (chain, bridge, token) triple. */
|
|
44
43
|
const linksCacheKey = ({ chainId, target, address, }) => `${chainId}-${target}-${address}`.toLowerCase();
|
|
45
|
-
/**
|
|
46
|
-
* Whether a {@link links} answer says the token has no mapping on this bridge
|
|
47
|
-
* yet. That answer is temporary: the first transfer of the token creates the
|
|
48
|
-
* mapping, so it must not be cached.
|
|
49
|
-
* @param pair - the bridged and native addresses the mediator returned
|
|
50
|
-
* @returns true when both are the zero address
|
|
51
|
-
*/
|
|
52
44
|
const isUnmappedAnswer = ([bridged, native]) => bridged === viem_1.zeroAddress && native === viem_1.zeroAddress;
|
|
53
|
-
/**
|
|
54
|
-
* Returns the bridged token address and native token address that a mediator
|
|
55
|
-
* holds for one token.
|
|
56
|
-
*
|
|
57
|
-
* A non-zero answer is cached for the life of the process: a mediator never
|
|
58
|
-
* changes a mapping once the first transfer creates it. A failed read, and a
|
|
59
|
-
* `[zero, zero]` answer (the token is not bridged yet), are not cached, so the
|
|
60
|
-
* next call reads the chain again. Call {@link clearChainInfoCaches} to drop
|
|
61
|
-
* every cached answer.
|
|
62
|
-
*
|
|
63
|
-
* @param inputs.chainId - the chain id being targeted
|
|
64
|
-
* @param inputs.target - the mediator to ask
|
|
65
|
-
* @param inputs.address - the token address
|
|
66
|
-
* @param inputs.client - a client for that chain
|
|
67
|
-
* @returns the bridged token address and native token address
|
|
68
|
-
*/
|
|
69
|
-
// The body reaches for `links.cache` to evict an answer, so the cache surface
|
|
70
|
-
// is spelled out to the extent this file uses it.
|
|
71
45
|
exports.links = (0, cache_1.memoizeByKey)(async (inputs) => {
|
|
72
46
|
const { chainId, target, address, client } = inputs;
|
|
73
47
|
const evict = () => exports.links.cache.delete(linksCacheKey(inputs));
|
|
@@ -81,35 +55,18 @@ exports.links = (0, cache_1.memoizeByKey)(async (inputs) => {
|
|
|
81
55
|
{ functionName: 'nativeTokenAddress', args: [address] },
|
|
82
56
|
],
|
|
83
57
|
}).catch((error) => {
|
|
84
|
-
// a transient read failure must not poison the cache for the session
|
|
85
58
|
evict();
|
|
86
59
|
throw error;
|
|
87
60
|
});
|
|
88
61
|
if (isUnmappedAnswer(pair)) {
|
|
89
|
-
// the token may be bridged a minute from now; ask again next time
|
|
90
62
|
evict();
|
|
91
63
|
}
|
|
92
64
|
return pair;
|
|
93
65
|
}, linksCacheKey);
|
|
94
|
-
/**
|
|
95
|
-
* Drops every answer this module has cached, so the next read goes to the chain.
|
|
96
|
-
*
|
|
97
|
-
* Use it after a token's first transfer, in a long-running process that wants
|
|
98
|
-
* a fresh view, or between tests.
|
|
99
|
-
*/
|
|
100
66
|
const clearChainInfoCaches = () => {
|
|
101
67
|
exports.links.cache.clear();
|
|
102
68
|
};
|
|
103
69
|
exports.clearChainInfoCaches = clearChainInfoCaches;
|
|
104
|
-
/**
|
|
105
|
-
* Returns the token bridge info for the given bridge key, asset in, is prod, from chain client, and to chain client
|
|
106
|
-
* @param bridgeKey - the bridge key
|
|
107
|
-
* @param assetIn - the asset in
|
|
108
|
-
* @param isProd - whether to use the production pathway
|
|
109
|
-
* @param fromChainClient - the from chain client
|
|
110
|
-
* @param toChainClient - the to chain client
|
|
111
|
-
* @returns the token bridge info
|
|
112
|
-
*/
|
|
113
70
|
const tokenBridgeInfo = async ({ bridgeKey, assetIn, isProd, fromChainClient, toChainClient, }) => {
|
|
114
71
|
const bridgePathway = (0, config_js_1.pathway)(bridgeKey, isProd, assetIn?.address);
|
|
115
72
|
if (!assetIn || !bridgePathway) {
|
|
@@ -177,7 +134,6 @@ const tokenBridgeInfo = async ({ bridgeKey, assetIn, isProd, fromChainClient, to
|
|
|
177
134
|
},
|
|
178
135
|
};
|
|
179
136
|
}
|
|
180
|
-
// the token has not been bridged yet
|
|
181
137
|
return {
|
|
182
138
|
originationChainId: toChain,
|
|
183
139
|
assetInAddress: assetInAddress,
|
|
@@ -198,23 +154,11 @@ const tokenBridgeInfo = async ({ bridgeKey, assetIn, isProd, fromChainClient, to
|
|
|
198
154
|
};
|
|
199
155
|
};
|
|
200
156
|
exports.tokenBridgeInfo = tokenBridgeInfo;
|
|
201
|
-
/**
|
|
202
|
-
* Check the prices that each router offers for the given paths
|
|
203
|
-
* @param assetInAddress the address of the asset going into the bridge
|
|
204
|
-
* @param oneTokenInt the number of tokens to push into the bridge (before fees)
|
|
205
|
-
* @param chain the chain of the asset going into the bridge
|
|
206
|
-
* @param bridgeKey the bridge key
|
|
207
|
-
* @param blockNumber the block number to use for the price
|
|
208
|
-
* @param paths the paths to check
|
|
209
|
-
* @returns the prices as bigint for each path, hex whenever the price is not available
|
|
210
|
-
*/
|
|
211
157
|
const readAmountOut = ({ amountIn, chain, paths, client, uniV2Router, }) => {
|
|
212
158
|
return (0, multicall_1.multicallRead)({
|
|
213
159
|
chain: chains_js_1.chainsMetadata[chain],
|
|
214
160
|
client,
|
|
215
161
|
abi: abis.univ2Router,
|
|
216
|
-
// pulsex router
|
|
217
|
-
// a chain with no router reads nothing, as lodash's flatMap over undefined did
|
|
218
162
|
calls: (uniV2Router ? [uniV2Router] : (config_js_1.uniV2Routers[chain] ?? [])).flatMap((target) => paths.map((path) => ({
|
|
219
163
|
functionName: 'getAmountsOut',
|
|
220
164
|
allowFailure: true,
|
|
@@ -223,22 +167,9 @@ const readAmountOut = ({ amountIn, chain, paths, client, uniV2Router, }) => {
|
|
|
223
167
|
}))),
|
|
224
168
|
});
|
|
225
169
|
};
|
|
226
|
-
/**
|
|
227
|
-
* Fetch the price corrective for the given bridge key, asset out, measurement token, from chain client, to chain client, asset link, amount in, and is prod
|
|
228
|
-
* @param bridgeKeyPartner - the bridge key partner
|
|
229
|
-
* @param assetOut - the asset out
|
|
230
|
-
* @param measurementToken - the measurement token
|
|
231
|
-
* @param fromChainClient - the from chain client
|
|
232
|
-
* @param toChainClient - the to chain client
|
|
233
|
-
* @param assetLink - the asset link
|
|
234
|
-
* @param amountIn - the amount in
|
|
235
|
-
* @param isProd - whether to use the production pathway
|
|
236
|
-
* @returns the price corrective
|
|
237
|
-
*/
|
|
238
170
|
const fetchPriceCorrective = ({ bridgeKeyPartner, assetOut, measurementToken, fromChainClient, toChainClient, assetLink, amountIn, isProd, }) => {
|
|
239
171
|
return {
|
|
240
172
|
getPaymentToken: async () => {
|
|
241
|
-
// fetch the token bridge info for the token that is about to be spent by the delivery service
|
|
242
173
|
return await (0, exports.tokenBridgeInfo)({
|
|
243
174
|
bridgeKey: bridgeKeyPartner,
|
|
244
175
|
assetIn: {
|
|
@@ -246,8 +177,6 @@ const fetchPriceCorrective = ({ bridgeKeyPartner, assetOut, measurementToken, fr
|
|
|
246
177
|
address: measurementToken,
|
|
247
178
|
},
|
|
248
179
|
isProd,
|
|
249
|
-
// clients are reversed here because we are actually fetching the
|
|
250
|
-
// tokens going the opposite direction to the provided bridge key
|
|
251
180
|
fromChainClient: toChainClient,
|
|
252
181
|
toChainClient: fromChainClient,
|
|
253
182
|
});
|
|
@@ -260,9 +189,7 @@ const fetchPriceCorrective = ({ bridgeKeyPartner, assetOut, measurementToken, fr
|
|
|
260
189
|
uniV2Router,
|
|
261
190
|
client,
|
|
262
191
|
paths: [
|
|
263
|
-
// check the direct route
|
|
264
192
|
[assetLink.assetInAddress, paymentTokenResult.assetOutAddress],
|
|
265
|
-
// might have heavier liquidity going through the native asset on the home side
|
|
266
193
|
[assetLink.assetInAddress, config_js_1.nativeAssetOut[chain], paymentTokenResult.assetOutAddress],
|
|
267
194
|
],
|
|
268
195
|
}),
|
|
@@ -272,22 +199,17 @@ const fetchPriceCorrective = ({ bridgeKeyPartner, assetOut, measurementToken, fr
|
|
|
272
199
|
uniV2Router,
|
|
273
200
|
client,
|
|
274
201
|
paths: [[assetOut.address, measurementToken]],
|
|
275
|
-
// only the direct route is available.
|
|
276
|
-
// might be able to create a whitelist for this at some point
|
|
277
202
|
}),
|
|
278
203
|
]);
|
|
279
204
|
},
|
|
280
205
|
reduceResults: ({ results, oneToken, }) => {
|
|
281
206
|
const outputFromRouter = (result) => {
|
|
282
207
|
if (typeof result === 'string') {
|
|
283
|
-
// the router failed to return a result
|
|
284
208
|
return 0n;
|
|
285
209
|
}
|
|
286
210
|
if (!result.length) {
|
|
287
|
-
// the router returned an empty result
|
|
288
211
|
return 0n;
|
|
289
212
|
}
|
|
290
|
-
// the last element is the amount of the output token
|
|
291
213
|
const last = result[result.length - 1];
|
|
292
214
|
return (last * oneToken) / amountIn;
|
|
293
215
|
};
|
|
@@ -296,7 +218,6 @@ const fetchPriceCorrective = ({ bridgeKeyPartner, assetOut, measurementToken, fr
|
|
|
296
218
|
.filter((amount) => amount !== undefined)
|
|
297
219
|
.reduce((max, current) => (max < current ? current : max), 0n);
|
|
298
220
|
};
|
|
299
|
-
// could do with a refactor to unify the results
|
|
300
221
|
const [outputs, inputs] = results;
|
|
301
222
|
const outputAmounts = outputs.map(outputFromRouter);
|
|
302
223
|
const inputAmounts = inputs.map(outputFromRouter);
|
|
@@ -312,29 +233,6 @@ const fetchPriceCorrective = ({ bridgeKeyPartner, assetOut, measurementToken, fr
|
|
|
312
233
|
};
|
|
313
234
|
};
|
|
314
235
|
exports.fetchPriceCorrective = fetchPriceCorrective;
|
|
315
|
-
/**
|
|
316
|
-
* Read the smallest amount the bridge will accept for this asset on this pathway.
|
|
317
|
-
*
|
|
318
|
-
* THE ENTRY MEDIATOR DECIDES, so this always reads `pathway.from` on the chain
|
|
319
|
-
* the funds leave. `feeManager` says which side prices the transfer; it has
|
|
320
|
-
* never said which side validates the amount, and using it for both is what
|
|
321
|
-
* produced the defect this replaces.
|
|
322
|
-
*
|
|
323
|
-
* Both mediators keep a `minPerTx` under the same name, and for a token that
|
|
324
|
-
* originates on the entry chain the two sides usually hold the same number. That
|
|
325
|
-
* agreement is a coincidence of configuration - each side is separately
|
|
326
|
-
* governed, and both happen to apply one blanket default. It breaks outright for
|
|
327
|
-
* a token that originates on the far side, because the two mediators key their
|
|
328
|
-
* limits by different addresses. Wrapped Pulse entering from Ethereum is the
|
|
329
|
-
* live case: the entry mediator enforces 50,000, and the destination mediator
|
|
330
|
-
* answers 0 for that same address because it files that token under its
|
|
331
|
-
* PulseChain address instead. Reading the destination got both the chain and the
|
|
332
|
-
* token key wrong, and reported no floor where a real one stood.
|
|
333
|
-
* @param assetIn - the asset the sender holds, on the chain it leaves from
|
|
334
|
-
* @param pathway - the pathway, with any per-asset overrides already applied
|
|
335
|
-
* @param fromPublicClient - a client for the chain the funds leave
|
|
336
|
-
* @returns the smallest amount the entry mediator will accept
|
|
337
|
-
*/
|
|
338
236
|
const minBridgeAmountIn = async ({ assetIn, pathway, fromPublicClient, }) => fromPublicClient.readContract({
|
|
339
237
|
abi: abis.inputBridge,
|
|
340
238
|
functionName: 'minPerTx',
|
|
@@ -342,7 +240,6 @@ const minBridgeAmountIn = async ({ assetIn, pathway, fromPublicClient, }) => fro
|
|
|
342
240
|
address: pathway.from,
|
|
343
241
|
});
|
|
344
242
|
exports.minBridgeAmountIn = minBridgeAmountIn;
|
|
345
|
-
/** get the symbol of the native asset, unwrap it if it needs to be */
|
|
346
243
|
const nativeSymbol = (asset, unwrap = false) => {
|
|
347
244
|
return asset
|
|
348
245
|
? unwrap && asset.address === config_js_1.nativeAssetOut[(0, config_js_1.toChain)(asset.chainId)]
|
|
@@ -351,12 +248,6 @@ const nativeSymbol = (asset, unwrap = false) => {
|
|
|
351
248
|
: '';
|
|
352
249
|
};
|
|
353
250
|
exports.nativeSymbol = nativeSymbol;
|
|
354
|
-
/**
|
|
355
|
-
* Returns the Multicall3 contract for the client's chain.
|
|
356
|
-
* @param client - a client whose `chain` is one of {@link chainsMetadata}'s chains
|
|
357
|
-
* @returns the Multicall3 contract instance
|
|
358
|
-
* @throws when the client carries no chain, or the chain has no Multicall3 address
|
|
359
|
-
*/
|
|
360
251
|
const chainMulticall = (client) => {
|
|
361
252
|
const chainId = client.chain?.id;
|
|
362
253
|
if (chainId === undefined) {
|
|
@@ -369,13 +260,6 @@ const chainMulticall = (client) => {
|
|
|
369
260
|
return (0, viem_1.getContract)({ abi: viem_1.multicall3Abi, client, address });
|
|
370
261
|
};
|
|
371
262
|
exports.chainMulticall = chainMulticall;
|
|
372
|
-
/**
|
|
373
|
-
* Load the bridge fees for the given pathway, from chain client, and to chain client
|
|
374
|
-
* @param pathway - the pathway
|
|
375
|
-
* @param fromChainClient - the from chain client
|
|
376
|
-
* @param toChainClient - the to chain client
|
|
377
|
-
* @returns the bridge fees
|
|
378
|
-
*/
|
|
379
263
|
const loadBridgeFees = async ({ pathway, fromChainClient, toChainClient, }) => {
|
|
380
264
|
const multicall = pathway.feeManager === 'from' ? (0, exports.chainMulticall)(fromChainClient) : (0, exports.chainMulticall)(toChainClient);
|
|
381
265
|
const [feeManagerResponse] = await multicall.read.aggregate3([
|