Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

createApyxClient

The single factory function. Pass a chain and a transport; receive a fully-typed client whose three contract modules know exactly which addresses to call.

import { createApyxClient } from '@koed_jang/apyx-sdk';
import { http } from 'viem';
import { mainnet } from 'viem/chains';

const apyx = createApyxClient({ chain: mainnet, transport: http() });

Signature

function createApyxClient(config: ApyxClientConfig): ApyxClient;
type ApyxClientConfig = {
  chain: Chain;
  transport: Transport;
  walletTransport?: Transport;
  account?: Account | Address;
  addresses?: Partial<ApyxAddresses>;
};
FieldRequiredEffect
chainyesviem Chain object. Drives chainId-based address lookup, gas estimation, and EIP-1559 vs legacy tx defaults.
transportyesviem Transport. Used for reads by the underlying publicClient, and for writes too unless walletTransport is set. Typically http(rpcUrl).
walletTransportnoSeparate transport for writes. Set this to custom(window.ethereum) in dApps while keeping transport: http(rpc) for reads — gives you a low-latency public RPC for state and the user’s wallet for signing.
accountnoEither a viem Account (e.g. privateKeyToAccount(...), a hardware-wallet account from a custom toAccount) or a bare Address. When omitted no walletClient is created and write methods throw WalletClientRequiredError.
addressesnoPartial<ApyxAddresses> overlay. Useful for forks, custom redeploys, or chains where you want to point the SDK at a non-canonical address. Each field is independently optional and falls back to the built-in registry; see Addresses for the merge semantics.

Return type

interface ApyxClient {
  chain: Chain;
  addresses: Readonly<ApyxAddresses>;
  publicClient: PublicClient;
  walletClient?: WalletClient;

  apxUSD: ApxUSD;
  apyUSD: ApyUSD;
  apyUSDRateView?: ApyUSDRateView;
}

interface ApyxClientCore {
  chain: Chain;
  addresses: Readonly<ApyxAddresses>;
  publicClient: PublicClient;
  walletClient?: WalletClient;
}

ApyxClientCore is the subset of ApyxClient that contract modules receive at construction. It’s exported because consumers occasionally build their own helpers that take a “client core” — pass it { chain, addresses, publicClient, walletClient } and you can construct your own apxUSD/apyUSD instances against the same fields.

What the factory does

  1. Resolves addresses. Looks up chain.id in APYX_ADDRESSES; throws UnsupportedChainError for any unknown chainId.
  2. Merges overrides. {...builtin, ...config.addresses}.
  3. Validates and freezes addresses. Each non-null entry runs through viem.isAddress(value, { strict: true }). Failure raises InvalidAddressError. The result is Object.freezed so apyx.addresses cannot be mutated post-construction.
  4. Builds clients. A publicClient is always built. A walletClient is built only when account is non-null.
  5. Wires modules. apxUSD(core), apyUSD(core), and (if the chain has a apyUSDRateView address) apyUSDRateView(core, address).
sequenceDiagram
  participant U as Caller
  participant F as createApyxClient
  participant V as viem
  U->>F: { chain, transport, account?, addresses? }
  F->>F: lookup APYX_ADDRESSES[chain.id]
  alt unknown chain
    F-->>U: throw UnsupportedChainError
  end
  F->>F: merge overrides
  F->>V: isAddress(strict) for each field
  alt malformed
    F-->>U: throw InvalidAddressError
  end
  F->>F: Object.freeze(addresses)
  F->>V: createPublicClient(chain, transport)
  alt account passed
    F->>V: createWalletClient(chain, walletTransport ?? transport, account)
  end
  F->>F: wire apxUSD / apyUSD / apyUSDRateView modules
  F-->>U: ApyxClient

Errors thrown at construction

ErrorWhenHow to recover
UnsupportedChainErrorchain.id is not in the built-in registryEither pass a supported chain (Ethereum or Base) or override addresses with the redeploy targets.
InvalidAddressErrorA built-in or overridden address fails viem.isAddress({ strict: true })Provide a properly checksummed (or all-lowercase) hex address of the right length.

Errors are thrown synchronously from createApyxClient itself — there is no async construction path. A successfully returned ApyxClient is guaranteed to have valid, frozen addresses.

Common patterns

Read-only client for a UI

const apyx = createApyxClient({
  chain: mainnet,
  transport: http(import.meta.env.VITE_ETH_RPC_URL),
});

Browser dApp — public RPC + injected wallet

const apyx = createApyxClient({
  chain: mainnet,
  transport: http(rpcUrl),                  // reads via Alchemy / etc
  walletTransport: custom(window.ethereum), // writes via the user's wallet
  account: userAddress,                     // populated after eth_requestAccounts
});

Server-side worker with a private key

const apyx = createApyxClient({
  chain: mainnet,
  transport: http(process.env.RPC_URL),
  account: privateKeyToAccount(process.env.PK as `0x${string}`),
});

Anvil fork test

const apyx = createApyxClient({
  chain: mainnet,
  transport: http('http://127.0.0.1:8545'),
  account: testAccount,
  addresses: {
    apyUSD: '0xRedeployedFork...',          // partial override
  },
});