First demo of Mainnet Bitcoin Cash library
So, we finally have a first demo of Mainnet Bitcoin Cash library.
It has been 2 months since the original FlipStarter has been funded. It took so long, because we have hit so many dead-ends while developing it (Kudos to 2qx for so much work done!) and had to change the interfaces too many times, because something was inconsistent.
Note that this is an early prototype, so things will be changing under you if you try to use it now.
Seriously, we don't recommend that you use it right now. It's unstable and some APIs will definitely change (as noted below). Use at your own risk.
Demo of JavaScript library
Finally! The demo is here:
https://jsfiddle.net/ghn19jmu/2/
It shows:
How to create a TestNet wallet
Wait for a transaction
Send a specific amount
Send the full amount
Get balances in BCH, satoshis and USD
Get transaction IDs for recent sends
Note: it donates any money left to Chris Troutner's Bitcoin Cash TestNet faucet (please don't drain it!).
You can use Chris' TestNet faucet with the demo (once per 24 hours), because it'll send all your TestNet satoshis back to the faucet.
Video of the demo
Or you can watch it as a video:
Sending is slower than usual, because of use of clusters, see below. You can adjust it to be fast, but less reliable.
These 1,273 BCH you see in the video are TestNet coins, they aren't worth anything. So, stop stalking me :)
A few highlights from the JavaScript API:
<script src="https://mainnet.cash/dist/mainnet-0.0.1-rc.js"></script>
If you want to yell at me for using <script src
and its security, then you already know what to do - host the .js file yourself :)
In the meantime, the npm package is coming.
We use a lot of async functions, so wrap it in async function if you want to use it in plain browser:
async function run() {
// your code goes here
}
run().catch(e => console.log(e));
Create a new wallet:
const wallet = await TestNetWallet.newRandom(); // new Testnet wallet
// ... or
const wallet = await Wallet.newRandom(); // production/mainnet wallet
const wallet = await RegTestWallet.newRandom(); // for local Bitcoin Cash node
Under the hood we use the awesome electrum cash library by Jonathan Silverblood, so by default you are protected by the cluster agreement available in the library.
This means that you are always connected to multiple redundant servers (Fulcrums!) at any time and they must agree on what's happening before you'll see any data. (Or you can change it and connect to a single instance only for high-speed) Kudos, Jonathan!
We also use Rosco Kalis' CashScript's Network Provider, so actually you could use electrum cash library, BitboxNetworkProvider, Chris Troutner's FullStackNetworkProvider or even write your own Custom NetworkProviders. (Yes, CashScript is coming to mainnet!) Kudos, Rosco!
Oh, yeah, and by default we connect to Fulcrums (by Calin Cullinau), which are these awesome high-performance servers, so even if you have tons of UTXOs, you'll get your response fast! Kudos, Calin!
We also use Jason Dreyzehner's libauth, which is awesome to build Bitcoin Cash transactions. Kudos, Jason!
Huge kudos to 2qx who managed to tie it all together. Kudos!
So, to re-iterate the goodies:
OpenAPI code generators (see below....)
Feel the power yet?
How to use it
What's the address?
wallet.getDepositAddress()
What's the private key?
wallet.privateKeyWif
How much money do we have there?
await wallet.getBalance('bch') // in Bitcoin Cash
await wallet.getBalance('sat') // in satoshis
await wallet.getBalance('usd') // in USD (doesn't really make sense on TestNet)
Now, you can create a second wallet the same way and send some money to it:
const result = await wallet.send([
[wallet2.getDepositAddress(), 500, 'satoshis'],
]);
The change is automatically calculated and sent back to your wallet (fees are set at 1sat/b).
Yes, you can send to multiple addresses at once. The result object not only has the transaction ID, but also the new balances:
result.txId
result.balance.bch
result.balance.sat
result.balance.usd
Wait for $0.05 (better way coming soon):
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
while((await wallet.getBalance('usd')) < 0.05) {
await sleep(0.1);
}
...or you can simply hammer the servers :) Though, it's not nice.
while((await wallet.getBalance('usd') < 0.05) {}
Send the full amount (except the fee of about ~$0.0015):
await wallet.sendMax('bchtest:qzt6sz836wdwscld0pgq2prcpck2pssmwge9q87pe9');
How much can we send?
await wallet.getMaxAmountToSend()
Frankly, this is more than enough to build something like read.cash with in-browser wallets :)
Ok, let's move on to the REST server.
REST server
Here be more dragons!
The REST server is available at https://rest-unstable.mainnet.cash/
Did you notice the "unstable" part? Hope that tells you something :)
Note that by default, you are sending your private key to the server.
To use it securely, you need to be running your own server! (It's not that hard, see below)
The API pretty useful and self-documenting (ok, the send
method docs are missing for now, sorry, we'll fix it, there's walletId
and to
, which is an array of objects that have cashaddr
, amount
and unit
= sat
, bch
or usd
), you can do everything you can do with the JavaScript library, but via REST:
Create a TestNet/Mainnet/Regtest wallet
Send a specific amount
Send the full amount
Get balances in BCH, satoshis and USD
Get transaction IDs for your sends
...also some other things like getting QR codes for addresses as images.
How to run your own server
docker run -d --env WORKERS=5 -p 127.0.0.1:3000:80 mainnet/mainnet-rest
or
git clone https://github.com/mainnet-cash/mainnet-js.git
cd mainnet-js
npm i
npm run api:build:server
npm run build
(cd generated/serve && npm i)
PORT=3000 WORKERS=5 npm run api:serve:cluster
Warning. Each worker takes about 70-100MB memory, which seems to be the norm for express.js servers :(
Oh and in case you are wondering, the better documentation and video tutorials are coming. Just a bit later.
Other languages
Did I mention dragons yet?
So, to generate bindings for the REST server, you need to generate them. Oh, you better believe the dragons are there.
Here's an example to generate PHP bindings:
npm run api:build:client php
Replace php
above in two places with any language:
android, c
cpp-qt5-client, cpp-restsdk, cpp-tizen, cpp-ue4
csharp, csharp-netcore
dart
elixir
go
haskell-http-client
java
javascript
kotlin
objc
php
python
r
ruby
rust
typescript
typescript-node
The bindings are a bit awkward, But they should work. More information will come soon.
Here's an example in PHP:
$walletId = 'wif:mainnet:2SamS....';
$walletApi = new WalletApi();
$balance = $walletApi->balance(['wallet_id' => $walletId]);
print($balance->usd);
This calls the /wallet/balance
endpoint as described here.
$config = new Configuration();
//$config->setHost('https://rest-unstable.mainnet.cash/v1');
$config->setHost('http://localhost:3000/v1');
$client = new WalletApi(null, $config);
// new wallet
$wallet = $client->createWallet(['network' => 'testnet']);
$walletId = $wallet->getWalletId();
// deposit address
$client->depositAddress(['walletId' => $walletId]);
// balance
$balance = $client->balance(['walletId' => $walletId]);
print($balance->getUsd());
// send
$result = $client->send([
'walletId' => $walletId,
'to' => [
[
'cashaddr' => 'bitcoincash:qp...',
'value' => 100,
'unit' => 'usd',
// this call might change to ['bitcoincash:qp...', '100', 'usd']
],
]
]);
(Code examples are for example only, I haven't tested them properly yet)
We hope that later people will write better wrappers in their languages, that will give people better use.
Money
Money spent from the original FlipStarter: ~15%
As I said, you can't hire the cheapest developers to do this stuff, and I underestimated badly how much time it will take. I really hope that we can get a lot of the original promise done, but I'm not as optimistic as I was when I started the FlipStarter, we're probably done with ~2% of the stuff, having spent about 15%. Not great. So much work ahead.
But frankly, I still see it as a great success. Even if it was just like this, it's VERY useful and can help a lot of people.
Next steps: polish the basics, fix minor bugs, stabilize it, write better docs... and hopefully then, next stop is WebHooks and escrow contracts (incl. CashScript).
As far as I have seen - this is the easiest way to interact with Bitcoin Cash blockchain. And probably the only one that is working with TestNet and RegTest (locally deployed Bitcoin Cash Node (yes, BCHN), so that you can run automated tests using all the same libraries, without worrying about getting TestNet coins or managing them).
Really appreciate the update and continued transparency. Only some flipstarter campaigns have followed up like this.
And this looks great!