# Ika Accounts documentation Source: https://docs-ika-accounts.mpckit.xyz # Sui accounts for people who already have a wallet Ika Accounts gives every user of your app a **Sui account controlled by the wallet they already have**: MetaMask, Rabby, Phantom, Backpack or any other EVM or Solana wallet. There is no new wallet to install, no seed phrase and no gas. Users can fund the account from any chain and withdraw to any chain, inside your app. Under the hood, each account is an [Ika](https://ika.xyz) zero-trust dWallet: a key split between the user and the Ika network, where the user's half is derived from their own wallet and never leaves their browser. Every transaction needs the user's approval, and that approval is checked on-chain. - [Quickstart](https://docs-ika-accounts.mpckit.xyz/quickstart/): Sign-in, a gasless transaction and a deposit panel in about 30 lines. - [Security model](https://docs-ika-accounts.mpckit.xyz/security/): What we can and can't do with a user's account, and why. - [llms.txt](https://docs-ika-accounts.mpckit.xyz/llms.txt): This documentation as plain text, for your coding assistant. ## What your users get - **Sign in with their wallet.** One approval on first visit; nothing to sign when they come back on the same device. - **One Sui address**, created instantly. The same key is also a Solana address and a NEAR Intents account. - **No gas, ever.** You sponsor it; the user never holds SUI to pay fees. - **Deposits from any chain.** Their balances on Ethereum, Base, Arbitrum, Solana and 30+ other chains show up in a built-in panel. One confirmation in their wallet, and it arrives on Sui in about a minute. - **Withdrawals to any chain**, from the same panel. - **Stay signed in.** After one approval, transactions within the scope you declare (your contracts, a spend cap, a time limit) run without a wallet prompt. ## What happens when a user clicks Buy 1. **Your app builds the transaction** (0 s). The SDK simulates it and our API wraps it with sponsored gas and a pre-computed Ika presign. 2. **The user approves** (+ approval). Their wallet shows a readable summary: what the transaction calls and how their balances change. Inside a session there is no prompt. 3. **The approval goes on-chain** (~2 s). Our Registry contract on Sui checks the wallet's signature (or the session) and asks the Ika network to sign. 4. **Ika signs** (~6 s). The Ika network completes the signature together with the user's half, computed in their browser. 5. **It executes on Sui** (~8 s). With gas paid by the sponsor. The user's first transaction also creates their dWallet, in the same step. Times are measured on Sui mainnet. ## What you get - A **TypeScript SDK** (`@ika-accounts/sdk`, plus React hooks in `@ika-accounts/react`) that handles sign-in, approvals, sessions, bridging and signing. - A **dashboard** for your API keys, allowed origins, users, activity and billing. - **Prepaid billing**: each sponsored transaction is billed at its cost (Sui gas and Ika fees) plus 0.3%. ## Networks Ika Accounts runs on **Sui mainnet** with Ika mainnet. Bridging uses NEAR Intents (1Click), which is mainnet-only. | | | |---|---| | API and key origin | `https://ika-accounts.mpckit.xyz` | | Dashboard | `https://dashboard-ika-accounts.mpckit.xyz` | | Example app | [Liftoff](https://liftoff.mpckit.xyz), a token launchpad built on Ika Accounts | --- # Quickstart By the end of this page your app has a sign-in button, runs a gas-free Sui transaction from the user's account and opens the deposit panel. ## 1. Get a platform key Log in to the [dashboard](https://dashboard-ika-accounts.mpckit.xyz) and: 1. Under **API keys**, create a key. It is public by design: it identifies your platform, it doesn't authorize anything on its own. 2. Under **Settings → Allowed origins**, add every origin your app runs on, for example `https://app.example.com`. The key frame refuses to work anywhere else. Until you add one, it only answers on `localhost`. 3. Under **Billing**, top up. Sponsored transactions are paid from this balance. ## 2. Install ```bash npm i @ika-accounts/sdk @mysten/sui ``` > During the pilot the SDK is shared directly with partners rather than through the public npm registry. Ask us for the package. ## 3. Create the client Create one instance for your whole app. ```ts import { createIkaAccounts } from '@ika-accounts/sdk'; export const accounts = createIkaAccounts({ apiKey: 'ika_…', // from the dashboard apiUrl: 'https://ika-accounts.mpckit.xyz', keysOrigin: 'https://ika-accounts.mpckit.xyz', // where users' keys live network: 'mainnet', }); accounts.preload(); // fetch Ika parameters in the background (~20 MB, cached) ``` ## 4. Sign in `openConnect()` shows the Ika Accounts sign-in modal: every EVM and Solana wallet installed in the browser, grouped, with its own icon. ```ts const addresses = await accounts.openConnect(); // null if the user closed it if (addresses) console.log('Sui address', addresses.sui); ``` When the user comes back, reconnect without any prompt: ```ts await accounts.reconnect(); // resolves null if there's nothing to restore ``` The Sui address is available immediately. The account's keys finish in the background, and the first transaction waits for them automatically. ## 5. Run a transaction Pass a Sui `Transaction`, or steps that add to one. Gas is sponsored, so don't use the gas coin. ```ts import { coinWithBalance } from '@mysten/sui/transactions'; const { digest } = await accounts.execute((tx, { address }) => { const payment = coinWithBalance({ type: '0x2::sui::SUI', balance: 100_000_000n, useGasCoin: false }); const item = tx.moveCall({ target: `${PACKAGE}::shop::buy`, arguments: [tx.object(SHOP), payment] }); tx.transferObjects([item], address); }); ``` The user's wallet shows what the transaction does and how their balances change, and asks them to approve. The first transaction also creates their dWallet. ## 6. Let users add funds ```ts await accounts.openFunds({ tab: 'deposit', receive: 'SUI' }); ``` The panel lists the user's balances on every chain, quotes what will arrive on Sui, and sends the deposit from their wallet with one confirmation. The same panel handles withdrawals: `openFunds({ tab: 'withdraw' })`. ## Next - Skip the wallet prompt for routine transactions with [sessions](https://docs-ika-accounts.mpckit.xyz/transactions/#sessions). - Fund a transaction and run it in one call with [`perform`](https://docs-ika-accounts.mpckit.xyz/transactions/#perform). - Using React? See [React hooks](https://docs-ika-accounts.mpckit.xyz/reference/#react). --- # Sign-in and accounts A user signs in with a wallet they already have. That wallet becomes the owner of a Sui account: it approves every transaction, and it is the only way to recover the account. ## The sign-in modal ```ts const addresses = await accounts.openConnect(); ``` The modal finds every installed wallet: EVM wallets through EIP-6963 (MetaMask, Rabby, Coinbase Wallet, Phantom's EVM side…) and Solana wallets through Wallet Standard (Phantom, Backpack, Solflare…). Wallets that support both appear in both groups. The last one used is marked, and if no wallet is installed the modal offers install links. It resolves with the account's addresses, or `null` if the user closed it. ### Bring your own wallet UI If you already have a wallet picker, list the wallets yourself and connect one by id: ```ts const wallets = await accounts.signInWallets(); // [{ id, name, icon, chain: 'evm' | 'solana' }] await accounts.connectWallet(wallets[0].id); ``` Or pass a provider you already hold, such as an EIP-1193 provider from wagmi or a Solana wallet with `signMessage`: ```ts await accounts.connect(await connector.getProvider()); ``` ## What the user signs | When | Prompts | |---|---| | First visit on a device | Approve your site once, then sign one message in the wallet. It derives the account key; it is not a transaction and costs nothing. | | First account for an EVM wallet | One extra signature of the same message, to confirm the wallet signs deterministically. | | Returning on the same device | Nothing. The key stays sealed in the browser, and `reconnect()` restores the session silently. | | Every transaction | One approval in the wallet, unless it falls inside an active [session](https://docs-ika-accounts.mpckit.xyz/transactions/#sessions). | The key message and the site approval happen in a small window on the Ika Accounts origin, so your page never sees the signature the key is derived from. > Wallets must sign deterministically: the same message must always give the same signature. Regular EOA wallets do. Smart-contract and passkey wallets don't, and are refused before an account is created. ## One key, three addresses ```ts accounts.addresses; // { sui, solana, nearIntents, publicKey } ``` The account is an Ed25519 key, so it is also a valid Solana address and a NEAR Intents implicit account. See [NEAR and Solana](https://docs-ika-accounts.mpckit.xyz/near-solana/). The Sui address exists as soon as the user signs in. The dWallet behind it is created on Ika with the user's first transaction, in the same request, so nothing is spent on users who never transact. ## State ```ts accounts.isConnected; // boolean accounts.address; // Sui address (throws before sign-in) accounts.owner; // { chain: 'evm' | 'solana', address } of the owner wallet accounts.wallet; // { id, name, icon, chain, address } when signed in through the modal accounts.subscribe(() => render()); // called on sign-in and sign-out await accounts.whenReady(); // resolves when the account's keys are ready (execute() waits anyway) ``` ## Signing out ```ts await accounts.disconnect(); // signs out and ends any active session on-chain await accounts.forgetDevice(); // also erases this browser's cached key and site approval ``` After `forgetDevice()`, the next sign-in on that browser asks the wallet again, as on a new device. The account itself is unchanged: the same wallet always derives the same key. --- # Transactions ## execute Runs a Sui transaction from the user's account. Gas is sponsored. ```ts await accounts.execute(tx); // a Transaction await accounts.execute(step); // (tx, { address }) => void await accounts.execute([step1, step2]); // steps compose into one transaction ``` It resolves with `{ digest }` once the transaction has executed, and throws `IkaAccountsError('transaction_failed')` if it failed on-chain. **Rules for sponsored transactions** - Don't spend from the gas coin. Use `coinWithBalance({ …, useGasCoin: false })` or coins from the user's account. - The transaction must fit the sponsor's gas budget, and a user can have up to 3 transactions in flight. - Transactions are checked by simulation before the user is asked to approve. ## What the user approves The wallet shows a plain-text message, generated by the key frame from the exact transaction: - your app's name and origin, - the Move calls it makes, with full package IDs, - every address it sends to that isn't the user's own, - balance changes from a simulation, with full coin types for anything that isn't SUI or USDC, - the transaction digest and an expiry. The signature is verified on-chain by the Registry before Ika signs. An approval can't be reused for another transaction, and it can't be forged by our backend or yours. ## perform `perform` makes sure the account holds what a transaction needs, bridges the difference from any chain if it doesn't, then runs it. ```ts await accounts.perform({ requires: [{ coinType: USDC, amount: 50_000_000n }], // 50 USDC fundWith: 'auto', // or a specific 1Click asset id transaction: [buy, stake], // one Sui transaction onStatus: (s) => setStage(s.stage), }); ``` Stages: `checking-balance` → `quoting` → `awaiting-deposit` → `bridging` → `swapping` (only for tokens bridging can't deliver) → `executing` → `done`. With `fundWith: 'auto'`, the SDK picks the user's largest balance that covers the shortfall with about 5% headroom, asks their wallet for one transfer, waits for the funds on Sui, then executes. If the account already holds enough, it goes straight to execution. Tokens that NEAR Intents can't deliver directly (a launchpad token, for example) are reached by bridging USDC and swapping on Sui through the Aftermath router. ## Sessions A session lets transactions within a declared scope run without a wallet prompt. The user sees the scope in the approval that grants it, and the limits are enforced in two places: the key frame only signs what fits, and the Registry contract enforces the session key, its expiry and its transaction count on-chain. ```ts createIkaAccounts({ // … session: { minutes: 60, // up to 1440 maxTransactions: 50, // up to 1000 packages: [YOUR_PACKAGE_ID], // contracts your transactions call spend: { '0x2::sui::SUI': '2000000000' }, // most that may leave the account, per coin allowPublish: false, // e.g. true for a launchpad publishing coins appTokens: false, // let uncapped tokens flow into your contracts }, }); ``` A transaction runs without a prompt only if all of these hold: - it only calls your packages and a short list of coin plumbing in the Sui framework, - it sends nothing to any address other than the user's own, - no object other than coins leaves the account, - the spend on every capped coin stays within the cap for the whole session, - coins without a cap only go into your contracts, and only with `appTokens: true` (SUI and USDC always need a cap), - it doesn't publish or upgrade packages, unless `allowPublish` is set, - the session hasn't expired or run out of transactions. Anything else falls back to a normal wallet approval. `disconnect()` ends the session on-chain. ## Cost and timing Measured on mainnet, at a SUI price of $1.18: | | Cost to you | Time | |---|---|---| | A user's first transaction (also creates the dWallet) | about $0.14 | about 10 s | | Every transaction after | about $0.07 | about 8.5 s | Plus the time the user takes to approve, and 0.3% on top of the cost. Most of the cost is Sui gas for the Ika request, not Ika fees. --- # Deposits and withdrawals Funds move between the user's Sui account and 36 other chains through [NEAR Intents](https://near-intents.org) (1Click). Users never touch a bridge. ## The funds panel ```ts await accounts.openFunds({ tab: 'deposit', receive: 'USDC' }); // or receive: 'SUI' await accounts.openFunds({ tab: 'withdraw' }); ``` It resolves when the user closes the panel. The panel renders in a closed shadow root, so your styles can't break it, and it looks the same in every app. **Deposit tab** - A token selector with search, chain filters and the user's balances first, with token and chain logos. - A live quote: what arrives on Sui, the rate, the fee, and the expected time. - Deposits from wallets the user connects are one confirmation. **Add wallet** connects a second wallet just for funding, for example Rabby on Base while signed in with Phantom. Funding wallets never control the account. - Anything else (another wallet, an exchange, Bitcoin) gets a deposit address and the exact amount to send. The transfer is detected on-chain automatically. - A status timeline until the funds arrive. **Withdraw tab**: USDC or SUI to any supported chain and token. The recipient defaults to the user's own wallet on that chain. ## Supported chains | | Chains | |---|---| | Sent directly from the user's wallet | Ethereum, Base, Arbitrum, Optimism, Polygon, BNB Chain, Avalanche, Gnosis, Berachain, Scroll, Monad, X Layer, Plasma, Abstract, Robinhood Chain, ADI Chain, and Solana | | Deposit address, any wallet or exchange | Bitcoin, NEAR, TON, Tron, XRP, Dogecoin, Litecoin, Bitcoin Cash, Zcash, Dash, Stellar, Cardano, Aptos, Starknet, Aleo, Movement, Hyperliquid, Fogo | If a user's wallet doesn't know an EVM chain yet, it is asked to add it before switching. ## Fees | | Fee | |---|---| | Deposits | 0.6% of the amount, inside the quote | | Withdrawals | 0.6% of the amount, inside the quote | | Gas on Sui | none for the user | Every quote returns `feeBps`, and the panel shows the fee in dollars before the user confirms. Route costs from NEAR Intents are included in the quoted output. ## Programmatic API For your own UI: ```ts // What would arrive, without creating an order const quote = await accounts.estimateDeposit({ asset, amount, receiveAsset }); // { amountIn, amountOut, amountInUsd, amountOutUsd, feeBps, timeEstimateSeconds } // Create the order, send it from the user's wallet, follow it const deposit = await accounts.deposit({ asset, amount }); await deposit.send(); await deposit.wait({ onUpdate: (order) => setStatus(order.status) }); // Withdraw (the user approves the Sui transaction in their wallet) const { order, wait } = await accounts.withdraw({ asset, amount, recipient }); await wait(); ``` `asset` is a 1Click asset id. List them with `accounts.tokens()`, the chains with `accounts.chains()`, and the user's bridgeable balances across connected wallets with `accounts.fundingOptions()`. Order statuses: `PENDING_DEPOSIT` → `KNOWN_DEPOSIT_TX` → `PROCESSING` → `SUCCESS`, or `REFUNDED`, `FAILED`, `INCOMPLETE_DEPOSIT`. Refunds go back to the address the deposit came from. > Very small amounts can fall below a route's minimum. The quote fails with a clear error before anything is sent. --- # NEAR Intents and Solana The account's Ed25519 key is also a NEAR Intents implicit account and a Solana address. The same approval rules apply: every signature needs the owner wallet's approval, which shows the decoded message. ## NEAR Intents ```ts accounts.near.accountId(); // the implicit account (hex public key) const signed = await accounts.near.signIntents([ { intent: 'token_diff', diff: { 'nep141:usdc…': '-100000000', 'nep141:wrap.near': '99000000' } }, ]); await accounts.near.publish(signed, [quoteHash]); // to the NEAR Intents solver relay ``` Intents are signed as `raw_ed25519` payloads. No NEAR account, gas or registration is needed. The approval lists each intent: what is given, received, transferred or withdrawn, and to whom. ## Solana ```ts accounts.solana.address(); const { signature, transaction } = await accounts.solana.signTransaction(messageBytes); await rpc.sendTransaction(transaction, { encoding: 'base64' }).send(); ``` The message must be a serialized Solana transaction message (legacy or v0) in which the account is the only signer and the fee payer. The account needs SOL for Solana fees. ## Raw signatures ```ts const signature = await accounts.signMessage(bytes); // 64-byte Ed25519 signature ``` Messages must be 1 to 4,096 bytes. 32-byte messages are refused, because they can't be told apart from a Sui transaction digest. Each signature costs the same as a Sui transaction (an Ika presign and sign), without the Sui execution gas. --- # Security model The short version: **only the user's wallet can authorize their account**. Not your app, not our backend. And the user can keep using their account even if we disappear. ## The account is a zero-trust dWallet Each account is an [Ika](https://ika.xyz) dWallet using 2PC-MPC: signing needs both the user's share of the key and the Ika network's share. Neither side can sign alone, and the full private key never exists anywhere. The user's share never leaves their browser in the clear. It is encrypted to a key only the user holds and stored on Ika, so it can be recovered on any device from the wallet alone. ## The key comes from the user's wallet When a user first signs in, their wallet signs a fixed message naming the Ika Accounts domain. The account's keys are derived from that signature: - the key that decrypts their share of the dWallet, - the key that signs their login to our API. Only the wallet can produce that signature, so only the wallet can recreate the keys. Nothing is stored on our servers that could rebuild them. This happens inside the **key origin**, `ika-accounts.mpckit.xyz`, in a hidden iframe and a small window, never in your page. On a device the user has used before, the derived secret stays sealed in that origin's storage under a non-extractable browser key. `forgetDevice()` erases it. ## Every signature is approved on-chain Our backend submits requests to Ika through the **Registry**, a Move contract on Sui that holds every account's dWallet capability. The Registry only asks Ika to sign when the request carries one of: - an approval signed by the owner wallet, naming the exact message to sign and this Registry, or - a signature from a session key the owner granted, within its expiry and transaction count. The Registry verifies EVM signatures (secp256k1) and Solana signatures (Ed25519) on-chain. A request without a valid approval is rejected by the contract, whoever sends it. When an account is created, the Registry also checks that the new dWallet is bound to its owner wallet, so a dWallet can't be attached to someone else. ## Users can leave without us If our service stops, or refuses a user, they don't lose their account: 1. The encrypted share lives on Ika. The user decrypts it with their wallet alone. 2. `registry::sign_permissionless` lets anyone sign for an account **with the owner's approval**, paying their own Ika fees and gas. No operator is involved. The SDK ships this path (`unlockFromChain`, `signWithoutOperator`, `executeWithoutOperator`). ## What we can and can't do | | | |---|---| | Sign a transaction for a user | No. The Registry requires the owner's approval. | | Read or rebuild a user's key | No. It is derived from the wallet's signature, in the user's browser. | | Refuse to sponsor a user's transactions | Yes. The user can then sign through `sign_permissionless` with their own gas. | | Change the contracts | Only through a 7-day public timelock on the upgrade capability, or never, once it is made immutable. | ## What your app can and can't do Your app decides which transactions to request and can grant itself a session scope. It can't approve anything on the user's behalf, can't see the user's keys, and can't exceed the session scope the user saw and accepted. ## Your responsibilities - Add only your real origins under **Allowed origins**. The key frame refuses to run anywhere else. - If your site sets a Content Security Policy, allow `https://ika-accounts.mpckit.xyz` in `frame-src`, and don't block its pop-up. - Keep session scopes tight: your own packages and realistic spend caps. ## Verify it yourself - The key origin publishes a hash of every file at `/manifest.json`. Build `apps/keys` and compare. - Mainnet contract addresses are in the [reference](https://docs-ika-accounts.mpckit.xyz/reference/#deployments). --- # Platform and billing ## Dashboard [dashboard-ika-accounts.mpckit.xyz](https://dashboard-ika-accounts.mpckit.xyz) is where you manage your platform: - **Overview**: balance, transactions and spend over time, recent activity. - **Users**: every account created through your platform. - **Activity**: each transaction with its status and cost. - **API keys**: create and revoke keys. - **Billing**: top-ups and charges. - **Settings**: allowed origins, webhook URL, team members. ## Billing Billing is prepaid in US dollars. 1. **Top up** by sending USDC or SUI on Sui to the treasury address shown under Billing, from a wallet registered to your platform. It is credited automatically. 2. **Each sponsored transaction** is charged its actual cost, Sui gas and Ika fees, converted at current prices, plus a **0.3% markup**. 3. **When the balance runs low**, new transactions are refused with `insufficient_platform_balance`. The dashboard shows how many transactions your balance still covers. Deposits and withdrawals through the funds panel are paid by the user, inside the bridge quote, not from your balance. ## Webhooks Set a URL in Settings to receive events: | Event | When | |---|---| | `transaction.updated` | a transaction changes status | | `bridge.order.updated` | a deposit or withdrawal changes status | | `account.updated` | an account is created or activated | Each request carries `x-ika-accounts-timestamp` and `x-ika-accounts-signature: sha256=`, an HMAC-SHA256 of `timestamp + "." + rawBody` with your webhook secret. Verify it, and reject timestamps older than 5 minutes. Failed deliveries are retried with backoff for about 7 hours. ```ts import { createHmac, timingSafeEqual } from 'node:crypto'; function verify(rawBody: string, timestamp: string, header: string, secret: string) { const expected = createHmac('sha256', secret).update(`${timestamp}.${rawBody}`).digest('hex'); const age = Date.now() / 1000 - Number(timestamp); return age < 300 && timingSafeEqual(Buffer.from(header), Buffer.from(`sha256=${expected}`)); } ``` Webhook URLs must be public HTTPS endpoints. ## Limits | Limit | Default | |---|---| | Sponsored transactions per user per day | 200 | | Sponsored transactions per platform per day | 5,000 | | New accounts per platform per day | 200 | | Transactions in flight per user | 3 | | API requests per user per minute | 60 | | Raw message size | 4,096 bytes | Hitting a limit returns `rate_limited`. Ask us to raise them for a launch. --- # Reference ## createIkaAccounts ```ts createIkaAccounts(options: CreateIkaAccountsOptions): IkaAccounts ``` | Option | Type | | |---|---|---| | `apiKey` | `string` | Your platform key, from the dashboard. | | `apiUrl` | `string` | `https://ika-accounts.mpckit.xyz` | | `keysOrigin` | `string` | `https://ika-accounts.mpckit.xyz`. Required in browsers. | | `network` | `'mainnet' \| 'testnet'` | Default `'mainnet'`. | | `session` | `SessionConfig` | Optional. See [sessions](https://docs-ika-accounts.mpckit.xyz/transactions/#sessions). | | `suiUrl` | `string` | Optional Sui gRPC endpoint for reads. | | `keyHost` | `KeyHost` | Node and tests: `createLocalKeyHost(...)` instead of the iframe. | ## Methods **Sign-in** | | | |---|---| | `openConnect(options?)` | Sign-in modal. Resolves addresses or `null`. | | `reconnect()` | Restores the last wallet silently, or resolves `null`. | | `signInWallets()` | Installed wallets: `{ id, name, icon, chain }[]`. | | `connectWallet(id)` | Signs in with one of them. | | `connect(provider)` | Signs in with an EIP-1193 provider or a Solana wallet. | | `disconnect()` | Signs out and ends the session on-chain. | | `forgetDevice()` | Also erases this browser's cached key. | | `preload()` | Fetches Ika parameters early. | | `whenReady()` | Resolves when the account's keys are ready. | | `subscribe(listener)` | Called on sign-in and sign-out. Returns an unsubscribe function. | **State**: `isConnected`, `address`, `addresses`, `owner`, `wallet`, `fundingWallets`. **Transactions** | | | |---|---| | `execute(input)` | Gasless Sui transaction. `{ digest }` | | `perform(options)` | Fund if needed, then execute. `{ digest, deposits }` | | `swap({ from, to, amountIn \| amountOut })` | Swap on Sui through Aftermath. | | `balance(coinType?)` | Balance on Sui, default USDC. `bigint` | | `signMessage(bytes)` | Raw Ed25519 signature. | | `near.signIntents(intents)`, `near.publish(signed)` | NEAR Intents. | | `solana.signTransaction(message)` | Solana. | **Funds** | | | |---|---| | `openFunds({ tab, receive })` | Deposit and withdraw panel. | | `estimateDeposit(params)`, `estimateWithdraw(params)` | Quote without an order. | | `deposit(params)` | Creates an order: `{ order, send(), wait() }`. | | `withdraw(params)` | Sends from Sui: `{ order, digest, wait() }`. | | `waitForOrder(id)` | Follows an order to `SUCCESS`, or throws. | | `tokens()`, `chains()` | Everything that can be bridged, with logos. | | `fundingOptions()` | The user's bridgeable balances, largest first. | | `availableWallets()`, `addFundingWallet(id)` | Extra wallets to deposit from. | ## React ```tsx import { IkaAccountsProvider, useIkaAccount, useBalance, usePerform } from '@ika-accounts/react'; const { connect, addresses, isReady } = useIkaAccount(); const { balance } = useBalance(USDC); const { perform, status, error } = usePerform(); ``` `useIkaAccounts()` returns the client, and `useFundingOptions()` the user's balances on other chains. ## Errors The SDK throws `IkaAccountsError` with a stable `code`. API errors surface with the API's code. | Code | Meaning | |---|---| | `not_connected` | Call a sign-in method first. | | `transaction_failed` | The transaction executed and failed on-chain. | | `insufficient_funds` | No balance on any connected chain covers the amount. | | `bridge_refunded`, `bridge_failed` | The bridge order was refunded or failed. | | `bridge_timeout`, `balance_timeout` | Funds didn't arrive in time. | | `approval_required`, `invalid_approval`, `approval_expired` | The wallet approval is missing, wrong or too old. | | `wallet_key_mismatch` | The wallet produced a different key than the account's (not deterministic). | | `rate_limited` | A limit was hit. See [limits](https://docs-ika-accounts.mpckit.xyz/platform/#limits). | | `insufficient_platform_balance` | Your platform balance is too low. Top up. | | `presign_pool_empty`, `service_underfunded`, `service_paused` | Temporary. Retry shortly. | ## Deployments Sui mainnet: | | | |---|---| | Accounts package | `0xc60bb39a956847eeb02651435809241e8a6aa83780e157f5523ddbdfa533cae0` | | Registry | `0xb83e52ab869e84bc435f8042403b6de28b3796b6e640feac6867759d20e53b76` | | Upgrade timelock (7 days) | `0xac3bdc737adf7b9e829759237f1bf9993b935012afbd4e0cd656693f1796cda2` | ## Endpoints | | | |---|---| | API | `https://ika-accounts.mpckit.xyz/v1` | | Key origin | `https://ika-accounts.mpckit.xyz` | | Dashboard | `https://dashboard-ika-accounts.mpckit.xyz` | | Health | `https://ika-accounts.mpckit.xyz/health` |