@gibs/bridge-client 1.12.0 → 1.13.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/LICENSE +15 -0
- package/README.md +53 -0
- package/dist/chain-table.d.ts +18 -0
- package/dist/chain-table.js +89 -0
- package/dist/client.d.ts +12 -6
- package/dist/client.js +33 -6
- package/dist/endpoints.d.ts +7 -1
- package/dist/endpoints.js +47 -3
- package/dist/image.d.ts +41 -19
- package/dist/image.js +117 -44
- package/dist/networks.js +51 -44
- package/dist/token-metadata.js +34 -12
- package/package.json +43 -16
package/LICENSE
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
ISC License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Gibs Finance
|
|
4
|
+
|
|
5
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
6
|
+
purpose with or without fee is hereby granted, provided that the above
|
|
7
|
+
copyright notice and this permission notice appear in all copies.
|
|
8
|
+
|
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
10
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
11
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
12
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
13
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
14
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
15
|
+
PERFORMANCE OF THIS SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# @gibs/bridge-client
|
|
2
|
+
|
|
3
|
+
Browser-side endpoints, public clients, and caching for a Gibs Finance bridge interface. It has no framework dependency.
|
|
4
|
+
|
|
5
|
+
It sits between `@gibs/bridge-sdk`, which prices and builds transfers but does no input or output, and an application that renders them.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
npm install @gibs/bridge-client viem
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
`viem` is a peer dependency. The supported range is `>=2.37.0 <3`.
|
|
14
|
+
|
|
15
|
+
## Requirements
|
|
16
|
+
|
|
17
|
+
- Node 20 or later, or a modern browser.
|
|
18
|
+
- The package is ESM only. Use `import`, not `require`.
|
|
19
|
+
- `@gibs/bridge-sdk` is a dependency, and it reaches TON code. A browser bundle needs a global `Buffer`. Install the `buffer` package and set `globalThis.Buffer` before you import this package. Node has it already.
|
|
20
|
+
|
|
21
|
+
## Example
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
import { clientFromChain } from '@gibs/bridge-client/client'
|
|
25
|
+
import { chainLogoUrl } from '@gibs/bridge-client/image'
|
|
26
|
+
import { isSupportedEvmChain } from '@gibs/bridge-client/networks'
|
|
27
|
+
|
|
28
|
+
const pulsechain = 369
|
|
29
|
+
|
|
30
|
+
if (isSupportedEvmChain(pulsechain)) {
|
|
31
|
+
const client = clientFromChain(pulsechain)
|
|
32
|
+
const blockNumber = await client.getBlockNumber()
|
|
33
|
+
console.log(blockNumber, chainLogoUrl({ chainId: pulsechain, displayPx: 32 }))
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Subpath exports
|
|
38
|
+
|
|
39
|
+
Import from a subpath so that your bundler loads only what you use.
|
|
40
|
+
|
|
41
|
+
| Subpath | Purpose |
|
|
42
|
+
| --- | --- |
|
|
43
|
+
| `@gibs/bridge-client/client` | `clientFromChain`, a cached viem public client per chain |
|
|
44
|
+
| `@gibs/bridge-client/endpoints` | Per-chain RPC endpoint lists, with storage and subscription |
|
|
45
|
+
| `@gibs/bridge-client/networks` | The supported viem chains |
|
|
46
|
+
| `@gibs/bridge-client/image` | Chain logo urls |
|
|
47
|
+
| `@gibs/bridge-client/token-metadata` | Token metadata reads and caching |
|
|
48
|
+
| `@gibs/bridge-client/chain-read` | Allowance reads |
|
|
49
|
+
| `@gibs/bridge-client/cache` | The `Cache` class |
|
|
50
|
+
|
|
51
|
+
## License
|
|
52
|
+
|
|
53
|
+
ISC
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/** One chain, carrying only what this application reads. */
|
|
2
|
+
export type ChainTableEntry = {
|
|
3
|
+
readonly id: number;
|
|
4
|
+
readonly name: string;
|
|
5
|
+
readonly nativeCurrency: {
|
|
6
|
+
readonly name: string;
|
|
7
|
+
readonly symbol: string;
|
|
8
|
+
readonly decimals: number;
|
|
9
|
+
};
|
|
10
|
+
readonly http: readonly string[];
|
|
11
|
+
readonly explorer: string | null;
|
|
12
|
+
/** Whether this is a test network, which a production build must not offer. */
|
|
13
|
+
readonly isTestnet: boolean;
|
|
14
|
+
/** The chain's Multicall3 deployment, or null where it has none. */
|
|
15
|
+
readonly multicall3: string | null;
|
|
16
|
+
};
|
|
17
|
+
/** Every supported chain, the bridge's own first. */
|
|
18
|
+
export declare const chainTable: readonly ChainTableEntry[];
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
// GENERATED by scripts/generate-chain-table.mjs — do not edit by hand.
|
|
2
|
+
//
|
|
3
|
+
// The Ethereum Virtual Machine chains LI.FI or Relay will quote, plus the
|
|
4
|
+
// bridge's own, with the fields a public client needs. Regenerate when either
|
|
5
|
+
// service adds a chain; the generator's own doc comment explains why this is a
|
|
6
|
+
// table rather than viem imports.
|
|
7
|
+
//
|
|
8
|
+
// Chains those services list that viem does not ship, and which are therefore
|
|
9
|
+
// absent here: 1672, 4663, 5042, 42018, 69000, 97477, 685689, 3586256, 5064014.
|
|
10
|
+
// They have no endpoint to seed from, so naming them would produce a chain the
|
|
11
|
+
// picker offers and no read can reach.
|
|
12
|
+
/** Every supported chain, the bridge's own first. */
|
|
13
|
+
export const chainTable = [
|
|
14
|
+
{ id: 1, name: "Ethereum", nativeCurrency: { "name": "Ether", "symbol": "ETH", "decimals": 18 }, http: ["https://eth.merkle.io"], explorer: "https://etherscan.io", isTestnet: false, multicall3: "0xca11bde05977b3631167028862be2a173976ca11" },
|
|
15
|
+
{ id: 369, name: "PulseChain", nativeCurrency: { "name": "Pulse", "symbol": "PLS", "decimals": 18 }, http: ["https://rpc.pulsechain.com"], explorer: "https://ipfs.scan.pulsechain.com", isTestnet: false, multicall3: "0xca11bde05977b3631167028862be2a173976ca11" },
|
|
16
|
+
{ id: 11155111, name: "Sepolia", nativeCurrency: { "name": "Sepolia Ether", "symbol": "ETH", "decimals": 18 }, http: ["https://11155111.rpc.thirdweb.com"], explorer: "https://sepolia.etherscan.io", isTestnet: true, multicall3: "0xca11bde05977b3631167028862be2a173976ca11" },
|
|
17
|
+
{ id: 943, name: "PulseChain V4", nativeCurrency: { "name": "V4 Pulse", "symbol": "v4PLS", "decimals": 18 }, http: ["https://rpc.v4.testnet.pulsechain.com"], explorer: "https://scan.v4.testnet.pulsechain.com", isTestnet: true, multicall3: "0xca11bde05977b3631167028862be2a173976ca11" },
|
|
18
|
+
{ id: 56, name: "BNB Smart Chain", nativeCurrency: { "decimals": 18, "name": "BNB", "symbol": "BNB" }, http: ["https://56.rpc.thirdweb.com"], explorer: "https://bscscan.com", isTestnet: false, multicall3: "0xca11bde05977b3631167028862be2a173976ca11" },
|
|
19
|
+
{ id: 42161, name: "Arbitrum One", nativeCurrency: { "name": "Ether", "symbol": "ETH", "decimals": 18 }, http: ["https://arb1.arbitrum.io/rpc"], explorer: "https://arbiscan.io", isTestnet: false, multicall3: "0xca11bde05977b3631167028862be2a173976ca11" },
|
|
20
|
+
{ id: 8453, name: "Base", nativeCurrency: { "name": "Ether", "symbol": "ETH", "decimals": 18 }, http: ["https://mainnet-preconf.base.org"], explorer: "https://basescan.org", isTestnet: false, multicall3: "0xca11bde05977b3631167028862be2a173976ca11" },
|
|
21
|
+
{ id: 81457, name: "Blast", nativeCurrency: { "decimals": 18, "name": "Ether", "symbol": "ETH" }, http: ["https://rpc.blast.io"], explorer: "https://blastscan.io", isTestnet: false, multicall3: "0xcA11bde05977b3631167028862bE2a173976CA11" },
|
|
22
|
+
{ id: 43114, name: "Avalanche", nativeCurrency: { "decimals": 18, "name": "Avalanche", "symbol": "AVAX" }, http: ["https://api.avax.network/ext/bc/C/rpc"], explorer: "https://snowtrace.io", isTestnet: false, multicall3: "0xca11bde05977b3631167028862be2a173976ca11" },
|
|
23
|
+
{ id: 137, name: "Polygon", nativeCurrency: { "name": "POL", "symbol": "POL", "decimals": 18 }, http: ["https://polygon.drpc.org"], explorer: "https://polygonscan.com", isTestnet: false, multicall3: "0xca11bde05977b3631167028862be2a173976ca11" },
|
|
24
|
+
{ id: 534352, name: "Scroll", nativeCurrency: { "name": "Ether", "symbol": "ETH", "decimals": 18 }, http: ["https://rpc.scroll.io"], explorer: "https://scrollscan.com", isTestnet: false, multicall3: "0xca11bde05977b3631167028862be2a173976ca11" },
|
|
25
|
+
{ id: 10, name: "OP Mainnet", nativeCurrency: { "name": "Ether", "symbol": "ETH", "decimals": 18 }, http: ["https://mainnet.optimism.io"], explorer: "https://optimistic.etherscan.io", isTestnet: false, multicall3: "0xca11bde05977b3631167028862be2a173976ca11" },
|
|
26
|
+
{ id: 59144, name: "Linea Mainnet", nativeCurrency: { "name": "Linea Ether", "symbol": "ETH", "decimals": 18 }, http: ["https://rpc.linea.build"], explorer: "https://lineascan.build", isTestnet: false, multicall3: "0xcA11bde05977b3631167028862bE2a173976CA11" },
|
|
27
|
+
{ id: 324, name: "ZKsync Era", nativeCurrency: { "decimals": 18, "name": "Ether", "symbol": "ETH" }, http: ["https://mainnet.era.zksync.io"], explorer: "https://explorer.zksync.io/", isTestnet: false, multicall3: "0xF9cda624FBC7e059355ce98a31693d299FACd963" },
|
|
28
|
+
{ id: 100, name: "Gnosis", nativeCurrency: { "decimals": 18, "name": "xDAI", "symbol": "XDAI" }, http: ["https://rpc.gnosischain.com"], explorer: "https://gnosisscan.io", isTestnet: false, multicall3: "0xca11bde05977b3631167028862be2a173976ca11" },
|
|
29
|
+
{ id: 122, name: "Fuse", nativeCurrency: { "name": "Fuse", "symbol": "FUSE", "decimals": 18 }, http: ["https://rpc.fuse.io"], explorer: "https://explorer.fuse.io", isTestnet: false, multicall3: "0xca11bde05977b3631167028862be2a173976ca11" },
|
|
30
|
+
{ id: 288, name: "Boba Network", nativeCurrency: { "decimals": 18, "name": "Ether", "symbol": "ETH" }, http: ["https://mainnet.boba.network"], explorer: "https://bobascan.com", isTestnet: false, multicall3: "0xca11bde05977b3631167028862be2a173976ca11" },
|
|
31
|
+
{ id: 130, name: "Unichain", nativeCurrency: { "name": "Ether", "symbol": "ETH", "decimals": 18 }, http: ["https://mainnet.unichain.org/"], explorer: "https://uniscan.xyz", isTestnet: false, multicall3: "0xca11bde05977b3631167028862be2a173976ca11" },
|
|
32
|
+
{ id: 1329, name: "Sei Network", nativeCurrency: { "name": "Sei", "symbol": "SEI", "decimals": 18 }, http: ["https://evm-rpc.sei-apis.com/"], explorer: "https://seiscan.io", isTestnet: false, multicall3: "0xcA11bde05977b3631167028862bE2a173976CA11" },
|
|
33
|
+
{ id: 13371, name: "Immutable zkEVM", nativeCurrency: { "decimals": 18, "name": "Immutable Coin", "symbol": "IMX" }, http: ["https://rpc.immutable.com"], explorer: "https://explorer.immutable.com", isTestnet: false, multicall3: "0x236bdA4589e44e6850f5aC6a74BfCa398a86c6c0" },
|
|
34
|
+
{ id: 146, name: "Sonic", nativeCurrency: { "decimals": 18, "name": "Sonic", "symbol": "S" }, http: ["https://rpc.soniclabs.com"], explorer: "https://sonicscan.org", isTestnet: false, multicall3: "0xca11bde05977b3631167028862be2a173976ca11" },
|
|
35
|
+
{ id: 1625, name: "Gravity Alpha Mainnet", nativeCurrency: { "name": "G", "symbol": "G", "decimals": 18 }, http: ["https://rpc.gravity.xyz"], explorer: "https://explorer.gravity.xyz", isTestnet: false, multicall3: "0xf8ac4BEB2F75d2cFFb588c63251347fdD629B92c" },
|
|
36
|
+
{ id: 25, name: "Cronos Mainnet", nativeCurrency: { "decimals": 18, "name": "Cronos", "symbol": "CRO" }, http: ["https://evm.cronos.org"], explorer: "https://explorer.cronos.org", isTestnet: false, multicall3: "0xcA11bde05977b3631167028862bE2a173976CA11" },
|
|
37
|
+
{ id: 252, name: "Fraxtal", nativeCurrency: { "name": "Frax", "symbol": "FRAX", "decimals": 18 }, http: ["https://rpc.frax.com"], explorer: "https://fraxscan.com", isTestnet: false, multicall3: "0xca11bde05977b3631167028862be2a173976ca11" },
|
|
38
|
+
{ id: 2741, name: "Abstract", nativeCurrency: { "decimals": 18, "name": "ETH", "symbol": "ETH" }, http: ["https://api.mainnet.abs.xyz"], explorer: "https://abscan.org", isTestnet: false, multicall3: "0xAa4De41dba0Ca5dCBb288b7cC6b708F3aaC759E7" },
|
|
39
|
+
{ id: 30, name: "Rootstock Mainnet", nativeCurrency: { "decimals": 18, "name": "Rootstock Bitcoin", "symbol": "RBTC" }, http: ["https://public-node.rsk.co"], explorer: "https://explorer.rsk.co", isTestnet: false, multicall3: "0xcA11bde05977b3631167028862bE2a173976CA11" },
|
|
40
|
+
{ id: 42220, name: "Celo", nativeCurrency: { "decimals": 18, "name": "CELO", "symbol": "CELO" }, http: ["https://forno.celo.org"], explorer: "https://celoscan.io", isTestnet: false, multicall3: "0xcA11bde05977b3631167028862bE2a173976CA11" },
|
|
41
|
+
{ id: 480, name: "World Chain", nativeCurrency: { "name": "Ether", "symbol": "ETH", "decimals": 18 }, http: ["https://worldchain-mainnet.g.alchemy.com/public"], explorer: "https://worldscan.org", isTestnet: false, multicall3: "0xca11bde05977b3631167028862be2a173976ca11" },
|
|
42
|
+
{ id: 5000, name: "Mantle", nativeCurrency: { "decimals": 18, "name": "MNT", "symbol": "MNT" }, http: ["https://rpc.mantle.xyz"], explorer: "https://mantlescan.xyz/", isTestnet: false, multicall3: "0xcA11bde05977b3631167028862bE2a173976CA11" },
|
|
43
|
+
{ id: 80094, name: "Berachain", nativeCurrency: { "decimals": 18, "name": "BERA Token", "symbol": "BERA" }, http: ["https://rpc.berachain.com"], explorer: "https://berascan.com", isTestnet: false, multicall3: "0xcA11bde05977b3631167028862bE2a173976CA11" },
|
|
44
|
+
{ id: 14, name: "Flare Mainnet", nativeCurrency: { "decimals": 18, "name": "Flare", "symbol": "FLR" }, http: ["https://flare-api.flare.network/ext/C/rpc"], explorer: "https://flare-explorer.flare.network", isTestnet: false, multicall3: "0xcA11bde05977b3631167028862bE2a173976CA11" },
|
|
45
|
+
{ id: 40, name: "Telos", nativeCurrency: { "decimals": 18, "name": "Telos", "symbol": "TLOS" }, http: ["https://rpc.telos.net"], explorer: "https://www.teloscan.io/", isTestnet: false, multicall3: "0xcA11bde05977b3631167028862bE2a173976CA11" },
|
|
46
|
+
{ id: 50, name: "XDC Network", nativeCurrency: { "decimals": 18, "name": "XDC", "symbol": "XDC" }, http: ["https://rpc.xdcrpc.com"], explorer: "https://xdcscan.com", isTestnet: false, multicall3: "0x0B1795ccA8E4eC4df02346a082df54D437F8D9aF" },
|
|
47
|
+
{ id: 88, name: "Viction", nativeCurrency: { "name": "Viction", "symbol": "VIC", "decimals": 18 }, http: ["https://rpc.viction.xyz"], explorer: "https://vicscan.xyz", isTestnet: false, multicall3: null },
|
|
48
|
+
{ id: 143, name: "Monad", nativeCurrency: { "name": "Monad", "symbol": "MON", "decimals": 18 }, http: ["https://rpc.monad.xyz", "https://rpc1.monad.xyz"], explorer: "https://monadvision.com", isTestnet: false, multicall3: "0xcA11bde05977b3631167028862bE2a173976CA11" },
|
|
49
|
+
{ id: 169, name: "Manta Pacific Mainnet", nativeCurrency: { "decimals": 18, "name": "ETH", "symbol": "ETH" }, http: ["https://pacific-rpc.manta.network/http"], explorer: "https://pacific-explorer.manta.network", isTestnet: false, multicall3: "0xcA11bde05977b3631167028862bE2a173976CA11" },
|
|
50
|
+
{ id: 196, name: "X Layer Mainnet", nativeCurrency: { "decimals": 18, "name": "OKB", "symbol": "OKB" }, http: ["https://rpc.xlayer.tech"], explorer: "https://www.oklink.com/xlayer", isTestnet: false, multicall3: "0xcA11bde05977b3631167028862bE2a173976CA11" },
|
|
51
|
+
{ id: 204, name: "opBNB", nativeCurrency: { "name": "BNB", "symbol": "BNB", "decimals": 18 }, http: ["https://opbnb-mainnet-rpc.bnbchain.org"], explorer: "https://opbnb.bscscan.com", isTestnet: false, multicall3: "0xcA11bde05977b3631167028862bE2a173976CA11" },
|
|
52
|
+
{ id: 232, name: "Lens", nativeCurrency: { "name": "GHO", "symbol": "GHO", "decimals": 18 }, http: ["https://rpc.lens.xyz"], explorer: "https://explorer.lens.xyz", isTestnet: false, multicall3: null },
|
|
53
|
+
{ id: 360, name: "Shape", nativeCurrency: { "name": "Ether", "symbol": "ETH", "decimals": 18 }, http: ["https://mainnet.shape.network"], explorer: "https://shapescan.xyz", isTestnet: false, multicall3: "0xca11bde05977b3631167028862be2a173976ca11" },
|
|
54
|
+
{ id: 747, name: "Flow EVM Mainnet", nativeCurrency: { "decimals": 18, "name": "Flow", "symbol": "FLOW" }, http: ["https://mainnet.evm.nodes.onflow.org"], explorer: "https://evm.flowscan.io", isTestnet: false, multicall3: "0xca11bde05977b3631167028862be2a173976ca11" },
|
|
55
|
+
{ id: 988, name: "Stable Mainnet", nativeCurrency: { "name": "USDT0", "symbol": "USDT0", "decimals": 18 }, http: ["https://rpc.stable.xyz"], explorer: "https://stablescan.xyz", isTestnet: false, multicall3: "0xcA11bde05977b3631167028862bE2a173976CA11" },
|
|
56
|
+
{ id: 999, name: "Zora Goerli Testnet", nativeCurrency: { "decimals": 18, "name": "Zora Goerli", "symbol": "ETH" }, http: ["https://testnet.rpc.zora.energy"], explorer: "https://testnet.explorer.zora.energy", isTestnet: true, multicall3: "0xcA11bde05977b3631167028862bE2a173976CA11" },
|
|
57
|
+
{ id: 1088, name: "Metis", nativeCurrency: { "decimals": 18, "name": "Metis", "symbol": "METIS" }, http: ["https://metis.rpc.hypersync.xyz", "https://metis-pokt.nodies.app", "https://api.blockeden.xyz/metis/67nCBdZQSH9z3YqDDjdm", "https://metis-andromeda.rpc.thirdweb.com", "https://metis-andromeda.gateway.tenderly.co", "https://metis.api.onfinality.io/public", "https://andromeda.metis.io/?owner=1088", "https://metis-mainnet.public.blastapi.io"], explorer: "https://explorer.metis.io", isTestnet: false, multicall3: "0xca11bde05977b3631167028862be2a173976ca11" },
|
|
58
|
+
{ id: 1135, name: "Lisk", nativeCurrency: { "decimals": 18, "name": "Ether", "symbol": "ETH" }, http: ["https://rpc.api.lisk.com"], explorer: "https://blockscout.lisk.com", isTestnet: false, multicall3: "0xA9d71E1dd7ca26F26e656E66d6AA81ed7f745bf0" },
|
|
59
|
+
{ id: 1337, name: "Tempo", nativeCurrency: { "name": "USD", "symbol": "USD", "decimals": 6 }, http: ["http://localhost:8545"], explorer: null, isTestnet: false, multicall3: null },
|
|
60
|
+
{ id: 1480, name: "Vana", nativeCurrency: { "decimals": 18, "name": "Vana", "symbol": "VANA" }, http: ["https://rpc.vana.org/"], explorer: "https://vanascan.io", isTestnet: false, multicall3: "0xD8d2dFca27E8797fd779F8547166A2d3B29d360E" },
|
|
61
|
+
{ id: 1776, name: "Injective", nativeCurrency: { "decimals": 18, "name": "Injective", "symbol": "INJ" }, http: ["https://sentry.evm-rpc.injective.network"], explorer: "https://blockscout.injective.network", isTestnet: false, multicall3: null },
|
|
62
|
+
{ id: 1868, name: "Soneium Mainnet", nativeCurrency: { "name": "Ether", "symbol": "ETH", "decimals": 18 }, http: ["https://rpc.soneium.org"], explorer: "https://soneium.blockscout.com", isTestnet: false, multicall3: "0xcA11bde05977b3631167028862bE2a173976CA11" },
|
|
63
|
+
{ id: 2020, name: "Ronin", nativeCurrency: { "name": "RON", "symbol": "RON", "decimals": 18 }, http: ["https://api.roninchain.com/rpc"], explorer: "https://app.roninchain.com", isTestnet: false, multicall3: "0xca11bde05977b3631167028862be2a173976ca11" },
|
|
64
|
+
{ id: 2818, name: "Morph", nativeCurrency: { "decimals": 18, "name": "Ether", "symbol": "ETH" }, http: ["https://rpc.morphl2.io"], explorer: "https://explorer.morphl2.io", isTestnet: false, multicall3: "0xcA11bde05977b3631167028862bE2a173976CA11" },
|
|
65
|
+
{ id: 4217, name: "Tempo Mainnet", nativeCurrency: { "name": "USD", "symbol": "USD", "decimals": 6 }, http: ["https://rpc.presto.tempo.xyz"], explorer: "https://explore.mainnet.tempo.xyz", isTestnet: false, multicall3: null },
|
|
66
|
+
{ id: 4326, name: "MegaETH", nativeCurrency: { "name": "Ether", "symbol": "ETH", "decimals": 18 }, http: ["https://mainnet.megaeth.com/rpc"], explorer: "https://mega.etherscan.io", isTestnet: false, multicall3: "0xcA11bde05977b3631167028862bE2a173976CA11" },
|
|
67
|
+
{ id: 5031, name: "Somnia", nativeCurrency: { "name": "Somnia", "symbol": "SOMI", "decimals": 18 }, http: ["https://api.infra.mainnet.somnia.network"], explorer: "https://explorer.somnia.network", isTestnet: false, multicall3: null },
|
|
68
|
+
{ id: 5330, name: "Superseed", nativeCurrency: { "name": "Ether", "symbol": "ETH", "decimals": 18 }, http: ["https://mainnet.superseed.xyz"], explorer: "https://explorer.superseed.xyz", isTestnet: false, multicall3: "0xcA11bde05977b3631167028862bE2a173976CA11" },
|
|
69
|
+
{ id: 8217, name: "Klaytn", nativeCurrency: { "decimals": 18, "name": "Klaytn", "symbol": "KLAY" }, http: ["https://public-en-cypress.klaytn.net"], explorer: "https://scope.klaytn.com", isTestnet: false, multicall3: "0xcA11bde05977b3631167028862bE2a173976CA11" },
|
|
70
|
+
{ id: 8333, name: "B3", nativeCurrency: { "name": "Ether", "symbol": "ETH", "decimals": 18 }, http: ["https://mainnet-rpc.b3.fun/http"], explorer: "https://explorer.b3.fun", isTestnet: false, multicall3: "0xca11bde05977b3631167028862be2a173976ca11" },
|
|
71
|
+
{ id: 9745, name: "Plasma", nativeCurrency: { "name": "Plasma", "symbol": "XPL", "decimals": 18 }, http: ["https://rpc.plasma.to"], explorer: "https://plasmascan.to", isTestnet: false, multicall3: "0xcA11bde05977b3631167028862bE2a173976CA11" },
|
|
72
|
+
{ id: 16661, name: "0G Mainnet", nativeCurrency: { "name": "0G", "symbol": "0G", "decimals": 18 }, http: ["https://evmrpc.0g.ai"], explorer: "https://chainscan.0g.ai", isTestnet: false, multicall3: null },
|
|
73
|
+
{ id: 33139, name: "ApeChain", nativeCurrency: { "name": "ApeCoin", "symbol": "APE", "decimals": 18 }, http: ["https://rpc.apechain.com/http"], explorer: "https://apescan.io", isTestnet: false, multicall3: "0xcA11bde05977b3631167028862bE2a173976CA11" },
|
|
74
|
+
{ id: 34443, name: "Mode Mainnet", nativeCurrency: { "name": "Ether", "symbol": "ETH", "decimals": 18 }, http: ["https://mainnet.mode.network"], explorer: "https://modescan.io", isTestnet: false, multicall3: "0xca11bde05977b3631167028862be2a173976ca11" },
|
|
75
|
+
{ id: 42170, name: "Arbitrum Nova", nativeCurrency: { "name": "Ether", "symbol": "ETH", "decimals": 18 }, http: ["https://nova.arbitrum.io/rpc"], explorer: "https://nova.arbiscan.io", isTestnet: false, multicall3: "0xca11bde05977b3631167028862be2a173976ca11" },
|
|
76
|
+
{ id: 42793, name: "Etherlink", nativeCurrency: { "decimals": 18, "name": "Tez", "symbol": "XTZ" }, http: ["https://node.mainnet.etherlink.com"], explorer: "https://explorer.etherlink.com", isTestnet: false, multicall3: "0xcA11bde05977b3631167028862bE2a173976CA11" },
|
|
77
|
+
{ id: 43111, name: "Hemi", nativeCurrency: { "name": "Ether", "symbol": "ETH", "decimals": 18 }, http: ["https://rpc.hemi.network/rpc"], explorer: "https://explorer.hemi.xyz", isTestnet: false, multicall3: null },
|
|
78
|
+
{ id: 43419, name: "Gunz Mainnet", nativeCurrency: { "name": "GUN", "symbol": "GUN", "decimals": 18 }, http: ["https://rpc.gunzchain.io/ext/bc/2M47TxWHGnhNtq6pM5zPXdATBtuqubxn5EPFgFmEawCQr9WFML/rpc"], explorer: "https://gunzscan.io/", isTestnet: false, multicall3: "0xcA11bde05977b3631167028862bE2a173976CA11" },
|
|
79
|
+
{ id: 48900, name: "Zircuit Mainnet", nativeCurrency: { "decimals": 18, "name": "Ether", "symbol": "ETH" }, http: ["https://mainnet.zircuit.com", "https://zircuit1-mainnet.liquify.com", "https://zircuit1-mainnet.p2pify.com", "https://zircuit-mainnet.drpc.org"], explorer: "https://explorer.zircuit.com", isTestnet: false, multicall3: "0xcA11bde05977b3631167028862bE2a173976CA11" },
|
|
80
|
+
{ id: 57073, name: "Ink", nativeCurrency: { "name": "Ether", "symbol": "ETH", "decimals": 18 }, http: ["https://rpc-gel.inkonchain.com", "https://rpc-qnd.inkonchain.com"], explorer: "https://explorer.inkonchain.com", isTestnet: false, multicall3: "0xcA11bde05977b3631167028862bE2a173976CA11" },
|
|
81
|
+
{ id: 60808, name: "BOB", nativeCurrency: { "decimals": 18, "name": "ETH", "symbol": "ETH" }, http: ["https://rpc.gobob.xyz"], explorer: "https://explorer.gobob.xyz", isTestnet: false, multicall3: "0xcA11bde05977b3631167028862bE2a173976CA11" },
|
|
82
|
+
{ id: 84532, name: "Base Sepolia", nativeCurrency: { "name": "Sepolia Ether", "symbol": "ETH", "decimals": 18 }, http: ["https://sepolia-preconf.base.org"], explorer: "https://sepolia.basescan.org", isTestnet: true, multicall3: "0xca11bde05977b3631167028862be2a173976ca11" },
|
|
83
|
+
{ id: 98866, name: "Plume", nativeCurrency: { "name": "Plume", "symbol": "PLUME", "decimals": 18 }, http: ["https://rpc.plume.org"], explorer: "https://explorer.plume.org", isTestnet: false, multicall3: "0xcA11bde05977b3631167028862bE2a173976CA11" },
|
|
84
|
+
{ id: 421614, name: "Arbitrum Sepolia", nativeCurrency: { "name": "Arbitrum Sepolia Ether", "symbol": "ETH", "decimals": 18 }, http: ["https://sepolia-rollup.arbitrum.io/rpc"], explorer: "https://sepolia.arbiscan.io", isTestnet: true, multicall3: "0xca11bde05977b3631167028862be2a173976ca11" },
|
|
85
|
+
{ id: 747474, name: "Katana", nativeCurrency: { "name": "Ether", "symbol": "ETH", "decimals": 18 }, http: ["https://rpc.katana.network"], explorer: "https://katanascan.com", isTestnet: false, multicall3: null },
|
|
86
|
+
{ id: 5042002, name: "Arc Testnet", nativeCurrency: { "name": "USDC", "symbol": "USDC", "decimals": 18 }, http: ["https://rpc.testnet.arc.network", "https://rpc.quicknode.testnet.arc.network", "https://rpc.blockdaemon.testnet.arc.network"], explorer: "https://testnet.arcscan.app", isTestnet: true, multicall3: "0xcA11bde05977b3631167028862bE2a173976CA11" },
|
|
87
|
+
{ id: 7777777, name: "Zora", nativeCurrency: { "decimals": 18, "name": "Ether", "symbol": "ETH" }, http: ["https://rpc.zora.energy"], explorer: "https://explorer.zora.energy", isTestnet: false, multicall3: "0xcA11bde05977b3631167028862bE2a173976CA11" },
|
|
88
|
+
{ id: 11155420, name: "OP Sepolia", nativeCurrency: { "name": "Sepolia Ether", "symbol": "ETH", "decimals": 18 }, http: ["https://sepolia.optimism.io"], explorer: "https://optimism-sepolia.blockscout.com", isTestnet: true, multicall3: "0xca11bde05977b3631167028862be2a173976ca11" },
|
|
89
|
+
];
|
package/dist/client.d.ts
CHANGED
|
@@ -1,13 +1,19 @@
|
|
|
1
|
-
import type { PublicClient } from 'viem';
|
|
1
|
+
import type { HttpTransportConfig, PublicClient } from 'viem';
|
|
2
2
|
/**
|
|
3
|
-
* The request-batching setting for a chain's client
|
|
4
|
-
*
|
|
5
|
-
* `
|
|
3
|
+
* The request-batching setting for a chain's client.
|
|
4
|
+
*
|
|
5
|
+
* `false` for chains whose nodes reject a batch body at all (see
|
|
6
|
+
* {@link chainsWithoutRpcBatching}). Otherwise batching stays on, capped at
|
|
7
|
+
* {@link MAX_SAME_METHOD_CALLS_PER_SECOND} so no single post can exceed the
|
|
8
|
+
* proxy's per-method budget on its own and lose every call in it.
|
|
9
|
+
*
|
|
10
|
+
* The `wait` of ten milliseconds is viem's own default, restated here because
|
|
11
|
+
* naming `batchSize` alone would otherwise drop it.
|
|
6
12
|
*
|
|
7
13
|
* @param chainId - the chain to resolve the batch setting for
|
|
8
|
-
* @returns `false` when batching must be disabled, otherwise
|
|
14
|
+
* @returns `false` when batching must be disabled, otherwise the batch config
|
|
9
15
|
*/
|
|
10
|
-
export declare const rpcBatchSetting: (chainId: number) =>
|
|
16
|
+
export declare const rpcBatchSetting: (chainId: number) => HttpTransportConfig["batch"];
|
|
11
17
|
/**
|
|
12
18
|
* Returns a viem {@link PublicClient} for a chain, reusing the cached instance
|
|
13
19
|
* while the chain's endpoint list is unchanged. The cache key is derived from the
|
package/dist/client.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { chainsMetadata } from '@gibs/bridge-sdk/chains';
|
|
2
|
+
import { toChain } from '@gibs/bridge-sdk/config';
|
|
3
|
+
import { chainKey, clientCache, clientFromChain as buildClient, MAX_SAME_METHOD_CALLS_PER_SECOND, } from '@gibs/common/client';
|
|
2
4
|
import * as _ from 'lodash-es';
|
|
3
5
|
import { bsc } from 'viem/chains';
|
|
4
6
|
import * as endpoints from './endpoints.js';
|
|
@@ -13,14 +15,22 @@ import { evmChainsById } from './networks.js';
|
|
|
13
15
|
*/
|
|
14
16
|
const chainsWithoutRpcBatching = new Set([bsc.id]);
|
|
15
17
|
/**
|
|
16
|
-
* The request-batching setting for a chain's client
|
|
17
|
-
*
|
|
18
|
-
* `
|
|
18
|
+
* The request-batching setting for a chain's client.
|
|
19
|
+
*
|
|
20
|
+
* `false` for chains whose nodes reject a batch body at all (see
|
|
21
|
+
* {@link chainsWithoutRpcBatching}). Otherwise batching stays on, capped at
|
|
22
|
+
* {@link MAX_SAME_METHOD_CALLS_PER_SECOND} so no single post can exceed the
|
|
23
|
+
* proxy's per-method budget on its own and lose every call in it.
|
|
24
|
+
*
|
|
25
|
+
* The `wait` of ten milliseconds is viem's own default, restated here because
|
|
26
|
+
* naming `batchSize` alone would otherwise drop it.
|
|
19
27
|
*
|
|
20
28
|
* @param chainId - the chain to resolve the batch setting for
|
|
21
|
-
* @returns `false` when batching must be disabled, otherwise
|
|
29
|
+
* @returns `false` when batching must be disabled, otherwise the batch config
|
|
22
30
|
*/
|
|
23
|
-
export const rpcBatchSetting = (chainId) => chainsWithoutRpcBatching.has(chainId)
|
|
31
|
+
export const rpcBatchSetting = (chainId) => chainsWithoutRpcBatching.has(chainId)
|
|
32
|
+
? false
|
|
33
|
+
: { batchSize: MAX_SAME_METHOD_CALLS_PER_SECOND, wait: 10 };
|
|
24
34
|
/**
|
|
25
35
|
* A chain's own default endpoints, used when the editable table has no entry.
|
|
26
36
|
*
|
|
@@ -31,6 +41,23 @@ const defaultUrlsFor = (chainId) => {
|
|
|
31
41
|
if (!chainId) {
|
|
32
42
|
throw new Error('chainId is required');
|
|
33
43
|
}
|
|
44
|
+
// The APPLICATION's metadata first, viem's chain object only for the chains it
|
|
45
|
+
// does not override.
|
|
46
|
+
//
|
|
47
|
+
// These are two different answers to the same question, and reading only the
|
|
48
|
+
// second is why demoting a rate-limited Sepolia endpoint in `chainsMetadata`
|
|
49
|
+
// changed nothing: the seed built from that map, while THIS function — which
|
|
50
|
+
// decides what a client actually talks to when the stored table is empty —
|
|
51
|
+
// returned viem's own default and went on hitting the demoted host first.
|
|
52
|
+
//
|
|
53
|
+
// The bridge chains are overridden precisely because viem's defaults are not
|
|
54
|
+
// the ones this application wants; the wider list (Arbitrum, Base, and the
|
|
55
|
+
// rest) has no override and correctly falls through.
|
|
56
|
+
const overridden = chainsMetadata[toChain(chainId)];
|
|
57
|
+
const overriddenHttp = overridden?.rpcUrls?.default?.http;
|
|
58
|
+
if (overriddenHttp?.length) {
|
|
59
|
+
return [...overriddenHttp];
|
|
60
|
+
}
|
|
34
61
|
const chain = evmChainsById.get(chainId);
|
|
35
62
|
if (!chain) {
|
|
36
63
|
return [];
|
package/dist/endpoints.d.ts
CHANGED
|
@@ -31,7 +31,13 @@ export type EndpointStorage = {
|
|
|
31
31
|
* rename silently reverts every one of them to the defaults on the next load.
|
|
32
32
|
*/
|
|
33
33
|
export declare const ENDPOINTS_STORAGE_KEY = "rpcs";
|
|
34
|
-
/**
|
|
34
|
+
/**
|
|
35
|
+
* Every chain the application can reach, the bridge's own first.
|
|
36
|
+
*
|
|
37
|
+
* The bridge's three keep taking their urls from `chainsMetadata`, which is
|
|
38
|
+
* where the product's own node choices live and which must win over viem's
|
|
39
|
+
* generic default for them.
|
|
40
|
+
*/
|
|
35
41
|
export declare const productionSeed: EndpointEntry[];
|
|
36
42
|
/** The bridge's test chains, for a build that is not production. */
|
|
37
43
|
export declare const testnetSeed: EndpointEntry[];
|
package/dist/endpoints.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { chainsMetadata } from '@gibs/bridge-sdk/chains';
|
|
2
2
|
import { Chains, toChain } from '@gibs/bridge-sdk/config';
|
|
3
|
+
import { chainTable } from './chain-table.js';
|
|
3
4
|
import * as _ from 'lodash-es';
|
|
4
5
|
/**
|
|
5
6
|
* The storage key holding the endpoint table.
|
|
@@ -8,10 +9,53 @@ import * as _ from 'lodash-es';
|
|
|
8
9
|
* rename silently reverts every one of them to the defaults on the next load.
|
|
9
10
|
*/
|
|
10
11
|
export const ENDPOINTS_STORAGE_KEY = 'rpcs';
|
|
11
|
-
/**
|
|
12
|
+
/**
|
|
13
|
+
* EVERY SUPPORTED CHAIN GETS AN ENTRY, and the entry comes from viem.
|
|
14
|
+
*
|
|
15
|
+
* This used to seed three chains — PulseChain, Ethereum and Binance Smart Chain
|
|
16
|
+
* — while the aggregators quote routes from seventy-odd. A chain absent from
|
|
17
|
+
* this table is not refused; `clientFromChain` falls through to viem's own
|
|
18
|
+
* public nodes for it. So every read on an aggregator origin went to a node
|
|
19
|
+
* nobody chose, which is where the rate limiting came from, and the endpoint
|
|
20
|
+
* editor could not show the chain at all: a reader whose Base node was throttled
|
|
21
|
+
* had no way to replace it, because Base was not in the list they were editing.
|
|
22
|
+
*
|
|
23
|
+
* Seeding from `chainTable` fixes both at once. The urls are viem's own
|
|
24
|
+
* defaults, which is what the three seeded chains always used — the change is
|
|
25
|
+
* the breadth, not the source.
|
|
26
|
+
*/
|
|
12
27
|
const seedFor = (chains) => chains.map((chain) => [Number(chain), [...chainsMetadata[chain].rpcUrls.default.http]]);
|
|
13
|
-
/** The bridge's
|
|
14
|
-
|
|
28
|
+
/** The bridge's own chains, kept first so a picker built from this reads well. */
|
|
29
|
+
const BRIDGE_CHAIN_IDS = [
|
|
30
|
+
Number(Chains.PLS),
|
|
31
|
+
Number(Chains.ETH),
|
|
32
|
+
Number(Chains.BNB),
|
|
33
|
+
];
|
|
34
|
+
/**
|
|
35
|
+
* Every chain the application can reach, the bridge's own first.
|
|
36
|
+
*
|
|
37
|
+
* The bridge's three keep taking their urls from `chainsMetadata`, which is
|
|
38
|
+
* where the product's own node choices live and which must win over viem's
|
|
39
|
+
* generic default for them.
|
|
40
|
+
*/
|
|
41
|
+
export const productionSeed = [
|
|
42
|
+
...seedFor([Chains.PLS, Chains.ETH, Chains.BNB]),
|
|
43
|
+
...chainTable
|
|
44
|
+
.filter((entry) =>
|
|
45
|
+
// The bridge's own three are seeded above, from `chainsMetadata`, and
|
|
46
|
+
// must not be seeded twice. That map is where the product's node
|
|
47
|
+
// choices live — demoting a rate-limited host there has to take effect,
|
|
48
|
+
// and a table entry added after it would silently win.
|
|
49
|
+
!BRIDGE_CHAIN_IDS.includes(entry.id) &&
|
|
50
|
+
// A PRODUCTION BUILD PROMISES NOT TO OFFER A TEST NETWORK, and the
|
|
51
|
+
// endpoint table is one of the places that promise can be broken: the
|
|
52
|
+
// chains seeded here are the chains the endpoint editor lists. The
|
|
53
|
+
// table carries test networks deliberately, because a client still has
|
|
54
|
+
// to be buildable for them on a testnet build; this is where they are
|
|
55
|
+
// held back.
|
|
56
|
+
!entry.isTestnet)
|
|
57
|
+
.map((entry) => [entry.id, [...entry.http]]),
|
|
58
|
+
];
|
|
15
59
|
/** The bridge's test chains, for a build that is not production. */
|
|
16
60
|
export const testnetSeed = seedFor([Chains.V4PLS, Chains.SEP]);
|
|
17
61
|
/** The seed the next load starts from. */
|
package/dist/image.d.ts
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Chain-logo resolution, in one place.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
4
|
+
* gib.show serves almost every chain a route can start from — including the
|
|
5
|
+
* non-Ethereum ones — but it keys them by a CAIP-2 style identifier rather than
|
|
6
|
+
* by Relay's invented decimal ids, so the two have to be mapped. Only Eclipse
|
|
7
|
+
* and Hyperliquid are genuinely absent from it, and those alone fall back to
|
|
8
|
+
* Relay's own icon service.
|
|
9
|
+
*
|
|
10
|
+
* This is a module rather than an inline template string because getting the
|
|
11
|
+
* key wrong is invisible: a 404 in an `<img src>` is drawn by the browser as a
|
|
12
|
+
* broken-image glyph, so the mistake surfaces as a blemish on a token pill
|
|
13
|
+
* rather than as an error anyone would go looking for.
|
|
12
14
|
*/
|
|
13
15
|
/**
|
|
14
16
|
* Relay's public chain-icon service, keyed on Relay's own chain identifiers —
|
|
@@ -16,31 +18,51 @@
|
|
|
16
18
|
*
|
|
17
19
|
* The `light` variant is the full-colour brand mark (the pair is light/dark
|
|
18
20
|
* BACKGROUND, not a monochrome inversion), so one variant serves both of our
|
|
19
|
-
* themes. Not every id is populated — The Open Network
|
|
20
|
-
*
|
|
21
|
+
* themes. Not every id is populated — The Open Network answers 403, which is
|
|
22
|
+
* what the bundled asset used to exist for — so callers must still tolerate a
|
|
23
|
+
* badge that fails to load. Only Eclipse and Hyperliquid reach this now.
|
|
21
24
|
*
|
|
22
25
|
* @param chainId - a Relay chain identifier
|
|
23
26
|
* @returns the icon url
|
|
24
27
|
*/
|
|
25
28
|
export declare const relayChainIconUrl: (chainId: number) => string;
|
|
26
29
|
/**
|
|
27
|
-
* Resolves the logo url for a chain, choosing the service that can
|
|
28
|
-
* serve it.
|
|
30
|
+
* Resolves the logo url for a chain, choosing the service that can serve it.
|
|
29
31
|
*
|
|
30
|
-
* A chain
|
|
31
|
-
* Otherwise Ethereum-Virtual-Machine
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
32
|
+
* A chain gib.show knows under its own identifier wins outright
|
|
33
|
+
* ({@link gibShowChainIdentifier}). Otherwise an Ethereum-Virtual-Machine chain
|
|
34
|
+
* goes to gib.show by number, honouring the configured image root so a
|
|
35
|
+
* self-hosted deployment is respected rather than hard-coding the public host.
|
|
36
|
+
* What remains is Eclipse and Hyperliquid, which gib.show does not carry, and
|
|
37
|
+
* they go to Relay.
|
|
35
38
|
*
|
|
36
39
|
* @param chainId - the decimal chain id, Relay's pseudo identifiers included
|
|
37
40
|
* @param displayPx - the CSS pixel size the logo renders at; when supplied,
|
|
38
41
|
* gib.show is asked for twice that in webp per its retina guidance. Ignored
|
|
39
|
-
* for a Relay-served icon and for
|
|
40
|
-
* sizing parameters.
|
|
42
|
+
* for a Relay-served icon and for an identifier-keyed mark, neither of which
|
|
43
|
+
* takes sizing parameters.
|
|
41
44
|
* @returns an image url for the chain
|
|
42
45
|
*/
|
|
43
46
|
export declare const chainLogoUrl: ({ chainId, displayPx, }: {
|
|
44
47
|
chainId: number;
|
|
45
48
|
displayPx?: number;
|
|
46
49
|
}) => string;
|
|
50
|
+
/**
|
|
51
|
+
* The gib.show sources for a chain's NATIVE COIN, best first.
|
|
52
|
+
*
|
|
53
|
+
* The service serves the first source that resolves: the coin as this chain
|
|
54
|
+
* keys it, then the coin as its home chain keys it, then the chain's own mark.
|
|
55
|
+
* The last is an honest fallback rather than a mistake — for a chain's own coin
|
|
56
|
+
* the two marks are the same picture.
|
|
57
|
+
*
|
|
58
|
+
* @param chainId - the chain the coin is being shown on
|
|
59
|
+
* @returns the ordered source list, for {@link imageLinks.images}
|
|
60
|
+
*/
|
|
61
|
+
export declare const nativeCoinImageSources: (chainId: number) => string[];
|
|
62
|
+
/**
|
|
63
|
+
* Resolves the picture of a chain's native coin, as opposed to of the chain.
|
|
64
|
+
*
|
|
65
|
+
* @param chainId - the chain the coin is being shown on
|
|
66
|
+
* @returns an image url
|
|
67
|
+
*/
|
|
68
|
+
export declare const nativeCoinLogoUrl: (chainId: number) => string;
|
package/dist/image.js
CHANGED
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
import * as imageLinks from '@gibs/bridge-sdk/image-links';
|
|
2
2
|
import { ecosystemByChainId, relayChainIds } from '@gibs/bridge-sdk/relay-quote';
|
|
3
|
+
import { zeroAddress } from 'viem';
|
|
4
|
+
import { chainTable } from './chain-table.js';
|
|
3
5
|
/**
|
|
4
6
|
* Chain-logo resolution, in one place.
|
|
5
7
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
8
|
+
* gib.show serves almost every chain a route can start from — including the
|
|
9
|
+
* non-Ethereum ones — but it keys them by a CAIP-2 style identifier rather than
|
|
10
|
+
* by Relay's invented decimal ids, so the two have to be mapped. Only Eclipse
|
|
11
|
+
* and Hyperliquid are genuinely absent from it, and those alone fall back to
|
|
12
|
+
* Relay's own icon service.
|
|
13
|
+
*
|
|
14
|
+
* This is a module rather than an inline template string because getting the
|
|
15
|
+
* key wrong is invisible: a 404 in an `<img src>` is drawn by the browser as a
|
|
16
|
+
* broken-image glyph, so the mistake surfaces as a blemish on a token pill
|
|
17
|
+
* rather than as an error anyone would go looking for.
|
|
14
18
|
*/
|
|
15
19
|
/**
|
|
16
20
|
* Relay's public chain-icon service, keyed on Relay's own chain identifiers —
|
|
@@ -18,59 +22,73 @@ import { ecosystemByChainId, relayChainIds } from '@gibs/bridge-sdk/relay-quote'
|
|
|
18
22
|
*
|
|
19
23
|
* The `light` variant is the full-colour brand mark (the pair is light/dark
|
|
20
24
|
* BACKGROUND, not a monochrome inversion), so one variant serves both of our
|
|
21
|
-
* themes. Not every id is populated — The Open Network
|
|
22
|
-
*
|
|
25
|
+
* themes. Not every id is populated — The Open Network answers 403, which is
|
|
26
|
+
* what the bundled asset used to exist for — so callers must still tolerate a
|
|
27
|
+
* badge that fails to load. Only Eclipse and Hyperliquid reach this now.
|
|
23
28
|
*
|
|
24
29
|
* @param chainId - a Relay chain identifier
|
|
25
30
|
* @returns the icon url
|
|
26
31
|
*/
|
|
27
32
|
export const relayChainIconUrl = (chainId) => `https://assets.relay.link/icons/${chainId}/light.png`;
|
|
28
33
|
/**
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
34
|
+
* gib.show's own key for a chain that Relay reaches us under a pseudo id.
|
|
35
|
+
*
|
|
36
|
+
* THE SERVICE WAS NEVER MISSING THESE CHAINS — WE WERE ASKING BY THE WRONG KEY.
|
|
37
|
+
* gib.show keys every chain by a CAIP-2 style identifier: `eip155-1`,
|
|
38
|
+
* `solana-501`, `bip122-0`. Relay invented its own decimal ids for the
|
|
39
|
+
* non-Ethereum origins (Solana is 792703809, Bitcoin 8253038), and asking
|
|
40
|
+
* gib.show for one of those 404s — which read as "gib.show does not serve
|
|
41
|
+
* Solana" and sent every non-Ethereum badge to a second service. It serves them
|
|
42
|
+
* all, under its own key.
|
|
43
|
+
*
|
|
44
|
+
* Each entry below was verified twice: the url returns 200 with a real PNG, and
|
|
45
|
+
* the picture was LOOKED AT and is the chain's genuine mark. A 200 alone proves
|
|
46
|
+
* nothing here — `/image/999` returns 200 and hands back a completely different
|
|
47
|
+
* chain's logo, which is why an identifier is only listed once someone has seen
|
|
48
|
+
* what comes back.
|
|
49
|
+
*
|
|
50
|
+
* ECLIPSE AND HYPERLIQUID ARE ABSENT ON PURPOSE. Neither appears anywhere in
|
|
51
|
+
* gib.show's network list under any key, so they keep Relay's service. Guessing
|
|
52
|
+
* a plausible identifier for them would be worse than falling back: Hyperliquid
|
|
53
|
+
* in particular collides with an unrelated chain at id 999, so a guess renders
|
|
54
|
+
* the wrong company's logo rather than none at all.
|
|
55
|
+
*
|
|
56
|
+
* The pay-by-hand chains (Zcash and, later, its siblings) are NOT listed by
|
|
57
|
+
* hand here. `bridge-sdk`'s `image-links.ts` is the one place that key is
|
|
58
|
+
* declared — see its `pseudoChainGibShowIdentifier` — and this table spreads
|
|
59
|
+
* that map in, so a pay-by-hand chain added there needs no matching edit here.
|
|
49
60
|
*/
|
|
50
|
-
const
|
|
51
|
-
[relayChainIds.
|
|
61
|
+
const gibShowChainIdentifier = {
|
|
62
|
+
[relayChainIds.solana]: 'solana-501',
|
|
63
|
+
[relayChainIds.bitcoin]: 'bip122-0',
|
|
64
|
+
[relayChainIds.tron]: 'tvm-195',
|
|
65
|
+
[relayChainIds.ton]: 'ton-607',
|
|
66
|
+
...imageLinks.pseudoChainGibShowIdentifier,
|
|
52
67
|
};
|
|
53
68
|
/**
|
|
54
|
-
* Resolves the logo url for a chain, choosing the service that can
|
|
55
|
-
* serve it.
|
|
69
|
+
* Resolves the logo url for a chain, choosing the service that can serve it.
|
|
56
70
|
*
|
|
57
|
-
* A chain
|
|
58
|
-
* Otherwise Ethereum-Virtual-Machine
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
71
|
+
* A chain gib.show knows under its own identifier wins outright
|
|
72
|
+
* ({@link gibShowChainIdentifier}). Otherwise an Ethereum-Virtual-Machine chain
|
|
73
|
+
* goes to gib.show by number, honouring the configured image root so a
|
|
74
|
+
* self-hosted deployment is respected rather than hard-coding the public host.
|
|
75
|
+
* What remains is Eclipse and Hyperliquid, which gib.show does not carry, and
|
|
76
|
+
* they go to Relay.
|
|
62
77
|
*
|
|
63
78
|
* @param chainId - the decimal chain id, Relay's pseudo identifiers included
|
|
64
79
|
* @param displayPx - the CSS pixel size the logo renders at; when supplied,
|
|
65
80
|
* gib.show is asked for twice that in webp per its retina guidance. Ignored
|
|
66
|
-
* for a Relay-served icon and for
|
|
67
|
-
* sizing parameters.
|
|
81
|
+
* for a Relay-served icon and for an identifier-keyed mark, neither of which
|
|
82
|
+
* takes sizing parameters.
|
|
68
83
|
* @returns an image url for the chain
|
|
69
84
|
*/
|
|
70
85
|
export const chainLogoUrl = ({ chainId, displayPx, }) => {
|
|
71
|
-
const
|
|
72
|
-
if (
|
|
73
|
-
|
|
86
|
+
const identifier = gibShowChainIdentifier[chainId];
|
|
87
|
+
if (identifier !== undefined) {
|
|
88
|
+
// gib.show serves this chain, just not under Relay's number. No sizing
|
|
89
|
+
// parameters: these are fixed-size marks rather than the resizable images
|
|
90
|
+
// the numeric endpoint serves.
|
|
91
|
+
return `${imageLinks.getImageRoot()}/image/${identifier}`;
|
|
74
92
|
}
|
|
75
93
|
if (ecosystemByChainId(chainId) !== 'evm') {
|
|
76
94
|
return relayChainIconUrl(chainId);
|
|
@@ -81,3 +99,58 @@ export const chainLogoUrl = ({ chainId, displayPx, }) => {
|
|
|
81
99
|
}
|
|
82
100
|
return `${base}?w=${displayPx * 2}&h=${displayPx * 2}&format=webp`;
|
|
83
101
|
};
|
|
102
|
+
/**
|
|
103
|
+
* The chain a native coin actually belongs to, found by its symbol.
|
|
104
|
+
*
|
|
105
|
+
* WHY THIS IS NEEDED. gib.show serves a coin's own picture under
|
|
106
|
+
* `<chain>/<zero address>`, and it carries that picture only for the chain the
|
|
107
|
+
* coin is native to — not for every chain the coin has been bridged onto. Ether
|
|
108
|
+
* on Base is the case that exposed it: `8453/<zero address>` is a 404, so the
|
|
109
|
+
* lookup fell through to the chain mark and drew Base's blue disc where the
|
|
110
|
+
* ether diamond belongs. The same picture is one source away under `1/<zero
|
|
111
|
+
* address>`, and gib.show's multi-source lookup will cross chains to reach it.
|
|
112
|
+
*
|
|
113
|
+
* READ FROM THE TABLE, NOT FROM A LIST WRITTEN HERE. The generated chain table
|
|
114
|
+
* orders the bridge's own chains first and the rest in the order the product
|
|
115
|
+
* chose, so the EARLIEST entry carrying a symbol is the chain that coin came
|
|
116
|
+
* from: ether resolves to Ethereum ahead of the dozen chains that also call
|
|
117
|
+
* their coin ETH, and the mapping stays right as the table grows. The table is
|
|
118
|
+
* reversed before the map is built because a later `set` wins — reversing makes
|
|
119
|
+
* the earliest entry the last one written.
|
|
120
|
+
*
|
|
121
|
+
* A coin whose home chain has no dedicated picture — Binance Coin, Polygon
|
|
122
|
+
* Ecosystem Token, Avalanche — loses nothing. Their home chain IS the chain
|
|
123
|
+
* they are asked about, so the list collapses to what it already was, and for
|
|
124
|
+
* a chain's own coin the chain mark is the coin mark.
|
|
125
|
+
*/
|
|
126
|
+
const homeChainOfSymbol = new Map([...chainTable].reverse().map((entry) => [entry.nativeCurrency.symbol, entry.id]));
|
|
127
|
+
/** Every chain's own native symbol, for resolving a coin from its chain alone. */
|
|
128
|
+
const symbolOfChain = new Map(chainTable.map((entry) => [entry.id, entry.nativeCurrency.symbol]));
|
|
129
|
+
/**
|
|
130
|
+
* The gib.show sources for a chain's NATIVE COIN, best first.
|
|
131
|
+
*
|
|
132
|
+
* The service serves the first source that resolves: the coin as this chain
|
|
133
|
+
* keys it, then the coin as its home chain keys it, then the chain's own mark.
|
|
134
|
+
* The last is an honest fallback rather than a mistake — for a chain's own coin
|
|
135
|
+
* the two marks are the same picture.
|
|
136
|
+
*
|
|
137
|
+
* @param chainId - the chain the coin is being shown on
|
|
138
|
+
* @returns the ordered source list, for {@link imageLinks.images}
|
|
139
|
+
*/
|
|
140
|
+
export const nativeCoinImageSources = (chainId) => {
|
|
141
|
+
const sources = [`${chainId}/${zeroAddress}`];
|
|
142
|
+
const symbol = symbolOfChain.get(chainId);
|
|
143
|
+
const home = symbol === undefined ? undefined : homeChainOfSymbol.get(symbol);
|
|
144
|
+
if (home !== undefined && home !== chainId) {
|
|
145
|
+
sources.push(`${home}/${zeroAddress}`);
|
|
146
|
+
}
|
|
147
|
+
sources.push(`${chainId}/`);
|
|
148
|
+
return sources;
|
|
149
|
+
};
|
|
150
|
+
/**
|
|
151
|
+
* Resolves the picture of a chain's native coin, as opposed to of the chain.
|
|
152
|
+
*
|
|
153
|
+
* @param chainId - the chain the coin is being shown on
|
|
154
|
+
* @returns an image url
|
|
155
|
+
*/
|
|
156
|
+
export const nativeCoinLogoUrl = (chainId) => imageLinks.images(nativeCoinImageSources(chainId));
|
package/dist/networks.js
CHANGED
|
@@ -1,10 +1,47 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
import { registerChainNames } from '@gibs/bridge-sdk/chain-names';
|
|
2
|
+
import { chainTable } from './chain-table.js';
|
|
3
|
+
/**
|
|
4
|
+
* Turns one row of the generated table into the shape viem wants.
|
|
5
|
+
*
|
|
6
|
+
* NAMED VIEM IMPORTS USED TO LIVE HERE — 37 of them, each pulling that chain's
|
|
7
|
+
* whole definition including fee logic, formatters and contract addresses this
|
|
8
|
+
* application never reads. That cost about 3.7 kB compressed for a third of the
|
|
9
|
+
* chains the aggregators quote; naming all 73 would have cost about 7.3 kB
|
|
10
|
+
* against roughly 7.8 kB of headroom under the first-load budget. The generated
|
|
11
|
+
* table carries the same 73 in 2.6 kB, so the whole supported set now weighs
|
|
12
|
+
* less than the third of it that shipped before.
|
|
13
|
+
*
|
|
14
|
+
* A namespace import is still never used, for the reason the old comment here
|
|
15
|
+
* gave: `Object.values(chains)` defeats tree-shaking and emitted all ~674
|
|
16
|
+
* definitions, measured at 255 kB. The generator does that read in Node, at
|
|
17
|
+
* build time, where it costs a reader nothing.
|
|
18
|
+
*
|
|
19
|
+
* `blockExplorers` is omitted rather than faked when a chain has no explorer —
|
|
20
|
+
* viem treats the field as optional and an empty url would render a dead link.
|
|
21
|
+
*/
|
|
22
|
+
const toViemChain = (entry) => ({
|
|
23
|
+
id: entry.id,
|
|
24
|
+
name: entry.name,
|
|
25
|
+
nativeCurrency: entry.nativeCurrency,
|
|
26
|
+
rpcUrls: { default: { http: [...entry.http] } },
|
|
27
|
+
...(entry.explorer === null
|
|
28
|
+
? {}
|
|
29
|
+
: { blockExplorers: { default: { name: 'Explorer', url: entry.explorer } } }),
|
|
30
|
+
// WITHOUT THIS, NOTHING CAN BATCH A READ. viem's `multicall` action reads the
|
|
31
|
+
// Multicall3 address off the chain and throws `ChainDoesNotSupportContract`
|
|
32
|
+
// when it is absent, so every chain built here refused — including
|
|
33
|
+
// PulseChain, whose token-metadata fallback failed with exactly that.
|
|
34
|
+
//
|
|
35
|
+
// It went missing when this table replaced viem's own chain objects to keep
|
|
36
|
+
// 255 kB of unused per-chain data out of the build. The table kept the four
|
|
37
|
+
// fields a TRANSPORT needs and dropped the one field an ACTION needs.
|
|
38
|
+
//
|
|
39
|
+
// Read per chain, never assumed: the canonical `0xcA11bde0…` covers most, but
|
|
40
|
+
// there are 8 distinct deployments across the chains listed here.
|
|
41
|
+
...(entry.multicall3 === null
|
|
42
|
+
? {}
|
|
43
|
+
: { contracts: { multicall3: { address: entry.multicall3 } } }),
|
|
44
|
+
});
|
|
8
45
|
/**
|
|
9
46
|
* Every Ethereum-Virtual-Machine chain this client can build a public client for.
|
|
10
47
|
*
|
|
@@ -18,43 +55,7 @@ import { abstract, arbitrum, aurora, avalanche, base, berachain, blast, boba, bs
|
|
|
18
55
|
* for them. Anything wallet-facing that needs them keys off the aggregator's
|
|
19
56
|
* chain identifiers instead.
|
|
20
57
|
*/
|
|
21
|
-
export const evmChains =
|
|
22
|
-
mainnet,
|
|
23
|
-
pulsechain,
|
|
24
|
-
sepolia,
|
|
25
|
-
pulsechainV4,
|
|
26
|
-
bsc,
|
|
27
|
-
arbitrum,
|
|
28
|
-
base,
|
|
29
|
-
blast,
|
|
30
|
-
avalanche,
|
|
31
|
-
polygon,
|
|
32
|
-
scroll,
|
|
33
|
-
optimism,
|
|
34
|
-
linea,
|
|
35
|
-
zksync,
|
|
36
|
-
polygonZkEvm,
|
|
37
|
-
gnosis,
|
|
38
|
-
fantom,
|
|
39
|
-
fuse,
|
|
40
|
-
boba,
|
|
41
|
-
unichain,
|
|
42
|
-
aurora,
|
|
43
|
-
sei,
|
|
44
|
-
immutableZkEvm,
|
|
45
|
-
sonic,
|
|
46
|
-
gravity,
|
|
47
|
-
taiko,
|
|
48
|
-
cronos,
|
|
49
|
-
cronoszkEVM,
|
|
50
|
-
fraxtal,
|
|
51
|
-
abstract,
|
|
52
|
-
rootstock,
|
|
53
|
-
celo,
|
|
54
|
-
worldchain,
|
|
55
|
-
mantle,
|
|
56
|
-
berachain,
|
|
57
|
-
];
|
|
58
|
+
export const evmChains = chainTable.map(toViemChain);
|
|
58
59
|
/**
|
|
59
60
|
* Lookup from a chain id to its viem chain definition, for supported chains only.
|
|
60
61
|
*
|
|
@@ -63,6 +64,12 @@ export const evmChains = [
|
|
|
63
64
|
* numeric-versus-string mismatch reads as "chain not supported".
|
|
64
65
|
*/
|
|
65
66
|
export const evmChainsById = new Map(evmChains.map((chain) => [chain.id, chain]));
|
|
67
|
+
// Hand these names to the SDK's display-name table so ONE function answers
|
|
68
|
+
// "what is this chain called" everywhere. Done at module load, before anything
|
|
69
|
+
// renders, because a name that arrives late is a name that changes under the
|
|
70
|
+
// reader — which is precisely the flicker this removes. The SDK's own entries
|
|
71
|
+
// win on conflict, so the product's chosen spellings are not overwritten.
|
|
72
|
+
registerChainNames(evmChains.map((chain) => [chain.id, chain.name]));
|
|
66
73
|
/**
|
|
67
74
|
* Whether this client can reach a chain over Ethereum-style remote procedure calls.
|
|
68
75
|
*
|
package/dist/token-metadata.js
CHANGED
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
import { nativeTokenName, nativeTokenSymbol, toChain } from '@gibs/bridge-sdk/config';
|
|
2
|
+
import { isNativeAsset } from '@gibs/bridge-sdk/ecosystems';
|
|
2
3
|
import * as _ from 'lodash-es';
|
|
3
|
-
import { erc20Abi, erc20Abi_bytes32, hexToString
|
|
4
|
+
import { erc20Abi, erc20Abi_bytes32, hexToString } from 'viem';
|
|
4
5
|
import { clientFromChain } from './client.js';
|
|
5
6
|
import { evmChainsById } from './networks.js';
|
|
7
|
+
/**
|
|
8
|
+
* How many tokens one multicall asks about. Results come back flat, so each
|
|
9
|
+
* loop below MUST pair a result triple with the address chunk that produced it
|
|
10
|
+
* — see the primary loop for what indexing the flat array cost.
|
|
11
|
+
*/
|
|
12
|
+
const TOKENS_PER_MULTICALL = 100;
|
|
6
13
|
const bytes32Whitelist = new Set();
|
|
7
14
|
// In-memory store for token metadata (loaded once, no persistence)
|
|
8
15
|
const tokenMetadataStore = new Map();
|
|
@@ -81,7 +88,11 @@ async function batchFetchTokenMetadata(chainId, tokenAddresses) {
|
|
|
81
88
|
const nativeTokens = [];
|
|
82
89
|
const erc20Tokens = [];
|
|
83
90
|
tokenAddresses.forEach((address) => {
|
|
84
|
-
|
|
91
|
+
// The registry's rule, not a hand-written one. Two spellings of the same
|
|
92
|
+
// comparison sat here — an exact match OR a lower-cased one — which is what
|
|
93
|
+
// a duplicated rule looks like once nobody is sure which half is load
|
|
94
|
+
// bearing.
|
|
95
|
+
if (isNativeAsset(address, 'evm')) {
|
|
85
96
|
nativeTokens.push(address);
|
|
86
97
|
}
|
|
87
98
|
else {
|
|
@@ -99,7 +110,7 @@ async function batchFetchTokenMetadata(chainId, tokenAddresses) {
|
|
|
99
110
|
return results;
|
|
100
111
|
}
|
|
101
112
|
// console.log(`Processing ${erc20Tokens.length} ERC20 tokens for chain ${chainId}:`, erc20Tokens)
|
|
102
|
-
const addressChunks = _.chunk(erc20Tokens,
|
|
113
|
+
const addressChunks = _.chunk(erc20Tokens, TOKENS_PER_MULTICALL);
|
|
103
114
|
const methods = ['symbol', 'name', 'decimals'];
|
|
104
115
|
const addressChunksToCallChunks = (addressChunks, abi) => addressChunks.map((chunk) => chunk.map((address) => methods.map((functionName) => ({
|
|
105
116
|
functionName,
|
|
@@ -111,16 +122,23 @@ async function batchFetchTokenMetadata(chainId, tokenAddresses) {
|
|
|
111
122
|
// Try with standard ERC20 ABI first
|
|
112
123
|
const chunkedCalls = addressChunksToCallChunks(addressChunks, (address) => bytes32Whitelist.has(getStoreKey(chainId, address)) ? erc20Abi_bytes32 : erc20Abi);
|
|
113
124
|
const fallback = [];
|
|
114
|
-
for (const chunk of chunkedCalls) {
|
|
115
|
-
//
|
|
125
|
+
for (const [chunkIndex, chunk] of chunkedCalls.entries()) {
|
|
126
|
+
// The addresses THIS chunk asked about. Indexing the flat `erc20Tokens`
|
|
127
|
+
// here instead was a silent data-corruption bug: `index` restarts at 0 for
|
|
128
|
+
// every chunk, so with more than TOKENS_PER_MULTICALL tokens on one chain,
|
|
129
|
+
// the second chunk's results were stored under the FIRST chunk's addresses
|
|
130
|
+
// — every token past the first 100 got another token's name, symbol and
|
|
131
|
+
// decimals. A wrong `decimals` misprints every amount rendered for that
|
|
132
|
+
// token. Reading from the same partition that built the calls makes the
|
|
133
|
+
// pairing structural rather than arithmetic.
|
|
134
|
+
const chunkAddresses = addressChunks[chunkIndex];
|
|
116
135
|
try {
|
|
117
136
|
const batchResults = await client.multicall({
|
|
118
137
|
allowFailure: true,
|
|
119
138
|
contracts: _.flatten(chunk),
|
|
120
139
|
});
|
|
121
|
-
// console.log(`Multicall results for chain ${chainId}:`, batchResults.length, 'results')
|
|
122
140
|
_.chunk(batchResults, 3).forEach((batch, index) => {
|
|
123
|
-
const tokenAddress =
|
|
141
|
+
const tokenAddress = chunkAddresses[index];
|
|
124
142
|
const symbol = batch[0].result;
|
|
125
143
|
const name = batch[1].result;
|
|
126
144
|
const decimals = Number(batch[2].result);
|
|
@@ -136,17 +154,21 @@ async function batchFetchTokenMetadata(chainId, tokenAddresses) {
|
|
|
136
154
|
}
|
|
137
155
|
catch (error) {
|
|
138
156
|
console.error(`Multicall failed for chain ${chainId}:`, error);
|
|
139
|
-
//
|
|
140
|
-
fallback
|
|
157
|
+
// Only THIS chunk's addresses. Pushing every token meant one failing
|
|
158
|
+
// chunk re-queued the whole set through the bytes32 fallback, including
|
|
159
|
+
// the tokens that had just succeeded.
|
|
160
|
+
fallback.push(...chunkAddresses);
|
|
141
161
|
}
|
|
142
162
|
}
|
|
143
163
|
if (fallback.length === 0) {
|
|
144
164
|
return results;
|
|
145
165
|
}
|
|
146
166
|
console.log(`Processing ${fallback.length} tokens in fallback with bytes32 ABI for chain ${chainId}:`, fallback);
|
|
147
|
-
const fallbackAddressChunks = _.chunk(fallback,
|
|
167
|
+
const fallbackAddressChunks = _.chunk(fallback, TOKENS_PER_MULTICALL);
|
|
148
168
|
const fallbackChunkedCalls = addressChunksToCallChunks(fallbackAddressChunks, () => erc20Abi_bytes32);
|
|
149
|
-
for (const chunk of fallbackChunkedCalls) {
|
|
169
|
+
for (const [chunkIndex, chunk] of fallbackChunkedCalls.entries()) {
|
|
170
|
+
// Same pairing rule as the primary loop above.
|
|
171
|
+
const chunkAddresses = fallbackAddressChunks[chunkIndex];
|
|
150
172
|
try {
|
|
151
173
|
console.log(`Executing fallback multicall for chain ${chainId} with ${_.flatten(chunk).length} contracts`);
|
|
152
174
|
const batchResults = await client.multicall({
|
|
@@ -155,7 +177,7 @@ async function batchFetchTokenMetadata(chainId, tokenAddresses) {
|
|
|
155
177
|
});
|
|
156
178
|
console.log(`Fallback multicall results for chain ${chainId}:`, batchResults.length, 'results');
|
|
157
179
|
_.chunk(batchResults, 3).forEach((batch, index) => {
|
|
158
|
-
const tokenAddress =
|
|
180
|
+
const tokenAddress = chunkAddresses[index];
|
|
159
181
|
const symbol = batch[0];
|
|
160
182
|
const name = batch[1];
|
|
161
183
|
const decimals = Number(batch[2]);
|
package/package.json
CHANGED
|
@@ -1,13 +1,32 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gibs/bridge-client",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "Browser-side
|
|
3
|
+
"version": "1.13.0",
|
|
4
|
+
"description": "Browser-side endpoints, clients, and caching for a Gibs Finance bridge interface.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"ethereum",
|
|
7
|
+
"pulsechain",
|
|
8
|
+
"bridge",
|
|
9
|
+
"viem",
|
|
10
|
+
"browser"
|
|
11
|
+
],
|
|
12
|
+
"license": "ISC",
|
|
13
|
+
"author": "Gibs Finance",
|
|
14
|
+
"homepage": "https://gibs.finance",
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "git+https://github.com/gibsfinance/bridge.git",
|
|
18
|
+
"directory": "packages/bridge-client"
|
|
19
|
+
},
|
|
20
|
+
"bugs": {
|
|
21
|
+
"url": "https://github.com/gibsfinance/bridge/issues"
|
|
22
|
+
},
|
|
23
|
+
"engines": {
|
|
24
|
+
"node": ">=20"
|
|
25
|
+
},
|
|
5
26
|
"type": "module",
|
|
27
|
+
"sideEffects": false,
|
|
6
28
|
"main": "./dist/index.js",
|
|
7
29
|
"types": "./dist/index.d.ts",
|
|
8
|
-
"files": [
|
|
9
|
-
"dist"
|
|
10
|
-
],
|
|
11
30
|
"exports": {
|
|
12
31
|
".": {
|
|
13
32
|
"gibs-source": "./src/index.ts",
|
|
@@ -50,27 +69,35 @@
|
|
|
50
69
|
"default": "./dist/token-metadata.js"
|
|
51
70
|
}
|
|
52
71
|
},
|
|
53
|
-
"
|
|
54
|
-
"
|
|
55
|
-
|
|
72
|
+
"files": [
|
|
73
|
+
"dist",
|
|
74
|
+
"!dist/tsconfig.tsbuildinfo",
|
|
75
|
+
"!dist/**/*.test-d.*",
|
|
76
|
+
"!dist/test-utils",
|
|
77
|
+
"LICENSE"
|
|
78
|
+
],
|
|
56
79
|
"scripts": {
|
|
80
|
+
"prepublishOnly": "npx tsc",
|
|
57
81
|
"build": "npx tsc",
|
|
58
82
|
"test": "vitest run",
|
|
59
83
|
"test:watch": "vitest"
|
|
60
84
|
},
|
|
61
|
-
"
|
|
62
|
-
|
|
63
|
-
|
|
85
|
+
"dependencies": {
|
|
86
|
+
"@gibs/bridge-sdk": "^1.13.0",
|
|
87
|
+
"@gibs/common": "^1.13.0",
|
|
88
|
+
"lodash-es": "^4.17.21"
|
|
89
|
+
},
|
|
90
|
+
"peerDependencies": {
|
|
91
|
+
"viem": ">=2.37.0 <3"
|
|
92
|
+
},
|
|
64
93
|
"devDependencies": {
|
|
65
94
|
"@types/lodash-es": "^4.17.12",
|
|
66
95
|
"@types/node": "^24",
|
|
67
96
|
"typescript": "~5.7.2",
|
|
97
|
+
"viem": "^2.46.3",
|
|
68
98
|
"vitest": "^3.1.1"
|
|
69
99
|
},
|
|
70
|
-
"
|
|
71
|
-
"
|
|
72
|
-
"@gibs/common": "^1.12.0",
|
|
73
|
-
"lodash-es": "^4.17.21",
|
|
74
|
-
"viem": "^2.46.3"
|
|
100
|
+
"publishConfig": {
|
|
101
|
+
"access": "public"
|
|
75
102
|
}
|
|
76
103
|
}
|