Skip to main content
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
  2. WalletProviderSlot: compile-time enforcement
  3. wallet-sdk-core: ready-to-use implementations
  4. Config type reference per chain
  5. React integration: useWalletProvider
  6. Custom implementations

1. Supported provider interfaces

Every chain family has a named interface that @sodax/sdk exports: 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: All config types include an optional defaults field for per-method behavioral overrides.

Provider reference


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)

The endpoint must speak gRPC-web; rpcUrl still works as a deprecated alias for grpcUrl, and the two are mutually exclusive. signTransaction takes the transaction positionally, so an options-shaped signer such as dAppKit.signTransaction needs the wrapper above rather than a direct assignment; walletAccount is dApp Kit’s UiWalletAccount, and naming it stops the wallet signing with whichever account happens to be connected. SuiWalletDefaults accepts: signAndExecuteTxn (dry-run toggle), 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$“) 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.
  4. EVM providers must honor options.expectedChainId — refuse to broadcast when the wallet’s active chain id differs; ignoring it silently disables the SDK’s wrong-chain protection. A provider that already declares its own second options parameter must widen it to YourOptions & EvmSendTransactionOptions to keep satisfying the interface.