Skip to content

Latest commit

 

History

History
241 lines (197 loc) · 12.8 KB

README.md

File metadata and controls

241 lines (197 loc) · 12.8 KB

Wallet CLI Tools

This repository contains some CLIs that are useful working with Ethereum wallets (more speficially externally owned accounts or EOAs) and EVM compatible blockchains.

Node.js

The CLIs have been successfully tested with the Node.js 16 ("Gallium") LTS release.

Build and install

The binaries are built and installed globally by

npm install -g

Executables

generate-private-key

This executable generates and outputs to standard out randomly generated private key(s) and optionally the associated address:

$ generate-private-key
0x5e0720fe097196c75f592339eafc74b32f940137682147514abdd853dd1889bb
$ generate-private-key -a
0xba5ced1d6812dd190458c5b28cfc068d1b66e645277b2eaff1e7aafb879c4432 0xf1227571ba64c7783c05245de987a8455951216a

The full outline of the usage is as follows:

$ generate-private-key -h
generate-private-key

Generate private key(s)

Options:
      --version  Show version number                                   [boolean]
  -c, --count    Number of private keys                    [number] [default: 1]
  -a, --address  Output address alongside the private key              [boolean]
  -i, --index    Prefix each line with index, for use with larger values of
                 count                                                 [boolean]
  -h, --help     Show help                                             [boolean]

private-key-to-keystore

With private key at hand it is sometimes useful to generate a keystore from it. The executable private-key-to-keystore is the tool to use for this purpose:

$ private-key-to-keystore -p my-password 0x1d565082dac27cc7a6cdb3edea39133823cb007f0610c14a430b2e4ebd278cc2
{"version":3,"id":"2d7a200e-7224-4b0a-bfc8-ed65c602f39e","address":"c247fea5d7db3121cd4e35952a27b695591c1ccd","crypto":{"ciphertext":"a9d7939c6c353861ff2a26dfe8ee1300e06136d000ed180e43d015716b0411df","cipherparams":{"iv":"929ef885f296616bc91e5eca4d3ded3c"},"cipher":"aes-128-ctr","kdf":"pbkdf2","kdfparams":{"dklen":32,"salt":"d39e83337a03d71d09b1db24043d59eebafc8fce3d7bd8f46357a8a356d94fca","c":262144,"prf":"hmac-sha256"},"mac":"552bbeb8a226a7f419f42e53293591fcd09470cb1a760426ba8b1848076fe749"}}

Add option -F and a file output will be generated instead of output of keystore to standard out:

$ private-key-to-keystore -p my-password -F 0x1d565082dac27cc7a6cdb3edea39133823cb007f0610c14a430b2e4ebd278cc2
Keystore output to 'keystore/UTC--2022-06-14T07-46-37.480Z--c247fea5d7db3121cd4e35952a27b695591c1ccd'

The usage is as follows:

$ private-key-to-keystore -h
private-key-to-keystore <private-key>

Generate keystore file from private key and password

Positionals:
  private-key  Private key                                              [string]

Options:
      --version                  Show version number                   [boolean]
  -h, --help                     Show help                             [boolean]
  -p, --password                 Password for encrypting the keystore   [string]
  -P, --password-generator       Password generator executable or text file with
                                 one password per line                  [string]
  -F, --file-output              Output to file if true, else output to std out
                                                      [boolean] [default: false]
  -d, --output-directory         Directory for file output
                                                  [string] [default: "keystore"]
  -f, --output-file              Directory for file output. If not provided the
                                 name will be generated according to a template
                                 of 'UTC--<timestamp>--<address>'       [string]
  -k, --key-derivation-function  Key derivation function
                      [string] [choices: "pbkdf2", "scrypt"] [default: "pbkdf2"]

Piped mode

private-key-to-keystore may also be called in a piped mode to receive input e.g. from generate-private-key. This allows the generation of multiple keystore files from randomly generated private keys:

$ generate-private-key -c 3 | private-key-to-keystore -F -p my-password
Keystore output to 'keystore/UTC--2022-06-14T07-48-32.588Z--b932d489954d42a077ef6e370d59f5f79a8d5b39'
Keystore output to 'keystore/UTC--2022-06-14T07-48-32.814Z--8c22274a3a012e5f3724cf69267973f1388c143d'
Keystore output to 'keystore/UTC--2022-06-14T07-48-32.814Z--41636dea774c8a05e1eaf8375de4fdf3bc22d273'

