Coder Social home page Coder Social logo

merklejerk / send-tokens Goto Github PK

View Code? Open in Web Editor NEW
30.0 3.0 10.0 538 KB

Simple CLI tool to send ERC20 tokens with a private key, mnemonic, or keystore.

License: Apache License 2.0

JavaScript 100.00%
ethereum cli erc20 tokens transfer send self-signed private-key wallet es2017

send-tokens's Introduction

build status npm package

send-tokens

A simple CLI tool (and library) for sending Ethereum ERC20 tokens using any of the following:

  • A wallet's private key
  • A keystore file
  • An HD wallet mnemonic phrase
  • A provider (node) wallet address

For the ether version of this package, check out send-ether.

Migrating from 1.x:

Token amounts are now in whole units, by default, which is defined by the number of decimal places a token contract supports. This means sending 100.123 tokens with a token that supports 18 decimal places, will actually send 100.123 * 10^18 of the smallest unit of that token. This behavior can be overridden with the --decimals option.

Contents

Installation

npm install -g send-tokens
# or
yarn global add send-tokens

Examples

# Address of token contract. May also be an ENS name.
TOKEN='0x1658164265555FA310d20bC601Dd32e9b996A436'
# Recipient of tokens. May also be an ENS name.
DST='0x0420DC92A955e3e139b52142f32Bd54C6D46c023'
# Sending wallet's private key.
PRIVATE_KEY='0x52c251b9e04740157471a724e9a3210b83fac5834b29c89d5bd57661bd2a7057'
# Sending wallet's HD mnemonic.
MNEMONIC='butter crepes sugar flour eggs milk ...'

# Send 100.53 WHOLE tokens to an address,
# on the mainnet, using a wallet's private key
$ send-tokens --key $PRIVATE_KEY $TOKEN $DST 100.53

# Send 32 of the smallest units of a token to an address, on ropsten,
# using an HD wallet mnemonic
$ send-tokens --network ropsten --mnemonic "$MNEMONIC" $TOKEN $DST 32 -d 0

# Send 99 WHOLE tokens to an address, on the mainnet,
# using a keystore file.
$ send-tokens --keystore './path/to/keystore.json' --password 'secret' $TOKEN $DST 99

# Send 64.3163512 WHOLE tokens to an address, on the provider's network,
# using the provider's default wallet, and wait for 3 confirmations.
$ send-tokens --provider 'http://localhost:8545' --confirmations 3 $TOKEN $DST 64.3163512

All Options

$ send-tokens --help
Usage: send-tokens [options] <token> <to> <amount>

Options:

  -v, --version               output the version number
  -d, --decimals <n>          decimal places amount is expressed in (default: max token supports)
  -k, --key <hex>             sending wallet's private key
  -f, --key-file <file>       sending wallet's private key file
  -s, --keystore-file <file>  sending wallet's keystore file
  --password <password        keystore file password
  -m, --mnemonic <phrase>     sending wallet's HD wallet phrase
  --mnemonic-index <n>        sending wallet's HD wallet account index (default: 0)
  -a, --account <hex>         sending wallet's account address (provider wallet)
  -c, --confirmations <n>     number of confirmations to wait for before returning (default: 0)
  -p, --provider <uri>        provider URI
  -n, --network <name>        network name
  -G, --gas-price <gwei>      explicit gas price, in gwei (e.g., 20)
  -l, --log <file>            append a JSON log to a file
  --no-confirm                bypass confirmation
  -h, --help                  output usage information

JSON Logs

If you pass the --log option, a JSON object describing the transfer will be appended to a file when the transaction is mined, one object per line.

Log Entries

Log entries follow this structure:

{
   // Unique transfer ID to identify related logs.
   id: '88fdd8a4b8084c36',
   // UNIX time.
   time: 1532471209842,
   // Address of token contract.
   token: '0x1658164265555FA310d20bC601Dd32e9b996A436',
   // Address of sender.
   from: '0x0420DC92A955e3e139b52142f32Bd54C6D46c023',
   // Address of recipient.
   to: '0x2621Ea417659Ad69BAE66AF05eBE5788e533E5e8',
   // Amount of tokens sent (in weis).
   amount: '20',
   // Transaction ID of transfer.
   txId: '0xd9255f8365305ebffd77cb30d09f82745eaa232e42739f5fc2788fa46f1347e3',
   // Block number where the transfer was mined.
   block: 4912040,
   // Gas used.
   gas: 40120
}

