Configuration

The integration examples in this folder use viemarrow-up-right with a public client (read-only) and a wallet client (signed transactions). Create both once and reuse them across Create a market, Resolve a market, Split, merge and redeem, Conditional market, and Futarchy markets.

Note: The viem configuration below is provided as an example. If your project already has publicClient and walletClient (e.g. from Wagmi, RainbowKit or another library), you can use them directly; the examples in this documentation only need clients compatible with viem’s interface for readContract, simulateContract, writeContract, and waitForTransactionReceipt.


Dependencies

npm i viem

Client helpers

Create two helpers that take a chain (from viem/chains) so the same code works on any network. The wallet client needs a private key (e.g. from process.env.PRIVATE_KEY).

import { createPublicClient, createWalletClient, http } from "viem";
import type { Chain } from "viem";
import { privateKeyToAccount } from "viem/accounts";

export function getPublicClient(chain: Chain) {
  return createPublicClient({
    chain,
    transport: http(),
  });
}

export function getWalletClient(chain: Chain, privateKey: `0x${string}`) {
  const account = privateKeyToAccount(privateKey);
  return createWalletClient({
    chain,
    transport: http(),
    account,
  });
}

/** ERC20 `approve(spender, amount)` ABI. Use for collateral and outcome token approvals (split, merge, redeem, swaps). */
export const ERC20_APPROVE_ABI = [
  {
    inputs: [
      { name: "spender", type: "address" },
      { name: "amount", type: "uint256" },
    ],
    name: "approve",
    outputs: [{ type: "bool" }],
    stateMutability: "nonpayable",
    type: "function",
  },
] as const;

/** Market contract ABI: resolve, wrappedOutcome(index), parentMarket, parentOutcome, numOutcomes. Use for resolve and for reading outcome token addresses. numOutcomes() returns the count without INVALID_RESULT; use numOutcomes() + 1 if you need to include it. */
export const MARKET_ABI = [
  {
    inputs: [],
    name: "resolve",
    outputs: [],
    stateMutability: "nonpayable",
    type: "function",
  },
  {
    inputs: [{ name: "index", type: "uint256" }],
    name: "wrappedOutcome",
    outputs: [
      { name: "wrapped1155", type: "address" },
      { name: "data", type: "bytes" },
    ],
    stateMutability: "view",
    type: "function",
  },
  {
    inputs: [],
    name: "parentMarket",
    outputs: [{ type: "address" }],
    stateMutability: "view",
    type: "function",
  },
  {
    inputs: [],
    name: "parentOutcome",
    outputs: [{ type: "uint256" }],
    stateMutability: "view",
    type: "function",
  },
  {
    inputs: [],
    name: "numOutcomes",
    outputs: [{ type: "uint256" }],
    stateMutability: "view",
    type: "function",
  },
] as const;

Usage (any chain):

  • publicClient: for readContract, simulateContract, waitForTransactionReceipt, etc.

  • walletClient: for writeContract (sending transactions).

  • account: use account.address when calling simulateContract with an explicit account.


Deployed contracts by chain

Contract addresses per chain ID. Use the entry for your chain when calling the contracts (e.g. SEER_CONTRACTS[chain.id]).

Chain ID
Chain

1

Ethereum Mainnet

10

Optimism

100

Gnosis

8453

Base

Export the SEER_CONTRACTS object from your setup module so the integration docs can use it. Get addresses for the current chain with SEER_CONTRACTS[chain.id]:


Using in the integration docs

In the rest of the integration docs we obtain clients with getPublicClient(chain) and getWalletClient(chain, process.env.PRIVATE_KEY!), use SEER_CONTRACTS[chain.id] for addresses, and import ERC20_APPROVE_ABI and MARKET_ABI from the same setup module (approve calls and market reads such as wrappedOutcome, resolve). Choose any chain from viem/chains (e.g. gnosis, mainnet, base); the examples are the same for all networks.

Last updated