The command line above creates multiple keystore files with the same password for each file. In most cases, however, it is fair to assume that a separate password should be used for each keystore file.

private-key-to-keystore supports the provision of an executable to generate password, one for each keystore. One example of a password generator is password-generator. With this executable installed the command line above may be modified to generate one password on the fly for each keystore.

$ generate-private-key -c 3 | private-key-to-keystore -F -P "password-generator -c"
Keystore output to 'keystore/UTC--2022-06-14T07-49-10.225Z--4544a8c5e8e3818567d1c40dbbafc918197a2857' - Password: pHxNyANsws
Keystore output to 'keystore/UTC--2022-06-14T07-49-10.450Z--79ce05cb48e60aeef476190df10f6926378cfc49' - Password: N5tvpuYFIS
Keystore output to 'keystore/UTC--2022-06-14T07-49-10.337Z--6c694cc85872996a8c632abda3ab5a6a7635b9c9' - Password: YfDrr2vOr1

As an alternative to executable password generator a text file may be used. If more passwords are needed than are contained in the provided text file the logics cycle through the password file as many times as required. The sample password file contains two passwords only.

$ generate-private-key -c 3 | private-key-to-keystore -F -P src/private-key-to-keystore/passwords/sample.txt
Keystore output to 'keystore/UTC--2022-06-14T07-49-35.642Z--e877cc3a2f93300cd8e6c11d2f51d8ebd210ce16' - Password: pw2
Keystore output to 'keystore/UTC--2022-06-14T07-49-35.642Z--e6bd5221d8d6771465ba7e38f37bb9cba0bddd42' - Password: pw1
Keystore output to 'keystore/UTC--2022-06-14T07-49-35.642Z--31a3058d50259ae9a096d66c6737671d610921ee' - Password: pw1

keystore-to-private-key

This executable acts in the opposite direction of private-key-to-keystore. With a keystore file or serialized keystore string available as well as the corresponding password it allows you to extract the private key. The executable keystore-to-private-key lets to operate as follows:

 $ keystore-to-private-key -p my-password '{"version":3,"id":"de45b927-5868-4970-abed-545baa11084a","address":"c247fea5d7db3121cd4e35952a27b695591c1ccd","crypto":{"ciphertext":"3eeb950cd72a7f00014f9133c2ac10e0b592d13e23a90feac4b34930583c0a23","cipherparams":{"iv":"9458157ea26a1e283dcd7c7430b127da"},"cipher":"aes-128-ctr","kdf":"pbkdf2","kdfparams":{"dklen":32,"salt":"58c4863aeb152976d100ba2a0c36df77e8accac576018a96e488349562449b55","c":262144,"prf":"hmac-sha256"},"mac":"70e66486c3ff9eaf0ac31ad6a8101be650fe2a176ae346fb6abcc6499305fdf7"}}'
0x1d565082dac27cc7a6cdb3edea39133823cb007f0610c14a430b2e4ebd278cc2

Note that in the above command line the keystore string is wrapped single quotes to avoid the shell from removing the JSON double quotes. Alternatively you may escape the JSON double quotes in the following manner:

$ keystore-to-private-key -p my-password "{\"version\":3,\"id\":\"de45b927-5868-4970-abed-545baa11084a\",\"address\":\"c247fea5d7db3121cd4e35952a27b695591c1ccd\",\"crypto\":{\"ciphertext\":\"3eeb950cd72a7f00014f9133c2ac10e0b592d13e23a90feac4b34930583c0a23\",\"cipherparams\":{\"iv\":\"9458157ea26a1e283dcd7c7430b127da\"},\"cipher\":\"aes-128-ctr\",\"kdf\":\"pbkdf2\",\"kdfparams\":{\"dklen\":32,\"salt\":\"58c4863aeb152976d100ba2a0c36df77e8accac576018a96e488349562449b55\",\"c\":262144,\"prf\":\"hmac-sha256\"},\"mac\":\"70e66486c3ff9eaf0ac31ad6a8101be650fe2a176ae346fb6abcc6499305fdf7\"}}"
0x1d565082dac27cc7a6cdb3edea39133823cb007f0610c14a430b2e4ebd278cc2

If on the other hand your keystore resides in a file you should specify its location

$ keystore-to-private-key -p my-password -f keystore/UTC--2022-06-14T07-55-27.184Z--c247fea5d7db3121cd4e35952a27b695591c1ccd
0x1d565082dac27cc7a6cdb3edea39133823cb007f0610c14a430b2e4ebd278cc2

