# Specification

### **Required APIs with Examples and Common Error Codes (Using OKX as Example)**

#### Window Global Variable Name

```typescript
// Get OKX wallet instance
const okx = (window as any).okxwallet;

// Get wallet API for different networks
const getWalletApi = (network: "livenet" | "testnet") => {
  const networkAttr = {
    livenet: "bitcoin",
    testnet: "bitcoinTestnet",
  };
  return okx[networkAttr[network]];
};
```

\\

#### Connect Wallet Method

```typescript
interface ConnectParams {
  network: "livenet" | "testnet";
  chain?: "BITCOIN_MAINNET" | "BITCOIN_TESTNET" | "BITCOIN_TESTNET4" | "FRACTAL_BITCOIN_MAINNET" | "FRACTAL_BITCOIN_TESTNET";
  handleMismatchChain?: boolean;
}

interface ConnectResult {
  name: "okx";
  network: "livenet" | "testnet";
  publicKey: string;
  accounts: string[];
  address: string;
  btcAddress: string;
  btcPublicKey: string;
  balance?: {
    confirmed?: number;
    total?: number;
    unconfirmed?: number;
  };
  chain?: string;
}

// Connect wallet
const connect = async (params: ConnectParams): Promise<ConnectResult> => {
  const { network, chain, handleMismatchChain } = params;
  const okx = getWalletApi(network);
  
  try {
    const info = await okx.connect();
    const { publicKey, address, compressedPublicKey } = info;
    
    let balance;
    if (network === "livenet") {
      balance = await okx.getBalance();
    }

    return {
      name: "okx",
      network,
      publicKey,
      accounts: [address],
      address,
      btcAddress: address,
      btcPublicKey: compressedPublicKey,
      balance,
      chain,
    };
  } catch (error) {
    throw {
      code: error.code || 1,
      msg: error.msg || error.message || "Connection failed",
      success: false,
    };
  }
};
```

\\

#### Disconnect Wallet Method

```typescript
interface DisconnectParams {
  network: "livenet" | "testnet";
  chain?: string;
  handleMismatchChain?: boolean;
}

const disconnect = async (params: DisconnectParams): Promise<void> => {
  const { network, chain, handleMismatchChain } = params;
  const okx = getWalletApi(network);
  
  try {
    await okx.disconnect();
  } catch (error) {
    throw {
      code: error.code || 1,
      msg: error.msg || error.message || "Disconnect failed",
      success: false,
    };
  }
};
```

\\

#### Sign Method

```typescript
interface SignParams {
  network: "livenet" | "testnet";
  msg: string;
  type?: string;
  chain?: string;
  handleMismatchChain?: boolean;
}

const sign = async (params: SignParams): Promise<string> => {
  const { network, msg, type, chain, handleMismatchChain } = params;
  const okx = getWalletApi(network);
  
  try {
    return await okx.signMessage(msg, type);
  } catch (error) {
    throw {
      code: error.code || 1,
      msg: error.msg || error.message || "Signing failed",
      success: false,
    };
  }
};
```

\\

#### Sign PSBT Method

```typescript
interface SignPsbtParams {
  psbt: string; // PSBT string in base64 or hex format
  option?: {
    autoFinalized: boolean;
    toSignInputs?: {
      index: number;
      address: string;
      publicKey: string;
      sighashTypes: number[];
      disableTweakSigner: boolean;
    }[];
  };
  network: "livenet" | "testnet";
  data: ConnectResult; // Wallet information
  chain?: string;
  handleMismatchChain?: boolean;
}

const signPsbt = async (params: SignPsbtParams): Promise<string> => {
  const { psbt, option, network, data, chain, handleMismatchChain } = params;
  const okx = getWalletApi(network);
  
  try {
    // Convert to hex format
    let handlePsbt = psbt;
    if (!/^[0-9a-fA-F]+$/.test(psbt)) {
      handlePsbt = Psbt.fromBase64(psbt).toHex();
    }
    
    const res = await okx.signPsbt(handlePsbt, {
      ...option,
      autoFinalized: false,
    });
    
    return res;
  } catch (error) {
    throw {
      code: error.code || 1,
      msg: error.msg || error.message || "PSBT signing failed",
      success: false,
    };
  }
};
```

\\

#### Send BTC Method

```typescript
interface SendBitcoinParams {
  from: string; // Sender address
  address: string; // Recipient address
  satoshis: number; // Amount to send (in satoshis)
  option?: {
    feeRate: number; // Fee rate
  };
  network: "livenet" | "testnet";
  chain?: string;
  handleMismatchChain?: boolean;
}

const sendBitcoin = async (params: SendBitcoinParams): Promise<string> => {
  const { from, address, satoshis, option, network, chain, handleMismatchChain } = params;
  const okx = getWalletApi(network);
  
  try {
    const sendOption: any = {
      from,
      to: address,
      value: (satoshis / 100000000).toFixed(8), // Convert to BTC
    };
    
    if (option && option.feeRate) {
      sendOption.fee = option.feeRate;
      sendOption.satBytes = option.feeRate;
    }
    
    const res = await okx.send(sendOption);
    return res.txhash;
  } catch (error) {
    throw {
      code: error.code || 1,
      msg: error.msg || error.message || "Send BTC failed",
      success: false,
    };
  }
};
```

\\

#### Sign PSBTs Method

```typescript
interface SignPsbtsParams {
  psbt: string[]; // Array of PSBT strings
  option?: Array<{
    autoFinalized: boolean;
    toSignInputs?: {
      index: number;
      address: string;
      publicKey: string;
      sighashTypes: number[];
      disableTweakSigner: boolean;
    }[];
  }>;
  network: "livenet" | "testnet";
  chain?: string;
  handleMismatchChain?: boolean;
}

const signPsbts = async (params: SignPsbtsParams): Promise<string[]> => {
  const { psbt, option = [], network, chain, handleMismatchChain } = params;
  const okx = getWalletApi(network);
  
  try {
    const handleOptions = option.length === 0
      ? psbt.map(() => ({ autoFinalized: false }))
      : option.map((item) => ({ ...item, autoFinalized: false }));

    const res = await okx.signPsbts(psbt, handleOptions);
    return res;
  } catch (error) {
    throw {
      code: error.code || 1,
      msg: error.msg || error.message || "Batch PSBT signing failed",
      success: false,
    };
  }
};
```

\\

#### Account Switch Monitoring Event

```typescript
interface WalletInfo {
  name: "okx";
  network: "livenet" | "testnet";
  publicKey: string;
  accounts: string[];
  address: string;
  btcAddress: string;
  btcPublicKey: string;
  balance?: {
    confirmed?: number;
    total?: number;
    unconfirmed?: number;
  };
}

const openMonitorOkx = (
  network: "livenet" | "testnet",
  callback?: (data: WalletInfo) => void,
) => {
  const okx = getWalletApi(network);
  
  okx.on("accountsChanged", async (accounts: string[]) => {
    if (accounts && accounts.length > 0) {
      try {
        const info = await okx.connect();
        const { publicKey, address, compressedPublicKey } = info;
        
        let balance;
        if (network === "livenet") {
          balance = await okx.getBalance();
        }

        callback?.({
          name: "okx",
          network,
          publicKey,
          accounts: [address],
          address,
          btcAddress: address,
          btcPublicKey: compressedPublicKey,
          balance,
        });
      } catch (error) {
        console.error("Account switch monitoring failed:", error);
      }
    }
  });
};
```

\\


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.on.nexus/dotswap/developers/wallet-specifications/wallet-access-specification/specification.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
