Browse Source

Merge pull request #28 from isocolsky/test_time

Refactor object construction
activeAddress
Matias Alejo Garcia 10 years ago
parent
commit
a469baac05
  1. 14
      lib/client/api.js
  2. 21
      lib/model/address.js
  3. 30
      lib/model/addressmanager.js
  4. 56
      lib/model/copayer.js
  5. 26
      lib/model/notification.js
  6. 42
      lib/model/txproposal.js
  7. 22
      lib/model/txproposalaction.js
  8. 77
      lib/model/wallet.js
  9. 8
      lib/server.js
  10. 2
      lib/walletutils.js
  11. 6
      test/addressmanager.js
  12. 10
      test/testdata.js

14
lib/client/api.js

@ -18,8 +18,8 @@ var BASE_URL = 'http://localhost:3001/copay/api';
var WALLET_CRITICAL_DATA = ['xPrivKey', 'm', 'publicKeyRing'];
function _createProposalOpts(opts, signingKey) {
var msg = opts.toAddress + '|' + opts.amount + '|' + opts.message;
opts.proposalSignature = WalletUtils.signMessage(msg, signingKey);
var hash = WalletUtils.getProposalHash(opts.toAddress, opts.amount, opts.message);
opts.proposalSignature = WalletUtils.signMessage(hash, signingKey);
return opts;
};
@ -346,10 +346,10 @@ API.prototype.import = function(str, cb) {
var xPubKey = (new Bitcore.HDPublicKey(data.xPrivKey)).toString();
data.publicKeyRing.push(xPubKey);
data.copayerId = WalletUtils.xpubToCopayerId(xPubKey);
data.copayerId = WalletUtils.xPubToCopayerId(xPubKey);
data.m = data.publicKeyRing.length;
data.signingPrivKey = (new Bitcore.HDPrivateKey(data.xPrivKey)).derive('m/1/0').privateKey.toWIF();
data.network = data.xPrivKey.substr(0,4) === 'tprv' ? 'testnet' : 'livenet';
data.network = data.xPrivKey.substr(0, 4) === 'tprv' ? 'testnet' : 'livenet';
self.storage.save(data, cb);
});
};
@ -371,9 +371,9 @@ API.prototype.signTxProposal = function(txp, cb) {
this._loadAndCheck(function(err, data) {
if (err) return cb(err);
if (!Verifier.checkTxProposal(data, txp)) {
return cb(new ServerCompromisedError('Server sent fake transaction proposal'));
}
if (!Verifier.checkTxProposal(data, txp)) {
return cb(new ServerCompromisedError('Server sent fake transaction proposal'));
}
//Derive proper key to sign, for each input

21
lib/model/address.js

@ -2,16 +2,23 @@
var Bitcore = require('bitcore');
function Address(opts) {
function Address() {
this.version = '1.0.0';
};
Address.create = function(opts) {
opts = opts || {};
this.createdOn = Math.floor(Date.now() / 1000);
this.address = opts.address;
this.path = opts.path;
this.publicKeys = opts.publicKeys;
var x = new Address();
x.createdOn = Math.floor(Date.now() / 1000);
x.address = opts.address;
x.path = opts.path;
x.publicKeys = opts.publicKeys;
return x;
};
Address.fromObj = function (obj) {
Address.fromObj = function(obj) {
var x = new Address();
x.createdOn = obj.createdOn;
@ -28,7 +35,7 @@ Address.fromObj = function (obj) {
* @param {number} threshold - amount of required signatures to spend the output
* @return {Script}
*/
Address.prototype.getScriptPubKey = function (threshold) {
Address.prototype.getScriptPubKey = function(threshold) {
return Bitcore.Script.buildMultisigOut(this.publicKeys, threshold).toScriptHashOut();
};

30
lib/model/addressmanager.js

@ -1,24 +1,34 @@
var _ = require('lodash');
var HDPath = require('../hdpath');
function AddressManager(opts) {
this.receiveAddressIndex = 0;
this.changeAddressIndex = 0;
this.copayerIndex = (opts && _.isNumber(opts.copayerIndex)) ? opts.copayerIndex : HDPath.SHARED_INDEX;
function AddressManager() {
this.version = '1.0.0';
};
AddressManager.create = function(opts) {
opts = opts || {};
AddressManager.fromObj = function (obj) {
var x = new AddressManager();
x.receiveAddressIndex = obj.receiveAddressIndex;
x.receiveAddressIndex = 0;
x.changeAddressIndex = 0;
x.copayerIndex = (opts && _.isNumber(opts.copayerIndex)) ? opts.copayerIndex : HDPath.SHARED_INDEX;
return x;
};
AddressManager.fromObj = function(obj) {
var x = new AddressManager();
x.receiveAddressIndex = obj.receiveAddressIndex;
x.changeAddressIndex = obj.changeAddressIndex;
x.copayerIndex = obj.copayerIndex;
return x;
};
AddressManager.prototype._incrementIndex = function (isChange) {
AddressManager.prototype._incrementIndex = function(isChange) {
if (isChange) {
this.changeAddressIndex++;
} else {
@ -26,11 +36,11 @@ AddressManager.prototype._incrementIndex = function (isChange) {
}
};
AddressManager.prototype.getCurrentAddressPath = function (isChange) {
return HDPath.Branch(isChange ? this.changeAddressIndex : this.receiveAddressIndex, isChange, this.copayerIndex);
AddressManager.prototype.getCurrentAddressPath = function(isChange) {
return HDPath.Branch(isChange ? this.changeAddressIndex : this.receiveAddressIndex, isChange, this.copayerIndex);
};
AddressManager.prototype.getNewAddressPath = function (isChange) {
AddressManager.prototype.getNewAddressPath = function(isChange) {
var ret = this.getCurrentAddressPath(isChange);
this._incrementIndex(isChange);
return ret;

56
lib/model/copayer.js

@ -11,49 +11,57 @@ var AddressManager = require('./addressmanager');
var Utils = require('../walletutils');
var VERSION = '1.0.0';
var MESSAGE_SIGNING_PATH = "m/1/0";
function Copayer(opts) {
function Copayer() {
this.version = '1.0.0';
};
Copayer.create = function(opts) {
$.checkArgument(opts && opts.xPubKey, 'need to provide an xPubKey');
opts.copayerIndex = opts.copayerIndex || 0;
this.xPubKey = opts.xPubKey;
this.id = Utils.xpubToCopayerId(this.xPubKey);
var x = new Copayer();
x.createdOn = Math.floor(Date.now() / 1000);
this.version = VERSION;
this.createdOn = Math.floor(Date.now() / 1000);
this.name = opts.name;
this.xPubKeySignature = opts.xPubKeySignature; // So third parties can check independently
if (this.xPubKey)
this.signingPubKey = this.getSigningPubKey();
this.addressManager = new AddressManager({ copayerIndex: opts.copayerIndex });
};
x.xPubKey = opts.xPubKey;
Copayer.prototype.getPublicKey = function(path) {
return HDPublicKey
.fromString(this.xPubKey)
.derive(path)
.publicKey
.toString();
};
x.id = Utils.xPubToCopayerId(x.xPubKey);
x.name = opts.name;
x.xPubKeySignature = opts.xPubKeySignature; // So third parties can check independently
x.signingPubKey = x.getSigningPubKey();
x.addressManager = AddressManager.create({
copayerIndex: opts.copayerIndex
});
Copayer.prototype.getSigningPubKey = function() {
return this.getPublicKey(MESSAGE_SIGNING_PATH);
return x;
};
Copayer.fromObj = function(obj) {
var x = new Copayer({
xPubKey: obj.xPubKey,
});
var x = new Copayer();
x.createdOn = obj.createdOn;
x.id = obj.id;
x.name = obj.name;
x.xPubKey = obj.xPubKey;
x.xPubKeySignature = obj.xPubKeySignature;
x.signingPubKey = obj.signingPubKey;
x.addressManager = AddressManager.fromObj(obj.addressManager);
return x;
};
Copayer.prototype.getPublicKey = function(path) {
return HDPublicKey
.fromString(this.xPubKey)
.derive(path)
.publicKey
.toString();
};
Copayer.prototype.getSigningPubKey = function() {
return this.getPublicKey(MESSAGE_SIGNING_PATH);
};
module.exports = Copayer;

26
lib/model/notification.js

@ -1,5 +1,3 @@
var Uuid = require('uuid');
/*
@ -20,25 +18,33 @@ var Uuid = require('uuid');
* { amount: 'xxx', address: 'xxx'}
* { txProposalId: 'xxx', copayerId: 'xxx' }
*
* Data is meant to provide only the needed information
* to notify the user
* Data is meant to provide only the needed information
* to notify the user
*
*/
function Notification() {
this.version = '1.0.0';
};
function Notification(opts) {
Notification.create = function(opts) {
opts = opts || {};
var x = new Notification();
var now = Date.now();
this.createdOn = Math.floor(now / 1000);
this.id = ('00000000000000' + now).slice(-14) + ('0000' + opts.ticker||0).slice(-4) ;
this.type = opts.type || 'general';
this.data = opts.data;
x.createdOn = Math.floor(now / 1000);
x.id = ('00000000000000' + now).slice(-14) + ('0000' + opts.ticker || 0).slice(-4);
x.type = opts.type || 'general';
x.data = opts.data;
return x;
};
Notification.fromObj = function(obj) {
var x= new Notification();
var x = new Notification();
x.createdOn = obj.createdOn;
x.id = obj.id;
x.type = obj.type,
x.data = obj.data;

42
lib/model/txproposal.js

@ -7,28 +7,32 @@ var Address = Bitcore.Address;
var TxProposalAction = require('./txproposalaction');
var VERSION = '1.0.0';
function TxProposal() {
this.version = '1.0.0';
};
function TxProposal(opts) {
TxProposal.create = function(opts) {
opts = opts || {};
this.version = VERSION;
var x = new TxProposal();
var now = Date.now();
this.createdOn = Math.floor(now / 1000);
this.id = ('00000000000000' + now).slice(-14) + Uuid.v4();
this.creatorId = opts.creatorId;
this.toAddress = opts.toAddress;
this.amount = opts.amount;
this.message = opts.message;
this.proposalSignature = opts.proposalSignature;
this.changeAddress = opts.changeAddress;
this.inputs = opts.inputs;
this.inputPaths = opts.inputPaths;
this.requiredSignatures = opts.requiredSignatures;
this.requiredRejections = opts.requiredRejections;
this.status = 'pending';
this.actions = {};
x.createdOn = Math.floor(now / 1000);
x.id = ('00000000000000' + now).slice(-14) + Uuid.v4();
x.creatorId = opts.creatorId;
x.toAddress = opts.toAddress;
x.amount = opts.amount;
x.message = opts.message;
x.proposalSignature = opts.proposalSignature;
x.changeAddress = opts.changeAddress;
x.inputs = [];
x.inputPaths = [];
x.requiredSignatures = opts.requiredSignatures;
x.requiredRejections = opts.requiredRejections;
x.status = 'pending';
x.actions = {};
return x;
};
TxProposal.fromObj = function(obj) {
@ -51,7 +55,7 @@ TxProposal.fromObj = function(obj) {
x.inputPaths = obj.inputPaths;
x.actions = obj.actions;
_.each(x.actions, function(action, copayerId) {
x.actions[copayerId] = new TxProposalAction(action);
x.actions[copayerId] = TxProposalAction.fromObj(action);
});
return x;
@ -136,7 +140,7 @@ TxProposal.prototype.getActionBy = function(copayerId) {
};
TxProposal.prototype.addAction = function(copayerId, type, comment, signatures, xpub) {
var action = new TxProposalAction({
var action = TxProposalAction.create({
copayerId: copayerId,
type: type,
signatures: signatures,

22
lib/model/txproposalaction.js

@ -1,14 +1,22 @@
'use strict';
function TxProposalAction(opts) {
function TxProposalAction() {
this.version = '1.0.0';
};
TxProposalAction.create = function(opts) {
opts = opts || {};
this.createdOn = Math.floor(Date.now() / 1000);
this.copayerId = opts.copayerId;
this.type = opts.type || (opts.signatures ? 'accept' : 'reject');
this.signatures = opts.signatures;
this.xpub = opts.xpub;
this.comment = opts.comment;
var x = new TxProposalAction();
x.createdOn = Math.floor(Date.now() / 1000);
x.copayerId = opts.copayerId;
x.type = opts.type || (opts.signatures ? 'accept' : 'reject');
x.signatures = opts.signatures;
x.xpub = opts.xpub;
x.comment = opts.comment;
return x;
};
TxProposalAction.fromObj = function(obj) {

77
lib/model/wallet.js

@ -10,24 +10,49 @@ var Copayer = require('./copayer');
var AddressManager = require('./addressmanager');
var WalletUtils = require('../walletutils');
var VERSION = '1.0.0';
function Wallet() {
this.version = '1.0.0';
};
function Wallet(opts) {
Wallet.create = function(opts) {
opts = opts || {};
this.version = VERSION;
this.createdOn = Math.floor(Date.now() / 1000);
this.id = Uuid.v4();
this.name = opts.name;
this.m = opts.m;
this.n = opts.n;
this.status = 'pending';
this.publicKeyRing = [];
this.addressIndex = 0;
this.copayers = [];
this.pubKey = opts.pubKey;
this.network = opts.network;
this.addressManager = new AddressManager();
var x = new Wallet();
x.createdOn = Math.floor(Date.now() / 1000);
x.id = Uuid.v4();
x.name = opts.name;
x.m = opts.m;
x.n = opts.n;
x.status = 'pending';
x.publicKeyRing = [];
x.addressIndex = 0;
x.copayers = [];
x.pubKey = opts.pubKey;
x.network = opts.network;
x.addressManager = AddressManager.create();
return x;
};
Wallet.fromObj = function(obj) {
var x = new Wallet();
x.createdOn = obj.createdOn;
x.id = obj.id;
x.name = obj.name;
x.m = obj.m;
x.n = obj.n;
x.status = obj.status;
x.publicKeyRing = obj.publicKeyRing;
x.copayers = _.map(obj.copayers, function(copayer) {
return Copayer.fromObj(copayer);
});
x.pubKey = obj.pubKey;
x.network = obj.network;
x.addressManager = AddressManager.fromObj(obj.addressManager);
return x;
};
/* For compressed keys, m*73 + n*34 <= 496 */
@ -60,26 +85,6 @@ Wallet.verifyCopayerLimits = function(m, n) {
return (n >= 1 && n <= 12) && (m >= 1 && m <= Wallet.COPAYER_PAIR_LIMITS[n]);
};
Wallet.fromObj = function(obj) {
var x = new Wallet();
x.createdOn = obj.createdOn;
x.id = obj.id;
x.name = obj.name;
x.m = obj.m;
x.n = obj.n;
x.status = obj.status;
x.publicKeyRing = obj.publicKeyRing;
x.copayers = _.map(obj.copayers, function(copayer) {
return Copayer.fromObj(copayer);
});
x.pubKey = obj.pubKey;
x.network = obj.network;
x.addressManager = AddressManager.fromObj(obj.addressManager);
return x;
};
Wallet.prototype.isShared = function() {
return this.n > 1;
};
@ -117,7 +122,7 @@ Wallet.prototype.createAddress = function(isChange) {
$.checkState(this.isComplete());
var path = this.addressManager.getNewAddressPath(isChange);
return new Address(WalletUtils.deriveAddress(this.publicKeyRing, path, this.m, this.network));
return Address.create(WalletUtils.deriveAddress(this.publicKeyRing, path, this.m, this.network));
};

8
lib/server.js

@ -114,7 +114,7 @@ CopayServer.prototype.createWallet = function(opts, cb) {
return cb(e.toString());
};
var wallet = new Wallet({
var wallet = Wallet.create({
name: opts.name,
m: opts.m,
n: opts.n,
@ -169,7 +169,7 @@ CopayServer.prototype._notify = function(type, data) {
var walletId = self.walletId || data.walletId;
$.checkState(walletId);
var n = new Notification({
var n = Notification.create({
type: type,
data: data,
ticker: this.notifyTicker++,
@ -212,7 +212,7 @@ CopayServer.prototype.joinWallet = function(opts, cb) {
if (wallet.copayers.length == wallet.n)
return cb(new ClientError('WFULL', 'Wallet full'));
var copayer = new Copayer({
var copayer = Copayer.create({
name: opts.name,
xPubKey: opts.xPubKey,
xPubKeySignature: opts.xPubKeySignature,
@ -496,7 +496,7 @@ CopayServer.prototype.createTx = function(opts, cb) {
locked: true
});
var txp = new TxProposal({
var txp = TxProposal.create({
creatorId: self.copayerId,
toAddress: opts.toAddress,
amount: opts.amount,

2
lib/walletutils.js

@ -57,7 +57,7 @@ WalletUtils.getProposalHash = function(toAddress, amount, message) {
return toAddress + '|' + amount + '|' + (message || '');
};
WalletUtils.xpubToCopayerId = function(xpub) {
WalletUtils.xPubToCopayerId = function(xpub) {
return (new Bitcore.HDPublicKey(xpub)).derive(HDPath.IdBranch).publicKey.toString();
};

6
test/addressmanager.js

@ -10,7 +10,7 @@ var AddressManager = require('../lib/model/addressmanager');
describe('AddressManager', function() {
describe('#getCurrentAddressPath', function() {
it('should return a valid BIP32 path for given index', function() {
var am = new AddressManager({
var am = AddressManager.create({
copayerIndex: 4
});
am.getCurrentAddressPath(false).should.equal('m/4/0/0');
@ -19,14 +19,14 @@ describe('AddressManager', function() {
});
describe('#getCurrentAddressPath', function() {
it('should return a valid BIP32 path for defaut Index', function() {
var am = new AddressManager();
var am = AddressManager.create();
am.getCurrentAddressPath(false).should.equal('m/2147483647/0/0');
am.getCurrentAddressPath(true).should.equal('m/2147483647/1/0');
});
});
describe('#getNewAddressPath', function() {
it('should return a new valid BIP32 path for given index', function() {
var am = new AddressManager({
var am = AddressManager.create({
copayerIndex: 2
});
am.getNewAddressPath(false).should.equal('m/2/0/0');

10
test/testdata.js

@ -9,60 +9,70 @@ var message = {
};
var copayers = [{
id: '03bc5f0504c8dd480926dbe90449ccc7b2fc4c96e79f1cb8ffcd31731e2ee8db9b',
xPrivKey: 'xprv9s21ZrQH143K2rMHbXTJmWTuFx6ssqn1vyRoZqPkCXYchBSkp5ey8kMJe84sxfXq5uChWH4gk94rWbXZt2opN9kg4ufKGvUM7HQSLjnoh7e',
xPubKey: 'xpub661MyMwAqRbcFLRkhYzK8eQdoywNHJVsJCMQNDoMks5bZymuMcyDgYfnVQYq2Q9npnVmdTAthYGc3N3uxm5sEdnTpSqBc4YYTAhNnoSxCm9',
xPubKeySignature: '30440220192ae7345d980f45f908bd63ccad60ce04270d07b91f1a9d92424a07a38af85202201591f0f71dd4e79d9206d2306862e6b8375e13a62c193953d768e884b6fb5a46', // signed using keyPair.priv
privKey: '5c0e043a513032907d181325a8e7990b076c0af15ed13dc5e611cda9bb3ae52a', // derived with 'm/1/0'
pubKey: '03814ac7decf64321a3c6967bfb746112fdb5b583531cd512cc3787eaf578947dc',
}, {
id: '0235223413f8219260aa892c518969701af7c339284afecc7044f98dd47d48754b',
xPrivKey: 'xprv9s21ZrQH143K2JgXh8Va3Taq22D2gXw2nYULffV5dc9acQvAmB3KhomPKGwV9AbVsBcAXMW2QxCnvmHU1rVtHRfZwTxdEEAN5ZojRYdryQ1',
xPubKey: 'xpub661MyMwAqRbcEnkzoA2aQbXZa43X5zet9mPwU3thBwgZVDFKJiMaFc5sAYS97qVtMxpvceittobtoH2JKmpweSN1CLSe91hiE1Wrf5YJhsQ',
xPubKeySignature: '3045022100b9079d0d9b70da828b0e9c776fe01c5c13fc254a314c0b09a638c8695ec9360c022079922950779080569163c692ed8ee882f9ef37e7b2dff03de9c6756e7599960e',
privKey: '7708f0b7a60da9b88893e41eb2f59acf13ddc38edd794e1af9c2b57d35e99d85',
pubKey: '0266efb3b02973233636b153296486cdbc1728e1f42a1062f030af193ab14e1321',
}, {
id: '023f31628856799ce6a12d02d362fbf6acc2c112207eeeb7bd34a048ec2127645d',
xPrivKey: 'xprv9s21ZrQH143K2DoxHNrecLmp121HU4nZRB57jj2cGmSkp9Wrgz2AevFT98AcYocYXEyyWDwC1JUn13beDjQU87FwfCaHiWhgoSx9G31tmDa',
xPubKey: 'xpub661MyMwAqRbcEhtRPQPeyUiYZ3qmsXWQnPziY7SDq6yjgwr1EXLRCiZvzQsfnQehH8hBzCxNPYCJXx51QKcbervpkBK931H1A9F39z5E1XD',
xPubKeySignature: '3045022100ed04aca131acf6f030018a7e3dd564788bbad5528e9edb7880f032ae6917bf10022022879ca8a60700c9c3bf9d603ae2555d4be1914084c912579b4bc09a432e9c32',
privKey: 'a8e36ab9e065a5cc0551938c225d40542b7780a84aff55cb52e4eb4d7f64de11',
pubKey: '033e44b94789a591380787effbad0a01f41aedd7ed315c931efc51284e99ae34a9',
}, {
id: '024062aae3d6575b03a8532e618feeb70d6926c069e24cca0cb1a24db4dec6562e',
xPrivKey: 'xprv9s21ZrQH143K3dHn6j7zuLSnnMpBAceHfQFDm6R3wbkD26pTSUuZ7JY4549T8mMhwwUeq6SW6guDwy6cUhqs6PwoF2svKKkLjJdeKi1BzUn',
xPubKey: 'xpub661MyMwAqRbcG7NFCkf1GUPXLPefa5N92dApZUpfVwHBtu9bz2Dof6rXvKjioVpLXRBHKeyX2AxLdtaCbUtz2zx3dE9F4mPkDsARrPaGsSL',
xPubKeySignature: '3045022100a17dee46810e379aa37104ec1a4e20276aa41eac67b7e555475b15db6f6ee8ca0220472d114368f6d78bd8dba5c5fed77b22437341621d7879331bc48f7ee7701853',
privKey: '68cc2c1776f3456fcdef12812e634b6adbd676c5b8168a4b2547cf73c5363cfd',
pubKey: '027597e3a18c829dfdd92f875ae87f2aa4654cbb13db28a92a19401cf6f8ac18cb',
}, {
id: '031114b2afe5d1e87d834ac71798028724f8f89e2d3324b5e6abb513fdcde2e69d',
xPrivKey: 'xprv9s21ZrQH143K3Wac3NKJ8nZsBsn4HboPtCD2LDB8zkXcmo9q97efAi9i6KkcyBoJ4vjD59corGsdJebmNXud4nH3bCBSo64uWfwauo3Kdco',
xPubKey: 'xpub661MyMwAqRbcFzf59PrJVvWbjucYh4XFFR8d8bakZ64bebUygexuiWUBwa7EnFosoFstoocLQTrLPeAQThonSrYTDQ18gkS219dLJuwUHDb',
xPubKeySignature: '30440220023c1902434aaca0c2ed3c92262d56ee4296cd5c7598b009b8556deab2df89e70220714117970debf5cc1232441aa2d1ce335b5b99958acb2d000c4241e2a2fc567f',
privKey: 'fc97d94e97857b2016a1e68ab0313ce2ea5a791638e8eb0bb6d5a5aa72de01df',
pubKey: '03a3e04a3fb218b074306ca2a4995ec1ea97ef2b73dd54edfbae9ee56651dd21cc',
}, {
id: '03d5352705f1f587dad9814cbdae1ec627a9252f18ca677cd9d5243d41d44a7fea',
xPrivKey: 'xprv9s21ZrQH143K2Hxh1Xj59WjAimbDuubNBFknLYPr563BBziVuLhMvw7F3CkYMYj1y6QSbDnKQVHrMGekXi7awjLwKR1XWcMoR3eKEcH65Pa',
xPubKey: 'xpub661MyMwAqRbcEn3A7ZG5WefuGoRiKNKDYUgP8voTdRaA4o3eSt1cUjRitVc75a2gsifRDufbicYXeQCchDvkRKSSTWi1uy7PPaNHnerGvTa',
xPubKeySignature: '3044022042f063cd154a359f1d49202d79efc0737c47077ee50e36ed3d796327b9b29a9602206a4baf2902b49d1cb265eb31b9ab12d470fd023a11d9d425679a1630ba0b0e29',
privKey: '72381546174e6165e39853510bf3353645cb2e19e0499d3bb1d8aef0027352eb',
pubKey: '037e4163f69c3e2b05e980e3ac5dac06730894b1ba520a15a9d8221245d4bfe2a4',
}, {
id: '036fa483c6f226afecb2782a69ab11d1cf43c26f277280cb2ec69f88681d8a4418',
xPrivKey: 'xprv9s21ZrQH143K2L2wxVQ5nJ8FrTjz2KHB4wy83Xu6y6jdxmzrKNWvh6g7apPJqwj5NjhrmyJ6TYe9Hk4fbYx4tRg7Zk4Y7dAdgej4RVeUBTn',
xPubKey: 'xpub661MyMwAqRbcEp7R4Ww69S4zQVaURn12SAtiqvJiXSGcqaKzruqBEtzbS97V145KiYxsW4g9M3pqsibfc5mtbMn4R52v7bnnrHGAoiHb1pz',
xPubKeySignature: '304402207b082a63fc39b90a0f18edeb20d191430f11a9e5378681f15a68aac052aa858202201fd127b374e4a301a45f0c73d2a747d156a60075e643308e489a672bd0a7b4fb',
privKey: 'daff48eab1268c23e9ecde993b93ace4a375e7c627da0d3662746c7e3fecbdfa',
pubKey: '02035c09deeef7436df39a09ef2167129c686c6177185216525b9d778af96bacd7',
}, {
id: '03bc5f0504c8dd480926dbe90449ccc7b2fc4c96e79f1cb8ffcd31731e2ee8db9b',
xPrivKey: 'xprv9s21ZrQH143K3Pqe7LhTkE84VM6GysvSvggfhS3KbHvgBLaaQeR9YNePRo3vpLMVBv5SNhNVAaEDyj6Q8vMRVYM4X9bWYCiPgsJXkH8WzX1',
xPubKey: 'xpub661MyMwAqRbcFLRkhYzK8eQdoywNHJVsJCMQNDoMks5bZymuMcyDgYfnVQYq2Q9npnVmdTAthYGc3N3uxm5sEdnTpSqBc4YYTAhNnoSxCm9',
xPubKeySignature: '30440220192ae7345d980f45f908bd63ccad60ce04270d07b91f1a9d92424a07a38af85202201591f0f71dd4e79d9206d2306862e6b8375e13a62c193953d768e884b6fb5a46',
privKey: '5c0e043a513032907d181325a8e7990b076c0af15ed13dc5e611cda9bb3ae52a',
pubKey: '03814ac7decf64321a3c6967bfb746112fdb5b583531cd512cc3787eaf578947dc',
}, {
id: '02ec9ec4fd013c67312e0365128d470a89e13e53d9b44f026c5eca0b6e2ab9ae29',
xPrivKey: 'xprv9s21ZrQH143K2QSAHGxQhUsJYFDcZ6h2oiTjKFPmbnzeNzXgRW73NwX7ifBgbJ35eHGR7toyj9CCXB6Wzf5iCjj3YDuJuvBoJFJsiQAdTUH',
xPubKey: 'xpub661MyMwAqRbcEtWdPJVR4cp36H46xZQtAwPL7doPA8XdFnrpy3RHvjqbZxERYNMd4E2tt84xy4F2PqtKkHFDzZbSAaUabp36oZDwwPEqFjK',
xPubKeySignature: '304502210081a88684d4e27cab752d0df6a746aeb4bbcac57e73edd3847ffb43f1cf6740b20220312598f47dc5e775ea2ba97048764675afa4796173115049b4dacc8882b5c7b7',
privKey: '01273975489d85ac06f2e47677149420cd4901264cb40e3a756ff901acfc11f6',
pubKey: '0210eed257f41c9a991f8bd9523f66c3a83c1aab27cd2ccf233f8f5c3caef77e7a',
}, {
id: '02ec5f9178f77b306bc92362f3c1ef8f10b8cce44dc255ba20435f24d6459981db',
xPrivKey: 'xprv9s21ZrQH143K2bj7Azs1rCkumDJmbNveDA96wDJThzsDEJjBngkFXEr646AbvrTAfRd2scqq7hN48fGXesobx4sKRkddCrLaCpoWUkMJErj',
xPubKey: 'xpub661MyMwAqRbcF5oaH2Q2DLheKF9FzqeVaP4hjbi5GLQC774LLE4W53AZuMztQ6e6SMmEMj8K8zsP3iMMnJgK2PawWZCh7QcdgAg7eJWSJFr',
xPubKeySignature: '304402207781231f8bd9a679938057373702afdeec43e84b5b239e2e4dc8e35c63e4ee7102207f7ed929c81dfb59ebd14f56609dcd8255de6337c967704340a2089080fd896f',

Loading…
Cancel
Save