Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "chain-pilot"
version = "1.1.0"
version = "1.2.0-rc.2"
description = "A CLI tool for on-chain DeFi operations on EVM-compatible networks"
homepage = "https://github.com/DODOEX/ChainPilot"
documentation = "https://github.com/DODOEX/ChainPilot#readme"
Expand Down
36 changes: 36 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,42 @@ chainpilot swap execute --quote-id <QUOTE_ID> --private-key 0x... --skip-estimat
| `--gas-buffer-pct` | Add N% buffer on top of `eth_estimateGas` result (e.g. `20` = +20%) |
| `--skip-estimate` | Skip `eth_estimateGas` and use the quote's gas estimate directly |

**Prepare an unsigned transaction for an external signer:**
```bash
# Swap execution payload from a saved quote
chainpilot --json swap prepare execute --quote-id <QUOTE_ID> --wallet 0xYourAddress

# ERC-20 approval payload
chainpilot --json swap prepare approve --quote-id <QUOTE_ID> --wallet 0xYourAddress
chainpilot --json swap prepare approve \
--token USDC \
--spender 0xSpenderAddr \
--amount 100 \
--wallet 0xYourAddress

# ERC-20 revoke payload
chainpilot --json swap prepare revoke \
--token 0xTokenAddr \
--spender 0xSpenderAddr \
--wallet 0xYourAddress
```

`swap prepare` does not sign or broadcast. In JSON mode it returns a stable
unsigned transaction payload with `source`, `operation`, `chain_id`, `caip2`,
`from`, `transaction { to, value, data, chain_id }`, and risk metadata. This is
intended for external signing systems such as Privy; user confirmation,
authorization checks, signing, and broadcasting must happen outside ChainPilot.
Use `swap simulate` to inspect route execution, gas, and warnings before this
step; use `swap prepare` only when an external signer needs the exact unsigned
transaction object.

`swap prepare approve --quote-id` only applies when the quote spends an ERC-20
input token. Native input tokens such as ETH, MATIC, BNB, or the chain native
asset do not require ERC-20 approval and are rejected. For explicit approvals,
`--token` accepts either a token address or a resolvable symbol from the
tokenlist/cache/custom token store; use the token address when the symbol is
ambiguous or unavailable.

**Check transaction status:**
```bash
chainpilot swap status --tx-hash 0x...
Expand Down
67 changes: 67 additions & 0 deletions src/cli/swap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ pub enum SwapAction {
Quote(QuoteArgs),
/// Simulate a swap from a saved quote
Simulate(SimulateArgs),
/// Prepare an unsigned transaction payload for an external signer
Prepare(PrepareCmd),
/// Execute a swap (requires wallet)
Execute(ExecuteArgs),
/// Check swap transaction status
Expand Down Expand Up @@ -55,6 +57,71 @@ pub struct SimulateArgs {
pub wallet: Option<String>,
}

#[derive(Args)]
pub struct PrepareCmd {
#[command(subcommand)]
pub action: PrepareAction,
}

#[derive(Subcommand)]
pub enum PrepareAction {
/// Prepare a swap execution transaction from a saved quote
Execute(PrepareExecuteArgs),
/// Prepare an ERC-20 approval transaction
Approve(PrepareApproveArgs),
/// Prepare an ERC-20 revoke transaction
Revoke(PrepareRevokeArgs),
}

#[derive(Args)]
pub struct PrepareExecuteArgs {
/// Quote ID returned by `chainpilot swap quote`
#[arg(long)]
pub quote_id: String,

/// Wallet address that will sign and send the transaction via an external signer
#[arg(long, env = "WALLET_ADDRESS")]
pub wallet: Option<String>,
}

#[derive(Args)]
pub struct PrepareApproveArgs {
/// Quote ID to derive token and spender from (uses from-token and DODOApprove spender)
#[arg(long)]
pub quote_id: Option<String>,

/// Token symbol or address to approve (overrides quote's from-token)
#[arg(long)]
pub token: Option<String>,

/// Spender contract address (overrides quote's spender)
#[arg(long)]
pub spender: Option<String>,

/// Amount to approve in human-readable units (omit for unlimited / U256::MAX)
#[arg(long)]
pub amount: Option<String>,

/// Wallet address that will sign and send the transaction via an external signer
#[arg(long, env = "WALLET_ADDRESS")]
pub wallet: Option<String>,
}

#[derive(Args)]
pub struct PrepareRevokeArgs {
/// Token contract address
#[arg(long)]
pub token: String,

/// Spender contract address
#[arg(long)]
pub spender: String,

/// Wallet address that will sign and send the transaction via an external signer
#[arg(long, env = "WALLET_ADDRESS")]
pub wallet: Option<String>,
}

#[derive(Args)]
pub struct ExecuteArgs {
/// Quote ID returned by `chainpilot swap quote`
Expand Down
Loading
Loading