Skip to main content
This guide sets up the shared building blocks — chain definition, read/write clients, addresses, and ABIs — used by every other Robinhood Chain guide. The examples use viem, but the same calls translate directly to ethers or any EVM library.

Prerequisites

Before starting, make sure you have:
  • Node.js 18+ and a TypeScript project. If you’re starting fresh, follow the TypeScript & Node.js Setup Guide for the base project, then install the EVM dependencies below.
  • Some ETH on Robinhood Chain (chain ID 4663) in the wallet you’ll sign with.
  • Read the Robinhood Chain Overview for the token lifecycle and address book.
No Bags API key is required for Robinhood Chain. You interact with the public smart contracts directly.

1. Install Dependencies

npm install viem dotenv

2. Set Up Environment Variables

Create a .env file. The public RPC works out of the box but is rate-limited; set a dedicated endpoint if you have one.
# .env
ROBINHOOD_RPC_URL=https://rpc.mainnet.chain.robinhood.com
# Required only for guides that send transactions (launch, trade, claim):
PRIVATE_KEY=0xYOUR_PRIVATE_KEY_HERE
Never commit your .env file. Add it to .gitignore. Treat your private key as a secret.

3. Define the Chain

Save this as chain.ts. It defines Robinhood Chain and tunes viem for the chain’s ~100 ms blocks.
chain.ts
import { defineChain } from "viem";

export const ROBINHOOD_CHAIN_ID = 4663;

export const ROBINHOOD_RPC_URL =
  process.env.ROBINHOOD_RPC_URL || "https://rpc.mainnet.chain.robinhood.com";

export const robinhoodChain = defineChain({
  id: ROBINHOOD_CHAIN_ID,
  name: "Robinhood Chain",
  nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 },
  rpcUrls: {
    default: { http: [ROBINHOOD_RPC_URL] },
  },
  blockExplorers: {
    default: { name: "Blockscout", url: "https://robinhoodchain.blockscout.com" },
  },
  contracts: {
    multicall3: { address: "0xcA11bde05977b3631167028862bE2a173976CA11" },
  },
});

4. Addresses & Protocol Constants

Save this as addresses.ts. These are the protocol singletons and shared infrastructure (see the full address book).
addresses.ts
export const ROBINHOOD_LAUNCHPAD = {
  /** Launch entry point + on-chain registry. */
  factory: "0x46aD6f53A3C26C8027826e2104cF0595b7b24D40",
  /** Stateless read aggregator — getTokenState(s), claimableOf. */
  lens: "0xcF8DA63Dd1cb58daDd2c1B350ac756ffA43EF2d4",
  /** Singleton v4 hook shared by all Bags pools. */
  hook: "0x208378dDc05eD5De1833624a30EB9C1d26f86EcC",
  /** Platform treasury (native ETH). */
  vault: "0x26e421917aeA64B615A3127A2BA3AC3051C3ab80",
  /** Robinhood-MODIFIED UniversalRouter fork (custom swap struct). */
  universalRouter: "0x8876789976dEcBfCbBbe364623C63652db8C0904",
  /** v4-periphery quoter (off-chain quoting only). */
  v4Quoter: "0x8Dc178eFB8111BB0973Dd9d722ebeFF267c98F94",
  /** v4 pool state reads: getSlot0(poolId), getLiquidity(poolId). */
  stateView: "0xF3334192D15450CdD385c8B70e03f9A6bD9E673b",
  /** v4 PoolManager singleton (Swap logs). */
  poolManager: "0x8366a39CC670B4001A1121B8F6A443A643e40951",
  /** Canonical Permit2 — spender route for UniversalRouter ERC-20 inputs. */
  permit2: "0x000000000022D473030F116dDEE9F6B43aC78BA3",
  /** aeWETH upgradeable proxy — WETH9-compatible interface. */
  weth: "0x0Bd7D308f8E1639FAb988df18A8011f41EAcAD73",
} as const;

/** First protocol deploy block — lower bound for any log scan. */
export const ROBINHOOD_DEPLOY_BLOCK = 6191492n;

/** Native ETH sentinel address. */
export const ROBINHOOD_NATIVE_TOKEN = "0x0000000000000000000000000000000000000000";

/**
 * Uniswap v4 PoolKey tuning for Bags pools. Must match the factory
 * byte-for-byte or derived poolIds are wrong.
 */
export const ROBINHOOD_POOL = {
  dynamicFeeFlag: 0x800000,
  tickSpacing: 60,
} as const;

