QRDXDocs

Wallet integration

Connect a dApp to QRDX Wallet: discovery, accounts, signing, transactions and errors.

QRDX Wallet is a standard EIP-1193 wallet with a QRDX namespace on top. Ethereum tooling works unchanged; post-quantum accounts and the native exchange use qrdx_* methods.

Find the wallet

Use EIP-6963. It works even when another wallet owns window.ethereum:

let qrdx
window.addEventListener('eip6963:announceProvider', (e) => {
  if (e.detail.info.rdns === 'org.qrdx.wallet') qrdx = e.detail.provider
})
window.dispatchEvent(new Event('eip6963:requestProvider'))

Also available: window.qrdx is always the QRDX provider (page scripts cannot overwrite it); window.ethereum is QRDX only if no other wallet took it first (window.ethereum.isQRDX).

Without the extension (the web wallet, the iPhone app), connect by QR code with QRDX Connect: you get the same provider over an encrypted relay.

Accounts

const [account] = await qrdx.request({ method: 'qrdx_requestAccounts' })
// { address: '0x…', pqAddress: '0xPQ…', pqAccountId: '0x…', pqPublicKey: '…', pqFingerprint: '…' }
const chain = await qrdx.request({ method: 'qrdx_chainInfo' })
// { id, name, chainId, isQrdx, isTestnet, nativeCurrency }
Method
eth_requestAccounts, eth_accountsthe shared 0x addresses, selected first; [] while locked or not connected
qrdx_requestAccounts, qrdx_accountseach account's address, pqAddress, pqAccountId, pqPublicKey, pqFingerprint
eth_chainId, net_version, qrdx_chainInfothe active network
wallet_switchEthereumChainnetworks in the wallet's registry only (unknown: 4902); asks the user
wallet_getPermissions, wallet_requestPermissions, wallet_revokePermissionsEIP-2255; revoking disconnects the site

Events: connect, disconnect, accountsChanged, chainChanged.

Signing

Method
personal_sign(message, address)EIP-191 with the classic key
eth_signTypedData_v4(address, typedData)EIP-712; refused if domain.chainId is not the active chain
qrdx_signPQMessage(message, address?)ML-DSA-65 over the QRDX message prefix; returns { signature, publicKey, address }. Verify with the public key (Keys and signing).
eth_signdisabled (4200): it signs arbitrary hashes and is a phishing vector

Transactions

Method
eth_sendTransaction(tx)from the classic 0x key; EIP-1559 fields are folded into a legacy gasPrice. Contract deployment from dApps is not supported.
qrdx_sendPQTransaction({ to, value, data?, gas? })from the post-quantum account, as a type-0x51 transaction; to may be any address form
qrdx_sendExchangeTransaction({ op, params, gasLimit? })any exchange operation, signed with the account's post-quantum key and next exchange nonce; returns { txHash, nonce }
wallet_watchAsset({ type: 'ERC20', options: { address, symbol, decimals } })adds a token after the user approves
Place a limit order
const { txHash } = await qrdx.request({
  method: 'qrdx_sendExchangeTransaction',
  params: [{ op: 'PLACE_ORDER', params: { pair: `QRDX:${token}`, side: 'buy', order_type: 'limit', price: '0.5', amount: '10' } }],
})
// poll exchange_getTransactionReceipt(txHash)

Every request opens an approval showing the site's real origin, the call decoded ("Buy 10 QRDX at 920 USDC", "Swap 1,000 USDC for at least 1.08 QRDX"), the result of a dry run against the latest block for EVM transactions, the maximum fee, and warnings (look-alike site names, unknown tokens, swaps without a minimum, token approvals).

Several operations per block. The wallet tracks the exchange nonces it has submitted that no block has included, so a dApp can, say, place an order and cancel it before the next block. A TOKEN_DEPLOY's token address is known before inclusion (0x + blake2b-160 of "<sender>:<nonce>:<symbol>"), so a dApp can create the token's pool in the same block.

Reads without connecting

These pass through to the active network's node: eth_blockNumber, eth_call, eth_estimateGas, eth_gasPrice, eth_getBalance, eth_getBlockBy*, eth_getCode, eth_getLogs, eth_getStorageAt, eth_getTransaction*, eth_getTransactionCount, eth_feeHistory, qrdx_getAccountId, qrdx_getIntrinsicGas, and the exchange_get*, exchange_quote* and perp_get* reads.

Errors

Code
4001the user rejected the request
4100not authorized: the site is not connected, or that account is not shared
4200method not supported
4900the wallet is unavailable
4902unknown chain id
-32602invalid parameters

Two accounts, one person

Each wallet account has a classic 0x address and a post-quantum 0xPQ address, which are two ledger accounts. eth_sendTransaction spends from the 0x one; qrdx_sendPQTransaction and every exchange operation from the post-quantum one (its ledger key is pqAccountId). Show users the 0xPQ address for anything they trade with.

On this page