@ -23,6 +23,7 @@ const {execFile} = require('child_process');
const sha256 = require ( 'sha256' ) ;
const sha256 = require ( 'sha256' ) ;
const CoinKey = require ( 'coinkey' )
const CoinKey = require ( 'coinkey' )
const bitcoinJS = require ( 'bitcoinjs-lib' ) ;
const bitcoinJS = require ( 'bitcoinjs-lib' ) ;
const coinSelect = require ( 'coinselect' ) ;
const fixPath = require ( 'fix-path' ) ;
const fixPath = require ( 'fix-path' ) ;
var ps = require ( 'ps-node' ) ;
var ps = require ( 'ps-node' ) ;
@ -292,7 +293,7 @@ shepherd.get('/electrum/login', function(req, res, next) {
const successObj = {
const successObj = {
msg : 'success' ,
msg : 'success' ,
result : 'true'
result : 'true' ,
} ;
} ;
res . end ( JSON . stringify ( successObj ) ) ;
res . end ( JSON . stringify ( successObj ) ) ;
@ -303,7 +304,7 @@ shepherd.get('/electrum/dev/logout', function(req, res, next) {
const successObj = {
const successObj = {
msg : 'success' ,
msg : 'success' ,
result : 'true'
result : 'true' ,
} ;
} ;
res . end ( JSON . stringify ( successObj ) ) ;
res . end ( JSON . stringify ( successObj ) ) ;
@ -311,18 +312,18 @@ shepherd.get('/electrum/dev/logout', function(req, res, next) {
shepherd . get ( '/electrum/bip39/seed' , function ( req , res , next ) {
shepherd . get ( '/electrum/bip39/seed' , function ( req , res , next ) {
// TODO
// TODO
var bip39 = require ( 'bip39' ) ; // npm i -S bip39
const bip39 = require ( 'bip39' ) ; // npm i -S bip39
var crypto = require ( 'crypto' ) ;
const crypto = require ( 'crypto' ) ;
// what you describe as 'seed'
// what you describe as 'seed'
var randomBytes = crypto . randomBytes ( 16 ) ; // 128 bits is enough
const randomBytes = crypto . randomBytes ( 16 ) ; // 128 bits is enough
// your 12 word phrase
// your 12 word phrase
var mnemonic = bip39 . entropyToMnemonic ( randomBytes . toString ( 'hex' ) ) ;
const mnemonic = bip39 . entropyToMnemonic ( randomBytes . toString ( 'hex' ) ) ;
// what is accurately described as the wallet seed
// what is accurately described as the wallet seed
// var seed = bip39.mnemonicToSeed(mnemonic) // you'll use this in #3 below
// var seed = bip39.mnemonicToSeed(mnemonic) // you'll use this in #3 below
var seed = bip39 . mnemonicToSeed ( req . query . seed ) ;
const seed = bip39 . mnemonicToSeed ( req . query . seed ) ;
console . log ( seed ) ;
console . log ( seed ) ;
@ -336,17 +337,17 @@ shepherd.get('/electrum/bip39/seed', function(req, res, next) {
res . end ( JSON . stringify ( successObj ) ) ;
res . end ( JSON . stringify ( successObj ) ) ;
console . log ( bitcoinJS . networks . komodo ) ;
console . log ( bitcoinJS . networks . komodo ) ;
var hdMaster = bitcoinJS . HDNode . fromSeedBuffer ( seed , electrumJSNetworks . komodo ) ; // seed from above
const hdMaster = bitcoinJS . HDNode . fromSeedBuffer ( seed , electrumJSNetworks . komodo ) ; // seed from above
var key1 = hdMaster . derivePath ( 'm/0' ) ;
const key1 = hdMaster . derivePath ( 'm/0' ) ;
var key2 = hdMaster . derivePath ( 'm/1' ) ;
const key2 = hdMaster . derivePath ( 'm/1' ) ;
console . log ( hdMaster ) ;
console . log ( hdMaster ) ;
console . log ( key1 . keyPair . toWIF ( ) ) ;
console . log ( key1 . keyPair . toWIF ( ) ) ;
console . log ( key1 . keyPair . getAddress ( ) ) ;
console . log ( key1 . keyPair . getAddress ( ) ) ;
console . log ( key2 . keyPair . toWIF ( ) ) ;
console . log ( key2 . keyPair . toWIF ( ) ) ;
var hdnode = bitcoinJS . HDNode . fromSeedBuffer ( seed , electrumJSNetworks . komodo ) . deriveHardened ( 0 ) . derive ( 0 ) . derive ( 1 ) ;
const hdnode = bitcoinJS . HDNode . fromSeedBuffer ( seed , electrumJSNetworks . komodo ) . deriveHardened ( 0 ) . derive ( 0 ) . derive ( 1 ) ;
console . log ( 'Address: ' + hdnode . getAddress ( ) ) ;
console . log ( 'Address: ' + hdnode . getAddress ( ) ) ;
console . log ( 'Private key (WIF): ' + hdnode . keyPair . toWIF ( ) ) ;
console . log ( 'Private key (WIF): ' + hdnode . keyPair . toWIF ( ) ) ;
} ) ;
} ) ;
@ -412,6 +413,44 @@ shepherd.get('/electrum/coins', function(req, res, next) {
res . end ( JSON . stringify ( successObj ) ) ;
res . end ( JSON . stringify ( successObj ) ) ;
} ) ;
} ) ;
shepherd . kdmCalcInterest = function ( locktime , value ) { // value in sats
const timestampDiff = ( Math . floor ( Date . now ( ) / 1000 ) - locktime - 777 ) ;
const currentTimeHours = Math . floor ( timestampDiff / 3600 ) ;
const currentTimeMinutes = Math . floor ( ( timestampDiff - ( currentTimeHours * 3600 ) ) / 60 ) ;
const currentTimeSeconds = timestampDiff - ( currentTimeHours * 3600 ) - ( currentTimeMinutes * 60 ) ;
let timestampDiffMinutes = timestampDiff / 60 ;
let interest = 0 ;
console . log ( ` locktime ${ locktime } ` ) ;
console . log ( ` minutes converted ${ timestampDiffMinutes } ` ) ;
console . log ( ` passed ${ currentTimeHours } h ${ currentTimeMinutes } m ${ currentTimeSeconds } s ` ) ;
// calc interest
if ( timestampDiffMinutes >= 60 ) {
if ( timestampDiffMinutes > 365 * 24 * 60 ) {
timestampDiffMinutes = 365 * 24 * 60 ;
}
timestampDiffMinutes -= 59 ;
console . log ( ` minutes if statement ${ timestampDiffMinutes } ` ) ;
let denominator = ( 365 * 24 * 60 ) / timestampDiffMinutes ;
if ( denominator === 0 ) {
denominator = 1 ; // max KOMODO_INTEREST per transfer, do it at least annually!
}
console . log ( ` denominator ${ denominator } ` ) ;
// TODO: check if interest is > 5% yr
const numerator = Number ( value ) * 0.00000001 / 20 ; // assumes 5%!
interest = ( ( Number ( value ) * 0.00000001 ) / 10512000 ) * timestampDiffMinutes ;
console . log ( ` interest ${ interest } ` ) ;
}
return interest ;
}
shepherd . get ( '/electrum/getbalance' , function ( req , res , next ) {
shepherd . get ( '/electrum/getbalance' , function ( req , res , next ) {
const network = req . query . network || shepherd . findNetworkObj ( req . query . coin ) ;
const network = req . query . network || shepherd . findNetworkObj ( req . query . coin ) ;
const ecl = new electrumJSCore ( electrumServers [ network ] . port , electrumServers [ network ] . address , electrumServers [ network ] . proto ) ; // tcp or tls
const ecl = new electrumJSCore ( electrumServers [ network ] . port , electrumServers [ network ] . address , electrumServers [ network ] . proto ) ; // tcp or tls
@ -419,172 +458,126 @@ shepherd.get('/electrum/getbalance', function(req, res, next) {
ecl . connect ( ) ;
ecl . connect ( ) ;
ecl . blockchainAddressGetBalance ( req . query . address )
ecl . blockchainAddressGetBalance ( req . query . address )
. then ( ( json ) => {
. then ( ( json ) => {
ecl . close ( ) ;
if ( network === 'komodo' ) {
console . log ( 'electrum getbalance ==>' ) ;
ecl . connect ( ) ;
console . log ( json ) ;
ecl . blockchainAddressListunspent ( req . query . address )
. then ( ( utxoList ) => {
if ( utxoList &&
utxoList . length ) {
// filter out < 10 KMD amounts
let _ utxo = [ ] ;
for ( let i = 0 ; i < utxoList . length ; i ++ ) {
console . log ( ` utxo ${ utxoList [ i ] [ 'tx_hash' ] } sats ${ utxoList [ i ] . value } value ${ Number ( utxoList [ i ] . value ) * 0.00000001 } ` ) ;
if ( Number ( utxoList [ i ] . value ) * 0.00000001 >= 10 ) {
_ utxo . push ( utxoList [ i ] ) ;
}
}
const successObj = {
console . log ( 'filtered utxo list =>' ) ;
msg : 'success' ,
console . log ( _ utxo ) ;
result : {
balance : 0.00000001 * json . confirmed ,
unconfirmed : json . unconfirmed ,
sats : json . confirmed ,
} ,
} ;
res . end ( JSON . stringify ( successObj ) ) ;
if ( _ utxo &&
} ) ;
_ utxo . length ) {
} ) ;
let interestTotal = 0 ;
shepherd . sortTransactions = function ( transactions ) {
for ( let i = 0 ; i < _ utxo . length ; i ++ ) {
return transactions . sort ( function ( b , a ) {
ecl . blockchainTransactionGet ( _ utxo [ i ] [ 'tx_hash' ] )
if ( a . height < b . height ) {
. then ( ( _ rawtxJSON ) => {
return - 1 ;
console . log ( 'electrum gettransaction ==>' ) ;
}
console . log ( i + ' | ' + ( _ rawtxJSON . length - 1 ) ) ;
console . log ( _ rawtxJSON ) ;
if ( a . height > b . height ) {
// decode tx
return 1 ;
const _ network = electrumJSNetworks [ network ] ;
}
const decodedTx = electrumJSTxDecoder ( _ rawtxJSON , _ network ) ;
return 0 ;
interestTotal += shepherd . kdmCalcInterest ( decodedTx . format . locktime , _ utxo [ i ] . value ) ;
} ) ;
console . log ( 'decoded tx =>' ) ;
}
console . log ( decodedTx ) ;
console . log ( decodedTx . format . locktime ) ;
if ( i === _ utxo . length - 1 ) {
const successObj = {
msg : 'success' ,
result : {
balance : 0.00000001 * json . confirmed ,
unconfirmed : json . unconfirmed ,
sats : json . confirmed ,
interest : interestTotal ,
interestSats : Math . floor ( interestTotal * 100000000 ) ,
total : ( 0.00000001 * json . confirmed ) + interestTotal ,
totalSats : json . confirmed + Math . floor ( interestTotal * 100000000 ) ,
} ,
} ;
/ * s h e p h e r d . g e t ( ' / e l e c t r u m / l i s t t r a n s a c t i o n s ' , f u n c t i o n ( r e q , r e s , n e x t ) {
res . end ( JSON . stringify ( successObj ) ) ;
const network = req . query . network || shepherd . findNetworkObj ( req . query . coin ) ;
}
const ecl = new electrumJSCore ( electrumServers [ network ] . port , electrumServers [ network ] . address , electrumServers [ network ] . proto ) ; // tcp or tls
} ) ;
}
} else {
const successObj = {
msg : 'success' ,
result : {
balance : 0.00000001 * json . confirmed ,
unconfirmed : json . unconfirmed ,
sats : json . confirmed ,
interest : 0 ,
interestSats : 0 ,
total : 0.00000001 * json . confirmed ,
totalSats : json . confirmed ,
} ,
} ;
if ( ! req . query . full ) {
res . end ( JSON . stringify ( successObj ) ) ;
ecl . connect ( ) ;
}
ecl . blockchainAddressGetHistory ( req . query . address )
} else {
. then ( ( json ) => {
const successObj = {
msg : 'success' ,
result : {
balance : 0.00000001 * json . confirmed ,
unconfirmed : json . unconfirmed ,
sats : json . confirmed ,
interest : 0 ,
} ,
} ;
res . end ( JSON . stringify ( successObj ) ) ;
}
} ) ;
} else {
ecl . close ( ) ;
ecl . close ( ) ;
console . log ( 'electrum listtransactions ==>' ) ;
console . log ( 'electrum getbalance ==>' ) ;
console . log ( json ) ;
console . log ( json ) ;
json = shepherd . sortTransactions ( json ) ;
const successObj = {
const successObj = {
msg : 'success' ,
msg : 'success' ,
result : {
result : {
listtransactions : json ,
balance : 0.00000001 * json . confirmed ,
unconfirmed : json . unconfirmed ,
sats : json . confirmed ,
} ,
} ,
} ;
} ;
res . end ( JSON . stringify ( successObj ) ) ;
res . end ( JSON . stringify ( successObj ) ) ;
} ) ;
}
} else {
} ) ;
// !expensive call!
} ) ;
// TODO: limit e.g. 1-10, 10-20 etc
const MAX_TX = 10 ;
ecl . connect ( ) ;
ecl . blockchainNumblocksSubscribe ( )
. then ( function ( currentHeight ) {
// TODO: block time, confs
ecl . blockchainAddressGetHistory ( req . query . address )
. then ( ( json ) => {
if ( json &&
json . length ) {
json = shepherd . sortTransactions ( json ) ;
json = json . slice ( 0 , MAX_TX ) ;
console . log ( json . length ) ;
let _ rawtx = [ ] ;
// get raw tx
for ( let i = 0 ; i < json . length ; i ++ ) {
ecl . blockchainTransactionGet ( json [ i ] [ 'tx_hash' ] )
. then ( ( _ json ) => {
console . log ( 'electrum gettransaction ==>' ) ;
console . log ( i + ' | ' + ( json . length - 1 ) ) ;
console . log ( _ json ) ;
// decode tx
const _ network = electrumJSNetworks [ network ] ;
const decodedTx = electrumJSTxDecoder ( _ json , _ network ) ;
// TODO: multi vin
if ( decodedTx . inputs [ 0 ] . txid === '0000000000000000000000000000000000000000000000000000000000000000' ) {
ecl . blockchainBlockGetHeader ( json [ i ] . height )
. then ( ( blockInfo ) => {
_ rawtx . push ( {
network : decodedTx . network ,
format : decodedTx . format ,
inputs : decodedTx . inputs ,
outputs : decodedTx . outputs ,
height : json [ i ] . height ,
timestamp : blockInfo . timestamp ,
confirmations : currentHeight - json [ i ] . height ,
miner : true ,
} ) ;
if ( i === json . length - 1 ) {
ecl . close ( ) ;
console . log ( 'electrum gettransaction array ==>' ) ;
console . log ( _ rawtx ) ;
const successObj = {
msg : 'success' ,
result : {
listtransactions : _ rawtx ,
} ,
} ;
res . end ( JSON . stringify ( successObj ) ) ;
shepherd . sortTransactions = function ( transactions ) {
}
return transactions . sort ( function ( b , a ) {
} ) ;
if ( a . height < b . height ) {
} else {
return - 1 ;
// get vin tx, decode
}
ecl . blockchainBlockGetHeader ( json [ i ] . height )
. then ( ( blockInfo ) => {
ecl . blockchainTransactionGet ( decodedTx . inputs [ 0 ] . txid )
. then ( ( __ json ) => {
console . log ( 'electrum decoderawtx input tx ==>' ) ;
console . log ( __ json ) ;
const decodedVin = electrumJSTxDecoder ( __ json , _ network ) ;
_ rawtx . push ( {
network : decodedTx . network ,
format : decodedTx . format ,
inputs : decodedVin . outputs [ decodedTx . inputs [ 0 ] . n ] ,
outputs : decodedTx . outputs ,
height : json [ i ] . height ,
timestamp : blockInfo . timestamp ,
confirmations : currentHeight - json [ i ] . height ,
} ) ;
if ( i === json . length - 1 ) {
ecl . close ( ) ;
console . log ( 'electrum gettransaction array ==>' ) ;
console . log ( _ rawtx ) ;
let result = [ ] ;
for ( let i = 0 ; i < _ rawtx . length ; i ++ ) {
result = result . concat ( shepherd . parseTransactionAddresses ( _ rawtx [ i ] , req . query . address ) ) ;
}
const successObj = {
if ( a . height > b . height ) {
msg : 'success' ,
return 1 ;
result : {
}
//listtransactions: _rawtx,
listtransactions : result ,
} ,
} ;
res . end ( JSON . stringify ( successObj ) ) ;
return 0 ;
}
} ) ;
} ) ;
}
} ) ;
}
} ) ;
}
}
} ) ;
} ) ;
}
} ) ; * /
shepherd . get ( '/electrum/listtransactions' , function ( req , res , next ) {
shepherd . get ( '/electrum/listtransactions' , function ( req , res , next ) {
const network = req . query . network || shepherd . findNetworkObj ( req . query . coin ) ;
const network = req . query . network || shepherd . findNetworkObj ( req . query . coin ) ;
@ -651,7 +644,6 @@ shepherd.get('/electrum/listtransactions', function(req, res, next) {
ecl . blockchainTransactionGet ( decodedTx . inputs [ j ] . txid )
ecl . blockchainTransactionGet ( decodedTx . inputs [ j ] . txid )
. then ( ( rawInput ) => {
. then ( ( rawInput ) => {
console . log ( 'electrum raw input tx ==>' ) ;
console . log ( 'electrum raw input tx ==>' ) ;
//console.log
const decodedVinVout = electrumJSTxDecoder ( rawInput , _ network ) ;
const decodedVinVout = electrumJSTxDecoder ( rawInput , _ network ) ;
console . log ( decodedVinVout . outputs [ decodedTx . inputs [ j ] . n ] ) ;
console . log ( decodedVinVout . outputs [ decodedTx . inputs [ j ] . n ] ) ;
txInputs . push ( decodedVinVout . outputs [ decodedTx . inputs [ j ] . n ] ) ;
txInputs . push ( decodedVinVout . outputs [ decodedTx . inputs [ j ] . n ] ) ;
@ -777,84 +769,7 @@ shepherd.get('/electrum/listtransactions', function(req, res, next) {
}
}
} ) ;
} ) ;
// TODO: multi vin
/ * i f ( d e c o d e d T x . i n p u t s [ 0 ] . t x i d = = = ' 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ' ) {
ecl . blockchainBlockGetHeader ( json [ i ] . height )
. then ( ( blockInfo ) => {
_ rawtx . push ( {
network : decodedTx . network ,
format : decodedTx . format ,
inputs : decodedTx . inputs ,
outputs : decodedTx . outputs ,
height : json [ i ] . height ,
timestamp : blockInfo . timestamp ,
confirmations : currentHeight - json [ i ] . height ,
miner : true ,
} ) ;
if ( i === json . length - 1 ) {
ecl . close ( ) ;
console . log ( 'electrum gettransaction array ==>' ) ;
console . log ( _ rawtx ) ;
const successObj = {
msg : 'success' ,
result : {
listtransactions : _ rawtx ,
} ,
} ;
res . end ( JSON . stringify ( successObj ) ) ;
}
} ) ;
} else {
// get vin tx, decode
ecl . blockchainBlockGetHeader ( json [ i ] . height )
. then ( ( blockInfo ) => {
ecl . blockchainTransactionGet ( decodedTx . inputs [ 0 ] . txid )
. then ( ( __ json ) => {
console . log ( 'electrum decoderawtx input tx ==>' ) ;
console . log ( __ json ) ;
const decodedVin = electrumJSTxDecoder ( __ json , _ network ) ;
_ rawtx . push ( {
network : decodedTx . network ,
format : decodedTx . format ,
inputs : decodedVin . outputs [ decodedTx . inputs [ 0 ] . n ] ,
outputs : decodedTx . outputs ,
height : json [ i ] . height ,
timestamp : blockInfo . timestamp ,
confirmations : currentHeight - json [ i ] . height ,
} ) ;
if ( i === json . length - 1 ) {
ecl . close ( ) ;
console . log ( 'electrum gettransaction array ==>' ) ;
console . log ( _ rawtx ) ;
let result = [ ] ;
for ( let i = 0 ; i < _ rawtx . length ; i ++ ) {
result = result . concat ( shepherd . parseTransactionAddresses ( _ rawtx [ i ] , req . query . address ) ) ;
}
const successObj = {
msg : 'success' ,
result : {
//listtransactions: _rawtx,
listtransactions : result ,
} ,
} ;
res . end ( JSON . stringify ( successObj ) ) ;
}
} ) ;
} ) ;
} * /
shepherd . get ( '/electrum/gettransaction' , function ( req , res , next ) {
shepherd . get ( '/electrum/gettransaction' , function ( req , res , next ) {
// TODO: block time, confs, current height
const ecl = new electrumJSCore ( electrumServers [ req . query . network ] . port , electrumServers [ req . query . network ] . address , electrumServers [ req . query . network ] . proto ) ; // tcp or tls
const ecl = new electrumJSCore ( electrumServers [ req . query . network ] . port , electrumServers [ req . query . network ] . address , electrumServers [ req . query . network ] . proto ) ; // tcp or tls
ecl . connect ( ) ;
ecl . connect ( ) ;
@ -995,29 +910,6 @@ shepherd.parseTransactionAddresses = function(tx, targetAddress) {
_ parse [ key ] [ i ] . value ) {
_ parse [ key ] [ i ] . value ) {
_ sum [ key ] += Number ( _ parse [ key ] [ i ] . value ) ;
_ sum [ key ] += Number ( _ parse [ key ] [ i ] . value ) ;
}
}
/ * i f ( k e y = = = ' o u t p u t s ' | |
( key === 'inputs' && _ parse [ key ] [ i ] . scriptPubKey && _ parse [ key ] [ i ] . scriptPubKey . addresses && _ parse [ key ] [ i ] . value ) ) {
if ( ! targetAddress || ( targetAddress === _ parse [ key ] [ i ] . scriptPubKey . addresses [ 0 ] && ! addressFound ) ) {
let _ type ;
if ( tx . miner ) {
_ type = 'miner' ;
} else {
_ type = key === 'inputs' ? 'sent' : 'received' ;
}
result . push ( {
type : _ type , // flip
amount : Number ( _ parse [ key ] [ i ] . value ) ,
address : _ parse [ key ] [ i ] . scriptPubKey . addresses [ 0 ] ,
timestamp : tx . timestamp ,
txid : tx . format . txid ,
confirmations : tx . confirmations ,
} ) ;
addressFound = true ;
}
} * /
}
}
}
}
@ -1203,63 +1095,8 @@ shepherd.get('/electrum/decoderawtx', function(req, res, next) {
}
}
} ) ;
} ) ;
// simple case
// deprecated, remove
shepherd . buildTestTx = function ( sendTo , changeAddress , wif , network ) {
// single utxo
const _ utxo = { "height" : 400118 , "value" : 20000 , "tx_hash" : "764cb67ef9d92942b0a3ef5f9c62ad2a552de07f575e1ab935c3cf45ace00cc8" , "tx_pos" : 0 } ;
const _ valToSpend = 10000 ;
var key = bitcoinJS . ECPair . fromWIF ( wif , electrumJSNetworks [ 'komodo' ] ) ;
var tx = new bitcoinJS . TransactionBuilder ( electrumJSNetworks [ network ] ) ;
console . log ( key ) ;
console . log ( key . getAddress ( ) . toString ( ) ) ;
// electrumServers[].txfee
const _ txSize = shepherd . estimateTxSize ( 1 , 2 ) ;
const _ feeEstimateByte = shepherd . estimateFee ( 'small' ) ;
const _ feeEstimateTx = Math . floor ( _ txSize * _ feeEstimateByte ) ;
const _ change = _ utxo . value - _ valToSpend - _ feeEstimateTx ;
console . log ( 'val to spend ' + _ valToSpend ) ;
console . log ( 'change value ' + _ change ) ;
tx . addInput ( _ utxo [ 'tx_hash' ] , _ utxo [ 'tx_pos' ] ) ;
tx . addOutput ( sendTo , _ valToSpend ) ;
tx . addOutput ( changeAddress , _ change ) ;
console . log ( 'estimate tx size ' + _ txSize ) ;
console . log ( 'fee per byte ' + _ feeEstimateByte ) ;
console . log ( 'tx fee ' + _ feeEstimateTx ) ;
console . log ( tx ) ;
// (in)15000 - (out)12000 = (fee)3000, this is the miner fee
tx . sign ( 0 , key ) ;
const rawtx = tx . build ( ) . toHex ( ) ;
console . log ( rawtx ) ;
return rawtx ;
}
shepherd . get ( '/electrum/txbuildtest' , function ( req , res , next ) {
const rawtx = shepherd . buildTestTx (
'RDbGxL8QYdEp8sMULaVZS2E6XThcTKT9Jd' ,
'RDbGxL8QYdEp8sMULaVZS2E6XThcTKT9Jd' ,
'UrA1TCN2j9iMYKBLkKGMo9MbndBNYVW9nJV9RdViR9CoVK82ApFb' ,
'komodo'
) ;
const successObj = {
msg : 'success' ,
result : {
rawtx : rawtx ,
} ,
} ;
res . end ( JSON . stringify ( successObj ) ) ;
} ) ;
shepherd . findUtxoSet = function ( utxoList , target ) {
shepherd . findUtxoSet = function ( utxoList , target ) {
// utxoList = [{"height":427959,"value":20000,"tx_hash":"3f7da2daef2ea59fd40eb28d2be04a17839f2073c16ea291b1b03a3d799fec3b","tx_pos":0},{"height":428139,"value":20000,"tx_hash":"aa4afdece59c46a6a1e34d6ae7bf2c46b282de0ce6ef1753e8766c08e87bdb36","tx_pos":0},{"height":428216,"value":20000,"tx_hash":"3ec5e982083ffc617aaa75e68e69f9da5f07faadcd870e144f6451c34936ee24","tx_pos":0},{"height":433459,"value":20000,"tx_hash":"b943330cb034f36c6d9f03c57a2e1f0a3970378825336b505d51d1f2561af3fe","tx_pos":0},{"height":459573,"value":100000,"tx_hash":"7fee95da75e9b77bf9cd03b460fcf04c31ce4dbe4bdfa1e66256c9beb1fe2308","tx_pos":0},{"height":505916,"value":20000,"tx_hash":"aa92df15b20a10543750db58fc6e885205d1eee3438ef79f01d3c4ec2616e7aa","tx_pos":0},{"height":505916,"value":90000,"tx_hash":"aa92df15b20a10543750db58fc6e885205d1eee3438ef79f01d3c4ec2616e7aa","tx_pos":1},{"height":505931,"value":20000,"tx_hash":"dd1ab56c0e3f63e3650aeca3e2aa4ecea54cca22e97932e48341e299c4640ef9","tx_pos":0},{"height":505931,"value":100000,"tx_hash":"dd1ab56c0e3f63e3650aeca3e2aa4ecea54cca22e97932e48341e299c4640ef9","tx_pos":1},{"height":505937,"value":20000,"tx_hash":"7bed6729de8be9b61b85716d8d1615d751c1dbb2bd2defd6f9c76354a591586c","tx_pos":0},{"height":505937,"value":70000,"tx_hash":"7bed6729de8be9b61b85716d8d1615d751c1dbb2bd2defd6f9c76354a591586c","tx_pos":1},{"height":506038,"value":20000,"tx_hash":"f47f4d5e2aaee19f98ebdf97deac3c471b919b71312a073d1b45dfc27fb64d24","tx_pos":0},{"height":506045,"value":20000,"tx_hash":"e8a92b174b768a050b4801ea497cdb9651d4647f20ec5a77b5af0d6558fdf468","tx_pos":0},{"height":506057,"value":20000,"tx_hash":"758ae45606ee43b55d72ec57284abac54c34b34badf4986b3d9e53e5aaf227d8","tx_pos":0},{"height":514498,"value":18902,"tx_hash":"b3918bc40a8ba4fb26383bdd54b8519d14200b7f2c700adb2ceea46d5ca36590","tx_pos":0},{"height":514722,"value":10000,"tx_hash":"a6c46b2168964f2e6f18a8cba40eac10a30a6bcc363b773696265f8450c5a881","tx_pos":0},{"height":514722,"value":4820,"tx_hash":"a6c46b2168964f2e6f18a8cba40eac10a30a6bcc363b773696265f8450c5a881","tx_pos":1}];
let result = [ ] ;
let result = [ ] ;
let sum = 0 ;
let sum = 0 ;
@ -1315,18 +1152,19 @@ shepherd.get('/electrum/subset', function(req, res, next) {
// single sig
// single sig
shepherd . buildSignedTx = function ( sendTo , changeAddress , wif , network , utxo , changeValue , spendValue ) {
shepherd . buildSignedTx = function ( sendTo , changeAddress , wif , network , utxo , changeValue , spendValue ) {
var key = bitcoinJS . ECPair . fromWIF ( wif , electrumJSNetworks [ network ] ) ;
let key = bitcoinJS . ECPair . fromWIF ( wif , electrumJSNetworks [ network ] ) ;
var tx = new bitcoinJS . TransactionBuilder ( electrumJSNetworks [ network ] ) ;
let tx = new bitcoinJS . TransactionBuilder ( electrumJSNetworks [ network ] ) ;
console . log ( 'buildSignedTx priv key ' + wif ) ;
console . log ( 'buildSignedTx priv key ' + wif ) ;
console . log ( 'buildSignedTx pub key ' + key . getAddress ( ) . toString ( ) ) ;
console . log ( 'buildSignedTx pub key ' + key . getAddress ( ) . toString ( ) ) ;
console . log ( 'buildSignedTx std tx fee ' + electrumServers [ network ] . txfee ) ;
// console.log('buildSignedTx std tx fee ' + electrumServers[network].txfee);
for ( let i = 0 ; i < utxo . length ; i ++ ) {
for ( let i = 0 ; i < utxo . length ; i ++ ) {
tx . addInput ( utxo [ i ] [ 'tx_hash' ] , utxo [ i ] [ 'tx_pos' ] ) ;
tx . addInput ( utxo [ i ] . txid , utxo [ i ] . vout ) ;
}
}
tx . addOutput ( sendTo , Number ( spendValue ) ) ;
tx . addOutput ( sendTo , Number ( spendValue ) ) ;
if ( changeValue > 0 ) {
if ( changeValue > 0 ) {
tx . addOutput ( changeAddress , Number ( changeValue ) ) ;
tx . addOutput ( changeAddress , Number ( changeValue ) ) ;
}
}
@ -1369,45 +1207,124 @@ shepherd.get('/electrum/createrawtx', function(req, res, next) {
const outputAddress = req . query . address ;
const outputAddress = req . query . address ;
const changeAddress = req . query . change ;
const changeAddress = req . query . change ;
let wif = req . query . wif ;
let wif = req . query . wif ;
const value = req . query . value ;
const value = Number ( req . query . value ) ;
const push = req . query . push ;
const push = req . query . push ;
const fee = electrumServers [ network ] . txfee ;
const fee = electrumServers [ network ] . txfee ;
console . log ( electrumCoins [ req . query . coin ] ) ;
if ( req . query . gui ) {
if ( req . query . gui ) {
wif = electrumCoins [ req . query . coin ] . priv ;
wif = electrumCoins [ req . query . coin ] . priv ;
}
}
ecl . connect ( ) ;
ecl . connect ( ) ;
ecl . blockchainAddressListunspent ( changeAddress )
//ecl.blockchainAddressListunspent(changeAddress)
shepherd . listunspent ( ecl , changeAddress , network , network === 'komodo' ? true : false )
. then ( ( utxoList ) => {
. then ( ( utxoList ) => {
ecl . close ( ) ;
ecl . close ( ) ;
let utxoListFormatted = [ ] ;
let totalInterest = 0 ;
let totalInterestUTXOCount = 0 ;
let interestClaimThreshold = 200 ;
for ( let i = 0 ; i < utxoList . length ; i ++ ) {
if ( network === 'komodo' ) {
utxoListFormatted . push ( {
txid : utxoList [ i ] . txid ,
vout : utxoList [ i ] . vout ,
value : Number ( utxoList [ i ] . amountSats ) ,
interestSats : Number ( utxoList [ i ] . interestSats ) ,
} ) ;
if ( Number ( utxoList [ i ] . interestSats ) > interestClaimThreshold ) {
totalInterest += Number ( utxoList [ i ] . interestSats ) ;
totalInterestUTXOCount ++ ;
}
} else {
utxoListFormatted . push ( {
txid : utxoList [ i ] [ 'tx_hash' ] ,
vout : utxoList [ i ] [ 'tx_pos' ] ,
value : Number ( utxoList [ i ] . value ) ,
height : utxoList [ i ] . height ,
} ) ;
}
}
console . log ( 'electrum listunspent ==>' ) ;
console . log ( 'electrum listunspent ==>' ) ;
console . log ( utxoListFormatted ) ;
let _ value = Number ( value ) + Number ( fee ) ;
let targets = [ {
let _ utxoSet = shepherd . findUtxoSet ( utxoList , _ value ) ; // target + txfee
address : outputAddress ,
value : value > Number ( shepherd . maxSpendBalance ( utxoListFormatted ) ) ? Number ( shepherd . maxSpendBalance ( utxoListFormatted ) ) : value ,
} ] ;
console . log ( 'targets =>' ) ;
console . log ( targets ) ;
const feeRate = 20 ; // sats/byte
// default coin selection algo blackjack with fallback to accumulative
// make a first run, calc approx tx fee
// if ins and outs are empty reduce max spend by txfee
let { inputs , outputs , fee } = coinSelect ( utxoListFormatted , targets , feeRate ) ;
console . log ( 'coinselect res =>' ) ;
console . log ( 'coinselect inputs =>' ) ;
console . log ( inputs ) ;
console . log ( 'coinselect outputs =>' ) ;
console . log ( outputs ) ;
console . log ( 'coinselect calculated fee =>' ) ;
console . log ( fee ) ;
if ( ! inputs &&
! outputs ) {
targets [ 0 ] . value = targets [ 0 ] . value - electrumServers [ network ] . txfee ;
console . log ( 'second run' ) ;
console . log ( 'coinselect adjusted targets =>' ) ;
console . log ( targets ) ;
const secondRun = coinSelect ( utxoListFormatted , targets , feeRate ) ;
inputs = secondRun . inputs ;
outputs = secondRun . outputs ;
fee = secondRun . fee ;
console . log ( 'coinselect inputs =>' ) ;
console . log ( inputs ) ;
console . log ( 'coinselect outputs =>' ) ;
console . log ( outputs ) ;
console . log ( 'coinselect fee =>' ) ;
console . log ( fee ) ;
}
if ( Number ( value ) >= shepherd . maxSpendBalance ( utxoList , fee ) ) {
let _ change = 0 ;
_ value = shepherd . maxSpendBalance ( utxoList , fee ) ;
_ utxoSet = {
if ( outputs . length === 2 ) {
set : utxoList ,
_ change = outputs [ 1 ] . value ;
change : 0 ,
} ;
}
}
console . log ( 'maxspend ' + shepherd . maxSpendBalance ( utxoList , fee ) ) ;
const _ maxSpend = shepherd . maxSpendBalance ( utxoListFormatted ) ;
console . log ( 'value ' + value ) ;
console . log ( ` maxspend ${ _ maxSpend } ( ${ _ maxSpend * 0.00000001 } ) ` ) ;
console . log ( ` value ${ value } ` ) ;
console . log ( ` sendto ${ outputAddress } amount ${ value } ( ${ value * 0.00000001 } ) ` ) ;
console . log ( ` changeto ${ changeAddress } amount ${ _ change } ( ${ _ change * 0.00000001 } ) ` ) ;
const _ rawtx = shepherd . buildSignedTx ( outputAddress , changeAddress , wif , network , _ utxoSet . set , _ utxoSet . change , _ utxoSet . change <= 0 ? _ value : value ) ;
// account for KMD interest
if ( network === 'komodo' &&
totalInterest > 0 ) {
const _ feeOverhead = shepherd . estimateTxSize ( 0 , 1 ) * 2 ;
console . log ( ` max interest to claim ${ totalInterest } ( ${ totalInterest * 0.00000001 } ) ` ) ;
console . log ( 'estimated fee overhead ' + _ feeOverhead ) ;
console . log ( ` current change amount ${ _ change } ( ${ _ change * 0.00000001 } ), boosted change amount ${ _ change + ( totalInterest - _ feeOverhead ) } ( ${ ( _ change + ( totalInterest - _ feeOverhead ) ) * 0.00000001 } ) ` ) ;
_ change = _ change + ( totalInterest - _ feeOverhead ) ;
}
const _ rawtx = shepherd . buildSignedTx ( outputAddress , changeAddress , wif , network , inputs , _ change , value ) ;
if ( ! push ) {
if ( ! push ) {
const successObj = {
const successObj = {
msg : 'success' ,
msg : 'success' ,
result : {
result : {
utxoSet : _ utxoSet . set ,
utxoSet : inp uts ,
change : _ utxoSet . change ,
change : _ change ,
// wif,
// wif,
fee ,
fee ,
value ,
value ,
@ -1430,9 +1347,10 @@ shepherd.get('/electrum/createrawtx', function(req, res, next) {
const successObj = {
const successObj = {
msg : 'success' ,
msg : 'success' ,
result : {
result : {
utxoSet : _ utxoSet . set ,
utxoSet : inputs ,
change : _ utxoSet . change ,
change : _ change ,
wif ,
fee ,
// wif,
value ,
value ,
outputAddress ,
outputAddress ,
changeAddress ,
changeAddress ,
@ -1448,37 +1366,6 @@ shepherd.get('/electrum/createrawtx', function(req, res, next) {
} ) ;
} ) ;
} ) ;
} ) ;
/ * s h e p h e r d . b u i l d T e s t T x = f u n c t i o n ( a d d r e s s , w i f , n e t w o r k ) {
const _ utxo = [ { "value" : 20000 , "tx_hash" : "2bb1a6d807ddfd1614317028748a6feddc585255c105438e3fa7e6384e607944" , "height" : 358804 , "tx_pos" : 0 } , { "value" : 20000 , "tx_hash" : "764cb67ef9d92942b0a3ef5f9c62ad2a552de07f575e1ab935c3cf45ace00cc8" , "height" : 400118 , "tx_pos" : 0 } , { "value" : 20000 , "tx_hash" : "3f7da2daef2ea59fd40eb28d2be04a17839f2073c16ea291b1b03a3d799fec3b" , "height" : 427959 , "tx_pos" : 0 } , { "value" : 20000 , "tx_hash" : "aa4afdece59c46a6a1e34d6ae7bf2c46b282de0ce6ef1753e8766c08e87bdb36" , "height" : 428139 , "tx_pos" : 0 } , { "value" : 20000 , "tx_hash" : "3ec5e982083ffc617aaa75e68e69f9da5f07faadcd870e144f6451c34936ee24" , "height" : 428216 , "tx_pos" : 0 } , { "value" : 20000 , "tx_hash" : "b943330cb034f36c6d9f03c57a2e1f0a3970378825336b505d51d1f2561af3fe" , "height" : 433459 , "tx_pos" : 0 } , { "value" : 100000 , "tx_hash" : "7fee95da75e9b77bf9cd03b460fcf04c31ce4dbe4bdfa1e66256c9beb1fe2308" , "height" : 459573 , "tx_pos" : 0 } , { "value" : 20000 , "tx_hash" : "aa92df15b20a10543750db58fc6e885205d1eee3438ef79f01d3c4ec2616e7aa" , "height" : 505916 , "tx_pos" : 0 } , { "value" : 90000 , "tx_hash" : "aa92df15b20a10543750db58fc6e885205d1eee3438ef79f01d3c4ec2616e7aa" , "height" : 505916 , "tx_pos" : 1 } , { "value" : 20000 , "tx_hash" : "dd1ab56c0e3f63e3650aeca3e2aa4ecea54cca22e97932e48341e299c4640ef9" , "height" : 505931 , "tx_pos" : 0 } , { "value" : 100000 , "tx_hash" : "dd1ab56c0e3f63e3650aeca3e2aa4ecea54cca22e97932e48341e299c4640ef9" , "height" : 505931 , "tx_pos" : 1 } , { "value" : 20000 , "tx_hash" : "7bed6729de8be9b61b85716d8d1615d751c1dbb2bd2defd6f9c76354a591586c" , "height" : 505937 , "tx_pos" : 0 } , { "value" : 70000 , "tx_hash" : "7bed6729de8be9b61b85716d8d1615d751c1dbb2bd2defd6f9c76354a591586c" , "height" : 505937 , "tx_pos" : 1 } , { "value" : 20000 , "tx_hash" : "f47f4d5e2aaee19f98ebdf97deac3c471b919b71312a073d1b45dfc27fb64d24" , "height" : 506038 , "tx_pos" : 0 } , { "value" : 20000 , "tx_hash" : "e8a92b174b768a050b4801ea497cdb9651d4647f20ec5a77b5af0d6558fdf468" , "height" : 506045 , "tx_pos" : 0 } , { "value" : 20000 , "tx_hash" : "758ae45606ee43b55d72ec57284abac54c34b34badf4986b3d9e53e5aaf227d8" , "height" : 506057 , "tx_pos" : 0 } ] ;
var key = bitcoinJS . ECPair . fromWIF ( 'UrA1TCN2j9iMYKBLkKGMo9MbndBNYVW9nJV9RdViR9CoVK82ApFb' , electrumJSNetworks [ 'komodo' ] ) ;
var tx = new bitcoinJS . TransactionBuilder ( electrumJSNetworks [ 'komodo' ] ) ;
console . log ( key ) ;
console . log ( key . getAddress ( ) . toString ( ) ) ;
// electrumServers[].txfee
const _ txSize = shepherd . estimateTxSize ( 1 , 1 ) ;
const _ feeEstimateByte = shepherd . estimateFee ( 'small' ) ;
const _ feeEstimateTx = Math . floor ( _ txSize * _ feeEstimateByte ) ;
console . log ( 'output val ' + ( 20000 - _ feeEstimateTx ) ) ;
// 20000
tx . addInput ( '2bb1a6d807ddfd1614317028748a6feddc585255c105438e3fa7e6384e607944' , 0 ) ;
tx . addOutput ( 'RDbGxL8QYdEp8sMULaVZS2E6XThcTKT9Jd' , 20000 - _ feeEstimateTx ) ;
console . log ( 'estimate tx size ' + _ txSize ) ;
console . log ( 'fee per byte ' + _ feeEstimateByte ) ;
console . log ( 'tx fee ' + _ feeEstimateTx ) ;
console . log ( tx ) ;
// (in)15000 - (out)12000 = (fee)3000, this is the miner fee
tx . sign ( 0 , key ) ;
const rawtx = tx . build ( ) . toHex ( ) ;
console . log ( rawtx ) ;
return rawtx ;
} * /
shepherd . get ( '/electrum/pushtx' , function ( req , res , next ) {
shepherd . get ( '/electrum/pushtx' , function ( req , res , next ) {
const rawtx = req . query . rawtx ;
const rawtx = req . query . rawtx ;
const ecl = new electrumJSCore ( electrumServers [ req . query . network ] . port , electrumServers [ req . query . network ] . address , electrumServers [ req . query . network ] . proto ) ; // tcp or tls
const ecl = new electrumJSCore ( electrumServers [ req . query . network ] . port , electrumServers [ req . query . network ] . address , electrumServers [ req . query . network ] . proto ) ; // tcp or tls
@ -1501,24 +1388,141 @@ shepherd.get('/electrum/pushtx', function(req, res, next) {
} ) ;
} ) ;
} ) ;
} ) ;
shepherd . listunspent = function ( ecl , address , network , full ) {
if ( full ) {
return new Promise ( function ( resolve , reject ) {
ecl . connect ( ) ;
ecl . blockchainAddressListunspent ( address )
. then ( ( _ utxo ) => {
if ( _ utxo &&
_ utxo . length ) {
let formattedUtxoList = [ ] ;
ecl . blockchainNumblocksSubscribe ( )
. then ( function ( currentHeight ) {
for ( let i = 0 ; i < _ utxo . length ; i ++ ) {
ecl . blockchainTransactionGet ( _ utxo [ i ] [ 'tx_hash' ] )
. then ( ( _ rawtxJSON ) => {
console . log ( 'electrum gettransaction ==>' ) ;
console . log ( i + ' | ' + ( _ rawtxJSON . length - 1 ) ) ;
console . log ( _ rawtxJSON ) ;
// decode tx
const _ network = electrumJSNetworks [ network ] ;
const decodedTx = electrumJSTxDecoder ( _ rawtxJSON , _ network ) ;
if ( network === 'komodo' ) {
let interest = 0 ;
if ( Number ( _ utxo [ i ] . value ) * 0.00000001 >= 10 ) {
interest = shepherd . kdmCalcInterest ( decodedTx . format . locktime , _ utxo [ i ] . value ) ;
}
formattedUtxoList . push ( {
txid : _ utxo [ i ] [ 'tx_hash' ] ,
vout : _ utxo [ i ] [ 'tx_pos' ] ,
address ,
// "scriptPubKey": "76a9140e78f3f7daf736f58eee93ccd3bfaa7b2b35f49a88ac",
amount : Number ( _ utxo [ i ] . value ) * 0.00000001 ,
amountSats : _ utxo [ i ] . value ,
interest : interest ,
interestSats : Math . floor ( interest * 100000000 ) ,
confirmations : currentHeight - _ utxo [ i ] . height ,
spendable : true
} ) ;
} else {
formattedUtxoList . push ( {
txid : _ utxo [ i ] [ 'tx_hash' ] ,
vout : _ utxo [ i ] [ 'tx_pos' ] ,
address ,
// "scriptPubKey": "76a9140e78f3f7daf736f58eee93ccd3bfaa7b2b35f49a88ac",
amount : Number ( _ utxo [ i ] . value ) * 0.00000001 ,
amountSats : _ utxo [ i ] . value ,
confirmations : currentHeight - _ utxo [ i ] . height ,
spendable : true
} ) ;
}
console . log ( 'decoded tx =>' ) ;
console . log ( decodedTx ) ;
console . log ( decodedTx . format . locktime ) ;
if ( i === _ utxo . length - 1 ) {
ecl . close ( ) ;
resolve ( formattedUtxoList ) ;
/ * c o n s t s u c c e s s O b j = {
msg : 'success' ,
result : {
listunspent : formattedUtxoList ,
} ,
} ;
res . end ( JSON . stringify ( successObj ) ) ; * /
}
} ) ;
}
} ) ;
} else {
ecl . close ( ) ;
resolve ( [ ] ) ;
/ * c o n s t s u c c e s s O b j = {
msg : 'success' ,
result : {
listunspent : [ ] ,
} ,
} ;
res . end ( JSON . stringify ( successObj ) ) ; * /
}
} ) ;
} ) ;
} else {
return new Promise ( function ( resolve , reject ) {
ecl . connect ( ) ;
ecl . blockchainAddressListunspent ( address )
. then ( ( json ) => {
ecl . close ( ) ;
resolve ( json ) ;
} ) ;
} ) ;
}
}
shepherd . get ( '/electrum/listunspent' , function ( req , res , next ) {
shepherd . get ( '/electrum/listunspent' , function ( req , res , next ) {
const ecl = new electrumJSCore ( electrumServers [ req . query . network ] . port , electrumServers [ req . query . network ] . address , electrumServers [ req . query . network ] . proto ) ; // tcp or tls
const network = req . query . network || shepherd . findNetworkObj ( req . query . coin ) ;
const ecl = new electrumJSCore ( electrumServers [ network ] . port , electrumServers [ network ] . address , electrumServers [ network ] . proto ) ; // tcp or tls
ecl . connect ( ) ;
if ( req . query . full ) {
ecl . blockchainAddressListunspent ( req . query . address )
shepherd . listunspent ( ecl , req . query . address , network , true )
. then ( ( json ) => {
. then ( ( listunspent ) => {
ecl . close ( ) ;
console . log ( 'electrum listunspent ==>' ) ;
console . log ( 'electrum listunspent ==>' ) ;
const successObj = {
const successObj = {
msg : 'success' ,
msg : 'success' ,
result : {
result : {
listunspent : json ,
listunspent ,
} ,
} ,
} ;
} ;
res . end ( JSON . stringify ( successObj ) ) ;
res . end ( JSON . stringify ( successObj ) ) ;
} ) ;
} ) ;
} else {
shepherd . listunspent ( ecl , req . query . address , network )
. then ( ( json ) => {
ecl . close ( ) ;
console . log ( 'electrum listunspent ==>' ) ;
const successObj = {
msg : 'success' ,
result : {
listunspent : json ,
} ,
} ;
res . end ( JSON . stringify ( successObj ) ) ;
} ) ;
}
} ) ;
} ) ;
shepherd . get ( '/electrum/estimatefee' , function ( req , res , next ) {
shepherd . get ( '/electrum/estimatefee' , function ( req , res , next ) {
@ -1546,20 +1550,6 @@ shepherd.estimateTxSize = function(numVins, numOuts) {
return numVins * 180 + numOuts * 34 + 11 ;
return numVins * 180 + numOuts * 34 + 11 ;
}
}
shepherd . estimateFee = function ( type ) {
return 20 ;
if ( type === 'small' ) {
return 0.00005 / 1024 * 100000000 ;
}
if ( type === 'medium' ) {
return 0.0001 / 1024 * 100000000 ;
}
if ( type === 'high' ) {
return 0.0003 / 1024 * 100000000 ;
}
}
/ *
/ *
* list native coind
* list native coind
* type :
* type :