Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
175 changes: 145 additions & 30 deletions lib/api_client.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,8 @@ var APIClient = function(options) {
options.apiNetwork = options.apiNetwork || normalizedNetwork[3];

self.bitcoinCash = options.network === "BCC";
self.chain = options.network;
self.rskTestnet = normalizedNetwork[4];
self.regtest = options.regtest;
self.testnet = options.testnet;
self.network = networkFromOptions(self);
Expand Down Expand Up @@ -132,32 +134,39 @@ var APIClient = function(options) {

};

APIClient.BITCOIN_NETWORK = "BTC";
APIClient.BITCOIN_CASH_NETWORK = "BCH";
APIClient.ROOTSTOCK_NETWORK = "RSK";

APIClient.normalizeNetworkFromOptions = function(options) {
/* jshint -W071, -W074 */
var network = 'BTC';
var testnet = false;
var regtest = false;
var apiNetwork = "BTC";
var rskTestnet = false;

var prefix;
var done = false;

if (options.network) {
var lower = options.network.toLowerCase();

var m = lower.match(/^([rt])?(btc|bch|bcc)$/);
var m = lower.match(/^([rt])?(btc|bch|bcc|rsk)$/);
if (!m) {
throw new Error("Invalid network [" + options.network + "]");
}

if (m[2] === 'btc') {
network = "BTC";
} else if (m[2] === 'rsk') {
network = "RSK";
} else {
network = "BCC";
}

prefix = m[1];
if (prefix) {
if (prefix && network !== "RSK") {
// if there's a prefix then we're "done", won't apply options.regtest and options.testnet after
done = true;
if (prefix === 'r') {
Expand All @@ -166,6 +175,11 @@ APIClient.normalizeNetworkFromOptions = function(options) {
} else if (prefix === 't') {
testnet = true;
}
} else if (prefix && network === "RSK") {
done = true;
if (prefix === 'r' || prefix === 't') {
rskTestnet = true;
}
}
}

Expand All @@ -183,7 +197,7 @@ APIClient.normalizeNetworkFromOptions = function(options) {

apiNetwork = (prefix || "") + network;

return [network, testnet, regtest, apiNetwork];
return [network, testnet, regtest, apiNetwork, rskTestnet];
};

APIClient.updateHostOptions = function(options) {
Expand Down Expand Up @@ -1277,34 +1291,61 @@ APIClient.prototype.initWallet = function(options, cb) {
throw new Error("Backup key returned from server didn't match our own copy");
}
}
var backupPublicKey = bitcoin.HDNode.fromBase58(result.backup_public_key[0], self.network);
var blocktrailPublicKeys = _.mapValues(result.blocktrail_public_keys, function(blocktrailPublicKey) {
return bitcoin.HDNode.fromBase58(blocktrailPublicKey[0], self.network);
});
var primaryPublicKeys = _.mapValues(result.primary_public_keys, function(primaryPublicKey) {

var backupPublicKey,blocktrailPublicKeys,primaryPublicKeys, wallet;

primaryPublicKeys = _.mapValues(result.primary_public_keys, function(primaryPublicKey) {
return bitcoin.HDNode.fromBase58(primaryPublicKey[0], self.network);
});

// initialize wallet
var wallet = new Wallet(
self,
identifier,
options.walletVersion,
result.primary_mnemonic,
result.encrypted_primary_seed,
result.encrypted_secret,
primaryPublicKeys,
backupPublicKey,
blocktrailPublicKeys,
keyIndex,
result.segwit || 0,
self.testnet,
self.regtest,
result.checksum,
result.upgrade_key_index,
options.useCashAddress,
options.bypassNewAddressCheck
);
// Initializing a rootstock wallet does not require backup public key and blocktrail public key.
if (self.chain === APIClient.ROOTSTOCK_NETWORK) {
wallet = new Wallet(
self,
identifier,
options.walletVersion,
result.primary_mnemonic,
result.encrypted_primary_seed,
result.encrypted_secret,
primaryPublicKeys,
backupPublicKey,
blocktrailPublicKeys,
keyIndex,
result.segwit || 0,
self.testnet,
self.regtest,
result.checksum,
result.upgrade_key_index,
options.useCashAddress,
options.bypassNewAddressCheck
);
} else {
backupPublicKey = bitcoin.HDNode.fromBase58(result.backup_public_key[0], self.network);
blocktrailPublicKeys = _.mapValues(result.blocktrail_public_keys, function(blocktrailPublicKey) {
return bitcoin.HDNode.fromBase58(blocktrailPublicKey[0], self.network);
});

// initialize wallet
wallet = new Wallet(
self,
identifier,
options.walletVersion,
result.primary_mnemonic,
result.encrypted_primary_seed,
result.encrypted_secret,
primaryPublicKeys,
backupPublicKey,
blocktrailPublicKeys,
keyIndex,
result.segwit || 0,
self.testnet,
self.regtest,
result.checksum,
result.upgrade_key_index,
options.useCashAddress,
options.bypassNewAddressCheck
);
}

wallet.recoverySecret = result.recovery_secret;

Expand Down Expand Up @@ -1351,7 +1392,6 @@ APIClient.CREATE_WALLET_PROGRESS_DONE = 100;
*/
APIClient.prototype.createNewWallet = function(options, cb) {
/* jshint -W071, -W074 */

var self = this;

if (typeof options !== "object") {
Expand Down Expand Up @@ -1655,7 +1695,6 @@ APIClient.prototype._createNewWalletV3 = function(options) {
if (options.primaryPrivateKey) {
throw new blocktrail.WalletInitError("Can't specify; Primary PrivateKey");
}

// seed should be provided or generated
options.primarySeed = options.primarySeed || randomBytes(Wallet.WALLET_ENTROPY_BITS / 8);

Expand Down Expand Up @@ -1944,6 +1983,58 @@ APIClient.prototype.getNewDerivation = function(identifier, path, cb) {
return self.blocktrailClient.post("/wallet/" + identifier + "/path", null, {path: path}, cb);
};

/**
* use the API to get account details for an Rootstock Address
*
* the return object has the following format:
* {
* "confirmed_balance" => 32746327,
* "address" => "0xaddress",
* "path" => "m/44'/1'/0'/0/13",
* "nonce" => 3,
* }
*
* @param identifier string the wallet identifier
* @param address string address associated with account
* @param options
* @param [cb] function callback(err, utxos, fee, change)
* @returns {q.Promise}
*/
APIClient.prototype.getRskAccount = function(identifier, address, options, cb) {
var self = this;

if (typeof options === "function") {
cb = options;
options = {};
}

options = options || {};

var deferred = q.defer();
deferred.promise.spreadNodeify(cb);

var params = {
address: address
};

deferred.resolve(
self.blocktrailClient.post("/wallet/" + identifier + "/account", params).then(
function(result) {
return [
String(result.confirmed_balance),
result.address,
result.path,
result.nonce
];
},
function(err) {
throw err;
}
)
);

return deferred.promise;
};

/**
* delete the wallet
Expand Down Expand Up @@ -2124,6 +2215,30 @@ APIClient.prototype.sendTransaction = function(identifier, txHex, paths, checkFe
);
};

APIClient.prototype.sendRskTransaction = function(identifier, txHex, twoFactorToken, options, cb) {
var self = this;

if (typeof twoFactorToken === "function") {
cb = twoFactorToken;
twoFactorToken = null;
} else if (typeof options === "function") {
cb = options;
options = {};
}

var data = {
two_factor_token: twoFactorToken,
raw_transaction: txHex
};


return self.blocktrailClient.post(
"/wallet/" + identifier + "/send",
data,
cb
);
};

/**
* setup a webhook for this wallet
*
Expand Down
Loading