Keythings Wallet API Reference

Complete, accurate reference for integrating with the Keythings (Keeta) in‑page provider available at window.keeta.

Note: The provider injects only on HTTPS origins or during development at http://localhost:3000 and http://127.0.0.1:3000.

Provider and Events

The provider exposes a request-based API plus convenience helpers and emits standard events:

  • accountsChanged — payload: string[] of account addresses
  • chainChanged — payload: chainId as 0x-prefixed hex string
  • lockChanged — payload: boolean (true when wallet locked)
  • disconnect — no payload

Example:

const provider = window.keeta;
provider.on('accountsChanged', (accounts) => console.log(accounts));
provider.on('chainChanged', (chainId) => console.log(chainId));

Capability Model

APIs are protected by capability tokens: read, sign, transact, network.

  • The built-in helpers automatically obtain and refresh tokens as needed.
  • When calling raw methods via provider.request, pass { capabilityToken } in the last parameter position shown below.

Requesting capabilities explicitly:

await provider.requestCapabilities(['sign', 'transact']);

Public APIs (no approval)

MethodDescription
keeta_getAccountsReturns [] until origin is approved. Wrapper: provider.getAccounts()
keeta_isLockedReturns true/false. Wrapper: provider.isLocked()

Connection API

MethodTriggersDefault capabilities
keeta_requestAccountsConnection approval UIread, transact

Optional: provider.request({ method: 'keeta_requestAccounts', params: [{ capabilities: ['read','sign'] }] })

Protected Read APIs (require prior approval)

MethodCapabilityWrapper
keeta_getNetworkreadprovider.getNetwork()
keeta_getAccountreadprovider.request({ method: 'keeta_getAccount', params: [ { capabilityToken } ] })
keeta_getBalancereadprovider.getBalance(address?)
keeta_getAllBalancesreadprovider.getAllBalances()
keeta_getNormalizedBalancesreadprovider.getNormalizedBalances()
keeta_getAccountStatereadprovider.getAccountState(address)
keeta_getNetworkInforeadprovider.request({ method: 'keeta_getNetworkInfo' })
keeta_getBaseTokenreadprovider.getBaseToken()
keeta_getAccountInfoapprovalprovider.getAccountInfo(address)
keeta_listStorageAccountsByOwnerapprovalprovider.listStorageAccountsByOwner(owner)
keeta_getKtaPriceapprovalprovider.getKtaPrice()

History: The wallet no longer exposes a transaction history RPC. For ledger history, use the Keeta JS SDK (UserClient.history / Client.history) or an indexer service directly with the account and network returned by the wallet.

  • keeta_getAccountInfo and keeta_listStorageAccountsByOwner require approval but no explicit capability token.

Write operations (approval + per‑request confirmation)

MethodCapabilityWrapper
keeta_sendTransactiontransactprovider.sendTransaction(tx)
keeta_signMessagesignprovider.signMessage(message)
keeta_sendtransactprovider.request({ method: 'keeta_send', params: [to, amount, token] })
keeta_receivetransactprovider.request({ method: 'keeta_receive', params: [from, amount, token] })
keeta_createTokentransactprovider.request({ method: 'keeta_createToken', params: [name, symbol, decimals, supply, accessMode] })
keeta_modifyTokenSupplytransactprovider.request({ method: 'keeta_modifyTokenSupply', params: [tokenAddress, amount, operation] })
keeta_modifyTokenBalancetransactprovider.request({ method: 'keeta_modifyTokenBalance', params: [account, amount, tokenAddress] })
keeta_updatePermissionstransactprovider.request({ method: 'keeta_updatePermissions', params: [account, permissions, target] })
keeta_setInfotransactprovider.request({ method: 'keeta_setInfo', params: [info, account] })
keeta_createStorageAccounttransactprovider.request({ method: 'keeta_createStorageAccount', params: [name, description, metadata, permissions] })

keeta_sendTransaction

Wrapper: provider.sendTransaction(tx)

The tx payload is a JSON object with this shape:

type KeetaTransaction = {
  to: string;                // required recipient account on Keeta
  amount: string;            // required amount as a string (decimal or raw, depending on integration)
  from?: string;             // optional explicit sender; usually omitted so the active account is used
  token?: string;            // optional token account; omitted for base token transfers
  data?: string;             // optional external payload (anchors, contract calls, protocol metadata)
  gasLimit?: string;         // optional network fee hint
  nonce?: string;            // optional client nonce
  operations?: unknown[];    // reserved for advanced builder-style operations
}

When data is provided, the wallet:

  • Validates the field with Zod as part of the transaction payload.
  • For direct dApp-initiated sends, passes tx.data into the underlying Keeta SDK builder as the external argument to builder.send(...).
  • This is the recommended way to attach asset-movement anchor payloads and other cross-network routing metadata (for example, bridging from KTA to Base).

Network and Capabilities

MethodCapabilityWrapper
keeta_switchNetworknetworkprovider.switchNetwork('test'
keeta_requestCapabilitiesapprovalprovider.requestCapabilities([...])
keeta_refreshCapabilitiesapprovalprovider.refreshCapabilities([...])

User Client and Builder

const client = await provider.getUserClient();
const builder = client.initBuilder();

// Generate a STORAGE or TOKEN identifier
const storage = builder.generateIdentifier('STORAGE');

// Example: send on behalf of a storage account
builder.send(
  'keeta_recipient_address',
  '1000000',
  client.baseToken,
  undefined,
  { account: storage.account }
);

// Compute and publish
await client.publishBuilder(builder);

Supported builder RPCs (raw): keeta_builder_generateIdentifier, keeta_builder_computeBlocks, keeta_builder_publish.

Quick examples

Detect and connect:

const provider = window.keeta;
if (!provider) throw new Error('Keythings Wallet not detected');
const accounts = await provider.requestAccounts();

Get balances:

const [account] = await provider.getAccounts();
const balance = await provider.getBalance(account);
const normalized = await provider.getNormalizedBalances();

Network:

const network = await provider.getNetwork();
await provider.switchNetwork('test');

Get balances:

Error codes

CodeMeaning
4001USER_REJECTED_REQUEST
4100UNAUTHORIZED
4200UNSUPPORTED_METHOD
4290RATE_LIMITED
4900DISCONNECTED
4901CHAIN_DISCONNECTED
5000UNKNOWN_ERROR
5100BALANCE_UNAVAILABLE