Skip to content

Instantly share code, notes, and snippets.

@Sjors
Last active September 8, 2022 03:15
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Sjors/b39f1e4135c05e8dfe2cf337608ec7a8 to your computer and use it in GitHub Desktop.
Save Sjors/b39f1e4135c05e8dfe2cf337608ec7a8 to your computer and use it in GitHub Desktop.
node_modules
*.pdf

footer: 2016-12-07 - Dutch Blockchain Hackathon - Technology Deep Dive - sjors@blockchain.com slidenumbers: true autoscale: false

right 350% filtered

  • Blockchain.info

  • Bitcoin blockchain1 info

  • Popular Bitcoin wallet

  • Offices in London & NYC

  • Sjors Provoost

  • Web Wallet Developer

  • Commutes between Utrecht and London

^ info: website + API


Wallet in Browser

95%, original

^ AngularJS UI

^ Pure Javascript core


Wallet in NodeJS

95%

^ Familiar with NodeJS?

Install

npm install blockchain/my-wallet-v3#v3.24.5

^ NPM = Node Package Manager

Load

^ In a file, or in a console (REPL)

Blockchain = require('blockchain-wallet-client')

^ Experimental


Create a wallet

email = 'sjors+delft@blockchain.com'
pwd = 'very_weak'

Blockchain.MyWallet.createNewWallet(
  email,
  pwd,
  '',
  'EUR',
  'en',
  console.log,  // Success
  console.error // Error
)
// 1822bb00-5c33-46a9-bbcb-b75de17fca66

^ Returns user identifier


Login

user_id = '1822bb00-5c33-46a9-bbcb-b75de17fca66'
pwd = 'very_weak'
Blockchain.MyWallet.login(
  user_id,
  pwd,
  { twoFactor: null, sessionToken: null }, {}
).then(MyWallet.wallet.fetchAccountInfo)

Get funding address

account = MyWallet.wallet.hdwallet.accounts[0]
account.receiveAddress
// '1ALfF8Ps8bkZT1qyf2TVa1Lu3P74wUfog2'

Show account balance

^ I funded this wallet manually

// Loads balance and recent transactions
MyWallet.wallet.getHistory()
account.balance
// 113702 (in Satoshi = €0,70)

About wallets

^ JSON file, stored on our server

^ Encrypted, with password

^ Most important: seed hex (from which all wallet private keys and addresses are derived)

^ BIP 39: seed -> set of words, as backup

{
  "user_id": "1822bb00-5c33-46a9-bbcb-b75de17fca66",
  "options": {
    "pbkdf2_iterations": 5000 // Password is hashed using PBKDF2
  },
  "seed_hex": "65b4cd78ba92d490466532a7939e5405",
  //           grant please funny inside coil else book play pole ostrich never arctic
  "address_labels": [{
    "index": 1, "label": "Zakgeld"
}
  • encrypted in browser, stored on server
  • we can't access your private keys, nor reset your password

Spend coins

p = new Blockchain.Payment()
p
  .to('1AvPkgjx2RKFW6xeqKVoKjsmJMZWrqs17w')
  .from(0)
  .amount(50000) // In Satoshi = €0.35
  .build()
  .sign()
  .publish()

^ From default (first) account


Import private key

^ E.g. from paper wallet

wallet = Blockchain.MyWallet.wallet
pk = 'L3qqTb8FD1wWhfZjjyJSiwQZyp3oLbycBNB9So45bj4uAYrP5YmS'
wallet.importLegacyAddress(pk, '')
addr = wallet.keys[0].address;
// 1AvPkgjx2RKFW6xeqKVoKjsmJMZWrqs17w

Show balance:

addr.getBalance()
// 50000 // In Satoshi = €0.35

Monitor address

^ Waiting for a payment

^ Construct command, send

^ Don't call us, we call you

op = MyWallet.ws.msgAddrSub(account.receiveAddress)
// '{"op":"addr_sub","addr":"1ALfF8Ps8bkZT1qyf2TVa1Lu3P74wUfog2"}'
MyWallet.ws.send(op)

WebSockets

  • "a computer communications protocol, providing full-duplex communication channels over a single TCP connection." - Wikipedia

{
	"op": "utx",
	"x": {
    "hash": "f22525fd3fdbac441267b4f68f13fb8f1cabd6d0967a48844647b91e3f9ef8ea",
		"inputs": [{
			"prev_out": {
			    "spent": true,
				"addr": "1Ea4SXJbd2z7NszrS23i5rAd4v7LjuuJCE", // Sender wallet
				"value": 3040127, // 0.003 BTC
			},
		}],
		"out": [{
			"spent": false,
			"addr": "1ALfF8Ps8bkZT1qyf2TVa1Lu3P74wUfog2", // Our wallet
		}, {
		   ... // Change
		}]

Process websocket message

MyWallet.getSocketOnMessage = (msg) => {
  obj = JSON.parse(msg)
  if (obj.op === 'utx') {
    if (obj.x.out.filter(
      (output) => output.addr === account.receiveAddress
    ).length) {
      console.log('Coins received!')
    }
  }    
}

Buy Bitcoin with NodeJS

  • Partner company handles the purchase
coinify = MyWallet.wallet.external.addCoinify()
coinify.signup('NL','EUR').then(console.log)
// user: ....,
// offlineToken: 'AkwyQ...'
  • Partner account details stored in wallet
  • Bitcoin goes straight to your wallet

^ Wallet communicates with partner API

^ JSON web token: proof that we verified your email


  • Ask quote and buy:
coinify.getBuyQuote(10 * 100, 'EUR', 'BTC').then((quote) => {
  console.log(quote.quoteAmount / 100000000, "BTC")
  quote.buy('card').then((trade) =>
    console.log(trade.address)
    // Do some manual stuff with your creditcard
  )
})
  • Monitor purchase address (web socket):
coinify.monitorPayments()
coinify.trades[0].watchAddress().then(() => console.log('Bitcoin Received!'))

Sign a message

  • Prove that you have the private key for an address:
addr = MyWallet.wallet.keys[0].address;
// 1AvPkgjx2RKFW6xeqKVoKjsmJMZWrqs17w
msg = 'Hallo Delft'
sig = MyWallet.wallet.keys[0].signMessage(msg)
// 'H2yfcyYDoSj+siL4rvMmnHIvKUDH4GThFHYGlQk28q79AhreibtQvmaH+5W6hRty+S1gQeFXbaKs04xjIsHRCOE='
  • Verify the proof:
Blockchain.Helpers.verifyMessage('1AvPkgjx2RKFW6xeqKVoKjsmJMZWrqs17w', sig, msg )
// true

Thank You

270%

Resources

Footnotes

  1. The Bitcoin blockchain still has the most hash power behind it.

{
"name": "delft-demo",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Sjors Provoost <sjors@blockchain.info>",
"license": "ISC",
"dependencies": {
"blockchain-wallet-client": "github:blockchain/my-wallet-v3#v3.22.24",
"xmlhttprequest": "^1.8.0"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment