Skip to content

Instantly share code, notes, and snippets.

@ivanminutillo
Created October 11, 2017 15:25
Show Gist options
  • Save ivanminutillo/84b7751447e4d542bd85002fd14fe6fe to your computer and use it in GitHub Desktop.
Save ivanminutillo/84b7751447e4d542bd85002fd14fe6fe to your computer and use it in GitHub Desktop.
import bip32utils from 'bip32-utils'
import bitcoin from 'bitcoinjs-lib'
import {hexEncode} from './utils'
// flow interfaces
import {HDWallet, HDNode, Tx} from '../types/wallet'
let NETWORKS = bitcoin.networks
let NETWORKS_FAIRCOIN = {
faircoin: {
messagePrefix: '\x18Faircoin Signed Message:\n',
bip32: {
public: 0x03273e4b,
private: 0x03273a10
},
pubKeyHash: 0x5f,
scriptHash: 0x24,
dustThreshold:546,
wif: 0xdf
},
faircoinTestnet: {
messagePrefix: '\x18Faircoin Signed Message:\n',
bip32: {
public: 0x03273e4b,
private: 0x03273a10
},
pubKeyHash: 0x6f,
scriptHash: 0xc4,
dustThreshold:546,
wif: 0xdf
}
}
/**
* Create a new Wallet from an existent xpub
* @param xpub : a valid xpub
* @return a new HDWallet
**/
export let createWalletFromXpub = (xpub:string, networks:string) : HDWallet => {
networks = networks || NETWORKS_FAIRCOIN.faircoin
let node = bitcoin.HDNode.fromBase58(xpub, NETWORKS_FAIRCOIN.faircoin)
console.log(node)
// let wallet = createWalletFromNode(node)
return node
}
/**
* Function to create a transaction
* @param utxos: the list of utxos to insert in the transaction
* @param machine: the machine address
* @param user: the user address
* @param profileOpReturn: the profile status of the user
* @param wantedFee: the amount of satoshis tokens to give to miners
* @param tokenAmount: the amount of satoshis tokens to send to machine
* @param node
* @return new unfirmed transaction
*/
export let createTransaction = (machine:string, user:string, change:string, orchestrator:string, profileOpReturn:number, utxos:Array<Object>, tokenAmount:number, wantedFee:number) : Tx => {
tokenAmount = tokenAmount || 150000
let tokenFixed = 150000
var network = NETWORKS_FAIRCOIN.faircoin
wantedFee = wantedFee || 1500
// Return the total amount of satoshis to spend in the input
let actualInputValue = utxos.reduce(function (a: number, x:Object) : number {
return a + x.satoshis
}, 0)
if (actualInputValue < Number(tokenAmount) + Number(wantedFee)) throw new Error('Not enough funds: ' + actualInputValue + ' < ' + tokenAmount + wantedFee)
// Calculate the tokens to give back to change address
let remainder
if (orchestrator.length > 0) {
remainder = actualInputValue - tokenAmount - tokenFixed - wantedFee
console.log(remainder)
}
if (orchestrator.length === 0) {
remainder = actualInputValue - tokenAmount - wantedFee
console.log(remainder)
}
// Start the new transaction
var txb = new bitcoin.TransactionBuilder(network)
// Add all available utxo to transaction
utxos.forEach(function (utxo) {
txb.addInput(utxo.txid, utxo.vout)
})
// Add first output: the machine and the choiced amount
txb.addOutput(user, Number(tokenAmount))
// Add second output (OP_RETURN): the user and the related profile
// var data = new Buffer(profileOpReturn)
console.log(profileOpReturn)
var userBuffer = new Buffer(80)
console.log(userBuffer)
// Safety check to initialize at 0 the 80byte Buffer
for (var i = 0; i < userBuffer.length; i++) {
userBuffer[i] = 0
}
for (i = 0; i < profileOpReturn.length; i++) {
console.log(profileOpReturn.length)
userBuffer[i] = profileOpReturn[i]
}
console.log('')
console.log(userBuffer)
// let userOpReturn = bitcoin.crypto.sha256(bitcoin.crypto.sha256(userBuffer))
// console.log(userOpReturn)
// var opR = []
// opR.push(profileOpReturn)
// userOpReturn.forEach(function (d) {
// opR.push(d)
// })
// console.log(opR)
var dataScript = bitcoin.script.nullDataOutput(userBuffer)
txb.addOutput(dataScript, 0)
// console.log(txb)
// Add third ouptup: the orchestrator and the amount
if(orchestrator.length > 0) {
txb.addOutput(orchestrator, Number(tokenAmount))
}
// Add third ouptup: the change and the remainder
txb.addOutput(change, remainder)
console.log(txb)
// return the unfirmed transaction
return txb
}
/**
* Function to sign a transaction
* @param tx: the unfirmed transaction
* @param privKey: the sender privateKey
* @return new firmed transaction
*/
export let signTransaction = (tx: Tx, privKey: string) => {
console.log('prob')
console.log(tx)
console.log(bitcoin)
console.log(privKey)
var keyPair = bitcoin.ECPair.fromWIF(privKey, NETWORKS_FAIRCOIN.faircoin)
console.log(keyPair)
for (let i = 0; i < tx.tx.ins.length; i++) {
tx.sign(i, keyPair)
}
console.log(tx)
return {
txFirmed: tx.build(),
txSerialized: tx.build().toHex()
}
}
/**
* Create a new HDNode from seed
* @param seed : the master password, don't forget it!
* @param network : if not specified it will use the bitcoin mainnet network
* @return the HDNode
**/
export let HDNodeFromSeed = (seed: string, networks: string): HDNode => {
console.log(NETWORKS_FAIRCOIN)
console.log(NETWORKS)
networks = networks || NETWORKS_FAIRCOIN.faircoin
let seedHex = hexEncode(seed)
// let seedBuffer = new Buffer(seedHex, 'hex')
let m = bitcoin.HDNode.fromSeedHex(seedHex, networks)
// m = m.deriveHardened(44)
// m = m.deriveHardened(0)
return m
}
/**
* Create a new Wallet from an existent HDNode
* @param node: the HDNode
* @return HDWallet
**/
export let createWalletFromNode = (node: HDNode) : HDWallet => {
let external = node.derive(0)
let internal = node.derive(1)
return new Wallet(external, internal)
}
/**
* Create a new Wallet from an existent HDNode
* @param seed : the master password, don't forget it!
* @param network : if not specified it will use the bitcoin mainnet network
* @return HDWallet
**/
export let walletFromSeed = (seed:string, networks:string): HDWallet => {
let node = HDNodeFromSeed(seed, networks)
node = node.deriveHardened(0)
let wallet = createWalletFromNode(node)
return wallet
}
export let nodeFromSeed = (seed:string, networks:string): HDWallet => {
let node = HDNodeFromSeed(seed, networks)
return node
}
/**
* Default function to create a new HD Wallet
* @param external
+ @param internal
* @return new account
*/
function Wallet (external: HDNode, internal: HDNode) : HDWallet {
let chains
if (Array.isArray(external)) {
chains = external
this.external = chains[0].getParent()
this.internal = chains[1].getParent()
} else {
chains = [
new bip32utils.Chain(external.neutered()),
new bip32utils.Chain(internal.neutered())
]
this.external = external
this.internal = internal
}
this.account = new bip32utils.Account(chains)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment