# @gibs/common > Low-level blockchain helpers shared across the Gibs Finance packages: > cached viem clients with fallback URLs, Multicall3 batching, ERC-20 > metadata reads, memoizing caches and bigint-safe JSON. Nothing in it is > specific to the bridge. ## Install - Run `npm install @gibs/common viem`. - It runs on Node 20 or later, in browsers, and in React Native under Hermes. - `import` loads the ECMAScript module build (`dist/`). `require` loads the CommonJS build (`dist/cjs/`). - React Native 0.77 or later: Metro's default configuration and the React Native jest preset load it with no extra setup. Add no `resolveRequest` hook and no `transformIgnorePatterns`. The `react-native` condition gives an `import` statement the ECMAScript module build and a `require` call the CommonJS build. - It needs no polyfill, not even for `URL`: React Native 0.77's own `URL` and `URLSearchParams` are partial, and no entry point reads them. - Import from the narrowest subpath, for example `@gibs/common/cache`. Metro does not drop unused exports. - It has no runtime dependency except viem. - 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. ## Entry points - `@gibs/common`: everything below. - `@gibs/common/client`: `clientFromChain({ chain, urls })`, `chainKey`, `clientCache`. - `@gibs/common/erc20`: `multicallErc20`, `erc20MetadataCalls`. - `@gibs/common/multicall`: `multicallRead`. - `@gibs/common/cache`: `maxMemoize`, `ttlMemoizeSingle`, `memoizeByKey`. - `@gibs/common/serialize`: `jsonAnyStringify`, `jsonAnyParse`, `isSerializedBigInt`. - `@gibs/common/types`: `Call`, `Erc20Metadata`. - `@gibs/common/url`: `buildUrl`, `buildQuery`, `parseQuery`, `setQueryParameter`, `splitUrl`, `isHttpUrl`, `encodeQueryComponent`, `decodeQueryComponent`. They build and read request addresses with string work, never with `URL`, and encode a query exactly as `URLSearchParams` does. ## Read a token's name, symbol and decimals ```ts import { clientFromChain } from '@gibs/common/client' import { multicallErc20 } from '@gibs/common/erc20' import { mainnet } from 'viem/chains' const client = clientFromChain({ chain: mainnet, urls: ['https://ethereum-rpc.publicnode.com'] }) const [name, symbol, decimals] = await multicallErc20({ client, chain: mainnet, target: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', }) ``` ## Keep a bigint through JSON ```ts import { jsonAnyParse, jsonAnyStringify } from '@gibs/common/serialize' const text = JSON.stringify({ balance: 10n ** 18n }, jsonAnyStringify) const restored = JSON.parse(text, jsonAnyParse) ``` ## Memoize ```ts import { maxMemoize, ttlMemoizeSingle } from '@gibs/common/cache' const square = maxMemoize((x: number) => x * x, 100) const price = ttlMemoizeSingle(async (symbol: string) => symbol, 30_000) ``` `memoizeByKey` keys each answer by a resolver you supply, and exposes the cache so you can evict one answer or clear them all. ```ts import { memoizeByKey } from '@gibs/common/cache' const decimals = memoizeByKey( async ({ chainId, address }: { chainId: number; address: string }) => (chainId === 1 ? 6 : 18), ({ chainId, address }) => `${chainId}-${address.toLowerCase()}`, ) decimals.cache.delete('1-0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48') decimals.cache.clear() ``` ## Rules - `multicallRead` and `multicallErc20` need a chain object that carries a Multicall3 deployment. A chain without one fails. - `clientFromChain` caches by chain id and URL list. The same URLs in a different order make a different client. - `@gibs/common/client` takes a viem chain and URLs. `@gibs/bridge-client/client` takes a chain id. They are different functions. - `multicallErc20` memoizes its answers. A repeat call with the same inputs does not read the chain again. - The `@gibs/common/test-utils/fuzz` subpath is for tests inside the source repository. It is not in the npm package. ## Links - [README](https://www.npmjs.com/package/@gibs/common) - [Gibs Finance llms.txt](https://next.gibs.finance/llms.txt): the whole platform.