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)
| Method | Description |
|---|---|
| keeta_getAccounts | Returns [] until origin is approved. Wrapper: provider.getAccounts() |
| keeta_isLocked | Returns true/false. Wrapper: provider.isLocked() |
Connection API
| Method | Triggers | Default capabilities |
|---|---|---|
| keeta_requestAccounts | Connection approval UI | read, transact |
Optional: provider.request({ method: 'keeta_requestAccounts', params: [{ capabilities: ['read','sign'] }] })
Protected Read APIs (require prior approval)
| Method | Capability | Wrapper |
|---|---|---|
| keeta_getNetwork | read | provider.getNetwork() |
| keeta_getAccount | read | provider.request({ method: 'keeta_getAccount', params: [ { capabilityToken } ] }) |
| keeta_getBalance | read | provider.getBalance(address?) |
| keeta_getAllBalances | read | provider.getAllBalances() |
| keeta_getNormalizedBalances | read | provider.getNormalizedBalances() |
| keeta_getAccountState | read | provider.getAccountState(address) |
| keeta_getNetworkInfo | read | provider.request({ method: 'keeta_getNetworkInfo' }) |
| keeta_getBaseToken | read | provider.getBaseToken() |
| keeta_getAccountInfo | approval | provider.getAccountInfo(address) |
| keeta_listStorageAccountsByOwner | approval | provider.listStorageAccountsByOwner(owner) |
| keeta_getKtaPrice | approval | provider.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_getAccountInfoandkeeta_listStorageAccountsByOwnerrequire approval but no explicit capability token.
Write operations (approval + per‑request confirmation)
| Method | Capability | Wrapper |
|---|---|---|
| keeta_sendTransaction | transact | provider.sendTransaction(tx) |
| keeta_signMessage | sign | provider.signMessage(message) |
| keeta_send | transact | provider.request({ method: 'keeta_send', params: [to, amount, token] }) |
| keeta_receive | transact | provider.request({ method: 'keeta_receive', params: [from, amount, token] }) |
| keeta_createToken | transact | provider.request({ method: 'keeta_createToken', params: [name, symbol, decimals, supply, accessMode] }) |
| keeta_modifyTokenSupply | transact | provider.request({ method: 'keeta_modifyTokenSupply', params: [tokenAddress, amount, operation] }) |
| keeta_modifyTokenBalance | transact | provider.request({ method: 'keeta_modifyTokenBalance', params: [account, amount, tokenAddress] }) |
| keeta_updatePermissions | transact | provider.request({ method: 'keeta_updatePermissions', params: [account, permissions, target] }) |
| keeta_setInfo | transact | provider.request({ method: 'keeta_setInfo', params: [info, account] }) |
| keeta_createStorageAccount | transact | provider.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.datainto the underlying Keeta SDK builder as theexternalargument tobuilder.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
| Method | Capability | Wrapper |
|---|---|---|
| keeta_switchNetwork | network | provider.switchNetwork('test' |
| keeta_requestCapabilities | approval | provider.requestCapabilities([...]) |
| keeta_refreshCapabilities | approval | provider.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
| Code | Meaning |
|---|---|
| 4001 | USER_REJECTED_REQUEST |
| 4100 | UNAUTHORIZED |
| 4200 | UNSUPPORTED_METHOD |
| 4290 | RATE_LIMITED |
| 4900 | DISCONNECTED |
| 4901 | CHAIN_DISCONNECTED |
| 5000 | UNKNOWN_ERROR |
| 5100 | BALANCE_UNAVAILABLE |