Quick Start
From zero to your first DomFi contract interaction in under 10 minutes. Read prices, open trades, and deposit into the vault.
Prerequisites
- JavaScript path: Node.js 20+ (required by
@domfi/sdk; any runtime with a globalfetchworks) - Solidity / CLI path: Foundry (includes
forge,cast, andanvil) - A wallet with ETH on Base for gas
- USDC on Base for collateral and oracle fees
- An RPC endpoint for Base:
https://mainnet.base.orgfor public access, or Alchemy/Infura for production
Recommended: the TypeScript SDK
For most integrations, the published @domfi/sdk is the fastest path. It gives you one typed client for REST reads, viem-backed RPC reads, wallet-signed trading, token approvals, position valuation, and vault flows — with mainnet/testnet contract addresses and API roots resolved for you. Calling the contracts directly (the rest of this page) remains the lower-level alternative for Foundry/Solidity users or teams that prefer raw ABIs.
Install the SDK
npm install @domfi/sdk viempnpm add @domfi/sdk viemyarn add @domfi/sdk viembun add @domfi/sdk viemviem is a peer dependency your application supplies. Requirements: Node.js >= 20 (or any runtime with global fetch), viem >= 2.21, TypeScript 5.6+ recommended. The package ships dual ESM + CJS builds with types, is side-effect-free / tree-shakeable, and runs in Node and modern browsers. Wallets stay application-owned — the SDK never holds private keys or relays transactions.
Read-only quick start
REST reads need no wallet or RPC. The built-in testnet / mainnet chain profiles ship default REST API roots (https://testnet-api.domination.finance/api/v2 and https://api.domination.finance/api/v2) and resolved contract addresses, so no address wiring is needed:
import { createDomfiClient } from "@domfi/sdk";
const domfi = createDomfiClient({ chain: "testnet" });
const status = await domfi.system.apiStatus();
const markets = await domfi.api.markets.list();
const headPrices = await domfi.api.prices.head();Write-enabled mode
Both the REST and RPC layers are optional. Add viem publicClient / walletClient / account to enable RPC reads and wallet-signed writes:
import { createDomfiClient } from "@domfi/sdk";
import { createPublicClient, createWalletClient, http } from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { base } from "viem/chains";
const account = privateKeyToAccount("0xYOUR_PRIVATE_KEY");
const publicClient = createPublicClient({ chain: base, transport: http("https://mainnet.base.org") });
const walletClient = createWalletClient({ account, chain: base, transport: http("https://mainnet.base.org") });
const domfi = createDomfiClient({
chain: "mainnet",
publicClient,
walletClient,
account: account.address,
});See the npm README for the full write-enabled example (open a trade, approve tokens, deposit into the vault).
What's in the client
| Namespace | Purpose |
|---|---|
domfi.api | Typed REST reads (markets, prices, positions, history) |
domfi.actions | High-level trade & vault actions |
domfi.trading | Prepare → simulate → send → track a trade |
domfi.token | Token approvals |
domfi.valuation | PnL / liquidation / watch |
domfi.vault | LP deposit & withdrawal flows |
domfi.delegation | EIP-712 delegated trading |
domfi.referrals | Referral program |
domfi.points | Points program |
domfi.chain | Resolved addresses / config |
@domfi/sdk/math | Pure bigint protocol math |
Full API documentation lives on the npm page.
Install
npm install viemnpm install etherscurl -L https://foundry.paradigm.xyz | bash
foundryupIncludes forge (build/test/script), cast (CLI calls), and anvil (local node). No Node.js required.
Connect to the Protocol
Start from the deployed Base mainnet addresses below. DomfiRegistry is the discovery entry point, but most integrations pin the current proxy addresses directly.
| Contract | Address | Use For |
|---|---|---|
| DomfiRegistry | 0xe438360464EaDa40b7921C993322bD4dA8881103 | Discover all other contracts |
| DomfiTrading | 0x7447cb5350a096364A13bEAf77916dfB35db9445 | Open and close trades |
| DomfiOracle | 0x1aB9c3A2E1A09f2D06bf4A75d1721c7e113B8D4D | Read dominance prices |
| DomfiVault | 0xA194082Aabb75Dd1Ca9Dc1BA573A5528BeB8c2Fb | LP deposits and withdrawals |
| DomfiTradingStorage | 0x608ff95777F419040a3b1E42ed73dD3EFf42Cc24 | Query open positions |
import { createPublicClient, http } from 'viem';
import { base } from 'viem/chains';
const client = createPublicClient({
chain: base,
transport: http('https://mainnet.base.org'),
});Or verify your connection with cast (included with Foundry):
cast chain-id --rpc-url https://mainnet.base.org
# Expected: 8453Use minimal ABI fragments for the specific calls you make. For full verified ABIs, use BaseScan:
Read a Dominance Price
const price = await client.readContract({
address: '0x1aB9c3A2E1A09f2D06bf4A75d1721c7e113B8D4D',
abi: [{
name: 'getPrice',
type: 'function',
stateMutability: 'view',
inputs: [{ name: 'pairIndex', type: 'uint16' }],
outputs: [{ name: '', type: 'uint256' }],
}],
functionName: 'getPrice',
args: [0], // 0 = BTCDOM
});
console.log('BTCDOM price:', Number(price) / 1e18);
// Expected: ~52.5 (Bitcoin dominance percentage)import { Contract, JsonRpcProvider } from 'ethers';
const provider = new JsonRpcProvider('https://mainnet.base.org');
const oracle = new Contract(
'0x1aB9c3A2E1A09f2D06bf4A75d1721c7e113B8D4D',
[{
name: 'getPrice',
type: 'function',
stateMutability: 'view',
inputs: [{ name: 'pairIndex', type: 'uint16' }],
outputs: [{ name: '', type: 'uint256' }],
}],
provider,
);
const price = await oracle.getPrice(0);
console.log('BTCDOM price:', Number(price) / 1e18);
// Expected: ~52.5 (Bitcoin dominance percentage)// ReadPrice.s.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Script, console} from "forge-std/Script.sol";
interface IDomfiOracle {
function getPrice(uint16 pairIndex) external view returns (uint256);
}
contract ReadPrice is Script {
function run() external view {
IDomfiOracle oracle = IDomfiOracle(
0x1aB9c3A2E1A09f2D06bf4A75d1721c7e113B8D4D
);
uint256 price = oracle.getPrice(0); // 0 = BTCDOM
console.log("BTCDOM price (18 decimals):", price);
// Expected: ~52500000000000000000 (52.5%)
}
}forge script ReadPrice.s.sol --rpc-url https://mainnet.base.orgNo setup required — read a price in one command:
cast call 0x1aB9c3A2E1A09f2D06bf4A75d1721c7e113B8D4D \
"getPrice(uint16)(uint256)" \
0 \
--rpc-url https://mainnet.base.org
# Returns: 52500000000000000000 (18 decimals → 52.5% BTCDOM)| Index | Pair |
|---|---|
| 0 | BTCDOM |
| 1 | ETHDOM |
| 2 | USDTDOM |
| 3 | BNBDOM |
| 4 | SOLDOM |
Open a Trade (Write)
openTrade() submits a real on-chain order. Approve USDC to DomfiTradingStorage, not DomfiTrading, then wait for the approval receipt before you submit the trade. Both steps spend real gas. The oracle fee is charged in USDC and pulled together with your collateral, so approve collateral + oracle fee — no ETH msg.value is needed.
Before you send the transaction:
- USDC must be approved to DomfiTradingStorage, not
DomfiTrading. This is the most common integration mistake. openTrade()charges a flat 0.10 USDC oracle fee, pulled together with your collateral. Read the per-pair fee fromDomfiPairsStorage.pairOracleFee(pairIndex)and approvecollateral + oracleFee— no ETHmsg.valueis required.- Collateral uses 6 decimals because USDC on Base is 6-decimal native USDC.
- Leverage uses 2-decimal precision:
100= 1x,1000= 10x,5000= 50x,25000= 250x. - Execution is asynchronous.
openTrade()queues the order, then an off-chain bot fulfills the price.
import { createPublicClient, createWalletClient, http, parseUnits } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
import { base } from 'viem/chains';
const USDC_ADDRESS = '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913';
const TRADING_ADDRESS = '0x7447cb5350a096364A13bEAf77916dfB35db9445';
const TRADING_STORAGE_ADDRESS = '0x608ff95777F419040a3b1E42ed73dD3EFf42Cc24';
const PAIRS_STORAGE_ADDRESS = '0x444079DDCaFd4feE3812E2fF79c5F74a1F4f9Be1';
const erc20Abi = [{
name: 'approve',
type: 'function',
stateMutability: 'nonpayable',
inputs: [
{ name: 'spender', type: 'address' },
{ name: 'amount', type: 'uint256' },
],
outputs: [{ name: '', type: 'bool' }],
}] as const;
const pairsStorageAbi = [{
name: 'pairOracleFee',
type: 'function',
stateMutability: 'view',
inputs: [{ name: 'pairIndex', type: 'uint16' }],
outputs: [{ name: '', type: 'uint256' }],
}] as const;
const tradingAbi = [{
name: 'openTrade',
type: 'function',
stateMutability: 'nonpayable',
inputs: [
{
name: 't',
type: 'tuple',
components: [
{ name: 'collateral', type: 'uint256' },
{ name: 'openPrice', type: 'uint192' },
{ name: 'tp', type: 'uint192' },
{ name: 'sl', type: 'uint192' },
{ name: 'trader', type: 'address' },
{ name: 'leverage', type: 'uint32' },
{ name: 'pairIndex', type: 'uint16' },
{ name: 'index', type: 'uint8' },
{ name: 'buy', type: 'bool' },
],
},
{ name: 'orderType', type: 'uint8' },
{ name: 'slippageP', type: 'uint256' },
],
outputs: [],
}] as const;
const account = privateKeyToAccount('0xYOUR_PRIVATE_KEY');
const publicClient = createPublicClient({
chain: base,
transport: http('https://mainnet.base.org'),
});
const walletClient = createWalletClient({
account,
chain: base,
transport: http('https://mainnet.base.org'),
});
const collateral = parseUnits('100', 6);
// Step 1: Read the per-pair oracle fee (USDC, 6 decimals)
const oracleFee = await publicClient.readContract({
address: PAIRS_STORAGE_ADDRESS,
abi: pairsStorageAbi,
functionName: 'pairOracleFee',
args: [0], // 0 = BTCDOM
});
// Step 2: Approve collateral + oracle fee to TradingStorage (not Trading)
const approvalHash = await walletClient.writeContract({
address: USDC_ADDRESS,
abi: erc20Abi,
functionName: 'approve',
args: [TRADING_STORAGE_ADDRESS, collateral + oracleFee],
});
await publicClient.waitForTransactionReceipt({ hash: approvalHash });
// Step 3: Submit a 10x long on BTCDOM — the oracle fee is pulled from the USDC approval
await walletClient.writeContract({
address: TRADING_ADDRESS,
abi: tradingAbi,
functionName: 'openTrade',
args: [
{
trader: account.address,
pairIndex: 0,
index: 0,
collateral,
openPrice: 0n,
buy: true,
leverage: 1000,
tp: 0n,
sl: 0n,
},
0,
50,
],
});// OpenTrade.s.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Script} from "forge-std/Script.sol";
interface IERC20 {
function approve(address spender, uint256 amount) external returns (bool);
}
interface IDomfiTrading {
struct Trade {
uint256 collateral;
uint192 openPrice;
uint192 tp;
uint192 sl;
address trader;
uint32 leverage;
uint16 pairIndex;
uint8 index;
bool buy;
}
function openTrade(Trade calldata t, uint8 orderType, uint256 slippageP) external;
}
interface IDomfiPairsStorage {
function pairOracleFee(uint16 pairIndex) external view returns (uint256);
}
contract OpenTrade is Script {
address constant USDC = 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913;
address constant TRADING = 0x7447cb5350a096364A13bEAf77916dfB35db9445;
address constant TRADING_STORAGE = 0x608ff95777F419040a3b1E42ed73dD3EFf42Cc24;
address constant PAIRS_STORAGE = 0x444079DDCaFd4feE3812E2fF79c5F74a1F4f9Be1;
function run() external {
vm.startBroadcast();
// Step 1: Read the per-pair oracle fee (USDC, 6 decimals)
uint256 oracleFee = IDomfiPairsStorage(PAIRS_STORAGE).pairOracleFee(0); // 0 = BTCDOM
// Step 2: Approve collateral + oracle fee to TradingStorage (not Trading)
IERC20(USDC).approve(TRADING_STORAGE, 100e6 + oracleFee); // 100 USDC + oracle fee
// Step 3: Submit a 10x long on BTCDOM (oracle fee taken from the USDC approval)
IDomfiTrading(TRADING).openTrade(
IDomfiTrading.Trade({
collateral: 100e6, // 100 USDC (6 decimals)
openPrice: 0, // market order — filled by oracle
tp: 0, // no take profit
sl: 0, // no stop loss
trader: msg.sender,
leverage: 1000, // 10x (2 decimal precision)
pairIndex: 0, // BTCDOM
index: 0, // first trade slot
buy: true // long
}),
0, // 0 = market order
50 // 0.5% slippage (2 decimals)
);
vm.stopBroadcast();
}
}forge script OpenTrade.s.sol \
--rpc-url https://mainnet.base.org \
--private-key 0xYOUR_PRIVATE_KEY \
--broadcastThe order is not opened immediately. Wait for the price bot to fulfill it, then read the resulting position from DomfiTradingStorage or watch the MarketOpenExecuted event.
Decimal Reference
| Value | Precision | Example |
|---|---|---|
| USDC amounts (collateral) | 6 decimals | $100 = 100000000 |
| Prices (dominance) | 18 decimals | 52.5% = 52500000000000000000 |
| Leverage | 2 decimals | 10x = 1000, 250x = 25000 |
| Slippage | 2 decimals | 0.5% = 50 |
| Fee rates | 2 decimals | 0.1% = 10 |