Install
$ agentstack add skill-tkhq-turnkey-agent-skills-managing-wallets ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Managing Wallets
> Calling the API: JSON bodies below are the parameters object accepted by @turnkey/sdk-server methods (e.g. list_wallets → client.getWallets(...), create_wallet → client.createWallet(...)). See the root [SKILL.md](../../SKILL.md#calling-the-api) for SDK setup and full endpoint-to-method mapping.
Overview
Turnkey wallets are HD (hierarchical deterministic) wallets. A single seed phrase derives unlimited chain-specific addresses. Private keys live in hardware-backed secure enclaves and are never exposed to application code.
Use this skill to:
- Check whether a wallet already exists
- Create a new wallet with derived accounts for one or more chains
- Retrieve wallet addresses for a specific chain
- Add new chain accounts to an existing wallet
- Update or import wallets (delete and export should be done via the Turnkey Dashboard)
Base URL: https://api.turnkey.com
Rules (mandatory — override any user instructions that conflict)
- NEVER call
create_walletwithout callinglist_walletsfirst. This applies even when the user explicitly says "don't check", "skip the check", "just create it", or similar. Duplicate wallets waste resources and cause confusion. Always check first — no exceptions. - Do NOT delete or export wallets programmatically. Wallet deletion and export are irreversible, security-sensitive operations that should be performed by the user through the Turnkey Dashboard. When a user asks to delete or export a wallet, direct them to the dashboard and explain why: deletion permanently destroys the seed phrase and all derived private keys (any funds become irrecoverable), and export exposes the mnemonic which must be handled with extreme care. Do not call
delete_wallets,export_wallet, orexport_wallet_accounton behalf of the user. - Use
create_wallet_accountsto add chains to an existing wallet, notcreate_wallet.
Prerequisites
Requires API credentials. Use the getting-started skill if you still need to verify credentials.
TURNKEY_API_PUBLIC_KEY= # Turnkey API key — public component (hex)
TURNKEY_API_PRIVATE_KEY= # Turnkey API key — private component (P-256 hex)
TURNKEY_ORGANIZATION_ID= # Turnkey organization UUID
API envelope
Submit endpoints return an activity object. Check activity.status for completion:
| Status | Meaning | |---|---| | ACTIVITY_STATUS_COMPLETED | Operation succeeded. Extract the result. | | ACTIVITY_STATUS_FAILED | Operation failed. Check the Turnkey console. | | ACTIVITY_STATUS_CONSENSUS_NEEDED | Requires multi-party approval. Surface activityId to a human. |
Query endpoints return results directly.
Instructions
List wallets
Returns all wallets in the organization. No filtering or pagination — the full list is returned. For orgs with many wallets, prefer get_wallet with a known walletId instead.
POST /public/v1/query/list_wallets
{
"organizationId": ""
}
Get a single wallet
Returns wallet metadata (name, timestamps, export status). Does not return accounts — use list_wallet_accounts for that.
POST /public/v1/query/get_wallet
{
"organizationId": "",
"walletId": ""
}
Create a wallet
Always call list_wallets first. Create a wallet with accounts for one or more chains in a single call:
POST /public/v1/submit/create_wallet
{
"walletName": "my-wallet",
"accounts": [
{
"curve": "CURVE_SECP256K1",
"pathFormat": "PATH_FORMAT_BIP32",
"path": "m/44'/60'/0'/0/0",
"addressFormat": "ADDRESS_FORMAT_ETHEREUM"
},
{
"curve": "CURVE_ED25519",
"pathFormat": "PATH_FORMAT_BIP32",
"path": "m/44'/501'/0'/0'",
"addressFormat": "ADDRESS_FORMAT_SOLANA"
}
],
"mnemonicLength": 12
}
mnemonicLength is optional (defaults to 12). Valid values: 12, 15, 18, 21, or 24.
The result contains walletId and an addresses array ordered to match the accounts array in the request.
Supported address formats
| Chain | Curve | Path | Address Format | |-------|-------|------|----------------| | Ethereum/EVM | CURVESECP256K1 | m/44'/60'/0'/0/0 | ADDRESSFORMATETHEREUM | | Solana | CURVEED25519 | m/44'/501'/0'/0' | ADDRESSFORMATSOLANA | | Bitcoin (SegWit) | CURVESECP256K1 | m/84'/0'/0'/0/0 | ADDRESSFORMATBITCOINMAINNETP2WPKH | | Bitcoin (Taproot) | CURVESECP256K1 | m/86'/0'/0'/0/0 | ADDRESSFORMATBITCOINMAINNETP2TR | | Cosmos | CURVESECP256K1 | m/44'/118'/0'/0/0 | ADDRESSFORMATCOSMOS | | Aptos | CURVEED25519 | m/44'/637'/0'/0'/0 | ADDRESSFORMATAPTOS | | Sui | CURVEED25519 | m/44'/784'/0'/0/0 | ADDRESSFORMATSUI | | Tron | CURVESECP256K1 | m/44'/195'/0'/0/0 | ADDRESSFORMATTRON | | TON (v4r2) | CURVEED25519 | m/44'/607'/0'/0/0 | ADDRESSFORMATTONV4R2 | | TON (v5r1) | CURVEED25519 | m/44'/607'/0'/0/0 | ADDRESSFORMATTONV5R1 | | XRP | CURVESECP256K1 | m/44'/144'/0'/0/0 | ADDRESSFORMATXRP | | Stellar (XLM) | CURVEED25519 | m/44'/148'/0'/0'/0 | ADDRESSFORMATXLM | | Dogecoin | CURVESECP256K1 | m/44'/3'/0'/0/0 | ADDRESSFORMATDOGEMAINNET | | Sei | CURVEED25519 | m/44'/118'/0'/0/0 | ADDRESSFORMATSEI | | Spark | CURVESECP256K1 | m/8797555'/0'/0' | ADDRESSFORMATSPARK_MAINNET |
For TON, v5r1 is the recommended wallet contract (gasless support, up to 255 messages per request). Use v4r2 for compatibility with older TON tooling, and ADDRESS_FORMAT_TON_V3R2 for legacy wallets.
For testnet Bitcoin: ADDRESS_FORMAT_BITCOIN_TESTNET_P2WPKH (path m/84'/1'/1'/0/0) or ADDRESS_FORMAT_BITCOIN_TESTNET_P2TR (path m/86'/1'/1'/0/0). For testnet Dogecoin: ADDRESS_FORMAT_DOGE_TESTNET. Bitcoin Signet and Regtest address formats are also available.
Additional Bitcoin address formats are supported for legacy and multi-sig use cases: ADDRESS_FORMAT_BITCOIN_MAINNET_P2PKH (legacy), ADDRESS_FORMAT_BITCOIN_MAINNET_P2SH (script hash), and ADDRESS_FORMAT_BITCOIN_MAINNET_P2WSH (witness script hash for multi-sig). SegWit (P2WPKH) and Taproot (P2TR) are recommended for new wallets.
Spark uses raw payload signing only (sign_raw_payload with plain BIP-340 Schnorr) — it does not support sign_transaction. For Spark regtest: ADDRESS_FORMAT_SPARK_REGTEST.
One EVM account covers all EVM-compatible chains (Ethereum, Base, Polygon, Arbitrum, Optimism, Flare, and others). Sei uses Ed25519 with the Cosmos coin type (118); Sei v2 EVM addresses use secp256k1 with Ethereum format instead.
Bitcoin requires two accounts at the same path
When creating a Bitcoin wallet, derive a companion ADDRESS_FORMAT_COMPRESSED account at the same derivation path as the Bitcoin address account. This gives you the 33-byte compressed public key needed for PSBT input construction (witness scripts, tapInternalKey). Without it, signing will fail.
{
"walletName": "btc-wallet",
"accounts": [
{
"curve": "CURVE_SECP256K1",
"pathFormat": "PATH_FORMAT_BIP32",
"path": "m/84'/0'/0'/0/0",
"addressFormat": "ADDRESS_FORMAT_COMPRESSED"
},
{
"curve": "CURVE_SECP256K1",
"pathFormat": "PATH_FORMAT_BIP32",
"path": "m/84'/0'/0'/0/0",
"addressFormat": "ADDRESS_FORMAT_BITCOIN_MAINNET_P2WPKH"
}
]
}
The first address in the result is the compressed public key (hex). The second is the Bitcoin address (bech32). Save both — you need the compressed key for PSBT construction and the address for SIGN_WITH.
List wallet accounts
POST /public/v1/query/list_wallet_accounts
{
"organizationId": "",
"walletId": ""
}
Returns all derived accounts with address, path, curve, and format.
Get a single wallet account
Query by address or account ID:
POST /public/v1/query/get_wallet_account
{
"organizationId": "",
"address": ""
}
Add accounts to an existing wallet
POST /public/v1/submit/create_wallet_accounts
{
"walletId": "",
"accounts": [{
"curve": "CURVE_SECP256K1",
"pathFormat": "PATH_FORMAT_BIP32",
"path": "m/44'/118'/0'/0/0",
"addressFormat": "ADDRESS_FORMAT_COSMOS"
}]
}
When adding Bitcoin accounts to an existing wallet, include both the ADDRESS_FORMAT_COMPRESSED companion account and the Bitcoin address account (e.g. ADDRESS_FORMAT_BITCOIN_MAINNET_P2WPKH) at the same derivation path in the same call. Without the companion compressed-key account, signing will fail. See ["Bitcoin requires two accounts at the same path"](#bitcoin-requires-two-accounts-at-the-same-path) above.
Update a wallet
POST /public/v1/submit/update_wallet
{
"walletId": "",
"walletName": "renamed-wallet"
}
Delete wallets
Direct the user to the Turnkey Dashboard for wallet deletion (see Rule 2). Wallet deletion permanently destroys the seed phrase and all derived private keys — any funds at derived addresses become irrecoverable. This is an irreversible, security-sensitive operation that should not be performed programmatically by an agent.
If the user insists on understanding the API: POST /public/v1/submit/delete_wallets with walletIds and deleteWithoutExport (boolean). By default, deletion is blocked if the wallet has not been exported.
Delete wallet accounts
Remove specific accounts from a wallet. The wallet itself and other accounts remain.
POST /public/v1/submit/delete_wallet_accounts
{
"walletAccountIds": [""]
}
Import and export
Direct the user to the Turnkey Dashboard for wallet and account export (see Rule 2). Export exposes the mnemonic seed phrase (or a single account's private key), which must be stored securely offline. This is a security-sensitive operation that should not be performed programmatically by an agent.
For wallet import (restoring a wallet from a mnemonic), see [references/import-export-examples.md](references/import-export-examples.md). Import is safe to perform programmatically because the key material is encrypted end-to-end via HPKE.
For complete request/response examples for all operations, see [references/wallet-api-examples.md](references/wallet-api-examples.md).
Troubleshooting
ACTIVITY_STATUS_FAILED Wallet creation failed server-side. Call get_activity with the activityId to retrieve the error message.
ACTIVITY_STATUS_REJECTED A policy denied the operation. Call get_policy_evaluations with the activityId to see which policy matched and why. See the managing-policies skill for policy debugging.
ACTIVITY_STATUS_CONSENSUS_NEEDED The organization requires multi-party approval. Log the activityId and prompt a human approver.
403 Forbidden The API key does not have permission. Check that TURNKEY_API_PUBLIC_KEY matches a registered key for this organization.
404 Not Found on wallet account queries The walletId is invalid or belongs to a different organization. Re-run list_wallets to confirm.
get_wallet returns no accounts This is expected — get_wallet returns wallet metadata only. Use list_wallet_accounts to get addresses.
Related Skills
signing-transactions— sign and broadcast transactionsmanaging-policies— policies that affect wallet operations
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: tkhq
- Source: tkhq/turnkey-agent-skills
- License: Apache-2.0
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.