# @gibs/bridge-sdk > A TypeScript library that prices and builds transfers across the Gibs > Finance omnibridges (PulseChain with Ethereum, PulseChain with BNB Smart > Chain). It also builds the requests for the aggregator routes (LI.FI, > Relay, NEAR Intents) that reach those bridges from other chains. It does > not sign or send anything. You bring a viem client and a wallet. ## Install - Run `npm install @gibs/bridge-sdk viem`. - It runs on Node 20 or later (`engines.node` is `>=20`), in browsers, and in React Native under Hermes. - viem is a peer dependency. The range is `>=2.35.0 <3`. - Version note: 1.12.0 and older on npm are broken. 1.13.0 is the first usable version. ## Ways to use the package The `exports` map picks the build. No consumer configuration is needed. - ECMAScript modules: `import { pathway } from '@gibs/bridge-sdk/config'` loads `dist/config.js`. - CommonJS: `require('@gibs/bridge-sdk/config')` loads `dist/cjs/config.js`, with its own declaration files. - React Native 0.77 or later, default `metro.config.js`. Add no `resolveRequest` hook. In 0.79 or later, Metro reads `exports`: the `react-native` condition gives an `import` statement the ECMAScript module build and a `require` call the CommonJS build. The SDK then shares your build of viem, so Metro bundles viem once. - React Native jest preset: loads the CommonJS build. Do not add `transformIgnorePatterns` for these packages. - Metro with package exports off (the default in React Native 0.77 and 0.78): every subpath resolves through a folder the package ships for it, such as `config/package.json`, which points at the CommonJS build. Import the subpath as usual, never a `dist` path. - No entry point except `@gibs/bridge-sdk/ton` needs a polyfill. That includes a `URL` polyfill: React Native 0.77's own `URL` and `URLSearchParams` are partial, and no entry point reads them. ```ts import { Chains, pathway, Providers } from '@gibs/bridge-sdk/config' import { amountAfterBridgeFee, bridgeCost } from '@gibs/bridge-sdk/settings' const route = pathway([Providers.PULSECHAIN, Chains.PLS, Chains.ETH], true) const cost = bridgeCost({ amountToBridge: 10n ** 18n, bridgeFee: 3n * 10n ** 15n }) console.log(route?.from, amountAfterBridgeFee({ amountToBridge: 10n ** 18n, bridgeCost: cost })) ``` Bundle weight. Metro does not drop unused exports, so the entry point decides the weight. Measured in a React Native 0.87.1 production bundle that already holds viem: - `/config` and `/settings` (offline quoting): about 24 kB. - `/chain-info` (live fee reads) with the above: about 1.16 MB, because it loads `viem/chains` (1.12 MB). About 41 kB if the app already imports `viem/chains`. - The root entry point: about 1.29 MB. About 164 kB if the app already imports `viem/chains`. TON: - `@gibs/bridge-sdk/ton-connect`: TON Connect requests and address re-encoding. No TON library, no `Buffer`. - `@gibs/bridge-sdk/ton`: the same, plus `tonExternalMessageHash`, which needs `@ton/core`. Set `globalThis.Buffer` (the `buffer` package) before importing it in a browser or React Native. In React Native, Metro also needs `expo-crypto` installed, because `@ton/crypto` requires it there. - `@gibs/bridge-sdk/ton-execution`: the old name of `@gibs/bridge-sdk/ton`. ## Entry points Import from the narrowest subpath. The root `@gibs/bridge-sdk` exports everything except TON. - `@gibs/bridge-sdk/config`: chains, providers, pathways, native-asset tables. - `@gibs/bridge-sdk/types`: shared types such as `BridgeKey` and `Token`. - `@gibs/bridge-sdk/chains`: viem chain objects with logos and public RPC URLs. `demoRpcUrls` is for demos only. - `@gibs/bridge-sdk/chain-info`: on-chain reads (token mappings, fees, minimum amounts). - `@gibs/bridge-sdk/settings`: fee and amount arithmetic. - `@gibs/bridge-sdk/consolidated-quote`: LI.FI request builders and parsers. - `@gibs/bridge-sdk/relay-quote`: Relay request builders and parsers. - `@gibs/bridge-sdk/near-intents`: NEAR Intents requests and parsers. - `@gibs/bridge-sdk/pre-quote`: price checks before a binding quote. - `@gibs/bridge-sdk/routing`: route search across carriers. - `@gibs/bridge-sdk/execution`: execution plans (`planExecution`, `planCandidateExecution`, `PlannedTx`, `DeliveryChoice`, `AllowanceReader`, `assumeNoAllowance`). - `@gibs/bridge-sdk/claims`: manual claim transactions (`buildClaimTransaction`, `claimCall`, `packSignatures`, `signatureToVRS`, `encodeReleaseWithoutTipData`, `encodeReleaseToRouterData`). - `@gibs/bridge-sdk/image-links`: image URLs from gib.show. - `@gibs/bridge-sdk/abis`: contract ABIs. - `@gibs/bridge-sdk/ton-connect`: TON Connect requests, with no TON library. - `@gibs/bridge-sdk/ton`: TON Connect requests and the external message hash (needs `@ton/core`). ## Chains and pathways A chain is a hex id from the `Chains` enum. A route is a `BridgeKey`: `[provider, fromChain, toChain]`. `pathway` returns the contract addresses for a key, or `undefined` when no pathway exists. ```ts import { Chains, Providers, pathway } from '@gibs/bridge-sdk/config' import type { BridgeKey } from '@gibs/bridge-sdk/types' const bridgeKey: BridgeKey = [Providers.PULSECHAIN, Chains.ETH, Chains.PLS] const route = pathway(bridgeKey, true) // true: mainnet only if (route) { route.from // the mediator on Ethereum, where funds enter route.feeManager // 'to': the PulseChain mediator owns the fee manager } ``` ## Fees: direction and units These rules must hold in every integration. - PulseChain is the home side of both omnibridges. - Foreign to home (`feeF2H`) means entering PulseChain. - Home to foreign (`feeH2F`) means leaving PulseChain. - Use the fee for your direction. Do not use one fee for both. - Bridge fees are a rate per `1e18`. `1e18` is one hundred percent. - Aggregator referral fees are basis points. `10_000n` is one hundred percent. - LI.FI takes its fee as a decimal fraction (`0.001` is a tenth of a percent). - Fees are on-chain settings. Read them. Do not hard-code them. ```ts import { loadBridgeFees } from '@gibs/bridge-sdk/chain-info' import { Chains, pathway, Providers } from '@gibs/bridge-sdk/config' import { amountAfterBridgeFee, bridgeCost } from '@gibs/bridge-sdk/settings' import type { PublicClient } from 'viem' declare const ethereumClient: PublicClient declare const pulsechainClient: PublicClient const route = pathway([Providers.PULSECHAIN, Chains.ETH, Chains.PLS], true) if (route) { const { feeF2H } = await loadBridgeFees({ pathway: route, fromChainClient: ethereumClient, toChainClient: pulsechainClient, }) const amountToBridge = 1_000_000n const cost = bridgeCost({ amountToBridge, bridgeFee: feeF2H }) const received = amountAfterBridgeFee({ amountToBridge, bridgeCost: cost }) } ``` `loadBridgeFees` reads the default rate. It does not read per-token rates. ## Tokens that are not bridged yet `tokenBridgeInfo` asks both mediators how a token maps across the bridge. A `null` `assetOutAddress` is a normal answer. The token gets an address on the far side when its first transfer arrives. Always check for `null`. ```ts import { tokenBridgeInfo } from '@gibs/bridge-sdk/chain-info' import { Chains, Providers } from '@gibs/bridge-sdk/config' import type { Token } from '@gibs/bridge-sdk/types' import type { PublicClient } from 'viem' declare const assetIn: Token declare const ethereumClient: PublicClient declare const pulsechainClient: PublicClient const info = await tokenBridgeInfo({ bridgeKey: [Providers.PULSECHAIN, Chains.ETH, Chains.PLS], assetIn, isProd: true, fromChainClient: ethereumClient, toChainClient: pulsechainClient, }) if (info && info.assetOutAddress === null) { // Not bridged yet. Do not treat this as an error. } ``` ## Aggregator identity: pass your own The package ships no API key. Pass your own. - Relay: pass your own `apiKey` to `relayRequestHeaders`. Name your own `relayReferrer`. The package sends no referrer by default, because Relay rejects a referrer without a key. - LI.FI: set your own `lifiIntegrator`. The package sends no integrator by default. A positive `lifiFee` without your own integrator throws. - NEAR Intents: no key is needed. No `referral` is sent unless you pass one. The `User-Agent` names Gibs Finance unless you pass your own `userAgent`, or `null` for none. Browsers drop it; Node and React Native send it. ```ts import { buildLifiContractCallsRequest, type ConsolidatedQuoteRequest, } from '@gibs/bridge-sdk/consolidated-quote' import { nearIntentsRequestHeaders } from '@gibs/bridge-sdk/near-intents' import { buildRelayQuoteRequest, relayQuoteUrl, relayRequestHeaders } from '@gibs/bridge-sdk/relay-quote' declare const baseRequest: ConsolidatedQuoteRequest declare const myRelayApiKey: string const request: ConsolidatedQuoteRequest = { ...baseRequest, lifiIntegrator: 'your-app.example', lifiFee: 0.001, relayReferrer: 'your-app.example', } const lifiBody = buildLifiContractCallsRequest(request) const relayBody = buildRelayQuoteRequest(request) if (relayBody) { await fetch(relayQuoteUrl, { method: 'POST', body: JSON.stringify(relayBody), headers: relayRequestHeaders(myRelayApiKey), }) } const nearHeaders = nearIntentsRequestHeaders(undefined, { userAgent: 'your-app/1.0' }) ``` ## Fees: nothing is added for you - No builder adds a fee, a payout address or a Gibs Finance label. A request carries one only when you pass it. - Bridge fee: on-chain, on every direct crossing. Read it with `loadBridgeFees`. You cannot turn it off. - Delivery fee: only with `shouldDeliver: true` and a fee director. See it with `deliveryFee`. - LI.FI fee: only with `lifiFee` and your own `lifiIntegrator`. - Relay application fee: only with `relayAppFee: { recipient, basisPoints }`. - Provider fees (gas, solver, protocol): charged by LI.FI, Relay or NEAR Intents. Read them with `lifiQuoteFees`, `relayQuoteFees` and the NEAR Intents quote parser. - NEAR Intents adds 25 basis points to a quote sent without a partner key. - `@gibs/bridge-sdk/referral` holds Gibs Finance's own values (`referralIntegrator`, `relayReferralRecipient`, `defaultReferralFeeBasisPoints`). They pay Gibs Finance. Do not pass them from your own app. ## RPC endpoints: the defaults are for demos only - Every reader takes your viem clients. None builds its own. - `chainsMetadata` carries public endpoints only. - `demoRpcUrls` and `demoRpcUrlsFor` add a shared valve.city key, `vk_demo`. They are for demos only. The key is public, but its rate budget is shared and the Gibs Finance operator runs the proxy. - In production, use your own RPC provider. ```ts import { demoRpcUrlsFor } from '@gibs/bridge-sdk/chains' import { createPublicClient, fallback, http } from 'viem' import { mainnet } from 'viem/chains' const ethereumClient = createPublicClient({ chain: mainnet, transport: http('https://your-rpc.example') }) const demoOnly = createPublicClient({ chain: mainnet, transport: fallback(demoRpcUrlsFor(mainnet.id).map((url) => http(url))), }) ``` ## Nulls and throws - A question the package cannot answer returns `null`, `undefined` or `false`. - A caller mistake or a failed chain read throws. - Every request builder returns `null` for a request its provider cannot express. - Every response parser returns `null` for an unexpected response shape. - Check each return value before you use it. ## Links - [Integrate Gibs into a wallet or app](https://next.gibs.finance/docs/): search, plan, send, track and claim, with two complete examples. The same guide ships in this package as `docs/integration-guide.md`. - [README](https://www.npmjs.com/package/@gibs/bridge-sdk): the full reference. - [Gibs Finance llms.txt](https://next.gibs.finance/llms.txt): the whole platform. - [@gibs/quotes](https://next.gibs.finance/docs/packages/quotes/llms.txt): live multi-provider quotes.