For the complete documentation index, see llms.txt. This page is also available as Markdown.

Setup Wallet Providers

The SODAX SDK does not force you to use a specific wallet library. Instead, SDK calls accept an IWalletProvider implementation that you supply — either by using the ready-made implementations in @sodax/wallet-sdk-core, or by writing your own against the interface contracts in @sodax/sdk.

Table of Contents


1. Supported provider interfaces

Every chain family has a named interface that @sodax/sdk exports:

Interface

chainType literal

Chains covered

IEvmWalletProvider

'EVM'

Sonic (hub), Ethereum, Arbitrum, Base, BSC, Optimism, Polygon, Avalanche, HyperEVM, Lightlink, Redbelly, Kaia, Hedera

ISolanaWalletProvider

'SOLANA'

Solana

ISuiWalletProvider

'SUI'

Sui

IIconWalletProvider

'ICON'

ICON

IInjectiveWalletProvider

'INJECTIVE'

Injective

IStellarWalletProvider

'STELLAR'

Stellar

IStacksWalletProvider

'STACKS'

Stacks

IBitcoinWalletProvider

'BITCOIN'

Bitcoin

INearWalletProvider

'NEAR'

NEAR

All interfaces extend WalletAddressProvider (from @sodax/sdk), which requires:

The full union of all nine interfaces is IWalletProvider. GetWalletProviderType<K> maps a chain key or ChainType literal to the appropriate specific interface.


2. WalletProviderSlot — compile-time enforcement

Every SDK method that executes a transaction uses WalletProviderSlot<K, Raw> (defined in packages/types/src/common/common.ts) to enforce the pairing between raw mode and the presence of a wallet provider at compile time:

Three rules enforced by TypeScript:

  1. raw: truewalletProvider is forbidden (?: never makes any value a type error). The SDK returns an unsigned transaction payload (TxReturnType<K, true>, e.g. EvmRawTransaction).

  2. raw: false (or omitted)walletProvider is required and is chain-narrowed to the exact interface for K via GetWalletProviderType<K>. The SDK signs and broadcasts, returning a transaction hash (TxReturnType<K, false>, e.g. Hash).

  3. Chain narrowing flows from the chain key — when the caller passes a literal chain key such as ChainKeys.ETHEREUM_MAINNET, TypeScript preserves that as a value type, resolving GetWalletProviderType<typeof ChainKeys.ETHEREUM_MAINNET> to IEvmWalletProvider automatically.


3. wallet-sdk-core: ready-to-use implementations

Install the package:

The package is dependency-free from React and can be used directly in Node.js scripts, bots, and server environments, as well as in browser dApps.

Each chain provider lives under src/wallet-providers/<chain>/:

BaseWalletProvider

All nine provider classes extend BaseWalletProvider<TDefaults>:

Subclass constructors call super(config.defaults). Per-call overrides shallow-merge over the stored defaults at invocation time — nested objects replace wholesale rather than deep-merging.

chainType discriminant

Every I*WalletProvider interface declares readonly chainType as a string literal. This lets both the SDK and application code discriminate at runtime without instanceof:

Valid chainType values: 'EVM', 'BITCOIN', 'SOLANA', 'STELLAR', 'SUI', 'ICON', 'INJECTIVE', 'STACKS', 'NEAR'.

packages/sdk/src/shared/guards.ts also exposes named guards for the most common cases:

Dual config modes (private-key vs browser-extension)

Every provider accepts a discriminated-union config: one variant for server-side/script usage (private key) and one for dApp usage (pre-built client from a browser wallet). Discriminant mechanism varies by chain:

Mechanism
Chains

Field presenceprivateKey field present vs. absent

EVM, ICON, Solana, Sui (uses mnemonics), NEAR

Explicit type field ('PRIVATE_KEY' / 'BROWSER_EXTENSION')

Bitcoin, Stellar

secret nested object ({ privateKey } or { mnemonics }) vs. msgBroadcaster

Injective

Field presenceprivateKey present vs. absent

Stacks

All config types include an optional defaults field for per-method behavioral overrides.

Provider reference

Chain

Provider class

