Skip to Content
wstGBP is live on Ethereum mainnet. All addresses in these docs are verifiable on-chain.
GuidesIntegration Recipes

Integration Recipes

Practical snippets for integrating wstGBP. They use viem  and wagmi ; the math mirrors the on-chain contract to the wei. Paste the ABI into ./wstgbpAbi.ts first.

addresses.ts
export const WSTGBP = '0x57C3571f10767E49C9d7b60feb6c67804783B7aE' export const TGBP = '0x27f6c8289550fCE67f6B50BeD1F519966aFE5287' export const MULTICALL3 = '0xcA11bde05977b3631167028862bE2a173976CA11'

Read NAV and quoting state

mintcost() and burncost() are already fee-adjusted, so use them directly rather than re-deriving from navprice().

import { createPublicClient, http } from 'viem' import { mainnet } from 'viem/chains' import { wstgbpAbi } from './wstgbpAbi' import { WSTGBP } from './addresses' const pub = createPublicClient({ chain: mainnet, transport: http() }) const [navprice, mintcost, burncost] = await Promise.all([ pub.readContract({ address: WSTGBP, abi: wstgbpAbi, functionName: 'navprice' }), pub.readContract({ address: WSTGBP, abi: wstgbpAbi, functionName: 'mintcost' }), pub.readContract({ address: WSTGBP, abi: wstgbpAbi, functionName: 'burncost' }), ])

Batch every read in one Multicall3 call

Separate calls can land on different blocks, so the values tear. Batch with viem’s multicall to read every value at one block (it routes through Multicall3 at 0xcA11bde05977b3631167028862bE2a173976CA11).

const wst = { address: WSTGBP, abi: wstgbpAbi } as const const [ navprice, mintcost, burncost, mintable, burnable, cooldown, capacity, totalSupply, ] = await pub.multicall({ allowFailure: false, contracts: [ { ...wst, functionName: 'navprice' }, { ...wst, functionName: 'mintcost' }, { ...wst, functionName: 'burncost' }, { ...wst, functionName: 'mintable' }, { ...wst, functionName: 'burnable' }, { ...wst, functionName: 'cooldown' }, { ...wst, functionName: 'capacity' }, { ...wst, functionName: 'totalSupply' }, ], })

Read the market window from the Gate

mintable() and burnable() report whether the market is open at the current block. The market gate (the act proxy) exposes the schedule itself, so a UI can show when minting opens next. See the Gate schedule reads for the full surface. These functions live on the gate, not the token:

import { parseAbi } from 'viem' export const ACT = '0xB59cB4d3075a8ce5013C78e8Bd7aDA3Fd1300f7f' export const gateAbi = parseAbi([ 'function bpsin() view returns (uint256)', 'function bpsout() view returns (uint256)', 'function nextOpenMint() view returns (uint256)', 'function nextHaltMint() view returns (uint256)', 'function nextOpenBurn() view returns (uint256)', 'function nextHaltBurn() view returns (uint256)', ]) const gate = { address: ACT, abi: gateAbi } as const const [bpsin, bpsout, nextOpenMint, nextHaltMint] = await pub.multicall({ allowFailure: false, contracts: [ { ...gate, functionName: 'bpsin' }, { ...gate, functionName: 'bpsout' }, { ...gate, functionName: 'nextOpenMint' }, { ...gate, functionName: 'nextHaltMint' }, ], }) // next* return the upcoming transition as a unix timestamp, with two sentinels: // 0n -> boundary already passed (no transition ahead) // 2n ** 256n - 1n (uint256.max) -> transition never scheduled // The current mainnet config (market open indefinitely) returns 0n from // nextOpen*() and uint256.max from nextHalt*(). Treat both as "no date", // never render them as timestamps.

Gasless approval with permit (EIP-2612)

Sign a standard Permit message instead of sending an approve transaction. The nonce comes from nonces(owner); the domain is spelled out in the Contract Reference. permit is ban-list screened: relayer, owner, and spender must all pass the cop screen.

const nonce = await pub.readContract({ address: WSTGBP, abi: wstgbpAbi, functionName: 'nonces', args: [owner], }) const signature = await wallet.signTypedData({ account, domain: { name: 'Wren Staked tGBP', version: '1', chainId: 1, verifyingContract: WSTGBP, }, types: { Permit: [ { name: 'owner', type: 'address' }, { name: 'spender', type: 'address' }, { name: 'value', type: 'uint256' }, { name: 'nonce', type: 'uint256' }, { name: 'deadline', type: 'uint256' }, ], }, primaryType: 'Permit', message: { owner, spender, value, nonce, deadline }, })

Preview mint & redeem

Quote previews with guard checks, so a UI can show why an amount won’t go through. The underlying WAD math (and reverse quoting) is derived in Mint & Redeem.

preview.ts
export const WAD = 10n ** 18n export const wdiv = (x: bigint, y: bigint) => (x * WAD) / y // floor export const wmul = (x: bigint, y: bigint) => (x * y) / WAD // floor // mint: tGBP in -> wstGBP out export function previewMint(args: { amountIn: bigint; mintcost: bigint; totalSupply: bigint; capacity: bigint; mintable: boolean }): { out: bigint; reason?: 'paused' | 'dust' | 'capacity' } { if (!args.mintable) return { out: 0n, reason: 'paused' } if (args.amountIn < args.mintcost) return { out: 0n, reason: 'dust' } const out = wdiv(args.amountIn, args.mintcost) if (args.totalSupply + out > args.capacity) return { out, reason: 'capacity' } return { out } } // redeem: wstGBP in -> tGBP out export function previewRedeem(args: { amountIn: bigint; burncost: bigint; burnable: boolean }): { out: bigint; reason?: 'paused' | 'dust' } { if (!args.burnable) return { out: 0n, reason: 'paused' } if (args.amountIn < WAD) return { out: 0n, reason: 'dust' } // min one whole wstGBP return { out: wmul(args.amountIn, args.burncost) } }

Watch events

import { parseAbiItem } from 'viem' // new mints const unwatchMint = pub.watchEvent({ address: WSTGBP, event: parseAbiItem( 'event ContractCreated(address indexed creator, uint256 indexed price, uint256 indexed amount)', ), onLogs: (logs) => console.log('minted', logs), }) // redemptions opened + claims settled const unwatchClaim = pub.watchEvent({ address: WSTGBP, event: parseAbiItem( 'event ClaimProcessed(uint256 indexed id, address indexed claimer, uint256 indexed amount)', ), onLogs: (logs) => console.log('claimed', logs), })

wagmi (React)

import { useReadContracts } from 'wagmi' import { wstgbpAbi } from './wstgbpAbi' import { WSTGBP } from './addresses' const wst = { address: WSTGBP, abi: wstgbpAbi } as const export function useWstgbpState() { return useReadContracts({ allowFailure: false, contracts: [ { ...wst, functionName: 'mintcost' }, { ...wst, functionName: 'burncost' }, { ...wst, functionName: 'mintable' }, { ...wst, functionName: 'burnable' }, { ...wst, functionName: 'cooldown' }, { ...wst, functionName: 'totalSupply' }, ], }) }

For mint/redeem write flows, see Mint & Redeem; for swaps, see Swap Recipes; for historical or aggregated data, use the subgraph in Data & Analytics.

Last updated on