multichain-protocol
通过 ICP 上的 MeneseSDK 将任何 AI 代理变成 19 链加密钱包。发送代币、在 DEX 上交换(Raydium、Uniswap、ICPSwap、KongSwap、Cetus、Minswap)、桥接跨链、管理 DeFi 头寸(Aave、Lido、LP)、自动交易(DCA、止损、再平衡)以及处理支付 — 所有这些都来自单个 ICP 容器。
安装 / 下载方式
TotalClaw CLI推荐
totalclaw install totalclaw:totalclaw~kyounesmercatura-multichain-protocolcURL直接下载,无需登录
curl -fsSL https://skills.taituai.com/api/skills/totalclaw%3Atotalclaw~kyounesmercatura-multichain-protocol/file -o kyounesmercatura-multichain-protocol.md## 概述(中文)
通过 ICP 上的 MeneseSDK 将任何 AI 代理变成 19 链加密钱包。发送代币、在 DEX 上交换(Raydium、Uniswap、ICPSwap、KongSwap、Cetus、Minswap)、桥接跨链、管理 DeFi 头寸(Aave、Lido、LP)、自动交易(DCA、止损、再平衡)以及处理支付 — 所有这些都来自单个 ICP 容器。
## 原文
# Multichain Protocol — MeneseSDK Wallet Skill
Operate across **19 blockchains** from a single ICP canister or CLI: Solana, Ethereum, Bitcoin, Arbitrum, Base, Polygon, BSC, Optimism, ICP, XRP, SUI, TON, Cardano, Aptos, NEAR, Tron, Litecoin, CloakCoin, THORChain.
**Powered by Menese Protocol** | **Canister ID (mainnet):** `urs2a-ziaaa-aaaad-aembq-cai`
---
## Pricing
**First 5 transactions are FREE** — no signup, no credit card, just install and go.
After the free tier, transaction signing is charged per action via your DeveloperKey (`msk_*`). Read-only operations (balances, addresses, pool queries) are always free.
---
## Quickstart (2 minutes)
### Step 1: Install dfx (ICP SDK)
If you don't have `dfx` installed, run this single command:
```bash
sh -ci "$(curl -fsSL https://internetcomputer.org/install.sh)"
```
Verify it works:
```bash
dfx --version
```
That's it. No accounts needed, no wallets to set up — dfx handles everything.
### Step 2: Install the skill
```bash
clawhub install multichain-protocol
```
Or manually: copy `SKILL.md` + `wallet_commands.py` to your workspace.
### Step 3: Create an ICP identity (if you don't have one)
```bash
dfx identity new my-wallet
dfx identity use my-wallet
```
### Step 4: Try it — your first 5 sends are free
Ask your bot:
```
"show my wallet addresses"
"what's my SOL balance?"
"send 0.1 ETH to 0xABC..."
"swap 100 USDC to SOL on Raydium"
"set up a DCA: buy $50 of BTC every day"
```
### Step 5 (optional): Deploy your own canister for production
For multi-user, automation, and timers — deploy `WalletBot.mo` as your own ICP canister.
---
## Two Integration Approaches
| | Canister (Recommended) | CLI (Quick) |
|---|---|---|
| **Flow** | User → ClawdBot → Your Canister → MeneseSDK | User → ClawdBot → `dfx canister call` → MeneseSDK |
| **Setup** | Deploy `WalletBot.mo`, register with SDK | Copy `scripts/wallet_commands.py`, done |
| **Best for** | Multi-user, automation, timers, production | Single-user, prototyping, testing |
| **Automation** | ICP timers for DCA/rebalance/bots | None (manual only) |
---
## Best Practice: Cache Addresses
Addresses are **deterministic** — the same principal always gets the same addresses on every chain. Fetch once, cache forever.
```motoko
// Canister pattern — cache in stable var
stable var cachedAddresses : ?AddressBook = null;
public shared func getAddresses() : async AddressBook {
switch (cachedAddresses) {
case (?addrs) { addrs }; // Return cached — no inter-canister call
case null {
let sol = await menese.getMySolanaAddress();
let evm = await menese.getMyEvmAddress();
// ... fetch all chains once ...
let addrs = { solana = sol.address; evm = evm.evmAddress; /* ... */ };
cachedAddresses := ?addrs;
addrs;
};
};
};
```
```python
# CLI pattern — fetch once, store in file
import json, os
CACHE_FILE = "addresses_cache.json"
def get_addresses():
if os.path.exists(CACHE_FILE):
return json.load(open(CACHE_FILE))
addrs = fetch_all_addresses() # dfx calls
json.dump(addrs, open(CACHE_FILE, "w"))
return addrs
```
**Why**: Saves inter-canister call latency + cycles. Addresses never change for a given principal.
---
## EVM Chains — Bring Your Own RPC
All EVM operations (ETH, Arbitrum, Base, Polygon, BSC, Optimism) require **your own RPC endpoint**. MeneseSDK does not manage EVM RPCs.
| Chain | Chain ID | Free Public RPC |
|-------|----------|----------------|
| Ethereum | 1 | `https://eth.llamarpc.com` |
| Arbitrum | 42161 | `https://arb1.arbitrum.io/rpc` |
| Base | 8453 | `https://mainnet.base.org` |
| Polygon | 137 | `https://polygon-rpc.com` |
| BSC | 56 | `https://bsc-dataseed1.binance.org` |
| Optimism | 10 | `https://mainnet.optimism.io` |
Use Alchemy/Infura for production reliability.
---
## Complete Tool Reference
Every operation available, organized by category. Each tool shows the function, parameters, return type, cost, and a usage example.
### Tool 1: Get Addresses (FREE)
Deterministic per-principal. **Cache after first call.**
| Chain | Function | Field to Extract |
|-------|----------|-----------------|
| Solana | `getMySolanaAddress` | `.address` |
| EVM (all 6) | `getMyEvmAddress` | `.evmAddress` (NOT `.address`) |
| Bitcoin | `getMyBitcoinAddress` | `.bech32Address` |
| Litecoin | `getMyLitecoinAddress` | `.bech32Address` |
| SUI | `getMySuiAddress` | `.suiAddress` (NOT `.address`) |
| XRP | `getMyXrpAddress` | `.classicAddress` |
| TON | `getMyTonAddress` | `.nonBounceable` (NOT `.address`) |
| Cardano | `getMyCardanoAddress` | `.bech32Address` |
| Aptos | `getMyAptosAddress` | `.address` |
| NEAR | `getMyNearAddress` | `.implicitAccountId` (NOT `.accountId`) |
| Tron | `getTronAddress` | `.base58Address` (NOT `.base58`) |
| CloakCoin | `getMyCloakAddress` | `.base58Address` |
| THORChain | `getMyThorAddress` | `.bech32Address` |
**Batch**: `getAllAddresses()` — all chains in one call.
**Solana ATA**: `getMySolanaAta(mintBase58)` — get associated token account for an SPL token.
```motoko
// Example: get SOL address
let info = await menese.getMySolanaAddress();
let myAddress = info.address; // "5xK2abc..."
```
```bash
# CLI
dfx canister call urs2a-ziaaa-aaaad-aembq-cai getMySolanaAddress --network ic --query
```
### Tool 2: Check Balances (FREE)
| Chain | Function | Returns | Unit |
|-------|----------|---------|------|
| Solana | `getMySolanaBalance` | `Result<Nat64, Text>` | lamports (÷10^9) |
| ICP | `getICPBalance` | `Result<Nat64, Text>` | e8s (÷10^8) |
| ICP (for addr) | `getICPBalanceFor(principal)` | `Result<Nat64, Text>` | e8s (÷10^8) |
| Bitcoin | `getBitcoinBalance` | `Nat64` | satoshis (÷10^8) |
| Litecoin | `getLitecoinBalance` | `Nat64` | litoshis (÷10^8) |
| EVM | `getMyEvmBalance(rpcUrl)` | `Result<Nat, Text>` | wei (÷10^18) |
| XRP | `getMyXrpBalance` | `Result<Text, Text>` | drops as text |
| SUI | `getMySuiBalance` | `Nat64` | mist (÷10^9) |
| TON | `getMyTonBalance` | `Result<Nat64, Text>` | nanotons (÷10^9) |
| Cardano | `getCardanoBalance` | `Result<Nat64, Text>` | lovelace (÷10^6) |
| Aptos | `getAptosBalance` | `Result<Nat64, Text>` | octas (÷10^8) |
| NEAR | `getMyNearBalance` | `Nat` | yoctoNEAR (÷10^24) |
| THORChain | `getThorBalance` | `[{amount, denom}]` | units (÷10^8) |
| CloakCoin | `getCloakBalance` | `Result<{address, balance, utxoCount}, Text>` | units (÷10^6) |
| Tron | `getTrxBalance(address)` | `Result<Nat64, Text>` | sun (÷10^6) |
| ICRC-1 tokens | `getICRC1Balance(ledgerId)` | `Result<Nat, Text>` | smallest unit |
| ICRC-1 (for addr) | `getICRC1BalanceFor(principal, ledgerId)` | `Result<Nat, Text>` | smallest unit |
| ICRC-1 info | `getICRC1TokenInfo(ledgerId)` | `Result<TokenInfo, Text>` | name, symbol, decimals |
| ICP tokens list | `getSupportedICPTokens()` | `[{name,symbol,canisterId,type_,category}]` | query |
| TRC-20 tokens | `getMyTrc20Balance(contract)` | `Result<Nat, Text>` | smallest unit |
**Batch**: `getAllBalances()` — parallel fetch across all chains.
**Performance tip**: For high-frequency reads, query chain RPCs directly using cached addresses. MeneseSDK is best for signing; your own RPC is faster for reads.
```motoko
// Example: check SOL balance, convert to human-readable
switch (await menese.getMySolanaBalance()) {
case (#ok(lamports)) { /* lamports / 1_000_000_000 = SOL */ };
case (#err(e)) { /* handle error */ };
};
```
### Tool 3: Send Tokens ($0.05 client / $0.10 agent)
**Return types differ by chain** — getting this wrong causes runtime errors.
| Chain | Function | Params | Return |
|-------|----------|--------|--------|
| Solana | `sendSolTransaction` | `(to, lamports:Nat64)` | `Result<Text, Text>` |
| ICP | `sendICP` | `(to:Principal, e8s:Nat64)` | `Result<SendICPResult, Text>` |
|