Skip to main content

Integrating a Wallet with OXN

If you build a wallet and want to add OXN support, this guide covers the specific things wallets need to do that go beyond standard Ethereum integration.

Basics: OXN as an EVM chain

OXN is a standard EVM-compatible chain from the wallet's perspective. Add it to your supported networks with:

  • Chain ID: 186
  • RPC: https://rpc.bout.network
  • Currency symbol: TBLUAI, 18 decimals
  • Explorer: https://explorer.bout.network

The Testnet Parameters page has the full details in JSON form for programmatic configuration.

What makes OXN different for wallets

Standard EVM wallets sign transactions and display the calldata for user review. On OXN:

  • Calldata is encrypted at the client side before signing.
  • Balances for confidential tokens are only visible via signed queries.
  • Event logs are encrypted per-caller.

If the wallet only signs whatever data the dApp passes, no changes are strictly needed. But to give users a good experience, the wallet needs to know about OXN's encryption.

Signing encrypted transactions

The dApp constructs the encrypted envelope. The wallet's job is to sign the outer transaction with the encrypted data as-is:

{
to: "0xContractAddress",
data: "0xa3...", // CBOR envelope from the dApp
value: 0,
gas: 500_000,
gasPrice: 100_000_000,
nonce: ...
}

The wallet signs this exactly as it would sign any Ethereum transaction. It does not need to decode the encrypted data.

Displaying encrypted transactions

The user sees the outer transaction — to, value, gas — but the data field is a long hex blob that isn't human-readable. To improve UX:

  • Detect the CBOR envelope prefix (0xa00xbf) and label the transaction "Encrypted".
  • Encourage the dApp to display a plain-language summary before sending the request.
  • Do not attempt to decode the encrypted data — the wallet cannot decrypt it without the enclave key.

Displaying confidential token balances

For a confidential ERC-20 (see Building a Confidential ERC-20), calling balanceOf(user) via a plain eth_call returns 0. To display the real balance, the wallet must:

  1. Detect that the token is confidential (via a well-known method or dApp hint).
  2. Construct a signed query: sign the eth_call payload with the user's private key.
  3. Send the signed query.
  4. Decrypt the response with the session key.
  5. Display the returned balance.

This requires the wallet to hold the private key (which it already does) and to implement the OXN encryption protocol client-side.

For wallets that don't want to implement encryption themselves, delegate this to the OXN SDK:

import { wrapEthersSigner } from "@oasisprotocol/sapphire-ethers-v6";

const wallet = new ethers.Wallet(privateKey, provider);
const wrapped = wrapEthersSigner(wallet);
// Use wrapped for signed queries

Deposit and withdraw

OXN has two address formats (see Accounts and Addresses). Users need to move value between them:

  • Deposit: consensus-layer oxn1… → EVM 0x…
  • Withdraw: EVM 0x… → consensus-layer oxn1…

Most wallets can skip this — the vast majority of dApp interaction is on the EVM side. The OXN Web Wallet handles the flow if a user needs it.

If your wallet targets validator staking (mainnet), you'll need to support both address formats and the deposit/withdraw operations.

Networks in a mobile wallet

For iOS / Android wallets, OXN Testnet works via WalletConnect or a direct RPC connection. The confidential-transaction encryption happens either in the dApp (browser side) or in a native SDK if your wallet wants first-class support.

For confidential features to work in a mobile wallet:

  • Include the OXN SDK's native equivalent (Go / Rust wrapping X25519 + Deoxys-II), or
  • Compile a WASM version of the encryption library from the TypeScript SDK.

Testing your integration

  • Add OXN Testnet to your wallet.
  • Fund a test address from the faucet.
  • Perform a simple transfer to another address.
  • Deploy or interact with a confidential contract.
  • Verify balances display correctly via signed query.
  • Test error handling: rejected transactions, network errors, wrong chain.

Next steps