The full usage goes like this:

$ keystore-to-private-key -h
keystore-to-private-key [keystore]

Retrieve private key from keystore file and password

Positionals:
  keystore  Serialized keystore                                         [string]

Options:
      --version   Show version number                                  [boolean]
  -h, --help      Show help                                            [boolean]
  -f, --file      Keystore file                                         [string]
  -p, --password  Password for encrypting the keystore       [string] [required]

Piped mode

As with its directional counterpart keystore-to-private-key may be called as part of piped command line.

$ echo '{"version":3,"id":"de45b927-5868-4970-abed-545baa11084a","address":"c247fea5d7db3121cd4e35952a27b695591c1ccd","crypto":{"ciphertext":"3eeb950cd72a7f00014f9133c2ac10e0b592d13e23a90feac4b34930583c0a23","cipherparams":{"iv":"9458157ea26a1e283dcd7c7430b127da"},"cipher":"aes-128-ctr","kdf":"pbkdf2","kdfparams":{"dklen":32,"salt":"58c4863aeb152976d100ba2a0c36df77e8accac576018a96e488349562449b55","c":262144,"prf":"hmac-sha256"},"mac":"70e66486c3ff9eaf0ac31ad6a8101be650fe2a176ae346fb6abcc6499305fdf7"}}' | keystore-to-private-key -p my-password
0x1d565082dac27cc7a6cdb3edea39133823cb007f0610c14a430b2e4ebd278cc2

Again please note the wrapping of the serialized JSON in single quotes.

Ultimately keystore-to-private-key could, primarily for testing purposes, be chained with the other two executables to the a complete flow of private key generation, transformation to keystore and finally back to private key.

$ generate-private-key | private-key-to-keystore -p my-password | keystore-to-private-key -p my-password
0x0cd7b571730dd8096e8978b4937023f52cdfaf9c1a273ba7ba0f04375d03b3f6

date-to-block

Executable date-to-block is able to extract temporal block info based on datetime(s) provided in the ISO 8601 format.

Extracting info of the first block after 2022-05-01T00:00:00Z may be done by invoking

$ date-to-block 2022-05-01T00:00:00Z
{"date":"2022-05-01T00:00:05.000Z","block":14688630,"timestamp":1651363205}

A start and end datetime may be provided in pair.

$ date-to-block 2022-05-01T00:00:00Z 2022-06-01T00:00:00Z | jq
[
  {
    "date": "2022-05-01T00:00:05.000Z",
    "block": 14688630,
    "timestamp": 1651363205
  },
  {
    "date": "2022-06-01T00:00:01.000Z",
    "block": 14881677,
    "timestamp": 1654041601
  }
]

Above the JSON output is prettified using jq (which also exists as node-jq as package for Node.js).

Possibly more useful is to output the range of blocks in the span from start to end datetimes. Below are the first blocks of every week over an entire month, with YAML output as a variation.

$ date-to-block 2022-05-01T00:00:00Z 2022-06-01T00:00:00Z -r -P week -o yaml
- date: '2022-05-01T00:00:05.000Z'
  block: 14688630
  timestamp: 1651363205
- date: '2022-05-08T00:00:29.000Z'
  block: 14732822
  timestamp: 1651968029
- date: '2022-05-15T00:00:20.000Z'
  block: 14776688
  timestamp: 1652572820
- date: '2022-05-22T00:00:12.000Z'
  block: 14820222
  timestamp: 1653177612
- date: '2022-05-29T00:00:58.000Z'
  block: 14863278
  timestamp: 1653782458

Note that for range queries the end datetime is excluded from the output.

Full usage info is as follows:

$ date-to-block -h
date-to-block <start> [end]

Extract block info from datetime(s)

Positionals:
  start  The start datetime in ISO format                               [string]
  end    The end datetime in ISO format                                 [string]

Options:
      --version        Show version number                             [boolean]
  -a, --after          If true search for the nearest block after the given
                       date, else before               [boolean] [default: true]
  -o, --output-format       [string] [choices: "json", "yaml"] [default: "json"]
  -P, --period         Period delimiting blocks in range
           [string] [choices: "year", "quarter", "month", "week", "day", "hour",
                                                     "minute"] [default: "hour"]
  -p, --provider       JSON-RPC provider URI
                                      [string] [default: "https://l1.nahmii.io"]
  -r, --range          Output range of block between start and end
                                                      [boolean] [default: false]
  -h, --help           Show help                                       [boolean]