Install
openclaw skills install gasless-crosschain-executorlocal-key swap planning and execution skill. Cross-chain (1inch Fusion+, gasless), same-chain gasless (1inch Fusion), and same-chain paid (1inch Aggregation...
openclaw skills install gasless-crosschain-executorPlan, validate, sign, submit, and monitor EVM swaps with local-only key custody. Same-chain and cross-chain paths are bundled.
This is not a trading strategy. It is an execution-safety workflow over 1inch Fusion+ (cross-chain gasless), 1inch Fusion (same-chain gasless), and 1inch Aggregation Router v6 (same-chain paid). custom is an escape hatch when the user supplies audited contracts.
Helpers are not installed system-wide. Before running anything in scripts/ or examples/:
./.venv with eth-account and web3. If a script raises ModuleNotFoundError, ask the user to run ./scripts/setup.sh from the skill root..venv/bin/python or after source .venv/bin/activate. Never pip install into system Python..mjs helpers also need Node 20+ and examples/node_modules/. setup.sh handles this when Node is available; without Node, only the Python tools work (sufficient for wallet bootstrap, validation, and signing).When the user says "buy PEPE" or "swap my USDC for ETH" without exact addresses / chains / amounts, expand the request before doing anything else. Do not infer fields silently.
examples/resolve_token.mjs --chain <id> {--symbol <SYM>|--address <addr>}. If the result has a warning (no verified match, multiple verified candidates), show the user the list and ask. Refuse to plan against an unverified address unless the user explicitly opts in.examples/portfolio_scan.py --owner <addr> and pick a candidate (e.g. a stablecoin or the largest verified holding) on a chain that can reach the destination. Confirm with the user.1inch-fusion-plus. Same-chain → check the wallet's native balance via preflight.py --token native: zero/dust → 1inch-fusion, otherwise → 1inch-aggregator. See the workflow decision tree below for the exact invocation.decimals. Fiat-denominated requests (e.g. "$10 worth") need an external price source the skill does not provide; ask the user for a token-unit amount or document the oracle used.Classify the request.
Choose provider mode. The choice follows from observable state; do not ask the user. Validator enum: {1inch-fusion-plus, 1inch-fusion, 1inch-aggregator, custom}.
Cross-chain (source_chain_id != destination_chain_id) → 1inch-fusion-plus. Pipeline: build_order_fusion_plus.mjs → local_signer.py (typed-data) → submit_fusion_plus.mjs → status_fusion_plus.mjs → submit_secret.mjs.
Same-chain (source_chain_id == destination_chain_id) — branch on the wallet's native balance on the source chain:
examples/preflight.py --rpc-url <RPC> --token native --owner <wallet> --spender <wallet> (--spender is unused but required; pass the wallet itself).1inch-fusion. Pipeline: build_order_fusion.mjs → local_signer.py (typed-data) → submit_fusion.mjs → status_fusion.mjs.1inch-aggregator. Pipeline: swap_aggregator.mjs → local_signer.py --mode tx → broadcast_tx.mjs.custom is reserved for user-supplied audited contracts; otherwise the rule above is non-negotiable.
If the wallet has no gas and 1inch-fusion returns no fillable preset, report the deadlock to the user. Do not silently fall through to the aggregator.
Same-chain vs cross-chain follows from the user-named chain ids. Never reroute through cross-chain to find liquidity.
To add a provider, see references/provider-adapters.md.
Decide whether the route is actually gasless.
Use this workflow only when the user has no usable signer or explicitly asks for help configuring one. The skill never accepts a key in chat; it only triggers a local generator that runs on the user's machine.
Confirm intent and risk acknowledgement.
Pick a generation mode.
keystore (default): an encrypted EIP-2335-style JSON keystore. The user types the passphrase into the local terminal, never into chat.file: raw 0x-prefixed private key in a 0600 file. Prototype only — read access by any other process means total loss of funds.env: prints a one-shot export LOCAL_PRIVATE_KEY=... line on the local terminal. The agent must never see, log, or store the printed value.Run the generator on the user's machine.
examples/generate_wallet.py (or an equivalent local tool) with the chosen mode and a target path under a directory whose permissions are 0700.0600, refuse to overwrite an existing wallet without --force, and print the address only — never the key — to standard output that the agent can read.Run the backup ceremony in the local terminal.
Wire the new wallet into subsequent plans.
signer_ref of the form keystore:<absolute path>, file:<absolute path>, or env:<VAR_NAME> per the chosen mode. Never embed the key.Gather required parameters.
Verify local signer setup.
Query balances and token metadata.
examples/preflight.py before recommending an approval transaction.Quote and build the signable payload.
references/execution-plan-schema.md.examples/build_order_fusion_plus.mjs produces typed-data + submit payload + 0600 secret files in one pass.examples/build_order_fusion.mjs produces typed-data + submit payload; no secrets.examples/swap_aggregator.mjs produces a tx envelope; add nonce from RPC eth_getTransactionCount before signing.Validate the plan before signing.
scripts/validate_execution_plan.py plan.json.ERROR. Disclose every WARNING to the user.Require explicit user authorization.
Sign locally.
examples/local_signer.py. Pass the full binding from the validated plan via --expect-* flags; the signer re-asserts every one before signing and refuses on any mismatch.--expect-chain-id. For typed-data, also pass --expect-verifying-contract.--expect-message-equal FIELD=VALUE per plan-bound message field.
salt, receiver, makerAsset, takerAsset, makingAmount, takingAmount, makerTraits (packs nonce, expiry, and partial-fill flags). Plus --expect-sender-field maker.owner, spender, value, nonce, deadline. Plus --expect-sender-field owner.--expect-domain-equal name=... / version=... whenever the provider docs pin those.--mode tx, for Aggregator swaps): bind --expect-to <plan.contracts.spender> and --expect-value <plan.fees.source_native_value> (typically 0 for ERC20→ERC20). Optional --expect-data-prefix 0x<selector> to pin the function selector.Submit and monitor.
submit_fusion_plus.mjs, submit_fusion.mjs) or RPC (broadcast_tx.mjs).$XDG_RUNTIME_DIR/gxe (Linux) or $TMPDIR/gxe-<uid> (macOS). submit_secret.mjs reads one file per fill and unlinks it after the relayer accepts the secret. Do not log, copy, or echo the secret values.Load these files only when relevant:
references/provider-adapters.md for 1inch Fusion+ and 1inch Aggregator adapter notes, plus the integration template for adding new providers.references/security-policy.md for key handling, allowance, signing, and local key generation guardrails.references/execution-plan-schema.md for the plan JSON shape that must be validated before signing.references/sample-plan.json for a minimal sample plan accepted by the validator.examples/ for runnable tools:
generate_wallet.py, local_signer.py (typed-data + --mode tx), preflight.py, portfolio_scan.py, resolve_token.mjsbuild_order_fusion_plus.mjs, submit_fusion_plus.mjs, status_fusion_plus.mjs, submit_secret.mjs, plus the standalone quote_fusion_plus.mjsbuild_order_fusion.mjs, submit_fusion.mjs, status_fusion.mjsswap_aggregator.mjs, broadcast_tx.mjsFor every real or proposed execution, return this structure before signing:
provider: <provider mode>
mode: dry_run | quote_only | approval_required | execute_after_user_approval | monitor_only
route: <source chain/token/amount> -> <destination chain/token/min received>
recipient: <destination recipient>
wallet: <locally derived wallet address>
contracts: <spender/settler/escrow/router addresses>
fees: <solver fee, protocol fee, source tx fee, destination gas, provider margin>
gasless verdict: fully_gasless | gasless_after_existing_allowance | gasless_after_permit | not_fully_gasless | unknown
user approval needed: yes/no and why
status tracking: <order id or tx hash plus endpoint>
plan hash: <sha256 of normalized plan json>
warnings: <non-fatal risks>
blocking errors: <must fix before signing>