ElectrumをCLIでいじってみる

# 趣旨
CLIでビットコインをいじれるウォレットを扱えるようになりたいので時間のある時にコマンドを試していって仕様を理解しようとしています。そんなことしなくてもヘルプコマンドを見ればわかる人はわかるんでしょうけど、僕は初学者なので出来るだけ自分で動かして学びます。

ElectrumをCLIでインストールする方法は以下に備忘録を残しました。インストール自体はすぐにできるんですがGPG署名を使ってファイルが不正に改竄されてないかどうかを確かめないと使用するのは危険なので、お試しになる方はかならず署名の確認をしてください。

https://qiita.com/danieltanaka/items/a6d0c3078689b5d083a9

# ヘルプコマンド結果
使い方は全部ここに記載されてるのでわからなければヘルプコマンドを使えばいいですね。外部のWebサイトなどに頼る必要はありません。
```
(bitenv) daniel@raspberrypi:~/Bitcoin/wallets $ electrum help
usage: electrum [-h] [--version] [-v VERBOSITY] [-V VERBOSITY_SHORTCUTS] [-D ELECTRUM_PATH] [-P] [--testnet] [--regtest] [--simnet] [--signet]
                [-o] [--rpcuser RPCUSER] [--rpcpassword RPCPASSWORD] [-w WALLET_PATH] [--forgetconfig]
                <command> ...

positional arguments:
  <command>
    gui                 Run GUI (default)
    daemon              Run Daemon
    add_peer
    add_request         Create a payment request, using the first unused address of the wallet
    addtransaction      Add a transaction to the wallet history
    broadcast           Broadcast a transaction to the network
    bumpfee             Bump the fee for an unconfirmed transaction
    changegaplimit      Change the gap limit of the wallet
    clear_invoices      Remove all invoices
    clear_ln_blacklist
    clear_requests      Remove all payment requests
    close_channel
    close_wallet        Close wallet
    commands            List of commands
    convert_currency    Converts the given amount of currency to another using the configured exchange rate source
    convert_xkey        Convert xtype of a master key
    create              Create a new wallet
    createmultisig      Create multisig address
    createnewaddress    Create a new receiving address, beyond the gap limit of the wallet
    decode_invoice
    decrypt             Decrypt a message encrypted with a public key
    delete_invoice      Remove an outgoing payment invoice
    delete_request      Remove an incoming payment request
    deserialize         Deserialize a serialized transaction
    dumpprivkeys        Deprecated
    enable_htlc_settle
    encrypt             Encrypt a message with a public key
    export_channel_backup
    freeze              Freeze address
    freeze_utxo         Freeze a UTXO so that the wallet will not spend it
    get                 Return item from wallet storage
    get_channel_ctx     return the current commitment transaction of a channel
    get_invoice         Returns an invoice (request for outgoing payment)
    get_request         Returns a payment request
    get_tx_status       Returns some information regarding the tx
    get_watchtower_ctn  return the local watchtower's ctn of channel
    getaddressbalance   Return the balance of any address
    getaddresshistory   Return the transaction history of any address
    getaddressunspent   Returns the UTXO list of any address
    getalias            Retrieve alias
    getbalance          Return the balance of your wallet
    getconfig           Return a configuration variable
    getfeerate          Return current fee rate settings and current estimate (in sat/kvByte)
    getinfo             network info
    getmasterprivate    Get master private key
    getmerkle           Get Merkle branch of a transaction included in a block
    getminacceptablegap
                        Returns the minimum value for gap limit that would be sufficient to discover all known addresses in the wallet
    getmpk              Get master public key
    getprivatekeyforpath
                        Get private key corresponding to derivation path (address index)
    getprivatekeys      Get private keys of addresses
    getpubkeys          Return the public keys for a wallet address
    getseed             Get seed phrase
    getservers          Return the list of known servers (candidates for connecting)
    gettransaction      Retrieve a transaction
    getunusedaddress    Returns the first unused address of the wallet, or None if all addresses are used
    help
    import_channel_backup
    importprivkey       Import a private key
    is_synchronized     return wallet synchronization status
    ismine              Check if address is in wallet
    lightning_history   lightning history
    list_channels
    list_invoices       Returns the list of invoices (requests for outgoing payments) saved in the wallet
    list_peers
    list_requests       Returns the list of incoming payment requests saved in the wallet
    list_wallets        List wallets open in daemon
    listaddresses       List wallet addresses
    listcontacts        Show your list of contacts
    listunspent         List unspent outputs
    lnpay
    load_wallet         Load the wallet in memory
    make_seed           Create a seed
    nodeid
    normal_swap         Normal submarine swap: send on-chain BTC, receive on Lightning Note that your funds will be locked for 24h if you do not
                        have enough incoming capacity
    notify              Watch an address
    onchain_history     Wallet onchain history
    open_channel
    password            Change wallet password
    payto               Create a transaction
    paytomany           Create a multi-output transaction
    rebalance_channels  Rebalance channels
    removelocaltx       Remove a 'local' transaction from the wallet, and its dependent transactions
    request_force_close
                        Requests the remote to force close a channel
    reset_liquidity_hints
    restore             Restore a wallet from text
    reverse_swap        Reverse submarine swap: send on Lightning, receive on-chain
    searchcontacts      Search through contacts, return matching entries
    serialize           Create a signed raw transaction from a json tx template
    setconfig           Set a configuration variable
    setfeerate          Set fee rate estimation method and value
    setlabel            Assign a label to an item
    signmessage         Sign a message with a key
    signtransaction     Sign a transaction
    signtransaction_with_privkey
                        Sign a transaction
    stop                Stop daemon
    sweep               Sweep private keys
    unfreeze            Unfreeze address
    unfreeze_utxo       Unfreeze a UTXO so that the wallet might spend it
    validateaddress     Check that an address is valid
    verifymessage       Verify a signature
    version             Return the version of Electrum
    version_info        Return information about dependencies, such as their version and path

options:
  -h, --help            show this help message and exit
  --version             Return the version of Electrum.
  -w WALLET_PATH, --wallet WALLET_PATH
                        wallet path
  --forgetconfig        Forget config on exit

global options:
  -v VERBOSITY          Set verbosity (log levels)
  -V VERBOSITY_SHORTCUTS
                        Set verbosity (shortcut-filter list)
  -D ELECTRUM_PATH, --dir ELECTRUM_PATH
                        electrum directory
  -P, --portable        Use local 'electrum_data' directory
  --testnet             Use Testnet
  --regtest             Use Regtest
  --simnet              Use Simnet
  --signet              Use Signet
  -o, --offline         Run offline
  --rpcuser RPCUSER     RPC user
  --rpcpassword RPCPASSWORD
                        RPC password

Run 'electrum help <command>' to see the help for a command
```