ENS Names

Anywhere you can pass an address, you can also pass an ENS name, like 'ethereum.eth', and the it will automatically be resolved to a real address.

ENS resolution only works on the mainnet, rinkeby, and ropsten, and the name must be fully registered with the ENS contract and a resolver.

Library Usage

The send-tokens package can be used as a library through the sendTokens() function.

sendTokens() asynchronously resolves to a transaction receipt once the transaction has been mined (or confirmed, if the confirmations option is > 0).

sendTokens() Examples

const {sendTokens} = require('send-tokens');
// Address of token contract.
const TOKEN_ADDRESS = '0x1658164265555FA310d20bC601Dd32e9b996A436';
// Recipient of tokens.
const RECIPIENT = '0x0420DC92A955e3e139b52142f32Bd54C6D46c023';

// Sending wallet's private key.
const PRIVATE_KEY = '0x52c251b9e04740157471a724e9a3210b83fac5834b29c89d5bd57661bd2a7057';
// Send 100 WHOLE tokens of tokens to someone using a private key and wait for
// it to be mined.
let receipt = await sendTokens(TOKEN_ADDRESS, RECIPIENT, '100',
  {key: PRIVATE_KEY});

// Sending wallet's mnemonic.
const MNEMONIC = 'butter crepes sugar flour eggs milk ...';
// Send 100.312 WHOLE tokens to someone using a (BIP39) mnemonic phrase
// and wait for it to be mined and confirmed 3 times.
receipt = await sendTokens(TOKEN_ADDRESS, RECIPIENT, '100.312',
  {mnemonic: MNEMONIC, confirmations: 3});

// Sending wallet's keystore file contents as a string.
const KEYSTORE = '{...}';
// Keystore password.
const PASSWORD = 'secret';
// Send 32 of the smallest unit of tokens to someone using a keystore file,
// print the transaction ID when it's available, and wait for it to be mined.
receipt = await sendTokens(TOKEN_ADDRESS, RECIPIENT, '32', {
    keystore: KEYSTORE,
    password: PASSWORD,
    decimals: 0,
    onTxId: console.log
  });

Full sendTokens() Options

const {sendTokens} = require('send-tokens');
// Send TOKEN_AMOUNT tokens to RECIPIENT via the token contract at
// TOKEN_ADDRESS.
{tx: Object} = async sendTokens(
  // Address of token contract.
  // Should be a hex string ('0x...')
  TOKEN_ADDRESS: String,
  // Address of recipient.
  // Should be a hex string ('0x...')
  RECIPIENT: String,
  // Amount of tokens to send. Units depend on `decimals` option.
  // Should be a base-10 decimal string (e.g., '1234.56').
  TOKEN_AMOUNT: String,
  // Options object
  {
    // Suppress output.
    quiet: Boolean,
    // If specified, append to a JSON log file at this path.
    log: String,
    // Call this function, passing the transaction hash/ID of the transaction
    // once it becomes available (transaction is posted to the blockchain but
    // not yet mined).
    onTxId: Function,
    // Decimal places of token amount.
    // E.g., 18 for 18 decimal places, 0 for smallest units.
    // Defaults to maximum decimal places supported by token contract.
    decimals: Number,
    // If connecting to a custom provider (e.g., a private node), this
    // can be the set to the address of an unlocked wallet on the provider
    // from which to send the tokens.
    account: String,
    // Hex-encoded 32-byte private key of sender (e.g., '0x1234...').
    key: String,
    // BIP39 mnemonic phrase of sender.
    mnemonic: String,
    // Sender's Mnemonic account index. Defaults to 0.
    mnemonicIndex: Number,
    // Sender's JSON-encoded keystore file contents.
    keystore: String,
    // Sender's keystore file path.
    keystoreFile: String,
    // Keystore password.
    password: String,
    // Ethereum network to use. May be 'main', 'ropsten', 'rinkeby', or 'kovan'.
    // Defaults to 'main',
    network: String,
    // Gas price for the transaction.
    // Should be a number in gweis.
    // Defaults to current network gas price.
    gasPrice: Number,
    // Number of confirmations to wait for after the transaction is mined.
    // Maximum of 12. Defaults to 0 (no confirmations).
    confirmations: Number,
    // Infura API key to use.
    infuraKey: String,
    // Custom provider. May either be a URI (e.g., http://localhost:8545) or
    // a Provider object from Web3.
    provider: String | Object,
    // Custom web3 object.
    web3: Object
  });