Native SDK

chainType

EVM (12 chains)

EvmWalletProvider

viem

'EVM'

Solana

SolanaWalletProvider

@solana/web3.js

'SOLANA'

Sui

SuiWalletProvider

@mysten/sui

'SUI'

ICON

IconWalletProvider

icon-sdk-js

'ICON'

Injective

InjectiveWalletProvider

@injectivelabs/sdk-ts

'INJECTIVE'

Stellar

StellarWalletProvider

@stellar/stellar-sdk

'STELLAR'

Stacks

StacksWalletProvider

@stacks/transactions

'STACKS'

Bitcoin

BitcoinWalletProvider

bitcoinjs-lib (PSBT)

'BITCOIN'

NEAR

NearWalletProvider

near-api-js

'NEAR'


4. Config type reference per chain

EVM (EvmWalletProvider)

EvmWalletDefaults accepts: sendTransaction, waitForTransactionReceipt, publicClient, walletClient, transport (all optional; applied per-call via mergePolicy).

Solana (SolanaWalletProvider)

SolanaWalletDefaults accepts: connectionCommitment, connectionConfig, sendOptions, confirmCommitment.

Sui (SuiWalletProvider)

SuiWalletDefaults accepts: signAndExecuteTxn (dry-run toggle + response options), getCoins (pagination limit).

ICON (IconWalletProvider)

IconWalletDefaults accepts: stepLimit, version, timestampProvider, jsonRpcId.

Note: rpcUrl is typed as `http${string}` (template literal), not a bare string. EVM and Injective rpcUrl fields have the same constraint. If you pass a string from an environment variable, either narrow it explicitly (e.g. process.env.RPC_URL as \http${string}``) or validate at the boundary.

Injective (InjectiveWalletProvider)

InjectiveWalletDefaults accepts: defaultFunds, defaultMemo, sequence, accountNumber.

Stellar (StellarWalletProvider)

StellarWalletDefaults accepts: pollInterval, pollTimeout, networkPassphrase.

Stacks (StacksWalletProvider)

StacksWalletDefaults accepts: network ('mainnet' | 'testnet'), postConditionMode.

Bitcoin (BitcoinWalletProvider)

BitcoinWalletDefaults accepts: defaultFinalize (whether to finalize PSBTs before returning).

NEAR (NearWalletProvider)

NearWalletDefaults accepts: throwOnFailure, waitUntil, gasDefault, depositDefault.


5. React integration — useWalletProvider

packages/wallet-sdk-react provides useWalletProvider — a hook that reads the chain-appropriate provider from the Zustand store and returns it typed to the correct I*WalletProvider interface.

Pass xChainId or xChainType, never both — the hook asserts this at runtime and the overloads enforce it at compile time.

The returned provider is ready to pass directly into any SDK call's walletProvider slot:

Wallet providers are populated into the store by:

  • Provider-managed chains (EVM, Solana, Sui) — Hydrator components (EvmHydrator, SolanaHydrator, SuiHydrator) sync the native SDK state into the store as the sole writers.

  • Non-provider chains (Bitcoin, ICON, Injective, Stellar, NEAR, Stacks) — providers are created as a side-effect of setXConnection() in the store, triggered when a user connects a wallet through ChainActions.

Configure which chains are active by passing a config prop to SodaxWalletProvider:

Omit a chain-type key entirely to skip mounting that adapter. useWalletProvider will return undefined for disabled chains and emit a one-time console warning.


6. Custom implementations

You can implement the SDK interfaces directly without using @sodax/wallet-sdk-core. Each interface is defined in @sodax/sdk (e.g. IEvmWalletProvider in @sodax/sdk):

Requirements for a valid custom implementation:

  1. Declare readonly chainType = '<CHAIN>' as const — the SDK and useWalletProvider both read this field for runtime dispatch. The value must exactly match the chainType literal of the target interface.

  2. Implement every method on the interface — TypeScript will flag missing methods at compile time.

  3. No base class required — extending BaseWalletProvider is optional; it only provides the defaults storage and merge helpers from @sodax/wallet-sdk-core.

Last updated