# IC Phantom — Agent Guide

Instructions for AI agents (including MCP clients such as [Internet Identity MCP](https://mcp.beta.id.ai/)) that act on behalf of a user with **Internet Identity**.

Human UI: https://hbxmr-wyaaa-aaaap-an3ia-cai.icp.net/  
Backend: `f4kcz-fqaaa-aaaap-an3hq-cai` (mainnet)

---

## 1. Security rules (mandatory)

1. Authenticate only with the user's consent via Internet Identity.
2. **Ask the user before every state-changing call** (any `transfer_*`, `withdraw_*`, `mint_*`, or fee-bearing operation).
3. Prefer **read-only** calls first (`whoami`, `get_*_ii`, balances).
4. Never log, export, or print private keys or PEM material.
5. Do not use Phantom methods (`transfer`, `transfer_sol`, … with signatures) unless the user is in a browser with Phantom — agents should use `*_ii` methods.
6. Pass **explicit Candid arguments**, including `'()'` for zero-arg methods (non-interactive shells cancel interactive prompts).
7. Always pass `--identity <NAME>` (or the MCP session equivalent). Do not rely on a shared default identity.

---

## 2. Authenticate with Internet Identity

### Goal

Obtain a time-limited **delegation** so canister calls use the same **app principal** the user has in the IC Phantom web UI.

### App domain for derivation

Use the bare frontend domain (no `https://`, no path):

```text
hbxmr-wyaaa-aaaap-an3ia-cai.icp0.io
```

If principal mismatch occurs, try `hbxmr-wyaaa-aaaap-an3ia-cai.icp.net` and confirm with the user against the principal shown in the UI after login.

### CLI pattern (`icp identity link web`)

Requires: local browser on the **same machine**, CLI access enabled in II settings (first run).

```bash
icp identity list
NAME="agent-icphantom-$(date +%Y%m%d-%H%M)"

# Background + newline for the "Press Enter to log in" prompt (icp 0.3.x)
printf '\n' | icp identity link web "$NAME" \
  --app hbxmr-wyaaa-aaaap-an3ia-cai.icp0.io \
  > "/tmp/icp-link-$NAME.log" 2>&1 &

# Relay any printed sign-in URL to the user; wait for them to finish II login
# Then verify:
icp identity list
icp canister call --identity "$NAME" -n ic \
  f4kcz-fqaaa-aaaap-an3hq-cai whoami '()'
```

The returned principal must match the Internet Identity principal shown in the IC Phantom UI for that user.

### MCP connector

If using https://mcp.beta.id.ai/ (or a compatible MCP host):

1. Connect the MCP server per its UI instructions.
2. Complete Internet Identity sign-in in the browser when prompted.
3. Scope calls to backend canister `f4kcz-fqaaa-aaaap-an3hq-cai` on mainnet.
4. Prefer the method map in **agent.json** and this guide.

---

## 3. Canister overview

| Role | Canister ID |
|------|-------------|
| Backend wallet | `f4kcz-fqaaa-aaaap-an3hq-cai` |
| Frontend assets | `hbxmr-wyaaa-aaaap-an3ia-cai` |
| ckBTC ledger | `mxzaz-hqaaa-aaaar-qaada-cai` |
| ckBTC minter | `mqygn-kiaaa-aaaar-qaadq-cai` |
| ICP ledger | `ryjl3-tyaaa-aaaaa-aaaba-cai` |

Candid file (static copy): `/backend.did` on the frontend host.

### Units

| Asset | API unit | Decimals | Human 1.0 |
|-------|----------|----------|-----------|
| ICP | e8s (`nat64`) | 8 | 100_000_000 e8s |
| ckBTC / BTC amounts on API | satoshis (`nat64`) | 8 | 100_000_000 sats |
| SOL | lamports (`nat64`) | 9 | 1_000_000_000 lamports |
| DOGE | satoshis (`nat64`) | 8 | 100_000_000 |

### Fees / limits (mainnet conventions)

| Operation | Note |
|-----------|------|
| ICP transfer | Ledger fee 10_000 e8s; app may also charge a small service fee on some paths |
| ckBTC ICRC transfer | **10 sats** fee |
| ckBTC → BTC withdraw | Minimum **50_000 sats** (0.0005 BTC); approve fee 10 sats |
| SOL / DOGE | Network/provider fees vary |

---

## 4. Method map for agents (Internet Identity)

All methods below use **caller = authenticated II principal**. Call with empty args as `'()'` when listed with no parameters.

### Identity

| Method | Type | Args | Returns | Notes |
|--------|------|------|---------|-------|
| `whoami` | query | `()` | `text` | Caller's principal text |

### ICP

| Method | Type | Args | Returns |
|--------|------|------|---------|
| `get_deposit_address_ii` | update | `()` | `text` account identifier hex |
| `get_balance_ii` | update | `()` | `nat64` e8s |
| `transfer_ii` | update | `(to: text, amount: nat64)` | `text` result |

`to` is an **ICP account identifier** (hex), not a principal.

### SOL

| Method | Type | Args | Returns |
|--------|------|------|---------|
| `get_sol_deposit_address_ii` | update | `()` | `text` base58 |
| `get_sol_balance_ii` | update | `()` | `nat64` lamports |
| `transfer_sol_ii` | update | `(to: text, amount: nat64)` | `text` |

### DOGE

| Method | Type | Args | Returns |
|--------|------|------|---------|
| `get_doge_deposit_address_ii` | update | `()` | `text` |
| `get_doge_balance_ii` | update | `()` | `nat64` |
| `get_doge_balance_details_ii` | update | `()` | `doge_balance_details` |
| `quote_doge_transfer_ii` | update | `(to: text, amount: nat64)` | `variant { Ok; Err }` |
| `transfer_doge_ii` | update | `(to: text, amount: nat64)` | `text` |

### BTC / ckBTC (II)

| Method | Type | Args | Returns | Notes |
|--------|------|------|---------|-------|
| `get_btc_deposit_address_ii` | update | `()` | `text` | Bitcoin address for native BTC deposits |
| `get_ckbtc_account_ii` | update | `()` | `CkBtcAccountInfo` | `account_text` / `owner` = II principal for principal-only deposits |
| `get_ckbtc_balance_ii` | update | `()` | `nat64` sats | Includes legacy canister-subaccount balance if any |
| `mint_ckbtc_from_btc_ii` | update | `()` | `text` | Call after BTC confirmations |
| `transfer_ckbtc_ii` | update | `(to: text, amount: nat64)` | `text` | Prefer browser path for principal-owned funds; may only move legacy canister-held balance |
| `withdraw_ckbtc_to_btc_ii` | update | `(btc_address: text, amount: nat64)` | `text` | Min 50_000 sats; principal-owned path may require direct ledger/minter calls as the user |

**Important BTC UX:** There is **no native BTC balance** API. After sending BTC to `get_btc_deposit_address_ii`, wait for confirmations, then `mint_ckbtc_from_btc_ii`, then `get_ckbtc_balance_ii`.

**ckBTC deposit for principal-only wallets:** use the II principal from `whoami` / `get_ckbtc_account_ii.owner`.  
**Do not** send ckBTC to backend canister `f4kcz-fqaaa-aaaap-an3hq-cai` alone (shared default account).

### Example calls

```bash
ID=f4kcz-fqaaa-aaaap-an3hq-cai
IDENT=agent-icphantom-YYYYMMDD-HHMM   # your linked identity

# Who am I?
icp canister call --identity "$IDENT" -n ic $ID whoami '()'

# ICP balance
icp canister call --identity "$IDENT" -n ic $ID get_balance_ii '()'

# ckBTC account + balance
icp canister call --identity "$IDENT" -n ic $ID get_ckbtc_account_ii '()'
icp canister call --identity "$IDENT" -n ic $ID get_ckbtc_balance_ii '()'

# Mint after BTC deposit
icp canister call --identity "$IDENT" -n ic $ID mint_ckbtc_from_btc_ii '()'

# Transfer ICP (example: 0.01 ICP = 1_000_000 e8s) — CONFIRM WITH USER FIRST
# icp canister call --identity "$IDENT" -n ic $ID transfer_ii '("ACCOUNT_ID_HEX", 1_000_000:nat64)'
```

---

## 5. Phantom methods (not for typical agents)

Methods that take `(sol_pubkey, signature, nonce)` require a Phantom wallet signature in a browser. Agents using only II should **ignore** these:

`get_deposit_address`, `get_balance`, `transfer`, `get_sol_*`, `transfer_sol`, `get_doge_*`, `transfer_doge`, `get_btc_deposit_address`, `get_ckbtc_*` (non-`_ii`), `transfer_ckbtc`, `withdraw_ckbtc_to_btc`, etc.

---

## 6. Recommended agent workflow

1. Read `/llms.txt` and this file (and optionally `/agent.json`).
2. Authenticate the user for app domain `hbxmr-wyaaa-aaaap-an3ia-cai.icp0.io`.
3. Call `whoami` and show principal to the user for confirmation.
4. For each asset the user cares about: fetch deposit address + balance (read path).
5. For deposits: give the correct address type (ICP account id / SOL base58 / DOGE / BTC address / II principal for ckBTC).
6. For spends: quote fees, show human amounts, **get explicit approval**, then call once.
7. After BTC chain deposits: remind user to wait for confirmations, then mint, then re-check ckBTC balance.

---

## 7. Cycle / cost awareness

- Prefer **query** methods when available (`whoami`).
- Do not poll balances in a tight loop; human UI uses ~10s client cooldown.
- Mint / DOGE / SOL balance updates use HTTPS outcalls or inter-canister calls — avoid spam.
- Deploy/storage: agent docs are static assets (cheap); no extra canisters.

---

## 8. Support links

| Resource | URL |
|----------|-----|
| Human UI | https://hbxmr-wyaaa-aaaap-an3ia-cai.icp.net/ |
| Agent index | https://hbxmr-wyaaa-aaaap-an3ia-cai.icp.net/llms.txt |
| Agent guide | https://hbxmr-wyaaa-aaaap-an3ia-cai.icp.net/agents.md |
| Agent JSON | https://hbxmr-wyaaa-aaaap-an3ia-cai.icp.net/agent.json |
| Candid | https://hbxmr-wyaaa-aaaap-an3ia-cai.icp.net/backend.did |
| II MCP (beta) | https://mcp.beta.id.ai/ |
| Source | https://github.com/dickhery/IC-SOL-Wallet |
