Created
October 11, 2017 15:25
-
-
Save ivanminutillo/84b7751447e4d542bd85002fd14fe6fe to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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