試してみたコマンドを随時記入していきます。基本的にそのコマンドが何かは明記しません。覚えたいコマンドだったら忘れないように何か明記するかもしれません。

```bash
electrum daemon -d
electrum getinfo
electrum stop
```
```bash
electrum create --wallet /path/to/wallet/walletname1
electrum create --wallet /path/to/wallet/walletname2
electrum load_wallet -w /path/to/wallet/walletname1
electrum load_wallet -w /path/to/wallet/walletname2
electrum list_wallets
electrum -w /path/to/wallet/walletname1 listaddresses
```
```bash
electrum -w /path/to/wallet/walletname1 payto bc1qmxc0denpues0agn5l0aprzwnezpsngm8udscnr 0.01
electrum payto 1JuiT4dM65d8vBt8qUYamnDmAMJ4MjjxRE !
electrum -w /path/to/wallet/walletname1 signmessage bc1q47hkeq7rg5p9dwt552jpye3n7520gduy92l6av "hello world testing"
```
```bash
electrum importprivkey :
electrum make_seed --seed_type 'standard' 
electrum make_seed --seed_type 'segwit' 
```
```bash
electrum getbalance -w ~/path/to/wallet
electrum getservers
electrum notify bc1q4n7mtzch70fqemkm2kdal2cjjddl6vus2f9eq4 0.0.0.0
electrum is_synchronized -w test1
```
```bash
electrum -w /path/to/wallet/test1 load_wallet
electrum -w /path/to/wallet/test1 payto 34kwsubU6ExhXJdTfdNN1CHYyPvfHajFnX 0.01 --fee=0.0001
electrum broadcast "0100000001..."
```

```bash
electrum -w /path/to/wallet/test1 signmessage bc1qshx9q0l9n7xhl9xapclphm3fcee6qxfua8nk4a "Hello, this is a test message"
ICl4Yxt0al+KpzBJOmsNjijxZAvKjQZeS4dnDL8ggedyftEGqgTrJ+/CvB4zLoxqGXEBYSJ3rISnTrD+pz5ZyDE=
electrum verifymessage bc1qshx9q0l9n7xhl9xapclphm3fcee6qxfua8nk4a ICl4Yxt0al+KpzBJOmsNjijxZAvKjQZeS4dnDL8ggedyftEGqgTrJ+/CvB4zLoxqGXEBYSJ3rISnTrD+pz5ZyDE= "Hello, this is a test message"
true
```

