An open API service indexing awesome lists of open source software.

https://github.com/renproject/send-crypto

A minimal JavaScript library / wallet for sending crypto assets
https://github.com/renproject/send-crypto

Last synced: 8 months ago
JSON representation

A minimal JavaScript library / wallet for sending crypto assets

Awesome Lists containing this project

README

          

send crypto


A minimal JavaScript library for sending crypto assets.

Currently doesn't support hierarchical or single-use addresses.

## Supported assets

- BTC

- LTC

- ZEC (transparent txs only)

- BCH

- FIL

- ETH

- ERC20 tokens



# Usage

```sh
npm install --save send-crypto
# or
yarn add send-crypto
```

Replace "BTC" with any supported asset:

```ts
const CryptoAccount = require("send-crypto");

/* Load account from private key */
const privateKey = process.env.PRIVATE_KEY || CryptoAccount.newPrivateKey();
const account = new CryptoAccount(privateKey);

/* Print address */
console.log(await account.address("BTC"));
// > "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa"

/* Print balance */
console.log(await account.getBalance("BTC"));
// > 0.01

/* Send 0.01 BTC */
const txHash = await account
.send("1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa", 0.01, "BTC")
.on("transactionHash", console.log)
// > "3387418aaddb4927209c5032f515aa442a6587d6e54677f08a03b8fa7789e688"
.on("confirmation", console.log);
// > 1
// > 2 ...
```

**UNITS**: `getBalance` and `send` can be replaced with `getBalanceInSats` and `sendSats` respectively to use the blockchain's smallest units (satoshis for BTC, wei for ETH, etc.).

**CONFIG**: Each of the functions `address`, `getBalance` and `send` accept an optional `options` parameter. See the available options in the sections "All balance and transaction options" for each asset below.



# Examples

## Setup



Load private key from a .env file

`.env`:

```sh
PRIVATE_KEY="1234512341"
```

Use the `dotenv` library (installed with `npm i -D dotenv`) or run `source .env` before running:

```ts
require("dotenv").config();
const CryptoAccount = require("send-crypto");
const account = new CryptoAccount(process.env.PRIVATE_KEY);
```




Create new account

```ts
const privateKey = CryptoAccount.newPrivateKey();
console.log(`Save your key somewhere: ${privateKey}`);
const account = new CryptoAccount(privateKey);
```


## BTC, ZEC, BCH



Send BTC (Bitcoin)

```ts
const CryptoAccount = require("send-crypto");
const account = new CryptoAccount(process.env.PRIVATE_KEY);

// Send BTC
await account.send("1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa", 0.01, "BTC");
```




Send ZEC (Zcash)

```ts
const CryptoAccount = require("send-crypto");
const account = new CryptoAccount(process.env.PRIVATE_KEY);

// Send ZEC
await account.send("t3Vz22vK5z2LcKEdg16Yv4FFneEL1zg9ojd", 0.01, "ZEC");
```




Send BCH (Bitcoin Cash)

CashAddr, BitPay and legacy addresses are supported.

```ts
const CryptoAccount = require("send-crypto");
const account = new CryptoAccount(process.env.PRIVATE_KEY);

// Send BCH
await account.send(
"bitcoincash:qp3wjpa3tjlj042z2wv7hahsldgwhwy0rq9sywjpyy",
0.01,
"BCH"
);
```


You can replace `"BTC"` with `"ZEC"` or `"BCH"` in the following examples:



Send entire balance

```ts
const balance = await account.getBalance("BTC");
await account.send("1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa", balance, "BTC", {
subtractFee: true,
});

// Or using sats as the unit
const balanceInSats = await account.getBalanceInSats("BTC");
await account.sendSats(
"1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa",
balanceInSats,
"BTC",
{ subtractFee: true }
);
```




Wait for 6 confirmations

```ts
await new Promise((resolve, reject) =>
account.send("1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa", 0.01, "BTC")
.on("confirmation", confirmations => { if (confirmations >= 6) { resolve(); } })
.catch(reject);
);
```




Send testnet funds

```ts
const testnetAccount = new CryptoAccount(process.env.PRIVATE_KEY, {
network: "testnet",
});
await testnetAccount.send("12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX", 0.01, "BTC");
```




All balance and transaction options

The `getBalance` and `getBalanceInSats` options are:

```ts
{
// Get the balance of an address other than the current account's
address?: string;

// The number of confirmations UTXOs must have to be included in the balance
confirmations?: number; // defaults to 0
}
```

The `send` and `sendSats` options are:

```ts
{
// The number of confirmations UTXOs must have to be included in the inputs
confirmations?: number; // defaults to 0

// The fee in satoshis/zatoshis to use
fee?: number; // defaults to 10000

// Whether the fee should be included or excluded from `value`
subtractFee?: boolean; // defaults to false
}
```


## ETH, ERC20



Send ETH (Ether, Ethereum)