toWallet()

Another exposed library function is toWallet(), which returns an address & private key pair from a private key, mnemonic, or keystore. Below are the full options.

const {toWallet} = require('send-tokens');
// Convert a private key, mnemonic, or keystore to an address and private-key
// pair object. Both fields will be a hex-encoded string.
{address: String, key: String} = toWallet({
    // Hex-encoded 32-byte private key of sender (e.g., '0x1234...').
    key: String,
    // BIP39 mnemonic phrase.
    mnemonic: String,
    // Mnemonic account index. Defaults to 0.
    mnemonicIndex: Number,
    // JSON-encoded keystore file contents.
    keystore: String,
    // Keystore password (if `keystore` is passed).
    password: String
  });

send-tokens's People

Contributors

dependabot[bot] avatar dorothy-zbornak avatar mareoraft avatar merklejerk avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

send-tokens's Issues

How to use send-tokens from another nodejs script

Hello! I'm basically writing a GUI for send-tokens. Since my program is also in nodejs, I would like to use one of your internal functions directly instead of making a command line call.

I think I just need to call the run function, but I'm wondering if your code needs to be further abstracted out a bit so that this run function is more user-facing. Instead of taking in program and args, perhaps we can make a function that takes in a single plain-old object of user inputs.

I would be more than happy to attempt making the changes myself, but since you understand your code better than I do, it would be good if you were somehow involved. Thanks in advance, and let me know if you'd like to do it yourself or let me have a go at it!

question about repeat transactions

This is more of a question for your sage advice than a feature request or bug report.