```bash
electrum listaddresses -w test1
# output
[
    "bc1qshx9q0l9n7xhl9xapclphm3fcee6qxfua8nk4a",
    "bc1q2ztx6vzg4vn0m5eu3cmt7mw0yq0tsfc3lv2yut",
    "bc1q3pqvc2jhzh99qa66uy43ghdre2a9v9576kyfj8",
    "bc1q40m40av2wsm4e3wuq5svd9yf87sw5vr8uxmfv5",
    "bc1q7wucjj8a9axry3t4qd677ft60vn6txkfvw5d7r",
    "bc1qf8ytmhu3zhjaulwy3neattmr43flcxwry86hlq",
    "bc1qpgz6pxgh2lzqwpgs064cpnruncljcg9cna7fm6",
    "bc1q7u5hmrq9h3qhts9dt8cvcncd6z97qhdx4xh5xk",
    "bc1qh5tngk9h58suy8pzldqtcjme53729lqzdffsdn",
    "bc1qpcw5225djsrv5ye29rsgvnwaq7su4s48y7e5ux",
    "bc1q3nav6q28vu87y9ne50fv0zw6r4g9mer0qqyz84",
    "bc1qyzdcjcxxqpy6tfejwhfr9t6ux2eaeynwgw4cdh",
    "bc1qj2aa3q7jyucux2x6z3p924ge0nw9hy2q5mp8m6",
    "bc1qmdc3gkatytlaqjrnv5ncecd9mfwh58kja4ql8e",
    "bc1q3wwrlljgptku77j3l0573wzcxsxk79pen097yr",
    "bc1qpl3zuj8lf2ehrgjj67d8r9n4drxjch59f43per",
    "bc1qp9d2nelmmxwqpe35r06chsda8svx5vrf8x34fz",
    "bc1qkxx52rjgxm7fz2zwj6dh5kwpvm4n9m6j96l02a",
    "bc1qkcclcxnd4uv535p2khj7u4ezef9lvneka6sr0f",
    "bc1qgzsft89f5km5dz0zyxg06cmhm4fpn3m723jjyh",
    "bc1qh53q4n3cs3vcqc0xlxffkj6fhmq8mpsatw9gmk",
    "bc1qlxpd0qt4pced65qkq20jna8k8wn0wd0vlmydcw",
    "bc1qj53lj974h2h9v5txpkmkhh6sw4p6n3z3yee89z",
    "bc1q8ua3rg2duj7gqvw6zg3kvkldfq8ehkfjhknlyq",
    "bc1qp6n95hf9vpddrvqzt3t03urjkgcnwd4futpss5",
    "bc1qj4m42xkmm4w5lxgqxufv9p45660hcddeuxaw3t",
    "bc1q8fypu7w8ypv53eu60z7ckzqt9r9ew2ay3ffs7e",
    "bc1qprxvr9s523wkustshxcxyjpruwvf4tje0tpmnl",
    "bc1q5s8lnx9546l4dqsapx9z75nsfj687e4gp5lrum",
    "bc1q4n7mtzch70fqemkm2kdal2cjjddl6vus2f9eq4"
]
# output end
electrum getpubkeys -w test1 bc1qshx9q0l9n7xhl9xapclphm3fcee6qxfua8nk4a
# output
[
    "021d4a50e78af88b9e9e5f0f6d97705066f3b69387f646c888520d6e980acad8bd"
]
# output end
lectrum encrypt 021d4a50e78af88b9e9e5f0f6d97705066f3b69387f646c888520d6e980acad8bd "im testing"
# output
QklFMQP0JYoVhz8T2cmSuqKqSwZafEgGJFElR4gxFH+CjAe0MzrrfbE9dzUFaKq07dmCWHic+/c6tzIvqlROpL3kUUu7pwOQm2ppQt94AxdHQMD1Fg==
# output end
electrum decrypt -w test1 021d4a50e78af88b9e9e5f0f6d97705066f3b69387f646c888520d6e980acad8bd QklFMQP0JYoVhz8T2cmSuqKqSwZafEgGJFElR4gxFH+CjAe0MzrrfbE9dzUFaKq07dmCWHic+/c6tzIvqlROpL3kUUu7pwOQm2ppQt94AxdHQMD1Fg==
# output
im testing
# output end
```

```bash
electrum freeze <address>
electrum freeze_utxo <UTXO>
electrum unfreeze <address>
electrum unfreeze_utxo <UTXO>
```

```bash
electrum setconfig --offline use_gossip True
electrum setconfig --offline run_local_network True
electrum setconfig --offline use_experimental_lightning True
electrum getunusedaddress -w <wallet_name>
electrum add_lightning_peer <peer_host> <peer_port>
electrum open_channel <peer_host> <peer_port> <local_amount> -w <wallet_name>
electrum payinvoice <invoice> -w <wallet_name>
electrum addrequest <amount> -m "<memo>" --lightning -w <wallet_name>
```

# 別ファイルからElectrumのコマンドをコール
Electrumを外から使えるとすごく便利になると思うので、その方法の一例を下に示しておきます。
```test.py
import subprocess
import json
import os

def get_blockchain_height():
    try:
        activate_script = "/path/to/venv//bin/activate"
        command = f"source {activate_script} && electrum getinfo"
        result = subprocess.run(command, shell=True, capture_output=True, text=True, executable='/bin/bash')
        info = json.loads(result.stdout)
        blockchain_height = info.get('blockchain_height')
        print(f"Blockchain Height: {blockchain_height}")

    except subprocess.CalledProcessError as e:
        print(f"An error occurred while calling electrum: {e}")
    except json.JSONDecodeError as e:
        print(f"Failed to parse JSON output: {e}")

if __name__ == "__main__":
    get_blockchain_height()
```
実行結果
```bash
(bitenv) user@linux:~/Bitcoin $ python test.py 
Blockchain Height: 843852
```