/** Fee model: 2% of the ETH/WETH leg on every trade, split 1% vault / 1% creator. */
export const ROBINHOOD_FEES = {
  txFeeBps: 200,
  creatorFeeBps: 100,
  bpsDenominator: 10_000,
} as const;

/** Fixed supply per Bags token: 1,000,000,000 x 1e18. FDV = spot price x 1e9. */
export const ROBINHOOD_TOKEN_SUPPLY_WEI = 1_000_000_000_000000000000000000n;

5. Create the Clients

Save this as clients.ts. The public client is for reads and simulations; the wallet client signs and sends transactions.
clients.ts
import { createPublicClient, createWalletClient, http } from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { robinhoodChain, ROBINHOOD_RPC_URL } from "./chain";

/**
 * Shared read client. `batch.multicall` coalesces parallel readContract calls
 * into single multicall3 requests — the main defense against public-RPC rate
 * limits. 500 ms polling suits the ~100 ms block time.
 */
export const publicClient = createPublicClient({
  chain: robinhoodChain,
  transport: http(ROBINHOOD_RPC_URL, { batch: true }),
  batch: { multicall: true },
  pollingInterval: 500,
});

/** Write client. Only needed for launch / trade / claim guides. */
export function getWalletClient() {
  const pk = process.env.PRIVATE_KEY;
  if (!pk) throw new Error("PRIVATE_KEY is required to send transactions");
  const account = privateKeyToAccount(pk as `0x${string}`);
  return createWalletClient({
    account,
    chain: robinhoodChain,
    transport: http(ROBINHOOD_RPC_URL),
  });
}
In a browser dApp, replace getWalletClient with a wallet-backed client, e.g. createWalletClient({ account, chain: robinhoodChain, transport: custom(window.ethereum) }), and switch the wallet to chain 4663 before writing.

6. Get the ABIs

The Bags contract ABIs are published in the public robinhood-abi directory of the bagsfm/bags-idl repository. It contains seven JSON files:
  • BagsFactory.json, BagsBondingCurve.json, BagsFeeShare.json, BagsLens.json, BagsToken.json, BagsV4Hook.json, BagsVault.json
Import each JSON as an ABI, for example:
abi/index.ts
import bagsFactory from "./BagsFactory.json";
import bagsBondingCurve from "./BagsBondingCurve.json";
import bagsFeeShare from "./BagsFeeShare.json";
import bagsLens from "./BagsLens.json";
import bagsToken from "./BagsToken.json";
import bagsV4Hook from "./BagsV4Hook.json";
import bagsVault from "./BagsVault.json";

export const bagsFactoryAbi = bagsFactory;
export const bagsBondingCurveAbi = bagsBondingCurve;
export const bagsFeeShareAbi = bagsFeeShare;
export const bagsLensAbi = bagsLens;
export const bagsTokenAbi = bagsToken;
export const bagsV4HookAbi = bagsV4Hook;
export const bagsVaultAbi = bagsVault;
Import the full ABIs including their custom error definitions — viem uses them to decode revert reasons into readable errors (e.g. BagsBondingCurve_SlippageExceeded). See the Contracts Reference for the error catalog.

Periphery ABIs (hand-written)

The Uniswap-style infrastructure (UniversalRouter, Permit2, WETH, V4Quoter, StateView) is not part of the Bags ABI export. The Trade Tokens guide includes the minimal hand-written ABIs you need for post-migration swaps. The full definitions are also listed in the Contracts Reference.

7. Verify Your Setup

Read a value from the factory to confirm everything is wired up.
verify.ts
import { publicClient } from "./clients";
import { ROBINHOOD_LAUNCHPAD } from "./addresses";
import { bagsFactoryAbi } from "./abi";

async function main() {
  const [creationFee, tokenCount] = await Promise.all([
    publicClient.readContract({
      address: ROBINHOOD_LAUNCHPAD.factory,
      abi: bagsFactoryAbi,
      functionName: "creationFee",
    }),
    publicClient.readContract({
      address: ROBINHOOD_LAUNCHPAD.factory,
      abi: bagsFactoryAbi,
      functionName: "allTokensLength",
    }),
  ]);

  console.log("Creation fee (wei):", creationFee.toString());
  console.log("Tokens launched:", tokenCount.toString());
}

main().catch(console.error);
npx ts-node verify.ts
If you see the creation fee (currently 0) and a token count printed, you’re ready to move on.

Next steps

Launch a Token

Create a token through the BagsFactory.

Trade Tokens

Buy and sell across both phases.

Read State & Discover

Query state and list tokens with BagsLens.

Claim Creator Fees

Claim accrued fees from BagsFeeShare.