Introduction
const { Token, Db, Wallet, Source } = require('bitcointoken')
The BitcoinToken library is a collection of tools that make it easy to integrate Bitcoin into web applications.
- BitcoinSource a readable JS implementation of Bitcoin
- BitcoinWallet send, store, and receive Bitcoin
- BitcoinDb store data on the blockchain
- BitcoinToken issue tokens
We will be supporting Bitcoin Cash and Bitcoin SV at launch.
Install and run
You need node.js and npm installed.
Install
Install BitcoinToken
npm i bitcointoken
Run npm init -yes
and
npm install bitcointoken
If you only want to use BitcoinWallet you are done. If you want to use BitcoinDb or BitcoinToken you need to install and run a non-standard server in a second terminal window.
Install and run the non-standard server
Install and run the non-standard server
git clone https://github.com/BitcoinDB/bitcoin-non-standard-server.git
cd bitcoin-non-standard-server
docker-compose up
We recommend to use Docker and Docker Compose to build and run the server using the commands on the right. If you do not use docker you can find instructions in the Github repo.
Run in Node
File index.js
const { Wallet } = require('bitcointoken')
const wallet = new Wallet()
console.log(`address: ${wallet.getAddress()}`)
After installing BitcoinToken, create a file index.js
with the content shown on the right. Run the code using
node index.js
The output should be similar to
address: mwZd1bgRYhxY4JLyx1sdEGBYFZnXVDvgmp
Run in the browser
File index.js
const Bitcoin = require('bitcointoken')
const wallet = new Bitcoin.Wallet()
document.body.innerHTML = `address: ${wallet.getAddress()}`
File index.html
<html>
<body>
<script src="./bundle.js"></script>
</body>
</html>
After installing BitcoinToken, create files index.js
and index.html
as shown.
Install and run browserify
npm install -g browserify
browserify index.js > bundle.js
Open index.html
in a web browser
Troubleshooting
If you have a problem that is not discussed here, please let us know in the Telegram group.
"Communication error: Service unavailable"
The problem is most likely that you are not running the non-standard server.
"Error: Insufficient balance in address ..."
File generate-mnemonic.js
const { Wallet } = require('bitcointoken')
console.log(Wallet.getRandomMnemonic())
You have to fund your wallet. First check that the same wallet is generated every time you run your code: Run it multiple times and check if the same address is logged every time.
If so you can fund that address using a testnet faucet.
Otherwise you need to initialize your object from a mnemonic. To generate a mnemonic, create the file generate-mnemonic.js
and run it using node --experimental-repl-await generate-mnemonic.js
. Now you can generate your object using the logged mnemonic using Wallet.fromMnemonic()
and fund it using the testnet faucet
BitcoinWallet
BitcoinWallet
allows you to receive, store, and send Bitcoin Cash.
const { Wallet } = require('bitcointoken')
A BitcoinWallet stores a secrete passphrase called menmonic. The mnemonic represents an identity, for example every user in an application would have their own mnemonic. The mnemonic can be used to send Bitcoin to another user, or to generate public addresses that can receive Bitcoin.
constructor
Generate a random BitcoinWallet
const randomWallet = new Wallet()
Generates a new BitcoinWallet
with a random mnemonic.
getRandomMnemonic
Generate a mnemonic
const mnemonic = Wallet.getRandomMnemonic()
// mnemonic === 'rail install size scorpion orchard kingdom vacuum collect pencil element fall enhance media island medal'
Generates a new mnemonic from a secure random source.
Type
static getRandomMnemonic(): string
fromMnemonic
Generate a BitcoinWallet from a mnemonic
const mnemonic = Wallet.getRandomMnemonic()
const wallet = Wallet.fromMnemonic(mnemonic)
Generates BitcoinWallet
from a mnemonic.
Type
static fromMnemonic(mnemonic: string): BitcoinWallet
getMnemonic
Return the mnemonic
const wallet = Wallet.fromMnemonic('rail install size scorpion orchard kingdom vacuum collect pencil element fall enhance media island medal')
const mnemonic = wallet.getMnemonic()
// menominc === 'rail install size scorpion orchard kingdom vacuum collect pencil element fall enhance media island medal'
Returns the mnemonic of the wallet
Type
getMnemonic(): string
getPrivateKey
Return the private key
const privateKey = wallet.getPrivateKey()
Every BitcoinWallet is associated with a Bitcoin account consisting of a private-public keypair and an address. These can be accessed using getPrivateKey
, getPublicKey
and getAddress
.
getPrivateKey
return the private key stored in the wallet.
Type
getPrivateKey(): string
getPublicKey
Return the public key
const publicKey = wallet.getPublicKey()
Returns the public key.
Type
getPublicKey(): string
getAddress
Return the address
const address = wallet.getAddress()
const CashAddress = wallet.getAddress('cashaddr')
Returns the address in legacy
format. To return the address in a different format pass in legacy
, bitpay
, or cashaddr
as a parameter.
Type
type Format = 'legacy' | 'bitpay' | 'cashaddr'
getAddress(format?: Format = 'legacy'): string
getBalance
Return the current balance
const satoshi = await wallet.getBalance()
const bitcoin = satoshi / 1e8
Returns the current balance in satoshi. Divide by 1e8
to compute the balance in Bitcoin.
Type
async getBalance(): number
send
Send Bitcoin
const address = randomWallet.getAddress()
const outputId = await wallet.send(15000, address)
// outputId === {
// txId: '3404832a17d996dffaa9ac1aea48a2fafc9d855e5fdca5100481d8a562523dfb',
// outputNumber: 0
// }
Sends bitcoin. The first parameter is the amount to send in satoshi, the second is the recipients address, and the third (optional) paramater is the change address. If no change address is provided, the address of the wallet is used.
Type
type OutputId = {|
txId: string,
outputNumber: number
}
async send(
amount: number,
address: string,
changeAddress: ?string
): Promise<OutputId>
transaction
Send Bitcoin to multiple recipients
const address = randomWallet.getAddress()
const data1 = { amount: 2000, address: 'mvQPGnzRT6gMWASZBMg7NcT3vmvsSKSQtf' }
const data2 = { amount: 5000, address: 'n1xqzrckuoohZPj3XoMn1mRgJZ3nkCLSq3' }
const outputIds = await wallet.transaction([data1, data2])
// outputIds === [{
// txId: '3404832a17d996dffaa9ac1aea48a2fafc9d855e5fdca5100481d8a562523dfb',
// outputNumber: 0
// }, {
// txId: '3404832a17d996dffaa9ac1aea48a2fafc9d855e5fdca5100481d8a562523dfb',
// outputNumber: 1
// }]
Use transaction
to pay multiple parties at once.
Type
type OutputId = {|
txId: string,
outputNumber: number
}
type PkhData = {|
amount: number,
address: string
|}
async transaction(
outputs: Array<PkhData>,
changeAddress?: string
): Promise<Array<OutputId>>
derive
Derive a child wallet
const derivedWallet = wallet.derive(4)
A BitcoinWallet can deterministically derive 232 child wallets. To derive a child wallet call derive
with a number ≤ 232. The second optional parameter determines if the wallet if hardened or not. Read more about hardened wallets in BIP32.
Derive wallet with path
m/44'/0'/0'
const wallet = wallet.derive('m', false).derive(44, true).derive(0, true).derive(0, true)
There exists a standard for how to use derivation paths to generate interoperable wallets (BIP44). Two popular derivation paths are
m/44'/0'/0'
used eg by Yours.org, Bitcoin.com, or Coinbase.comm/44'/145'/0'
used eg by Bitpay.
Type
derive(
index: ?number = 0,
hardened: ?boolean = false
): BitcoinWallet
getPath
Return the current derivation path
const wallet = wallet.derive('m', false).derive(44, true).derive(0, true).derive(0, true)
const path = wallet.getPath()
// path === `m/44'/0'/0'`
Returns the current derivation path.
Type
getPath(): string
BitcoinDb
BitcoinDb
can read, store, and update data on the Bitcoin Cash blockchain.
const { Db } = require('bitcointoken')
Bitcoin exposes two ways to store data: in op_return outputs and in output scripts via p2sh. Both are supported by BitcoinToken.
To store flat files that do not need to be updated we recommended you use
db.putReturn
to store data in an op_return output.If your application requires data types, updates, or transactions it is recommended to store data in p2sh outputs via
db.put
. The trade off is that your data will only be stored on the blockchain once you update the data, before that only a hash of the data is stored in the blockchain.
constructor
Create random BitcoinDb
const randomDb = new Db()
A BicoinDb
object stores a BitcoinWallet
object to pay for storage space on the blockchain. To generate a BitcoinDb
object from a new randomly generated BitcoinWallet
object call the constructor without a parameter.
Create BitcoinDb from a BitcoinWallet
const wallet = new Wallet()
const db = new Db(wallet)
You can also create a new BitcoinWallet
object from an existing BitcoinWallet
object by passing it into the constructor.
fromMnemonic
Generate a BitcoinDb from a mnemonic
const mnemonic = Wallet.getRandomMnemonic()
const db = Db.fromMnemonic(mnemonic)
Generates BitcoinDb
object and initialize the embedded BitcoinWallet
using the mnemonic.
Type
static fromMnemonic(mnemonic: string): BitcoinWallet
getWallet
Return the wallet stored in the db
const wallet = db.getWallet()
// wallet.constructor.name === 'BitcoinWallet`
Returns the BitcoinWallet
stored in a BitcoinDb
object.
Type
getWallet(): BitcoinWallet
putReturn
Store a string on the blockchain
const data = 'some string'
const outputId = await db.putReturn(data)
// outputId === {
// txId: '3404832a17d996dffaa9ac1aea48a2fafc9d855e5fdca5100481d8a562523dfb',
// outputNumber: 0
// }
Stores a string in an op_return output of a Bitcoin transaction. The string can have up to 110 characters.
Type
async putReturn(data: string): OutputId
put
Store structured data
const outputId = await db.put({
text: 'Lorem ipsum',
author: 'Alice'
})
// outputId === {
// txId: '3404832a17d996dffaa9ac1aea48a2fafc9d855e5fdca5100481d8a562523dfb',
// outputNumber: 0
// }
Stores json on the Bitcoin Cash blockchain.
The data is stored in a Bitcoin output script. Data stored in this way can be updated the same way that coin ownership is updated in Bitcoin: by spending the outputs containing the old data into outputs containing the new data.
Script encoding the above json
// 1-of-1 multisig script
OP_1
33 0x03a70e0e5f7c300d9685195bbac132873cb5b68e9787aa7d63549cd0de5e4ace10
OP_1
OP_CHECKMULTISIG
// section encoding the data
4 0x74657874 OP_DROP // text
11 0x4c6f72656d20697073756d OP_DROP // Lorem ipsum
6 0x617574686f72 OP_DROP // author
13 0x416c69636520616e6420426f62 OP_DROP // Alice and Bob
The json data get's encoded into the script on the right. It consists of a 1-of-1 multisig script and a section that encodes the data. The data is stored by pushing a value onto the stack and popping it off immediately thereafter (OP_DROP).
Data stored in this way comes with a very strong guaranty: only the person in possession of the private key for 0x03a70e0e5f7...
can spend the output containing the data. We call that user the owner of the data. By default the user to issue the command is the owner, to designate a different owner, pass in that users public key as the second argument. Multiple public keys can be passed in to model co-ownership of data.
Store structured data and it's owner
const publicKey = randomWallet.getPublicKey()
const outputId = await db.put({ key: 'string value'}, [publicKey])
The third argument is an amount of satoshi that will be stored in the output containing the data.
Store a structured data, it's owner, and an amount
const publicKey = randomWallet.getPublicKey()
const outputId = await db.put({ key: 'string value'}, [publicKey], 1 * 1e8)
Type
type OutputId = {|
txId: string,
outputNumber: number
|}
async put(
data: Object,
owners?: Array<string>,
amount?: number = MIN_NON_DUST_AMOUNT
): Promise<OutputId>
get
Retrieve data from the blockchain
const id = BitcoinDb.put({ value: 'a' })
const res = BitcoinDb.get(id)
// res === {
// data: { value: 'a' },
// owners: [ '03223d34686d6f19d20519156a030f7216e5d5bd6daa9442572bbaa446d06c8dfe' ],
// amount: 2750
// }
Retrieves a json object from the Bitcoin Cash blockchain given an OutputId
object that specifies a location on the blockchain.
The return value is an object with three keys: data
contains the data stored at the OutputId
, owners
contains the owners string encoded public keys, and amount
is the number of satoshis stored in the output.
Type
type OutputId = {|
txId: string,
outputNumber: number
|}
type OutputData = {|
data: string,
owners: Array<string>,
amount: number
|}
async get(
outputId: OutputId
): Promise<OutputData>
update
Update a piece of data
const db = new BitcoinDb()
const outputId1 = await db.put({ value: 'a' })
const outputId2 = await db.update(outputId1, { value: 'b'})
// outputId2 === {
// txId: '3404832a17d996dffaa9ac1aea48a2fafc9d855e5fdca5100481d8a562523dfb',
// outputNumber: 0
// }
Updates an object stored on the blockchain and returns the location of the new data. The first parameter is the OutputId
of the output containing the data that is to be updated, the second parameter is the new data. There are two optional parameters "owners" and "amount" that act just like the optional parameters of db.put
.
Only the owner can update data
const db1 = new BitcoinDb()
const db2 = new BitcoinDb()
const outputId1 = await db1.put({ value: 'a' })
// works bc data at outputId1 is owned by db1
const outputId2 = await db1.update(outputId1, { value: 'b'}, [db2.getWallet().getPublicKey()])
// throws an error bc the data at outputId2 is owned by db2
const outputId3 = await db1.update(outputId2, { value: 'c'})
BitcoinDb enforces two properties with respect to updates:
Only the owner of a piece of data can update it,
db.update()
with throw an error if a user that does not own the data is trying to update it.Data can only be updated once, an attempt to update the same data twice will throw an error
Data can only be updated once
const db = new BitcoinDb()
const outputId1 = await db.put({ value: 'a' })
// works
const outputId2 = await db.update(outputId1, { value: 'b'})
// throws an error bc the data at outputId1 has been updated
const outputId3 = await db.update(outputId1, { value: 'c'})
Type
type OutputId = {|
txId: string,
outputNumber: number
|}
async update(
outputId: OutputId,
data: object,
owners?: Array<string>,
amount?: number = MIN_NON_DUST_AMOUNT
): Promise<OutputId>
transaction
Update multiple pieces of data simultaneously
const db = new BitcoinDb()
const outputId1 = await db.put({ value: 'a' })
const outputId2 = await db.put({ value: 'b' })
const [outputId3, outputId4] = await db.transaction([
{
outputId: outputId1,
value: 'aa'
}, {
outputId: outputId2,
value: 'bb',
owners: [<publicKey>]
}
])
You can group multiple updates into a single transaction by calling db.transaction
. A BitcoinDb transaction satisfies the ACID properties of traditional database systems.
Type
type OutputId = {|
txId: string,
outputNumber: number
|}
type Update = {|
outputId: OutputId,
data: Object,
owners: Array<string>,
amount?: number
|}
async transaction(
update: Array<Update>
): Promise<Array<OutputId>> {
BitcoinToken
BitcoinToken
can issue, send, and store tokens on the Bitcoin Cash blockchain.
const { Token } = require('bitcointoken')
It uses BitcoinDb
to build and broadcast transactions that encode meta information about token issuances and transfers.
constructor
Create random BitcoinToken
const { Token } = require('bitcointoken')
const randomToken = new Token()
A BitcoinToken
object contains a BitcoinDb
object to store data on the blockchain. Recall that each BitcoinDb
object stores a mnemonic that serves as it's identity. To generate a BitcoinToken
object from a new randomly generated BitcoinWallet
object call the constructor without a parameter.
Create BitcoinToken from a BitcoinDb
const { Token, Db } = require('bitcointoken')
const db = new Db()
const token = new Token(db)
You can also create a new BitcoinToken
object from an existing BitcoinDb
object by passing it into the constructor.
fromMnemonic
Generate a BitcoinToken from a mnemonic
const mnemonic = Wallet.getRandomMnemonic()
const token = Token.fromMnemonic(mnemonic)
Generates BitcoinToken
object and initialize the embedded BitcoinWallet
using the mnemonic.
Type
static fromMnemonic(mnemonic: string): BitcoinToken
getWallet
Return the wallet
const wallet = token.getWallet()
// wallet.constructor.name === 'Wallet`
Returns the wallet stored in the db contained in the BitcoinToken
object.
Type
getWallet(): BitcoinWallet
getDb
Return the db
const db = token.getDb()
// db.constructor.name === 'Db`
Returns the BitcoinDb
stored in the BitcoinToken
object.
Type
getDb(): BitcoinDb
create
Issue a token
const tokenId = await token.create({
balance: '10',
name: 'my-token',
url: 'www.mytoken.com',
})
Issues a new fungible token, similar to ERC20 tokens on Ethereum. The parameter must be an object that can be passes into BitcoinDb.put
, that is a json object with string keys and string values. It must have one key balance
whose value indicates the initial number of tokens.
The create command calls db.put
to store the token meta data in the blockchain. The return value is the id of the output that stores the data.
Type
async create(data: Object): Promise<OutputId>
join
Connect to an issued token
const tokenAlice = new Token()
const tokenBob = new Token()
const tokenId = await tokenAlice.create({ balance: '10' })
tokenBob.join(tokenId)
Connects a BitcoinToken
object a token that has been issued using token.create
. The balance will be calculated with respect to the token being joined.
Type
join(tokenId: OutputId): void
send
Send a token
const tokenAlice = new Token()
const tokenId = await tokenAlice.create({ balance: '10' })
const tokenBob = new Token()
tokenBob.join(tokenId)
const publicKeyBob = tokenBob.getWallet().getPublicKey()
const outputIds = const tokenAlice.send(1, publicKeyBob)
// outputIds === [{
// txId: '3404832a17d996dffaa9ac1aea48a2fafc9d855e5fdca5100481d8a562523dfb',
// outputNumber: 0
// }]
Sends tokens to another user. The first parameter is the number of tokens to send and the second is the public key of the recipient. Sending a token might involve a change output, just like the change output used when sending Bitcoin. The function returns a promise that resolves to an array of OutputIds that containing the newly created outputs that reflect the new state.
token.send
calls db.transaction
to broadcast a transaction that stores meta data about associated with the token transfer.
Type
type OutputId = {|
txId: string,
outputNumber: number
|}
async send(
amount: number,
publicKey: string
): Promise<Array<OutputId>>
getBalance
Return the balance in tokens
const token = new BitcoinToken()
const tokenId = await token.create({
balance: 10
})
const balance1 = await token.getBalance()
// balance1 === 10
const randomPublicKey = new BitcoinWallet().getPublicKey()
await token.send(1, randomPublicKey)
const balance2 = await token.getBalance()
// balance2 === 9
Returns the number of tokens owned by the current BitcoinToken
object. The balance will be computed with respect to the token that was created by the object, or with respect to the token that was joined. token.getBalance()
will throw an error if the token
object has not created or joined a token.
Type
async getBalance(): Promise<number>
BitcoinSource
BitcoinSource
is a readable Bitcoin implementation in modern Javascript.
const { Source } = require('bitcointoken')
It is a fork of Bitcore and shares it's api. You can find the source code here