```ts
const CryptoAccount = require("send-crypto");
const account = new CryptoAccount(process.env.PRIVATE_KEY);

// Send ETH
await account.send("0x05a56e2d52c817161883f50c441c3228cfe54d9f", 0.01, "ETH");
```




Send ERC20 tokens

You can transfer arbitrary ERC20 tokens by providing the token's address:

```ts
const CryptoAccount = require("send-crypto");
const account = new CryptoAccount(process.env.PRIVATE_KEY);

await account.send("0x05a56e2d52c817161883f50c441c3228cfe54d9f", 1.234, {
type: "ERC20",
address: "0x408e41876cccdc0f92210600ef50372656052a38",
});
```

A few well known ERC20 tokens can be referenced by name:

```ts
await account.send("0x05a56e2d52c817161883f50c441c3228cfe54d9f", 1.234, {
type: "ERC20",
name: "DAI",
});
```

See the [ERC20s.ts](./src/handlers/ERC20/ERC20s.ts) to see the tokens than can be referenced by name.




Send testnet funds (ropsten, kovan, etc.)

The supported testnets are `mainnet`, `ropsten`, `kovan`, `rinkeby` and `goerli`.

```ts
// Use "testnet" BTC, BCH & ZEC; use "ropsten" ETH.
const testnetAccount = new CryptoAccount(process.env.PRIVATE_KEY, {
network: "testnet",
});
const testnetAccount = new CryptoAccount(process.env.PRIVATE_KEY, {
network: "ropsten",
});
```

```ts
// Use "testnet" BTC, BCH & ZEC; use "kovan" ETH.
const testnetAccount = new CryptoAccount(process.env.PRIVATE_KEY, {
network: "kovan",
});
```




All balance and transaction options

The `getBalance` and `getBalanceInSats` options are:

```ts
{
// Get the balance of an address other than the current account's
address?: string;
}
```

The `send` and `sendSats` options are:

```ts
{
// Gas limit
gas?: number | string;

// Gas price in WEI
gasPrice?: number | string | BN;

// Include data with the transfer
data?: string;

// Override the transaction nonce
nonce?: number;

// [ETH] Whether the fee should be included or excluded from `value`
subtractFee?: boolean; // defaults to false

// [ERC20] Approve instead of transferring
approve?: boolean; // defaults to false
}
```








# Custom assets

If you want to send a cryptocurrency or token that isn't supported by the library, or enhance support for one of the assets above (e.g. add support for a new address format), you can write your own handler using the instructions below.



Adding custom assets

Handlers must implement the (TypeScript) interface below.

The `handlesAsset` function is called to ask if the handler can handle an asset.

All other functions are optional. If a function isn't provided, the next handler is called instead.

```ts
export abstract class Handler<
ConstructorOptions = {},
AddressOptions = {},
BalanceOptions extends { address?: string } = { address?: string },
TxOptions = {}
> {
// sharedState allows multiple handlers access common state.
constructor(
privateKey: string,
network: string,
constructorOptions?: ConstructorOptions,
sharedState?: any
) {
/* */
}

// Returns whether or not this can handle the asset
public handlesAsset!: (asset: Asset) => boolean;

// Returns the address of the account
public address?: (
asset: Asset,
options?: AddressOptions,
deferHandler?: DeferHandler
) => Promise;

// Returns the balance of the account
public getBalance?: (
asset: Asset,
options?: BalanceOptions,
deferHandler?: DeferHandler
) => Promise;
public getBalanceInSats?: (
asset: Asset,
options?: BalanceOptions,
deferHandler?: DeferHandler
) => Promise;

// Transfers the asset to the provided address
public send?: (
to: string,
value: BigNumber,
asset: Asset,
options?: TxOptions,
deferHandler?: DeferHandler
) => PromiEvent;
public sendSats?: (
to: string,
value: BigNumber,
asset: Asset,
options?: TxOptions,
deferHandler?: DeferHandler
) => PromiEvent;
}
```

And then register the handler:

```ts
const CryptoAccount = require("send-crypto");
const account = new CryptoAccount(process.env.PRIVATE_KEY);
account.registerHandler(MyCystomHandler);
```

`registerHandler` accepts an optional `priority` parameter for setting the order of handlers (see [`index.ts`](./src/index.ts) to see the default ordering).

You can wrap around other handlers by using the `defer` parameter passed in to each function. For example, to add support for ENS names for Ethereum, you can resolve the `to` address and then call `defer`:

```ts
class ENSResolver {
/* ... */

handlesAsset = (asset: Asset) => asset === "ETH";

resolveENSName = (to: string): Promise => {
/* ... */
};

send = async (
to: string,
value: BigNumber,
asset: Asset,
deferHandler: Handler
): PromiEvent => {
return deferHandler.send(await resolveENSName(to), value, asset);
};
}
```

See the following handlers as references:

- [BTC Handler](./src/handlers/BTC/BTCHandler.ts) (ZEC and BCH handlers are similar)
- [ETH Handler](./src/handlers/ETH/ETHHandler.ts)
- [ERC20 Handler](./src/handlers/ERC20/ERC20Handler.ts)