Install
openclaw skills install impossible-finance-skillBSC (Binance Smart Chain) trading on Impossible Finance DEX — wallet creation, token swaps, pair discovery, and balance management.
openclaw skills install impossible-finance-skillThis skill enables an AI agent to trade tokens on Impossible Finance DEX (BSC mainnet). Impossible Finance V3 Swap is interface-compatible with Uniswap V2 but includes modifications for higher capital efficiency trades (lower slippage for supported pairs, especially stablecoins).
It covers:
clawchain skill (skill.md or curl_skills.md).~/.config/impossible_agent/ and optionally ~/.config/clawchain/credentials.json (read-only, for EVM key registration only).| File | Access | Purpose |
|---|---|---|
~/.config/impossible_agent/wallet.json | Read/Write (created once) | Stores the agent's BSC private key and address for signing transactions |
~/.config/clawchain/credentials.json | Read-only (optional) | Used only if registering BSC public key on ClawChain for EVM event tracking |
| Endpoint | Purpose |
|---|---|
BSC RPC (BSC_RPC_URL) | Read blockchain state (balances, pair info) and submit signed transactions |
| Impossible Finance Router/Factory contracts | On-chain calls to discover pairs, get quotes, execute swaps |
Set these environment variables before using the skill. All have sensible defaults for BSC mainnet:
export BSC_RPC_URL="https://bsc-dataseed1.binance.org"
export BSC_CHAIN_ID=56
# Impossible Finance V3 (BSC mainnet)
export IF_ROUTER="0xCCF4881b849d94C15c98567Ba71b08eD829ABA33"
export IF_FACTORY="0xBf9D97eAF551877E4710d8E9d0519F79E03E5E69"
export WBNB="0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c"
Block explorer: https://bscscan.com
Impossible Finance Swap UI: https://app.impossible.finance/swap
This skill requires Node.js 18+ and the ethers npm package (v6):
npm install ethers
# or: pnpm add ethers
The agent needs a local wallet file containing a private key and public address so it can sign transactions. This file is created once during initial setup and reused for all subsequent operations.
⚠️ Security: The wallet file contains sensitive key material. See the Security Notes section for encryption and file permission best practices. Only use a dedicated, small-balance wallet — never your main funds.
Run this script to generate a new wallet and write it to a file:
node -e "
const fs = require('fs');
const path = require('path');
const { ethers } = require('ethers');
const wallet = ethers.Wallet.createRandom();
const dir = process.env.HOME + '/.config/impossible_agent';
fs.mkdirSync(dir, { recursive: true });
const file = dir + '/wallet.json';
fs.writeFileSync(file, JSON.stringify({
privateKey: wallet.privateKey,
address: wallet.address,
publicKey: wallet.publicKey
}, null, 2), { mode: 0o600 });
console.log('Wallet saved to ' + file);
console.log('Address: ' + wallet.address);
"
Default file location: ~/.config/impossible_agent/wallet.json
File format (wallet.json):
{
"privateKey": "0x...",
"address": "0x...",
"publicKey": "0x..."
}
chmod 600). Never log or expose this value.To use a different path, set the environment variable:
export IF_WALLET_FILE="$HOME/.config/impossible_agent/wallet.json"
# Then in the script, write to process.env.IF_WALLET_FILE
address and publicKey from wallet.json.<address>This step is optional. It links your BSC wallet public key to your ClawChain agent account to enable tracking EVM events on Chromia. Skip this if you don't need on-chain event tracking.
Prerequisite: You must already have a registered and claimed agent on ClawChain. See the
clawchainskill for registration instructions.
wallet.json file with publicKey (required) and optionally address~/.config/clawchain/credentials.json (created by the clawchain skill)These are the same variables used by the clawchain skill — set them if not already configured:
export CLAWCHAIN_BRID="9D728CC635A9D33DAABAC8217AA8131997A8CBF946447ED0B98760245CE5207E"
export CLAWCHAIN_NODE="https://chromia.01node.com:7740"
# Read wallet info
WALLET_FILE="${IF_WALLET_FILE:-$HOME/.config/impossible_agent/wallet.json}"
PUBLIC_KEY=$(cat $WALLET_FILE | grep -o '"publicKey": "[^"]*' | cut -d'"' -f4)
ADDRESS=$(cat $WALLET_FILE | grep -o '"address": "[^"]*' | cut -d'"' -f4)
# Register public key on Chromia
chr tx register_evm_public_key \
"impossible_finance" \
"$PUBLIC_KEY" \
"BSC" \
56 \
"$ADDRESS" \
--ft-auth \
--secret ~/.config/clawchain/credentials.json \
-brid $CLAWCHAIN_BRID \
--api-url $CLAWCHAIN_NODE \
--await
Arguments: wallet_type public_key chain network_id address
Network IDs:
569715137Note: If you don't have an address, use "" (empty string) for the last parameter.
If you're integrating this into a web application with an authenticated FT4 session:
const fs = require('fs');
const walletFile = process.env.IF_WALLET_FILE || '~/.config/impossible_agent/wallet.json';
const walletData = JSON.parse(fs.readFileSync(walletFile, 'utf8'));
// Assuming you have a Chromia session object (from @chromia/ft4)
const result = await session.call({
name: 'register_evm_public_key',
args: [
'impossible_finance', // wallet_type
walletData.publicKey, // public_key (required)
'BSC', // chain
56, // network_id (56 for BSC mainnet, 97 for testnet)
walletData.address || "" // address (optional)
]
});
console.log('Public key registered:', result);
To check which public keys are registered for your agent:
# Get all registered public keys for an agent
chr query get_evm_public_keys 'agent_name=your_agent_name' \
-brid $CLAWCHAIN_BRID --api-url $CLAWCHAIN_NODE
# Get specific public key by wallet type
chr query get_evm_public_key_by_type \
'agent_name=your_agent_name' \
'wallet_type=impossible_finance' \
-brid $CLAWCHAIN_BRID --api-url $CLAWCHAIN_NODE
0x and be at least 66 characters (0x + 64 hex chars).The agent does not have an "account" on a server — it has a BSC address (from wallet.json). Fund the agent by sending BNB and tokens to that address:
<address> from wallet.json.<address>. The agent can swap via Impossible Finance if a pair exists (e.g. USDT/BNB, BUSD/BNB, IF/BNB).provider.getBalance(address)balanceOf(address) on the token contract.The agent can work with any BEP-20 token and determine which swaps are possible. No fixed token list is required.
symbol() → e.g. "USDT", "WBNB", "IF"decimals() → use for amount math and display (e.g. 18 or 6)name() → full name (optional)IF_FACTORY).factory.getPair(tokenA, tokenB). If the result is the zero address (0x000...), no pair exists. Otherwise it is the pair contract address.getReserves(). If both reserves are > 0, the pair has liquidity and that swap is available.getAmountsOut(amountIn, path) (read-only). If the call reverts or returns zero for the output amount, the swap is not feasible (no liquidity or invalid path).[tokenA, WBNB, tokenB]. Call getAmountsOut(amountIn, path); if it succeeds and returns a positive amount, the swap is available.The agent uses the private key from wallet.json to sign a swap transaction and sends it to BSC.
| Contract | Address |
|---|---|
| Router | 0xCCF4881b849d94C15c98567Ba71b08eD829ABA33 |
| Factory | 0xBf9D97eAF551877E4710d8E9d0519F79E03E5E69 |
| WBNB | 0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c |
| Method | Use case |
|---|---|
swapExactETHForTokens | Swap exact BNB for tokens (min amount out) |
swapExactTokensForETH | Swap exact tokens for BNB |
swapExactTokensForTokens | Swap exact token A for token B |
swapTokensForExactTokens | Swap tokens for exact amount of token B |
wallet.json (privateKey + address).new ethers.JsonRpcProvider(BSC_RPC_URL) (mainnet: chain id 56).getAmountsOut(amountIn, path). If it reverts or returns zero, try a multi-hop path (e.g. [tokenA, WBNB, tokenB]) or inform the user the pair has no liquidity.[WBNB, tokenAddress]; token → BNB: [tokenAddress, WBNB]; token → token: [tokenA, WBNB, tokenB] (or direct if pair exists).swapExactETHForTokens, swapExactTokensForETH, or swapExactTokensForTokens.Math.floor(Date.now() / 1000) + 300 (e.g. 5 minutes).getAmountsOut(amountIn, path) then apply slippage (e.g. 1% = amountOut * 0.99).{ value: amountInWei }; for token → BNB or token → token, approve router for the token first, then call the swap.1e18 wei.~/.config/impossible_agent/wallet.json (or IF_WALLET_FILE).address when telling the user where to top up.privateKey only inside the signing process (ethers Wallet). Never log or print the private key.wallet.json.ethers.Wallet(privateKey, provider).swapExactETHForTokens) with path, deadline, amountOutMin.tx = await router.swapExactETHForTokens(...); await tx.wait().https://bscscan.com/tx/<hash>.getAmountsOut(amountIn, path) (read-only) to get expected amountOut, then compute amountOutMin with slippage.| Symbol | Address | Notes |
|---|---|---|
| WBNB | 0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c | Native wrapped; use in paths |
| USDT | 0x55d398326f99059fF775485246999027B3197955 | Stablecoin |
| BUSD | 0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56 | Stablecoin |
| IF | 0xb0e1fc65c1a741b4662b813eb787d369b8614af1 | Impossible Finance governance token |
| IDIA | 0x0b15Ddf19D47E6a86A56148fb4aFFFc6929BcB89 | Impossible Decentralized Incubator Access token |
Do not limit to these. The agent should accept any BEP-20 address and discover availability via getPair / getReserves and getAmountsOut (see §3). If a pair has no liquidity, try a multi-hop path via WBNB or use the Impossible Finance UI.
mode: 0o600 automatically. Verify with:
chmod 600 ~/.config/impossible_agent/wallet.json
ls -la ~/.config/impossible_agent/wallet.json
# Should show: -rw-------
ethers.Wallet instance for signing. It is never sent to any remote endpoint.Wallet.encrypt()) for production use. The agent would prompt for a password to decrypt at startup.For enhanced security, use ethers.js encrypted wallet format instead of plaintext:
// Create encrypted wallet (during setup)
const encrypted = await wallet.encrypt("your-password");
fs.writeFileSync(file, encrypted, { mode: 0o600 });
// Load encrypted wallet (during operations)
const wallet = await ethers.Wallet.fromEncryptedJson(
fs.readFileSync(file, 'utf8'),
"your-password"
);
| Error | Meaning / action |
|---|---|
| insufficient funds | Not enough BNB for gas or not enough token/BNB for the swap. User should top up. |
| execution reverted: INSUFFICIENT_OUTPUT_AMOUNT | Slippage too low; increase or retry. |
| execution reverted: EXPIRED | Deadline passed; rebuild tx with new deadline. |
| nonce too low | Reuse of nonce; wait and retry or refresh nonce from chain. |
| execution reverted: PAIR_NOT_EXIST | No pair exists for this token combination. Try a multi-hop path via WBNB. |