| name | ledger-claw-plugin |
| description | Sign EVM transactions and connect Ledger hardware wallets via Telegram Mini App. Use when: (1) a payment or on-chain transaction needs to be executed, (2) you need the user's wallet address, (3) the user asks to sign something with their Ledger. Requires the Telegram channel to be configured. |
| metadata | {"openclaw":{"emoji":"🔐","requires":{"config":["channels.telegram"]}}} |
Ledger Claw
Sign EVM transactions with a Ledger hardware wallet via a Telegram Mini App.
Wallets (optional)
Saved wallets are optional — they let you check balances and suggest addresses, but they are never required to sign a transaction. At sign time, the user picks whichever wallet they want in Ledger Live.
- To save a wallet: Call
ledger_connect → once the address comes back, offer to save it with ledger_claw_config({ updates: { addWallet: { label: "Main", address: "0x..." } } }).
- To check balances: Use saved wallet addresses with
ledger_claw_rpc (action: "balance" or action: "token_balance").
- Multiple wallets: The user can connect and save as many wallets as they want (e.g. "Main", "Trading").
- To remove a wallet:
ledger_claw_config({ updates: { removeWallet: "Main" } }).
Sending a transaction
When the user asks to send funds (e.g. "send 10 USDC to Jean"):
- Resolve the recipient:
- If the user gave a name instead of an address, call
ledger_claw_contacts({ action: "resolve", name: "Jean" }).
- If a contact is found → use that address.
- If not found → ask the user for the address. After a successful transaction, offer to save it as a contact.
- Clarify missing details — if not specified by the user, ask for:
- Chain: which chain to use (arbitrum, ethereum, optimism, polygon, base).
- Currency: ETH, POL, USDC, or USDT. Note: Polygon uses POL as native token, not ETH.
- If the user specifies a USD amount (e.g. "send $30 in ETH"): call
get_token_price({ symbol: "ETH" }) to get the current price, then divide the USD amount by the price to get the token amount.
- Convert the amount: call
token_to_smallest_unit with the amount (and decimals: 6 for USDC/USDT).
- Check that the chain is enabled in config (
chains object).
- If the user has saved wallets, check the balance with
ledger_claw_rpc (action: "balance" for native tokens, action: "token_balance" for ERC-20) — if insufficient, warn the user. If no wallets are saved, skip the balance check.
- Call
ledger_sign with the transaction details.
- A button appears in Telegram. The user taps it, connects their Ledger, and signs.
- The tx hash comes back as a message in the chat (or an error if the user rejected/failed).
- Verify the transaction with
ledger_claw_rpc (action: "tx") and confirm status to the user.
- If the recipient was a new address, offer to save it:
ledger_claw_contacts({ action: "add", name: "Jean", address: "0x..." }).
Tools
ledger_claw_config
Read or update the extension config. Call without params to read, pass updates to change.
{ "updates": { "requireSigningAbove": "1.00", "chains": { "polygon": false } } }
Settings:
requireSigningAbove: ETH threshold for requiring Ledger signing (default "0.00" = always)
wallets: Array of saved wallets [{ label, address }] — optional, for balance checks
chains: Object mapping chain names to enabled/disabled (all enabled by default)
To add/update a wallet:
{ "updates": { "addWallet": { "label": "Main", "address": "0x..." } } }
To remove a wallet:
{ "updates": { "removeWallet": "Main" } }
ledger_claw_contacts
Manage saved contacts for quick transfers.
{ "action": "resolve", "name": "Jean" }
{ "action": "add", "name": "Jean", "address": "0xaB90D6..." }
{ "action": "list" }
{ "action": "remove", "name": "Jean" }
resolve: Look up a contact by name. Returns the address if found, or indicates no match.
add: Save a new contact (name + 0x address).
list: Show all saved contacts.
remove: Delete a contact by name.
ledger_sign
Send a transaction for signing.
{
"chatId": "123456789",
"to": "0xaB90D6666eeb450562B29DD2B10fD3d50d1CCEE8",
"value": "0x38D7EA4C68000",
"chain": "arbitrum"
}
chatId: Telegram chat ID (from conversation context)
to: Recipient address (0x-prefixed, 40 hex chars)
value: Amount in smallest unit as hex — use token_to_smallest_unit to convert
data: Optional calldata hex. Omit for simple transfers
chain: arbitrum, ethereum, optimism, polygon, or base
token: Optional token symbol (usdc or usdt). Omit for native transfers (ETH on most chains, POL on Polygon).
get_token_price
Get the current USD price of a token. Use when the user specifies amounts in USD.
{ "symbol": "ETH" }
symbol: Token symbol — ETH, POL, USDC, or USDT.
- Returns the current price (e.g.
ETH = $2192.06).
Workflow for USD amounts (e.g. "send $30 in ETH"):
get_token_price({ symbol: "ETH" }) → $2192.06
- Calculate:
30 / 2192.06 = 0.01368
token_to_smallest_unit({ amount: "0.01368" }) → hex
ledger_sign({ ... value: hex })
token_to_smallest_unit
Convert a human-readable amount to hex. Always use this instead of hardcoding.
{ "amount": "0.001" }
{ "amount": "100", "decimals": 6 }
amount: Human-readable amount (e.g. "0.001", "100")
decimals: Token decimals. ETH/POL = 18 (default), USDC/USDT = 6.
ledger_connect
Ask the user to connect their Ledger to get their wallet address. Not required before signing — use this when the user wants to save a wallet for balance checks.
{ "chatId": "123456789", "chain": "arbitrum" }
Once the address comes back, offer to save it with ledger_claw_config (addWallet).
ledger_claw_rpc
Query chain data. Use to check balance before signing or verify a tx after.
{ "action": "balance", "chain": "arbitrum", "address": "0x..." }
{ "action": "token_balance", "chain": "arbitrum", "address": "0x...", "token": "usdc" }
{ "action": "tx", "chain": "arbitrum", "txHash": "0x..." }
action: "balance" (native token: ETH or POL), "token_balance" (USDC/USDT), or "tx" (transaction receipt)
chain: Chain to query
address: Wallet address (for balance/token_balance)
token: Token symbol (for token_balance): usdc or usdt
txHash: Transaction hash (for tx receipt)
Important
- Handle RPC rate limits — if an RPC call fails with a rate-limit error (429 or similar), wait a few seconds before retrying.
- Resolve contacts first — always try to resolve a name before asking for an address.
- Ask for chain and currency if the user didn't specify them. Don't assume.
- Check config first before every transaction to know the threshold, enabled chains, and saved wallets.
- Saved wallets are optional — never block a transaction because no wallet is saved. The user chooses which wallet to sign with in Ledger Live.
- Never auto-sign without explicit user intent. Always confirm transaction details before calling
ledger_sign.
- The result is asynchronous — after calling the tool, wait for the user's message with the tx hash or address.
- If the amount is below
requireSigningAbove, tell the user the amount is under their configured threshold and ask if they still want to sign with Ledger.
- Always convert amounts with
token_to_smallest_unit before calling ledger_sign.
- After a successful transfer to a new address, offer to save the contact.