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
cli keys or root key 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.js from the skill directory. It creates payment + stake keypairs and prints base address, stake address, and PAYMENT_SKEY_CBOR_HEX / STAKE_SKEY_CBOR_HEX. Optionally set WALLET_DIR=./wallet to write addresses.json, payment.skey, stake.skey, and (if @noble/ed25519 is installed) payment.vkey, stake.vkey. Use those CBOR hex values with agent-wallet.js for 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.
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.
Verify funding with Koios
- Use
KoiosProvider.fetchAddressUTxOs or provider.get(...) with an OpenAPI endpoint.
- If the wallet is unfunded on a testnet, direct the user to a faucet before retrying.
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.
Staking readiness
- Get reward address:
const rewardAddress = (await wallet.getRewardAddresses())[0]
- Check registration/delegation:
provider.fetchAccountInfo(rewardAddress)
Confirmation after submit
- Use
provider.fetchTxInfo(txHash) or poll until confirmed.
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, or tx.
- 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-submit preserves 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.js from the skill directory. Uses MeshJS + Koios only (no cardano-cli, no mnemonic).
- Env (optional):
NETWORK=mainnet (default) or preprod / preview; KOIOS_API_KEY for Koios; WALLET_DIR=./wallet to write addresses.json, payment.skey, stake.skey, and (if @noble/ed25519 is 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 .vkey files, install @noble/ed25519 alongside @meshsdk/core.
- Requires
@meshsdk/core and 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.js with MODE=stake, REGISTER_STAKE=1, and POOL_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) or preprod / 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=1 to poll for tx confirmation.
Staking gotchas (agent must respect)
- Stake address not registered: Always use
REGISTER_STAKE=1 for 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 see MissingVKeyWitnessesUTXOW or KeyHash {...}, the missing witness is usually the stake key. The skill’s agent-wallet.js uses CSL FixedTransaction to get the tx hash (CSL 15.x+), create make_vkey_witness for both payment and stake keys, and rebuild Transaction.new(body, witnessSet, auxiliaryData) so auxiliary data is preserved (avoids MissingTxMetadata). 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 generic bech32 library 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 the pool1... 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...). Pass POOL_ID as bech32 when possible; hex (56 chars) is supported and converted via the bech32 package, 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
network string and optional apiKey; 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 CSL FixedTransaction to 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 via bech32, but manual hex→bech32 conversion can be wrong — prefer the explorer’s pool1... ID. Deps: @meshsdk/core, @emurgo/cardano-serialization-lib-nodejs; for hex POOL_ID, also bech32.
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
1---2name: koios-agent-wallet3description: Quick setup of key-based Cardano agent wallets with MeshJS (MeshWallet) and KoiosProvider: generate wallet (no mnemonic), register stake address, and stake to a pool. Use when users ask to generate a wallet, register it, stake it, send transactions, or query wallet state via Koios.4---56# koios-agent-wallet78## Operating rules (must follow)910- Default to mainnet unless the user explicitly requests preprod/preview/guild.11- Confirm target network (mainnet, preprod, preview, guild) before giving endpoints if unclear.12- Use KoiosProvider for read + submit; do not suggest it for key generation.13- Never request seed phrases or private keys; keep examples with placeholder addresses only.14- Agent runtime must not use mnemonic phrases for signing/staking; use `cli` keys or `root` key mode only.15- Use the correct Koios base URL per network and confirm with the user if unsure.16- Staking requires a stake signing key; if only a payment key is available, staking cannot be signed.1718## Quickstart workflow19201. Confirm key-based setup and environment2122 - Ask: CLI-generated signing keys or root private key?23 - If user only has a mnemonic, instruct them to derive/export keys offline first; do not use mnemonic directly in agent runtime.24 - Ask: Node.js or browser? TypeScript or JavaScript?25262. Provide key-based wallet creation path2728 - **When the user wants a new wallet:** run `scripts/generate-key-based-wallet.js` from the skill directory. It creates payment + stake keypairs and prints base address, stake address, and `PAYMENT_SKEY_CBOR_HEX` / `STAKE_SKEY_CBOR_HEX`. Optionally set `WALLET_DIR=./wallet` to write `addresses.json`, `payment.skey`, `stake.skey`, and (if `@noble/ed25519` is installed) `payment.vkey`, `stake.vkey`. Use those CBOR hex values with `agent-wallet.js` for send/stake.29 - Use MeshWallet for key-based wallets (CLI keys or root key).30 - For staking, require both payment.skey and stake.skey (or a root key).31 - 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).32 - If mnemonic is provided to the agent, fail fast with a clear error and request CLI/root key input.33343. Provide Koios base URL for the network3536 - Mainnet: `https://api.koios.rest`37 - Preprod: `https://preprod.koios.rest`38 - Preview: `https://preview.koios.rest`39 - Guild: `https://guild.koios.rest`40 - Use the OpenAPI docs at the base URL to confirm endpoint paths.41424. Verify funding with Koios4344 - Use `KoiosProvider.fetchAddressUTxOs` or `provider.get(...)` with an OpenAPI endpoint.45 - If the wallet is unfunded on a testnet, direct the user to a faucet before retrying.46475. Core actions (must support)48 - Send ADA transactions with MeshTxBuilder.49 - Register and delegate stake with MeshTxBuilder + `deserializePoolId`.50 - Confirm staking status with `provider.fetchAccountInfo`.51 - Sign + submit prebuilt txs from dApp mint builders (e.g., Nexus).5253## MeshJS key-based wallet (MeshWallet)5455### Koios provider (recommended for agent read-only queries)5657```typescript58import { KoiosProvider } from "@meshsdk/core";5960const provider = new KoiosProvider("api", "<KOIOS_API_KEY>"); // api=mainnet61```6263Network values: `api` (mainnet), `preview`, `preprod`, `guild`.6465### Load from Cardano CLI keys (recommended for agents)6667```typescript68import { MeshWallet } from "@meshsdk/core";6970const wallet = new MeshWallet({71 networkId: 1, // 1 = mainnet72 fetcher: provider,73 submitter: provider,74 key: {75 type: "cli",76 payment: "<PAYMENT_SKEY_CBOR_HEX>",77 stake: "<STAKE_SKEY_CBOR_HEX>", // required for staking78 },79});8081await wallet.init();82const address = await wallet.getChangeAddress();83console.log(address);84```8586### Load from a root private key (alternative)8788```typescript89import { MeshWallet } from "@meshsdk/core";9091const wallet = new MeshWallet({92 networkId: 1, // 1 = mainnet93 fetcher: provider,94 submitter: provider,95 key: {96 type: "root",97 bech32: "xprv1...", // root private key (keep secure)98 },99});100101await wallet.init();102const address = await wallet.getChangeAddress();103console.log(address);104```105106### Read-only wallet (address only)107108```typescript109import { MeshWallet } from "@meshsdk/core";110111const wallet = new MeshWallet({112 networkId: 1, // 1 = mainnet113 fetcher: provider,114 key: {115 type: "address",116 address: "addr1...",117 },118});119120await wallet.init();121const address = await wallet.getChangeAddress();122console.log(address);123```124125## Minimal Koios check (UTxOs)126127### TypeScript (KoiosProvider)128129```typescript130import { KoiosProvider } from "@meshsdk/core";131132const provider = new KoiosProvider("api", "<KOIOS_API_KEY>");133const address = "addr1...";134135const utxos = await provider.fetchAddressUTxOs(address);136console.log(utxos);137```138139## Funding + confirmation checklist1401411. Funding142143 - Check UTxOs: `provider.fetchAddressUTxOs(address)`144 - Ensure enough ADA for fees and (if first-time staking) the stake deposit.1451462. Staking readiness147148 - Get reward address: `const rewardAddress = (await wallet.getRewardAddresses())[0]`149 - Check registration/delegation: `provider.fetchAccountInfo(rewardAddress)`1501513. Confirmation after submit152 - Use `provider.fetchTxInfo(txHash)` or poll until confirmed.153154## Agent wallet dossier (output format)155156```157=== Agent Wallet Dossier ===158Network: mainnet (api)159Payment Address: addr1...160Stake Address: stake1...161Koios Provider: api162Funding UTxOs: <count>163Stake Status: registered | unregistered164Delegated Pool: pool1... | none165Last Tx: <txHash> | none166```167168## Send ADA (MeshTxBuilder)169170```typescript171import { KoiosProvider, MeshTxBuilder } from "@meshsdk/core";172173const provider = new KoiosProvider("api", "<KOIOS_API_KEY>");174const txBuilder = new MeshTxBuilder({ fetcher: provider });175176const utxos = await wallet.getUtxos();177const changeAddress = await wallet.getChangeAddress();178179const unsignedTx = await txBuilder180 .txOut("addr1...", [{ unit: "lovelace", quantity: "1000000" }])181 .changeAddress(changeAddress)182 .selectUtxosFrom(utxos)183 .complete();184185const signedTx = await wallet.signTx(unsignedTx);186const txHash = await wallet.submitTx(signedTx);187console.log(txHash);188```189190## Mint NFTs via dApp builder (Nexus / similar)191192Minting 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**.193194### Step 1: Capture the unsigned tx (CBOR hex)195196- Use the dApp’s mint API that the website calls after wallet connect.197- Capture the request/response in browser devtools; look for response fields like `txCbor`, `cborHex`, `unsignedTx`, or `tx`.198- If the API returns base64, convert to hex before using the script.199200### Step 2: Sign + submit (agent)201202```bash203KOIOS_NETWORK=api MODE=sign-submit \204 PAYMENT_SKEY_CBOR_HEX=<your_payment_skey_cbor_hex> \205 TX_CBOR_HEX=<unsigned_tx_cbor_hex_from_api> \206 node scripts/agent-wallet.js207```208209- Optional: `TX_FILE=/path/to/tx.cborhex`, `PRINT_SIGNED=1`, `CONFIRM=1`.210- The payment key must match the address used in the mint request.211- `MODE=sign-submit` preserves existing script witnesses/redeemers in the tx.212213## Stake to a pool (register + delegate)214215```typescript216import { KoiosProvider, MeshTxBuilder, deserializePoolId } from "@meshsdk/core";217218const provider = new KoiosProvider("api", "<KOIOS_API_KEY>");219const txBuilder = new MeshTxBuilder({ fetcher: provider, verbose: true });220221const utxos = await wallet.getUtxos();222const changeAddress = await wallet.getChangeAddress();223const rewardAddresses = await wallet.getRewardAddresses();224const rewardAddress = rewardAddresses[0]!;225const poolIdHash = deserializePoolId("pool1...");226227const unsignedTx = await txBuilder228 .registerStakeCertificate(rewardAddress)229 .delegateStakeCertificate(rewardAddress, poolIdHash)230 .selectUtxosFrom(utxos)231 .changeAddress(changeAddress)232 .complete();233234const signedTx = await wallet.signTx(unsignedTx);235const txHash = await wallet.submitTx(signedTx);236console.log(txHash);237```238239## Agent workflow: generate → fund → register + stake240241Use 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).242243### Step 1: Generate wallet (agent runs the script)244245- Run `scripts/generate-key-based-wallet.js` from the skill directory. Uses **MeshJS + Koios only** (no cardano-cli, no mnemonic).246- Env (optional): `NETWORK=mainnet` (default) or `preprod` / `preview`; `KOIOS_API_KEY` for Koios; `WALLET_DIR=./wallet` to write `addresses.json`, `payment.skey`, `stake.skey`, and (if `@noble/ed25519` is installed) `payment.vkey`, `stake.vkey`. Keys are also printed to stdout.247- Output: base address, stake address, and export lines for `PAYMENT_SKEY_CBOR_HEX` / `STAKE_SKEY_CBOR_HEX`. For `.vkey` files, install `@noble/ed25519` alongside `@meshsdk/core`.248- Requires `@meshsdk/core` and network access (Koios) for address derivation.249250```bash251cd skills/koios-agent-wallet252NETWORK=mainnet node scripts/generate-key-based-wallet.js253# Optional: WALLET_DIR=./wallet to persist keys to disk254```255256- From the script output, capture the **base address** (user funds this), and the two **CBOR hex** values for Step 3.257258### Step 2: Fund the wallet259260- User must send ADA to the **base address** (payment address) printed in the dossier.261- 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.262263### Step 3: Register stake address and delegate (one transaction)264265- **Register and stake in a single tx:** run `scripts/agent-wallet.js` with `MODE=stake`, `REGISTER_STAKE=1`, and `POOL_ID=pool1...`. This registers the stake address and delegates to the pool; no separate "register only" step is needed.266- Env: `PAYMENT_SKEY_CBOR_HEX`, `STAKE_SKEY_CBOR_HEX` (from Step 1), `KOIOS_NETWORK=api` (mainnet) or `preprod` / `preview`, `POOL_ID`, `REGISTER_STAKE=1`.267268```bash269KOIOS_NETWORK=api MODE=stake REGISTER_STAKE=1 POOL_ID=pool1... \270 PAYMENT_SKEY_CBOR_HEX=<from_step_1> STAKE_SKEY_CBOR_HEX=<from_step_1> \271 node scripts/agent-wallet.js272```273274- Optional: `CONFIRM=1` to poll for tx confirmation.275276### Staking gotchas (agent must respect)277278- **Stake address not registered**: Always use `REGISTER_STAKE=1` for the first delegation (or the stake cert will fail). Omit or set to 0 when changing delegation only.279- **Insufficient funds for deposit**: Stake registration locks ~2 ADA. Ensure wallet has 2 ADA + fees before running Step 3.280- **Staking requires stake key**: Wallet must be loaded with `STAKE_SKEY_CBOR_HEX` (or root key); payment-only cannot sign stake certs.281- **Stake cert signing**: `MeshWallet.signTx()` only adds the payment key witness; stake registration/delegation certs require the **stake key witness** too. If you see `MissingVKeyWitnessesUTXOW` or `KeyHash {...}`, the missing witness is usually the stake key. The skill’s `agent-wallet.js` uses CSL `FixedTransaction` to get the tx hash (CSL 15.x+), create `make_vkey_witness` for both payment and stake keys, and rebuild `Transaction.new(body, witnessSet, auxiliaryData)` so auxiliary data is preserved (avoids `MissingTxMetadata`). For staking with CLI keys, install: `@meshsdk/core`, `@emurgo/cardano-serialization-lib-nodejs`, and (if using hex pool ID) `bech32`.282- **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 generic `bech32` library 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 the `pool1...` ID shown there. The script can accept hex and attempt conversion, but the canonical source is the explorer’s bech32.283- **Pool ID format:** `deserializePoolId()` expects bech32 (`pool1...`). Pass `POOL_ID` as bech32 when possible; hex (56 chars) is supported and converted via the `bech32` package, but using the bech32 ID from Cardanoscan is more reliable.284- MeshJS staking reference: <https://meshjs.dev/apis/txbuilder/staking#stake-address-not-registered-error>285286### Summary287288| Step | Action | Script / API |289| ---- | ----------------------------- | ------------------------------------------------------- |290| 1 | Generate wallet (no mnemonic) | `generate-key-based-wallet.js` |291| 2 | Fund base address | User sends ADA; verify with `fetchAddressUTxOs` |292| 3 | Register + delegate | `agent-wallet.js` MODE=stake, REGISTER_STAKE=1, POOL_ID |293294## Response checklist (agent wallet setup)295296- Network and Koios base URL297- Wallet address used for funding298- Koios query used (endpoint + payload)299- Transaction intent (send or stake), tx hash, and confirmation method300301## Notes302303- Koios provides OpenAPI docs at each network base URL; use them to confirm endpoints and payloads.304- KoiosProvider expects a `network` string and optional `apiKey`; it can submit transactions.305- MeshTxBuilder staking flows are documented in MeshJS staking transactions.306307## Scripts308309- `scripts/agent-wallet.js` — end-to-end template (wallet init, send ADA, stake, confirm). **Staking with CLI keys:** uses CSL `FixedTransaction` to 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 via `bech32`, but manual hex→bech32 conversion can be wrong — prefer the explorer’s `pool1...` ID. Deps: `@meshsdk/core`, `@emurgo/cardano-serialization-lib-nodejs`; for hex `POOL_ID`, also `bech32`.310- `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).311312### Generate new wallet (key-based, stakable)313314```bash315# Optional: NETWORK=mainnet (default) | preprod | preview; KOIOS_API_KEY=...; WALLET_DIR=./my-wallet (writes addresses.json only)316node scripts/generate-key-based-wallet.js317```318319Outputs: 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`.320321### Script usage examples322323```bash324# Status (read-only)325KOIOS_NETWORK=api MODE=status ADDRESS_ONLY=addr1... \\326 node scripts/agent-wallet.js327328# Send ADA (CLI keys)329KOIOS_NETWORK=api MODE=send PAYMENT_SKEY_CBOR_HEX=<...> \\330 RECIPIENT_ADDR=addr1... SEND_LOVELACE=1000000 \\331 node scripts/agent-wallet.js332333# Register + delegate (prefer POOL_ID as pool1... from Cardanoscan)334KOIOS_NETWORK=api MODE=stake PAYMENT_SKEY_CBOR_HEX=<...> \\335 STAKE_SKEY_CBOR_HEX=<...> POOL_ID=pool1... REGISTER_STAKE=1 \\336 node scripts/agent-wallet.js337```338339## References340341- `shared/PRINCIPLES.md`342- Koios API base: `https://api.koios.rest/`343- Koios API guide: `https://koios.rest/guide/`344- MeshJS Koios provider: `https://meshjs.dev/providers/koios`345- MeshJS MeshWallet: `https://meshjs.dev/apis/wallets/meshwallet`346- MeshJS MeshTxBuilder basics: `https://meshjs.dev/apis/txbuilder/basics`347- MeshJS staking transactions: `https://meshjs.dev/apis/txbuilder/staking`