diff --git a/completions/README.md b/completions/README.md new file mode 100644 index 0000000..4f02a01 --- /dev/null +++ b/completions/README.md @@ -0,0 +1,117 @@ +# Wallet CLI Completion + +Completion scripts for the LSSA `wallet` command. + +## ZSH + +Works with both vanilla zsh and oh-my-zsh. + +### Features + +- Full completion for all wallet subcommands +- Contextual option completion for each command +- Dynamic account ID completion via `wallet account list` +- Descriptions for all commands and options + +### Supported Commands + +| Command | Description | +|------------------------|-------------------------------------------------------------| +| `wallet auth-transfer` | Authenticated transfer (init, send) | +| `wallet chain-info` | Chain info queries (current-block-id, block, transaction) | +| `wallet account` | Account management (get, list, new, sync-private) | +| `wallet pinata` | Piñata faucet (claim) | +| `wallet token` | Token operations (new, send) | +| `wallet amm` | AMM operations (new, swap, add-liquidity, remove-liquidity) | +| `wallet check-health` | Health check | + +### Installation + +#### Vanilla Zsh + +1. Create a completions directory: + + ```sh + mkdir -p ~/.zsh/completions + ``` + +2. Copy the completion file: + + ```sh + cp ./zsh/_wallet ~/.zsh/completions/ + ``` + +3. Add to your `~/.zshrc` (before any `compinit` call, or add these lines if you don't have one): + + ```sh + fpath=(~/.zsh/completions $fpath) + autoload -Uz compinit && compinit + ``` + +4. Reload your shell: + + ```sh + exec zsh + ``` + +#### Oh-My-Zsh + +1. Create the plugin directory and copy the file: + + ```sh + mkdir -p ~/.oh-my-zsh/custom/plugins/wallet + cp _wallet ~/.oh-my-zsh/custom/plugins/wallet/ + ``` + +2. Add `wallet` to your plugins array in `~/.zshrc`: + + ```sh + plugins=(... wallet) + ``` + +3. Reload your shell: + + ```sh + exec zsh + ``` + +### Requirements + +The completion script calls `wallet account list` to dynamically fetch account IDs. Ensure the `wallet` command is in your `$PATH`. + +### Usage + +```sh +# Main commands +wallet + +# Account subcommands +wallet account + +# Options for auth-transfer send +wallet auth-transfer send -- + +# Account types when creating +wallet account new +# Shows: public private + +# Account IDs (fetched dynamically) +wallet account get --account-id +# Shows: Public/... Private/... +``` + +## Troubleshooting + +### Completions not appearing + +1. Check that `compinit` is called in your `.zshrc` +2. Rebuild the completion cache: + + ```sh + rm -f ~/.zcompdump* + exec zsh + ``` + +### Account IDs not completing + +Ensure `wallet account list` works from your command line. diff --git a/completions/zsh/_wallet b/completions/zsh/_wallet new file mode 100644 index 0000000..a4aa86f --- /dev/null +++ b/completions/zsh/_wallet @@ -0,0 +1,325 @@ +#compdef wallet + +# Zsh completion script for the wallet CLI +# See instructions in ../README.md + +_wallet() { + local -a commands + local -a subcommands + local curcontext="$curcontext" state line + typeset -A opt_args + + _arguments -C \ + '1: :->command' \ + '*:: :->args' + + case $state in + command) + commands=( + 'auth-transfer:Authenticated transfer subcommand' + 'chain-info:Generic chain info subcommand' + 'account:Account view and sync subcommand' + 'pinata:Pinata program interaction subcommand' + 'token:Token program interaction subcommand' + 'amm:AMM program interaction subcommand' + 'check-health:Check the wallet can connect to the node and builtin local programs match the remote versions' + 'help:Print help message or the help of the given subcommand(s)' + ) + _describe -t commands 'wallet commands' commands + ;; + args) + case $line[1] in + auth-transfer) + _wallet_auth_transfer + ;; + chain-info) + _wallet_chain_info + ;; + account) + _wallet_account + ;; + pinata) + _wallet_pinata + ;; + token) + _wallet_token + ;; + amm) + _wallet_amm + ;; + help) + _wallet_help + ;; + esac + ;; + esac +} + +# auth-transfer subcommand +_wallet_auth_transfer() { + local -a subcommands + + _arguments -C \ + '1: :->subcommand' \ + '*:: :->args' + + case $state in + subcommand) + subcommands=( + 'init:Initialize account under authenticated transfer program' + 'send:Send native tokens from one account to another with variable privacy' + 'help:Print this message or the help of the given subcommand(s)' + ) + _describe -t subcommands 'auth-transfer subcommands' subcommands + ;; + args) + case $line[1] in + init) + _arguments \ + '--account-id[Account ID to initialize]:account_id:_wallet_account_ids' + ;; + send) + _arguments \ + '--from[Source account ID]:from_account:_wallet_account_ids' \ + '--to[Destination account ID (for owned accounts)]:to_account:_wallet_account_ids' \ + '--to-npk[Destination nullifier public key (for foreign private accounts)]:npk:' \ + '--to-ipk[Destination viewing public key (for foreign private accounts)]:ipk:' \ + '--amount[Amount of native tokens to send]:amount:' + ;; + esac + ;; + esac +} + +# chain-info subcommand +_wallet_chain_info() { + local -a subcommands + + _arguments -C \ + '1: :->subcommand' \ + '*:: :->args' + + case $state in + subcommand) + subcommands=( + 'current-block-id:Get current block id from sequencer' + 'block:Get block at id from sequencer' + 'transaction:Get transaction at hash from sequencer' + 'help:Print this message or the help of the given subcommand(s)' + ) + _describe -t subcommands 'chain-info subcommands' subcommands + ;; + args) + case $line[1] in + block) + _arguments \ + '--id[Block ID to retrieve]:block_id:' + ;; + transaction) + _arguments \ + '--hash[Transaction hash to retrieve]:tx_hash:' + ;; + esac + ;; + esac +} + +# account subcommand +_wallet_account() { + local -a subcommands + + _arguments -C \ + '1: :->subcommand' \ + '*:: :->args' + + case $state in + subcommand) + subcommands=( + 'get:Get account data' + 'list:List all accounts' + 'new:Produce new public or private account' + 'sync-private:Sync private accounts' + 'help:Print this message or the help of the given subcommand(s)' + ) + _describe -t subcommands 'account subcommands' subcommands + ;; + args) + case $line[1] in + get) + _arguments \ + '--account-id[Account ID to query]:account_id:_wallet_account_ids' + ;; + new) + _arguments \ + '1:account type:(public private)' + ;; + esac + ;; + esac +} + +# pinata subcommand +_wallet_pinata() { + local -a subcommands + + _arguments -C \ + '1: :->subcommand' \ + '*:: :->args' + + case $state in + subcommand) + subcommands=( + 'claim:Claim tokens from the Piñata faucet' + 'help:Print this message or the help of the given subcommand(s)' + ) + _describe -t subcommands 'pinata subcommands' subcommands + ;; + args) + case $line[1] in + claim) + _arguments \ + '--to[Destination account ID to receive claimed tokens]:to_account:_wallet_account_ids' + ;; + esac + ;; + esac +} + +# token subcommand +_wallet_token() { + local -a subcommands + + _arguments -C \ + '1: :->subcommand' \ + '*:: :->args' + + case $state in + subcommand) + subcommands=( + 'new:Produce a new token' + 'send:Send tokens from one account to another with variable privacy' + 'help:Print this message or the help of the given subcommand(s)' + ) + _describe -t subcommands 'token subcommands' subcommands + ;; + args) + case $line[1] in + new) + _arguments \ + '--name[Token name]:name:' \ + '--total-supply[Total supply of tokens to mint]:total_supply:' \ + '--definition-account-id[Account ID for token definition]:definition_account:_wallet_account_ids' \ + '--supply-account-id[Account ID to receive initial supply]:supply_account:_wallet_account_ids' + ;; + send) + _arguments \ + '--from[Source holding account ID]:from_account:_wallet_account_ids' \ + '--to[Destination holding account ID]:to_account:_wallet_account_ids' \ + '--amount[Amount of tokens to send]:amount:' + ;; + esac + ;; + esac +} + +# amm subcommand +_wallet_amm() { + local -a subcommands + + _arguments -C \ + '1: :->subcommand' \ + '*:: :->args' + + case $state in + subcommand) + subcommands=( + 'new:Create a new liquidity pool' + 'swap:Swap tokens using the AMM' + 'add-liquidity:Add liquidity to an existing pool' + 'remove-liquidity:Remove liquidity from a pool' + 'help:Print this message or the help of the given subcommand(s)' + ) + _describe -t subcommands 'amm subcommands' subcommands + ;; + args) + case $line[1] in + new) + _arguments \ + '--user-holding-a[User token A holding account ID]:holding_a:_wallet_account_ids' \ + '--user-holding-b[User token B holding account ID]:holding_b:_wallet_account_ids' \ + '--user-holding-lp[User LP token holding account ID]:holding_lp:_wallet_account_ids' \ + '--balance-a[Amount of token A to deposit]:balance_a:' \ + '--balance-b[Amount of token B to deposit]:balance_b:' + ;; + swap) + _arguments \ + '--user-holding-a[User token A holding account ID]:holding_a:_wallet_account_ids' \ + '--user-holding-b[User token B holding account ID]:holding_b:_wallet_account_ids' \ + '--amount-in[Amount of tokens to swap]:amount_in:' \ + '--min-amount-out[Minimum tokens expected in return]:min_amount_out:' \ + '--token-definition[Definition ID of the token being provided]:token_def:' + ;; + add-liquidity) + _arguments \ + '--user-holding-a[User token A holding account ID]:holding_a:_wallet_account_ids' \ + '--user-holding-b[User token B holding account ID]:holding_b:_wallet_account_ids' \ + '--user-holding-lp[User LP token holding account ID]:holding_lp:_wallet_account_ids' \ + '--max-amount-a[Maximum amount of token A to deposit]:max_amount_a:' \ + '--max-amount-b[Maximum amount of token B to deposit]:max_amount_b:' \ + '--min-amount-lp[Minimum LP tokens to receive]:min_amount_lp:' + ;; + remove-liquidity) + _arguments \ + '--user-holding-a[User token A holding account ID]:holding_a:_wallet_account_ids' \ + '--user-holding-b[User token B holding account ID]:holding_b:_wallet_account_ids' \ + '--user-holding-lp[User LP token holding account ID]:holding_lp:_wallet_account_ids' \ + '--balance-lp[Amount of LP tokens to burn]:balance_lp:' \ + '--min-amount-a[Minimum token A to receive]:min_amount_a:' \ + '--min-amount-b[Minimum token B to receive]:min_amount_b:' + ;; + esac + ;; + esac +} + +# help subcommand +_wallet_help() { + local -a commands + commands=( + 'auth-transfer:Authenticated transfer subcommand' + 'chain-info:Generic chain info subcommand' + 'account:Account view and sync subcommand' + 'pinata:Pinata program interaction subcommand' + 'token:Token program interaction subcommand' + 'amm:AMM program interaction subcommand' + 'check-health:Check the wallet can connect to the node' + ) + _describe -t commands 'wallet commands' commands +} + +# Helper function to complete account IDs +# Uses `wallet account list` to get available accounts +# Only includes accounts with /N prefix (where N is a number) +_wallet_account_ids() { + local -a accounts + local line + + # Try to get accounts from wallet account list command + # Filter to lines starting with /N (numbered accounts) and extract the account ID + if command -v wallet &>/dev/null; then + while IFS= read -r line; do + # Remove trailing comma if present and add to array + [[ -n "$line" ]] && accounts+=("${line%,}") + done < <(wallet account list 2>/dev/null | grep '^/[0-9]' | awk '{print $2}') + fi + + # Provide type prefixes as fallback if command fails or returns nothing + if (( ${#accounts} == 0 )); then + compadd -S '' -- 'Public/' 'Private/' + return + fi + + _multi_parts / accounts +} + +_wallet "$@"