Developers

One extension,
four chains

Qiubit exposes EVM, Octra, Solana and Sui from a single wallet. It speaks EIP-1193, EIP-6963 and the Solana and Sui Wallet Standards, so most stacks find it without any code from you. This page covers the rest.

The entire integration
bash
pnpm add @qiubit/wallet-sdk @qiubit/react
tsx
import { ConnectQiubit } from "@qiubit/react"; export function Nav() {  return <ConnectQiubit chain="evm" appName="My dApp" />;}
4chains
EVM · Octra · Solana · Sui
3standards
Discovered without your code
1component
<ConnectQiubit />
0adapters
For three of the four
Compatibility

What you have to write, per chain

Only one of the four asks anything of you. Read the last column first.

  • EVMNone

    Speaks

    EIP-1193 · EIP-6963

    Reach it with

    wagmi · viem · RainbowKit

  • OctraAdapter

    Speaks

    No wallet standard

    Reach it with

    connectOctra()

  • SolanaNone

    Speaks

    Wallet Standard

    Reach it with

    @solana/wallet-adapter

  • SuiNone

    Speaks

    Wallet Standard

    Reach it with

    Sui dApp Kit

Quickstart

Connecting takes one component

Install, drop in the button, done. The states people actually hit are handled for you.

01

Install

Two packages. The SDK is framework-free; the React package is the button and the hook.

bash
pnpm add @qiubit/wallet-sdk# React apps, optionalpnpm add @qiubit/react
02

Connect

One component covers every state a connection can be in — including the two most integrations skip: the extension still injecting, and the person rejecting the approval.

tsx
import { ConnectQiubit } from "@qiubit/react"; export function Nav() {  return <ConnectQiubit chain="evm" appName="My dApp" />;}
03

Without React

The SDK has no framework dependency. connectEvm resolves with the address and chain, or throws a QiubitError you can branch on.

ts
import { connectEvm, QiubitError } from "@qiubit/wallet-sdk"; try {  const { address, chainId } = await connectEvm();  console.log(address, chainId);} catch (err) {  if (err instanceof QiubitError && err.isUserRejection) {    // A choice, not a fault. Show nothing.  }}
Chains

What each chain needs

Three of the four need nothing beyond the standards. Octra is the exception, and here is why.

11

EVM

Standard EIP-1193 on window.ethereum, announced over EIP-6963 as io.qiubit.wallet. wagmi, viem and RainbowKit discover it with no adapter.

ts
import { connectEvm, signMessage, switchChain } from "@qiubit/wallet-sdk"; const { address } = await connectEvm();const signature = await signMessage("gm", address); // Adds the chain first when the wallet answers 4902.await switchChain(8453, {  chainId: 8453,  chainName: "Base",  rpcUrls: ["https://mainnet.base.org"],  nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 },});
12

Octra

Octra has its own connect rather than eth_requestAccounts: the approval is scoped to the Octra network, and it returns both addresses the wallet derives from one seed.

It is also the only chain here with no wallet standard behind it, so @qiubit/adapters ships an adapter for it.

ts
import { connectOctra } from "@qiubit/wallet-sdk"; const { octraAddress, evmAddress } = await connectOctra("My dApp");
13

Solana and Sui

Both register as Wallet Standard wallets, so @solana/wallet-adapter and Sui dApp Kit list Qiubit without any code from you. Use the SDK only when you want to skip those libraries.

ts
import { connectSolana, solanaSignMessage } from "@qiubit/wallet-sdk"; const connection = await connectSolana();const { signature } = await solanaSignMessage(  connection,  new TextEncoder().encode("gm"),);
Errors

Every failure has a name

A rejected approval and a missing wallet need opposite handling. The SDK never collapses them into one null.

CodeWhat happenedWhat to do
NOT_INSTALLEDNo Qiubit on the pageLink to qiubitwallet.com/downloads
USER_REJECTEDRejected in the walletNothing. It is a choice, not a fault
UNAUTHORIZEDSite not authorised, or wallet lockedPrompt to connect again
CHAIN_NOT_ADDEDWallet does not know that chainPass addIfMissing to switchChain
UNSUPPORTED_METHODWallet does not expose that callCheck the chain's feature list
REQUEST_FAILEDAnything elseShow the message; it is a real failure
Troubleshooting

The three things that go wrong

All three are environment problems rather than bugs, and all three have a specific fix.

21

The wallet is installed but not detected

Almost always a race: the page read window.ethereum before the extension injected. detectQiubit listens for the EIP-6963 announcement and polls the window until a timeout, so it survives either order.

If you check the window yourself, you will hit this. Use the SDK, or wait for the announcement.

ts
import { detectQiubit } from "@qiubit/wallet-sdk"; // Resolves null when it is genuinely absent — never throws.const provider = await detectQiubit({ timeoutMs: 3000 });
22

Another extension owns window.ethereum

MetaMask has shipped window.ethereum as non-writable. When that happens Qiubit stays reachable through EIP-6963 and through its own window.octra key, and the SDK checks all three, including the window.ethereum.providers array.

23

disconnect() does not revoke anything

The extension owns the permission; a page cannot revoke it. disconnect() clears local state only. To actually revoke, the person removes the site in the wallet's connections screen.

Ship it against a real wallet

The example dApp in the repo walks every connection path, with the failure states left visible rather than hidden.