koios-agent-wallet
koios-agent-wallet
Operating rules (must follow)
- Default to mainnet unless the user explicitly requests preprod/preview/guild.
- Confirm target network (mainnet, preprod, preview, guild) before giving endpoints if unclear.
- Use KoiosProvider for read + submit; do not suggest it for key generation.
- Never request seed phrases or private keys; keep examples with placeholder addresses only.
- Agent runtime must not use mnemonic phrases for signing/staking; use
clikeys orrootkey mode only. - Use the correct Koios base URL per network and confirm with the user if unsure.
- Staking requires a stake signing key; if only a payment key is available, staking cannot be signed.
Quickstart workflow
-
Confirm key-based setup and environment
- Ask: CLI-generated signing keys or root private key?
- If user only has a mnemonic, instruct them to derive/export keys offline first; do not use mnemonic directly in agent runtime.
- Ask: Node.js or browser? TypeScript or JavaScript?
-
Provide key-based wallet creation path
- When the user wants a new wallet: run
scripts/generate-key-based-wallet.jsfrom the skill directory. It creates payment + stake keypairs and prints base address, stake address, andPAYMENT_SKEY_CBOR_HEX/STAKE_SKEY_CBOR_HEX. Optionally setWALLET_DIR=./walletto writeaddresses.json,payment.skey,stake.skey, and (if@noble/ed25519is installed)payment.vkey,stake.vkey. Use those CBOR hex values withagent-wallet.jsfor send/stake. - Use MeshWallet for key-based wallets (CLI keys or root key).
- For staking, require both payment.skey and stake.skey (or a root key).
- If CLI keys are needed and the user does not have them, use
scripts/generate-key-based-wallet.js(MeshJS + Koios only; no cardano-cli). - If mnemonic is provided to the agent, fail fast with a clear error and request CLI/root key input.
- When the user wants a new wallet: run
-
Provide Koios base URL for the network
- Mainnet:
https://api.koios.rest - Preprod:
https://preprod.koios.rest - Preview:
https://preview.koios.rest - Guild:
https://guild.koios.rest - Use the OpenAPI docs at the base URL to confirm endpoint paths.
- Mainnet:
-
Verify funding with Koios
- Use
KoiosProvider.fetchAddressUTxOsorprovider.get(...)with an OpenAPI endpoint. - If the wallet is unfunded on a testnet, direct the user to a faucet before retrying.
- Use
-
Core actions (must support)
- Send ADA transactions with MeshTxBuilder.
- Register and delegate stake with MeshTxBuilder +
deserializePoolId. - Confirm staking status with
provider.fetchAccountInfo. - Sign + submit prebuilt txs from dApp mint builders (e.g., Nexus).
MeshJS key-based wallet (MeshWallet)
Koios provider (recommended for agent read-only queries)
import { KoiosProvider } from "@meshsdk/core";
const provider = new KoiosProvider("api", "<KOIOS_API_KEY>"); // api=mainnet
Network values: api (mainnet), preview, preprod, guild.
Load from Cardano CLI keys (recommended for agents)
import { MeshWallet } from "@meshsdk/core";
const wallet = new MeshWallet({
networkId: 1, // 1 = mainnet
fetcher: provider,
submitter: provider,
key: {
type: "cli",
payment: "<PAYMENT_SKEY_CBOR_HEX>",
stake: "<STAKE_SKEY_CBOR_HEX>", // required for staking
},
});
await wallet.init();
const address = await wallet.getChangeAddress();
console.log(address);
Load from a root private key (alternative)
import { MeshWallet } from "@meshsdk/core";
const wallet = new MeshWallet({
networkId: 1, // 1 = mainnet
fetcher: provider,
submitter: provider,
key: {
type: "root",
bech32: "xprv1...", // root private key (keep secure)
},
});
await wallet.init();
const address = await wallet.getChangeAddress();
console.log(address);
Read-only wallet (address only)
import { MeshWallet } from "@meshsdk/core";
const wallet = new MeshWallet({
networkId: 1, // 1 = mainnet
fetcher: provider,
key: {
type: "address",
address: "addr1...",
},
});
await wallet.init();
const address = await wallet.getChangeAddress();
console.log(address);
Minimal Koios check (UTxOs)
TypeScript (KoiosProvider)
import { KoiosProvider } from "@meshsdk/core";
const provider = new KoiosProvider("api", "<KOIOS_API_KEY>");
const address = "addr1...";
const utxos = await provider.fetchAddressUTxOs(address);
console.log(utxos);
Funding + confirmation checklist
-
Funding
- Check UTxOs:
provider.fetchAddressUTxOs(address) - Ensure enough ADA for fees and (if first-time staking) the stake deposit.
- Check UTxOs:
-
Staking readiness
- Get reward address:
const rewardAddress = (await wallet.getRewardAddresses())[0] - Check registration/delegation:
provider.fetchAccountInfo(rewardAddress)
- Get reward address:
-
Confirmation after submit
- Use
provider.fetchTxInfo(txHash)or poll until confirmed.
- Use
Agent wallet dossier (output format)
=== Agent Wallet Dossier ===
Network: mainnet (api)
Payment Address: addr1...
Stake Address: stake1...
Koios Provider: api
Funding UTxOs: <count>
Stake Status: registered | unregistered
Delegated Pool: pool1... | none
Last Tx: <txHash> | none
Send ADA (MeshTxBuilder)
import { KoiosProvider, MeshTxBuilder } from "@meshsdk/core";
const provider = new KoiosProvider("api", "<KOIOS_API_KEY>");
const txBuilder = new MeshTxBuilder({ fetcher: provider });
const utxos = await wallet.getUtxos();
const changeAddress = await wallet.getChangeAddress();
const unsignedTx = await txBuilder
.txOut("addr1...", [{ unit: "lovelace", quantity: "1000000" }])
.changeAddress(changeAddress)
.selectUtxosFrom(utxos)
.complete();
const signedTx = await wallet.signTx(unsignedTx);
const txHash = await wallet.submitTx(signedTx);
console.log(txHash);
Mint NFTs via dApp builder (Nexus / similar)
Minting on hosted dApps typically means their backend builds an unsigned transaction and your wallet only signs. Koios submits it. You cannot recreate these mint transactions without the policy script + server rules, so the agent should sign and submit the dApp-built tx.
Step 1: Capture the unsigned tx (CBOR hex)
- Use the dApp’s mint API that the website calls after wallet connect.
- Capture the request/response in browser devtools; look for response fields like
txCbor,cborHex,unsignedTx, ortx. - If the API returns base64, convert to hex before using the script.
Step 2: Sign + submit (agent)
KOIOS_NETWORK=api MODE=sign-submit \
PAYMENT_SKEY_CBOR_HEX=<your_payment_skey_cbor_hex> \
TX_CBOR_HEX=<unsigned_tx_cbor_hex_from_api> \
node scripts/agent-wallet.js
- Optional:
TX_FILE=/path/to/tx.cborhex,PRINT_SIGNED=1,CONFIRM=1. - The payment key must match the address used in the mint request.
MODE=sign-submitpreserves existing script witnesses/redeemers in the tx.
Stake to a pool (register + delegate)
import { KoiosProvider, MeshTxBuilder, deserializePoolId } from "@meshsdk/core";
const provider = new KoiosProvider("api", "<KOIOS_API_KEY>");
const txBuilder = new MeshTxBuilder({ fetcher: provider, verbose: true });
const utxos = await wallet.getUtxos();
const changeAddress = await wallet.getChangeAddress();
const rewardAddresses = await wallet.getRewardAddresses();
const rewardAddress = rewardAddresses[0]!;
const poolIdHash = deserializePoolId("pool1...");
const unsignedTx = await txBuilder
.registerStakeCertificate(rewardAddress)
.delegateStakeCertificate(rewardAddress, poolIdHash)
.selectUtxosFrom(utxos)
.changeAddress(changeAddress)
.complete();
const signedTx = await wallet.signTx(unsignedTx);
const txHash = await wallet.submitTx(signedTx);
console.log(txHash);
Agent workflow: generate → fund → register + stake
Use this sequence when the user wants a new wallet, then to register its stake address and delegate to a pool. All steps use key-based setup (no mnemonic in agent runtime). Yes: the agent can register, then stake — both happen in one transaction (Step 3).
Step 1: Generate wallet (agent runs the script)
- Run
scripts/generate-key-based-wallet.jsfrom the skill directory. Uses MeshJS + Koios only (no cardano-cli, no mnemonic). - Env (optional):
NETWORK=mainnet(default) orpreprod/preview;KOIOS_API_KEYfor Koios;WALLET_DIR=./walletto writeaddresses.json,payment.skey,stake.skey, and (if@noble/ed25519is installed)payment.vkey,stake.vkey. Keys are also printed to stdout. - Output: base address, stake address, and export lines for
PAYMENT_SKEY_CBOR_HEX/STAKE_SKEY_CBOR_HEX. For.vkeyfiles, install@noble/ed25519alongside@meshsdk/core. - Requires
@meshsdk/coreand network access (Koios) for address derivation.
cd skills/koios-agent-wallet
NETWORK=mainnet node scripts/generate-key-based-wallet.js
# Optional: WALLET_DIR=./wallet to persist keys to disk
- From the script output, capture the base address (user funds this), and the two CBOR hex values for Step 3.
Step 2: Fund the wallet
- User must send ADA to the base address (payment address) printed in the dossier.
- For first-time staking: wallet needs enough for ~2 ADA stake deposit plus fees (e.g. 3+ ADA total). Check with
provider.fetchAddressUTxOs(baseAddress)before Step 3.
Step 3: Register stake address and delegate (one transaction)
- Register and stake in a single tx: run
scripts/agent-wallet.jswithMODE=stake,REGISTER_STAKE=1, andPOOL_ID=pool1.... This registers the stake address and delegates to the pool; no separate "register only" step is needed. - Env:
PAYMENT_SKEY_CBOR_HEX,STAKE_SKEY_CBOR_HEX(from Step 1),KOIOS_NETWORK=api(mainnet) orpreprod/preview,POOL_ID,REGISTER_STAKE=1.
KOIOS_NETWORK=api MODE=stake REGISTER_STAKE=1 POOL_ID=pool1... \
PAYMENT_SKEY_CBOR_HEX=<from_step_1> STAKE_SKEY_CBOR_HEX=<from_step_1> \
node scripts/agent-wallet.js
- Optional:
CONFIRM=1to poll for tx confirmation.
Staking gotchas (agent must respect)
- Stake address not registered: Always use
REGISTER_STAKE=1for the first delegation (or the stake cert will fail). Omit or set to 0 when changing delegation only. - Insufficient funds for deposit: Stake registration locks ~2 ADA. Ensure wallet has 2 ADA + fees before running Step 3.
- Staking requires stake key: Wallet must be loaded with
STAKE_SKEY_CBOR_HEX(or root key); payment-only cannot sign stake certs. - Stake cert signing:
MeshWallet.signTx()only adds the payment key witness; stake registration/delegation certs require the stake key witness too. If you seeMissingVKeyWitnessesUTXOWorKeyHash {...}, the missing witness is usually the stake key. The skill’sagent-wallet.jsuses CSLFixedTransactionto get the tx hash (CSL 15.x+), createmake_vkey_witnessfor both payment and stake keys, and rebuildTransaction.new(body, witnessSet, auxiliaryData)so auxiliary data is preserved (avoidsMissingTxMetadata). For staking with CLI keys, install:@meshsdk/core,@emurgo/cardano-serialization-lib-nodejs, and (if using hex pool ID)bech32. - Pool ID (recommended): The skill uses MeshJS’s
deserializePoolId(pool1...)with a bech32 pool ID — that is correct. Prefer the bech32 pool ID from a trusted source (e.g. Cardanoscan or the pool’s official page) instead of manually converting hex to bech32; manual conversion with a genericbech32library can produce the wrong ID (wrong checksum / wrong pool). When an API gives you a hex pool ID, look up the pool on Cardanoscan and use thepool1...ID shown there. The script can accept hex and attempt conversion, but the canonical source is the explorer’s bech32. - Pool ID format:
deserializePoolId()expects bech32 (pool1...). PassPOOL_IDas bech32 when possible; hex (56 chars) is supported and converted via thebech32package, but using the bech32 ID from Cardanoscan is more reliable. - MeshJS staking reference: https://meshjs.dev/apis/txbuilder/staking#stake-address-not-registered-error
Summary
| Step | Action | Script / API |
|---|---|---|
| 1 | Generate wallet (no mnemonic) | generate-key-based-wallet.js |
| 2 | Fund base address | User sends ADA; verify with fetchAddressUTxOs |
| 3 | Register + delegate | agent-wallet.js MODE=stake, REGISTER_STAKE=1, POOL_ID |
Response checklist (agent wallet setup)
- Network and Koios base URL
- Wallet address used for funding
- Koios query used (endpoint + payload)
- Transaction intent (send or stake), tx hash, and confirmation method
Notes
- Koios provides OpenAPI docs at each network base URL; use them to confirm endpoints and payloads.
- KoiosProvider expects a
networkstring and optionalapiKey; it can submit transactions. - MeshTxBuilder staking flows are documented in MeshJS staking transactions.
Scripts
scripts/agent-wallet.js— end-to-end template (wallet init, send ADA, stake, confirm). Staking with CLI keys: uses CSLFixedTransactionto get the tx hash (CSL 15.x+), create vkey witnesses for both payment and stake keys, and rebuild the transaction with auxiliary data preserved (MeshWallet.signTx only signs with payment key; stake certs need both). Pool ID: use the bech32 pool ID (pool1...) from Cardanoscan or the pool’s page when possible; the script accepts hex and converts viabech32, but manual hex→bech32 conversion can be wrong — prefer the explorer’spool1...ID. Deps:@meshsdk/core,@emurgo/cardano-serialization-lib-nodejs; for hexPOOL_ID, alsobech32.scripts/generate-key-based-wallet.js— generate new key-based wallet (no mnemonic, no cardano-cli); uses MeshJS + Koios only; creates payment + stake keys and outputs CBOR hex for use with agent-wallet (staking-ready).
Generate new wallet (key-based, stakable)
# Optional: NETWORK=mainnet (default) | preprod | preview; KOIOS_API_KEY=...; WALLET_DIR=./my-wallet (writes addresses.json only)
node scripts/generate-key-based-wallet.js
Outputs: base + stake addresses and PAYMENT_SKEY_CBOR_HEX / STAKE_SKEY_CBOR_HEX export lines. If WALLET_DIR is set, writes addresses.json, payment.skey, stake.skey, and (if @noble/ed25519 is installed) payment.vkey, stake.vkey. No cardano-cli required. Requires @meshsdk/core and Koios (network). For staking with agent-wallet.js (CLI keys), also install @emurgo/cardano-serialization-lib-nodejs; if you pass a hex POOL_ID, install bech32.
Script usage examples
# Status (read-only)
KOIOS_NETWORK=api MODE=status ADDRESS_ONLY=addr1... \\
node scripts/agent-wallet.js
# Send ADA (CLI keys)
KOIOS_NETWORK=api MODE=send PAYMENT_SKEY_CBOR_HEX=<...> \\
RECIPIENT_ADDR=addr1... SEND_LOVELACE=1000000 \\
node scripts/agent-wallet.js
# Register + delegate (prefer POOL_ID as pool1... from Cardanoscan)
KOIOS_NETWORK=api MODE=stake PAYMENT_SKEY_CBOR_HEX=<...> \\
STAKE_SKEY_CBOR_HEX=<...> POOL_ID=pool1... REGISTER_STAKE=1 \\
node scripts/agent-wallet.js
References
shared/PRINCIPLES.md- Koios API base:
https://api.koios.rest/ - Koios API guide:
https://koios.rest/guide/ - MeshJS Koios provider:
https://meshjs.dev/providers/koios - MeshJS MeshWallet:
https://meshjs.dev/apis/wallets/meshwallet - MeshJS MeshTxBuilder basics:
https://meshjs.dev/apis/txbuilder/basics - MeshJS staking transactions:
https://meshjs.dev/apis/txbuilder/staking