Skip to content
Open
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
59 changes: 55 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
11. [Pipe Commands](#11-pipe-commands)
12. [Transaction Simulation](#12-transaction-simulation)
13. [RNS Operations](#13-rns-operations)
14. [Gas Estimator](#14-gas-estimator)
15. [Swap Command](#15-swap-command)
- [Contributing](#contributing)

## Installation
Expand Down Expand Up @@ -1090,8 +1092,7 @@ Output example:
> - Both checksummed and non-checksummed addresses are supported
> - The command will show appropriate error messages if the name or address cannot be resolved

<<<<<<< HEAD
### 12. Gas Estimator
### 14. Gas Estimator

The `gas` command allows you to estimate gas costs for transactions and contract interactions on the Rootstock blockchain. It provides detailed analysis including gas price, estimated gas limits, and optimization tips.

Expand Down Expand Up @@ -1147,8 +1148,58 @@ The command provides:
- Cost in RBTC and Wei
- Recommended gas limits (with buffers)
- Optimization tips (if applicable)
=======
>>>>>>> main

### 15. Swap Command

The `swap` command lets you quickly convert `BTC <-> RBTC` using the Flyover protocol.

The command uses the Flyover SDK to fetch live liquidity providers and quotes. Peg-out executes a Rootstock transaction via your local wallet. Peg-in accepts the quote and prepares the deposit flow through the Flyover protocol.

#### Liquidity Providers (quote only)

```bash
rsk-cli swap --testnet --liquidity
```

#### Peg-in (BTC -> RBTC)

```bash
rsk-cli swap --testnet --pegin --amount 0.1
# Force a specific LP by name or URL
rsk-cli swap --testnet --pegin --amount 0.1 --provider "teks-staging"
# Bypass captcha using a trusted (whitelisted) account (recommended for automation)
rsk-cli swap --testnet --pegin --amount 0.1 --trusted-wallet <trustedWalletName>
```

#### Peg-out (RBTC -> BTC)

```bash
rsk-cli swap --testnet --pegout --amount 0.01 --btc-address <address>
# Force a specific LP by apiBaseUrl
rsk-cli swap --testnet --pegout --amount 0.01 --btc-address <address> --provider "https://staging.lps.tekscapital.com"
# Bypass captcha using a trusted (whitelisted) account (recommended for automation)
rsk-cli swap --testnet --pegout --amount 0.01 --btc-address <address> --trusted-wallet <trustedWalletName>
```

#### Interactive Mode

```bash
rsk-cli swap --interactive
```

#### Available Options

- `--testnet`: Use Rootstock testnet
- `--liquidity`: Show available liquidity providers (quote only, no wallet required)
- `--pegin`: Peg-in (BTC -> RBTC). Requires `--amount`
- `--pegout`: Peg-out (RBTC -> BTC). Requires `--amount` and `--btc-address`
- `--amount <amount>`: Amount in BTC (for `--pegin`) or RBTC (for `--pegout`)
- `--btc-address <address>`: Destination BTC address (required for `--pegout`)
- `--provider <name-or-url>`: Force LP selection by provider name or apiBaseUrl
- `--trusted-wallet <name>`: Use a trusted (whitelisted) Rootstock wallet to accept quotes without captcha
- `--trusted-private-key <hex>`: Use a trusted (whitelisted) private key to accept quotes without captcha (avoid in shared shells)
- `--interactive`: Run guided interactive swap flow
- `--wallet <name>`: Wallet name to use for signing (uses current wallet by default)

## Contributing

Expand Down
60 changes: 59 additions & 1 deletion bin/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import { configCommand } from "../src/commands/config.js";
import { transactionCommand } from "../src/commands/transaction.js";
import { pipeCommand } from "../src/commands/pipe.js";
import { monitorCommand, listMonitoringSessions, stopMonitoringSession } from "../src/commands/monitor.js";
import { attestationCommand } from "../src/commands/attestation.js";
import { gasCommand } from "../src/commands/gas.js";
import { simulateCommand, TransactionSimulationOptions } from "../src/commands/simulate.js";
import { parseEther } from "viem";
Expand All @@ -29,12 +28,14 @@ import { validateAndFormatAddressRSK } from "../src/utils/index.js";
import { rnsUpdateCommand } from "../src/commands/rnsUpdate.js";
import { rnsTransferCommand } from "../src/commands/rnsTransfer.js";
import { rnsRegisterCommand } from "../src/commands/rnsRegister.js";
import { swapCommand } from "../src/commands/swap.js";

interface CommandOptions {
testnet?: boolean;
address?: Address;
contract?: Address;
value?: string;
amount?: string;
txid?: string;
abi?: string;
bytecode?: string;
Expand Down Expand Up @@ -81,6 +82,13 @@ interface CommandOptions {
attestRecipient?: string;
attestReason?: string;
rns?: string;
btcAddress?: string;
liquidity?: boolean;
pegin?: boolean;
pegout?: boolean;
provider?: string;
trustedWallet?: string;
trustedPrivateKey?: string;
}

const orange = chalk.rgb(255, 165, 0);
Expand Down Expand Up @@ -139,6 +147,52 @@ program
});
});

program
.command("swap")
.description("Swap BTC <-> RBTC using the Flyover protocol")
.option("-t, --testnet", "Use testnet network")
.option("--liquidity", "Show available liquidity providers (quote only)")
.option("--pegin", "Peg-in: convert BTC -> RBTC (requires --amount)")
.option("--pegout", "Peg-out: convert RBTC -> BTC (requires --amount and --btc-address)")
.option("--amount <amount>", "Amount in BTC (for --pegin) or RBTC (for --pegout)")
.option("--btc-address <address>", "Destination BTC address (required for --pegout)")
.option(
"--provider <name-or-url>",
"Force a specific liquidity provider by name or apiBaseUrl (optional)"
)
.option(
"--trusted-wallet <name>",
"Use a trusted (whitelisted) Rootstock wallet name to accept quotes without captcha (optional)"
)
.option(
"--trusted-private-key <hex>",
"Use a trusted (whitelisted) private key to accept quotes without captcha (optional; avoid using in shared shells)"
)
.option("-i, --interactive", "Run guided interactive swap flow")
.option("--wallet <name>", "Wallet name to use for signing (optional; defaults to current wallet)")
.action(async (options: CommandOptions) => {
try {
const amount = options.amount ? parseFloat(options.amount) : undefined;

await swapCommand({
testnet: options.testnet,
liquidity: !!options.liquidity,
pegin: !!options.pegin,
pegout: !!options.pegout,
amount: amount && !Number.isNaN(amount) ? amount : undefined,
btcAddress: options.btcAddress,
provider: options.provider,
trustedWalletName: options.trustedWallet,
trustedPrivateKey: options.trustedPrivateKey,
interactive: !!options.interactive,
walletName: options.wallet,
isExternal: false,
});
} catch (error: any) {
logError(false, `Error during swap: ${error.message || error}`);
}
});

program
.command("transfer")
.description("Transfer RBTC or ERC20 tokens to the provided address")
Expand Down Expand Up @@ -683,6 +737,10 @@ program
.option("--revocable", "Whether the schema should be revocable (for schema action)")
.action(async (options: CommandOptions) => {
try {
// Lazy-load to avoid eager importing heavy EAS SDK.
// This also prevents startup crashes when the dependency's ESM subpath resolution is broken.
const { attestationCommand } = await import("../src/commands/attestation.js");

if (!options.action || !['create', 'verify', 'revoke', 'list', 'schema'].includes(options.action)) {
console.error(chalk.red("🚨 Invalid action. Use: create, verify, revoke, list, or schema"));
return;
Expand Down
Loading