In my GUI, we want each transaction (tx) specified by the user to be separate. If the user specifies multiple payments to the same address, this is a problem because the network will interpret the second tx as redundant or as a replacement order (ref: https://ethereum.stackexchange.com/questions/27256/error-replacement-transaction-underpriced) if it is executed before the first transaction is completed.

My proposed solution is to check if there is a pending tx with the same from and to address as the new tx before submitting the new tx. When ready to send a new tx, the following will occur:

  1. Wait X seconds (maybe X = 15?) before checking, in case the old tx was just sent and the network wasn't updated yet
  2. Check the network to see if there is a pending tx with the same from and to address
  3. If no pending tx, execute. Otherwise, set a timeout of Y seconds (maybe Y = 20) to wait and then go to step 2

So my main question for you is do you know of a good way to check the network for pending transactions? I see that you wrote the awesome flex-contract library, and I'm wondering if that functionality is there. Thanks in advance for pointing me in the right direction!

TypeError: inst._eth.resolveAddress is not a function

I'm submitting a ...
[*] bug report
[ ] feature request
[ ] question about the decisions made in the repository
[ ] question about how to use this project

Summary
In v2.1.1.
After confirming "yes", the following error occurs:

Proceed? [y/N]: y
TypeError: inst._eth.resolveAddress is not a function

non-hex keys

Would it be difficult to support keys that are not Hex-encoded 32-byte? I imagine some users will have such keys, and we could potentially make it more convenient for them if we can support those keys. In the meantime, I'll do a little research so I can understand the issue better.

can we change default unit to 1 token?

I would like to make a proposal for a "major" change, in the sense that it would require incrementing the major version number of the project. I've thought a lot about this, so please hear me out :)

default unit proposal

Given the contract (token) address, the default (user-facing) unit of currency in this repo is 10^(-18) tokens. I propose changing it to 1 token. (It is perfectly fine if a different unit is used internally)

why?

While it is common (and you probably know better than I do) to use 10^(-18) tokens as the unit in smart contracts, I think it is common to use 1 token as the unit for user-facing wallets. For example, if a user wants to send his friend some money in Bela, he usually thinks "I'm going to send John 15 Bela". Since this repo is user-facing and not meant as a building block for smart contracts, I think it will be easier for users if an amount of "4" and all other options default would send 4 tokens. The popular MEW which focuses on etherium and etherium tokens also follows the convention of using 1 token (when sending ERC20 tokens) or 1 ether (when working in etherium) as the default unit that amounts are expressed in. Also, as a "token" is the unit that was chosen to express ERC20 currency amounts in the first place, changing that unit introduces an extra layer of complication.

exponentiation naming scheme proposal

I propose changing the name of the "base" option to "exponent" and changing "b" to "e" and/or "E".

why?

Consider a situation of exponentiation such as 10^7. In mathematics, the word "base" refers to the number that it repeatedly multiplied by itself (in this case 10), while the word "power" or "exponent" refers to the number of times the base is multiplied by itself (in this case 7). Since we are expressing amounts in the form 3 * 10^7 (for example), the most reasonable choice for variable names referring to the "7" are "power", "exponent", and "order" ("order" being a shortening of "order of magnitude"). I think "exponent" is most appropriate because there is already a prevailing convention and international standard of expressing a number in the form 3e7 or 3E7 (for example). In that convention (https://en.wikipedia.org/wiki/Scientific_notation#E-notation), the "e" does in fact stand for "exponent".

default exponent value proposal

I propose changing the default exponent to 0.

why?

For the same reasons as in the default unit proposal, I believe a user entering "4" as the amount and accepting all defaults should sent 4 tokens. Since 4 = 4e0, this would necessitate a default exponent of 0.

'migration' proposal

I propose warning Tyler and anybody who starred this repo directly about the upcoming change and making this change sooner rather than later. I would also add a warning message in the send-tokens CLI itself to warn people about the change and force them to hit enter to continue the transaction. This warning can be temporary for a few months.

why?

My natural instinct is to worry that this change will cause people to accidentally send the wrong amount to others. However, there are some good reasons why this should not be a huge issue. Firstly, this repository is extremely young (only 1 month old). There is a good chance that you only have 1 or 2 users at this point. Better to bite the bullet now than later, when the repo becomes super popular! Secondly, a factor of 10^18 is so large that it works in our favor. Someone trying to send 1 Bela, for example, would now try to send 10^18 Bela. They don't have that many Bela in their wallet, so the transaction will be rejected. In order for the transaction to go through, they would have to be trying to send around 10^(-12) Bela or less in the first place. But no reasonable person would send such a small amount of Bela, since the transaction fee alone is thousands of times more than the amount they are sending. Thirdly, a warning message should successfully get the attention of users. Fourthly, temporarily requiring "enter" or some bypass_warning to be passed in will prevent scripts from automatically executing the command and thus bring the change to any programmer's attention.

Thank you kindly for hearing me out. I am happy to dicuss more. Have a great day.
Matt

Sending NFT Using MerkleJerk

hello,

If I want to use this to send an NFT how do I enter the specific token id I want to send ?

The examples show how to send 20 tokens but how do i send 1 token , token id 25 , to an address using the private key.

Cannot read property 'toLowerCase' of undefined

How to reproduce:

~/Desktop/temp % send-tokens 0x2e98a6804e4b6c832ed0ca876a943abd3400b224 0x1e512fc62f01b6becf955b673a72085ca0e2ec2c 1
Cannot read property 'toLowerCase' of undefined

I'm guessing the issue is that the private key is missing, and it's trying to make the private key lowercase. If the private key is undefined, the error message should read "No private key inputted. A private key is mandatory." or similar.

branch wrap

Use div contenteditable true to get widths to adjust automatically.

Have we tried just doing input display: inline instead???

We should TRY that.

We SHOULD DO THE SETTINGS DROPDOWN BEFORE DEALING WITH THIS.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.