PHP WebShell
Текущая директория: /opt/BitGoJS/modules/sdk-coin-ada/test/unit
Просмотр файла: ada.ts
/**
* @prettier
*/
import should = require('should');
import { randomBytes } from 'crypto';
import * as sinon from 'sinon';
import { TestBitGo, TestBitGoAPI } from '@bitgo/sdk-test';
import { BitGoAPI } from '@bitgo/sdk-api';
import {
rawTx,
enterpriseAccounts as accounts,
privateKeys,
publicKeys,
wrwUser,
consolidationWrwUser,
address,
endpointResponses,
testnetUTXO,
ovcResponse,
ovcResponse2,
} from '../resources';
import * as _ from 'lodash';
import { Ada, KeyPair, Tada } from '../../src';
import { Transaction } from '../../src/lib';
import { TransactionType } from '../../../sdk-core/src/account-lib/baseCoin/enum';
describe('ADA', function () {
const coinName = 'ada';
const tcoinName = 't' + coinName;
let bitgo: TestBitGoAPI;
let basecoin;
let newTxPrebuild;
let newTxParams;
const txPrebuild = {
txHex: rawTx.unsignedTx,
txInfo: {},
};
const txParams = {
recipients: [
{
address: rawTx.outputAddress1.address,
amount: '5000000',
},
{
address: rawTx.outputAddress2.address,
amount: '248329150',
},
],
};
const transactionExplanation = {
displayOrder: ['id', 'outputAmount', 'changeAmount', 'outputs', 'changeOutputs', 'fee', 'type'],
id: 'f48f6ea0f75f3f942855cc0edf29e81e1e0724e75f5db8a1575b166fb202176c',
outputs: [
{
address:
'addr_test1qqnnvptrc3rec64q2n9jh572ncu5wvdtt8uvg4g3aj96s5dwu9nj70mlahzglm9939uevupsmj8dcdqv25d5n5r8vw8sn7prey',
amount: '7823121',
},
{
address: 'addr_test1vr8rakm66rcfv4fcxqykg5lf0yv7lsyk9mvapx369jpvtcgfcuk7f',
amount: '13041729',
},
],
outputAmount: '20864850',
changeOutputs: [],
changeAmount: '0',
fee: { fee: '167173' },
type: 'Transfer',
certificates: [],
withdrawals: [],
pledgeDetails: undefined,
};
before(function () {
bitgo = TestBitGo.decorate(BitGoAPI, { env: 'mock' });
bitgo.initializeTestVars();
bitgo.safeRegister(coinName, Ada.createInstance);
bitgo.safeRegister(tcoinName, Tada.createInstance);
basecoin = bitgo.coin(tcoinName);
newTxPrebuild = () => {
return _.cloneDeep(txPrebuild);
};
newTxParams = () => {
return _.cloneDeep(txParams);
};
});
it('should instantiate the coin', function () {
let localBasecoin = bitgo.coin(tcoinName);
localBasecoin.should.be.an.instanceof(Tada);
localBasecoin.getChain().should.equal(tcoinName);
localBasecoin.getFullName().should.equal('Testnet Ada');
localBasecoin = bitgo.coin(coinName);
localBasecoin.should.be.an.instanceof(Ada);
localBasecoin.getChain().should.equal(coinName);
localBasecoin.getFullName().should.equal('Cardano ADA');
});
describe('Sign Message', () => {
it('should be performed', async () => {
const keyPair = new KeyPair();
const messageToSign = Buffer.from(randomBytes(32)).toString('hex');
const signature = await basecoin.signMessage(keyPair.getKeys(), messageToSign);
keyPair.verifySignature(messageToSign, Uint8Array.from(signature)).should.equals(false);
});
it('should fail with missing private key', async () => {
const keyPair = new KeyPair({
pub: '7788327c695dca4b3e649a0db45bc3e703a2c67428fce360e61800cc4248f4f7',
}).getKeys();
const messageToSign = Buffer.from(randomBytes(32)).toString('hex');
await basecoin.signMessage(keyPair, messageToSign).should.be.rejectedWith('Invalid key pair options');
});
});
describe('Sign transaction', () => {
it('should sign transaction', async function () {
const signed = await basecoin.signTransaction({
txPrebuild: {
txHex: rawTx.unsignedTx2,
},
pubs: [publicKeys.pubKey1],
prv: privateKeys.prvKey4,
});
signed.txHex.should.equal(rawTx.signedTx2);
});
it('should fail to sign transaction with an invalid key', async function () {
try {
await basecoin.signTransaction({
txPrebuild: {
txHex: rawTx.unsignedTx2,
},
pubs: [publicKeys.pubKey1],
prv: privateKeys.prvKey2,
});
} catch (e) {
should.equal(e.message, 'Private key cannot sign the transaction');
}
});
it('should fail to build transaction with missing params', async function () {
try {
await basecoin.signTransaction({
txPrebuild: {
txHex: rawTx.unsignedTx,
key: accounts.account1.publicKey,
},
prv: accounts.account1.secretKey,
});
} catch (e) {
should.notEqual(e, null);
}
});
});
describe('Generate wallet key pair: ', () => {
it('should generate key pair', () => {
const kp = basecoin.generateKeyPair();
basecoin.isValidPub(kp.pub).should.equal(true);
basecoin.isValidPrv(kp.prv).should.equal(true);
});
it('should generate key pair from seed', () => {
const seed = Buffer.from('9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60', 'hex');
const kp = basecoin.generateKeyPair(seed);
basecoin.isValidPub(kp.pub).should.equal(true);
basecoin.isValidPrv(kp.prv).should.equal(true);
});
});
describe('Verify transaction: ', () => {
it('should succeed to verify unsigned transaction in hex encoding', async () => {
const txParams = newTxParams();
const txPrebuild = newTxPrebuild();
const verification = {};
const isTransactionVerified = await basecoin.verifyTransaction({ txParams, txPrebuild, verification });
isTransactionVerified.should.equal(true);
});
it('should succeed to verify signed transaction in hex encoding', async () => {
const txPrebuild = {
txHex: rawTx.signedTx,
txInfo: {},
};
const txParams = newTxParams();
const verification = {};
const isTransactionVerified = await basecoin.verifyTransaction({ txParams, txPrebuild, verification });
isTransactionVerified.should.equal(true);
});
it('should fail verify transactions when have different recipients', async () => {
const txPrebuild = newTxPrebuild();
const txParams = {
recipients: [
{
address: '9f7b0675db59d19b4bd9c8c72eaabba75a9863d02b30115b8b3c3ca5c20f0254',
amount: '1000000000000000000000000',
},
{
address: '9f7b0675db59d19b4bd9c8c72eaabba75a9863d02b30115b8b3c3ca5c20f0254',
amount: '2000000000000000000000000',
},
],
};
const verification = {};
await basecoin
.verifyTransaction({ txParams, txPrebuild, verification })
.should.be.rejectedWith('cannot find recipient in expected output');
});
it('should verify when input `recipients` is absent', async function () {
const txParams = newTxParams();
txParams.recipients = undefined;
const txPrebuild = newTxPrebuild();
const validTransaction = await basecoin.verifyTransaction({ txParams, txPrebuild });
validTransaction.should.equal(true);
});
it('should fail verify when txHex is invalid', async function () {
const txParams = newTxParams();
txParams.recipients = undefined;
const txPrebuild = {};
await basecoin
.verifyTransaction({ txParams, txPrebuild })
.should.rejectedWith('missing required tx prebuild property txHex');
});
it('should succeed to verify transactions when recipients has extra data', async function () {
const txPrebuild = newTxPrebuild();
const txParams = newTxParams();
txParams.data = 'data';
const validTransaction = await basecoin.verifyTransaction({ txParams, txPrebuild });
validTransaction.should.equal(true);
});
});
describe('Explain Transactions:', () => {
it('should explain an unsigned transfer transaction', async function () {
const explainedTransaction = await basecoin.explainTransaction({
txPrebuild: {
txHex: rawTx.unsignedTx2,
},
});
console.log(explainedTransaction);
explainedTransaction.should.deepEqual(transactionExplanation);
});
it('should fail to explain transaction with missing params', async function () {
try {
await basecoin.explainTransaction({
txPrebuild: {},
});
} catch (error) {
should.equal(error.message, 'Invalid transaction');
}
});
it('should fail to explain transaction with wrong params', async function () {
try {
await basecoin.explainTransaction({
txPrebuild: {
txHex: 'invalidTxHex',
},
});
} catch (error) {
should.equal(error.message, 'Invalid transaction');
}
});
});
describe('Parse Raw Transactions', () => {
it('should parse staking pledge transaction', function () {
const tx = new Transaction(basecoin);
tx.fromRawTransaction(rawTx.unsignedNewPledgeTx);
should.equal(tx.type, TransactionType.StakingPledge);
});
it('should parse staking activation tx', function () {
const tx = new Transaction(basecoin);
tx.fromRawTransaction(rawTx.unsignedStakingActiveTx);
should.equal(tx.type, TransactionType.StakingActivate);
});
it('should parse staking deactivation tx', function () {
const tx = new Transaction(basecoin);
tx.fromRawTransaction(rawTx.unsignedStakingDeactiveTx);
should.equal(tx.type, TransactionType.StakingDeactivate);
});
});
describe('Parse Transactions:', () => {
it('should parse an unsigned transfer transaction', async function () {
const parsedTransaction = await basecoin.parseTransaction({
txPrebuild: {
txHex: rawTx.unsignedTx2,
},
});
parsedTransaction.should.deepEqual(transactionExplanation);
});
it('should parse a signed transfer transaction', async function () {
const parsedTransaction = await basecoin.parseTransaction({
txPrebuild: {
txHex: rawTx.signedTx2,
},
});
parsedTransaction.should.deepEqual(transactionExplanation);
});
it('should fail parse a signed transfer transaction when explainTransaction response is undefined', async function () {
const stub = sinon.stub(Ada.prototype, 'explainTransaction');
stub.resolves(undefined);
await basecoin
.parseTransaction({
txPrebuild: {
txHex: rawTx.signedTx,
},
})
.should.be.rejectedWith('Invalid transaction');
stub.restore();
});
});
describe('Recover Transactions:', () => {
const destAddr = address.address2;
const sandBox = sinon.createSandbox();
beforeEach(function () {
const callBack = sandBox.stub(Ada.prototype, 'getDataFromNode' as keyof Ada);
callBack
.withArgs('address_info', {
_addresses: [wrwUser.walletAddress0],
})
.resolves(endpointResponses.addressInfoResponse.OneUTXO);
callBack.withArgs('tip').resolves(endpointResponses.tipInfoResponse);
});
afterEach(function () {
sandBox.restore();
});
it('should take OVC output and generate a signed sweep transaction', async function () {
const params = ovcResponse;
const recoveryTxn = await basecoin.createBroadcastableSweepTransaction(params);
recoveryTxn.transactions[0].serializedTx.should.equal(
'84a400818258204bd0f991c1532cffe31d4a10db492b43175ec326765b6b29ceee598df2b61f470001818258390087379ebc5533ebe621963c915c3cbc5f08537fcdca4af8f8ae08ed4c87379ebc5533ebe621963c915c3cbc5f08537fcdca4af8f8ae08ed4c1a05f359ff021a00028701031a024972e1a10081825820bbacb13431b99208e6e8cdbf710147feaf06a39d71565e60b411ce9e4fa3f137584001a4ab8236563f69ff309e5786e8f39c629ed57676c692159cb2e0494c9e663355384c13c749d04c17a80ba2a45cc127df480fc64a43199a772f11acd5b14a0ff5f6'
);
recoveryTxn.transactions[0].scanIndex.should.equal(0);
recoveryTxn.lastScanIndex.should.equal(0);
});
it('should take consolidation OVC output and generate multiple signed sweep transactions', async function () {
const params = ovcResponse2;
const recoveryTxn = await basecoin.createBroadcastableSweepTransaction(params);
recoveryTxn.transactions[0].serializedTx.should.equal(
'84a400818258203e62e5ee8b12012c4b949f9777b72165239bb2146ae8b078b4d1c5ca8d3168e300018182583900baf55ebcf9ada1b8ecb1640880fba54d2817690f12b3a106afd08004baf55ebcf9ada1b8ecb1640880fba54d2817690f12b3a106afd080041a00960f7f021a00028701031a0250f7eaa10081825820500e0d725a5ba3a306da3503dfe57b8a14068a09b61b36ec068fcf8cf5c391de5840c836ce6d3262d5654706ea06721522d3b75f6d545245047a7be7463629d88b3f4264b995f591df52bdffcf09da1e6ab9e88de3714c6e2ec1961786cf1c586a07f5f6'
);
recoveryTxn.transactions[0].scanIndex.should.equal(1);
recoveryTxn.transactions[1].serializedTx.should.equal(
'84a4008182582029c10acf0e08f9523325c88243565af6b32274992189c1153903c410bed7c2c700018182583900baf55ebcf9ada1b8ecb1640880fba54d2817690f12b3a106afd08004baf55ebcf9ada1b8ecb1640880fba54d2817690f12b3a106afd080041a00960f7f021a00028701031a0250f7eaa1008182582062770b224bd314bc526fbd6a94e9082fb6458c425e6e09bad74004dd897e962358403842544f2ff28be054eb7c7997bc303b1e251eb13a41802c82318e592bb24eaa3197c450e797cc8559f0356cd5cdd1ab5eb80c5173e34e9e1d1737533a89520cf5f6'
);
recoveryTxn.transactions[1].scanIndex.should.equal(2);
recoveryTxn.transactions[2].serializedTx.should.equal(
'84a40081825820dd140f133d865e1bb5642e708fe685bf7601d71d0c99511e5d552da7f8bd10ff00018182583900baf55ebcf9ada1b8ecb1640880fba54d2817690f12b3a106afd08004baf55ebcf9ada1b8ecb1640880fba54d2817690f12b3a106afd080041a00960f7f021a00028701031a0250f7eaa1008182582053b4bb74aa38add458dafc8153f0aa8266acad59322b877ca9c23c5d3873779d5840e94ce7896957d094c6bafbf2ec10df5ebb0f1d2a27a7e31f2d45c531fb687edd6c4d33f8e9b99c7692b6fac6d8399bd8fd47641baae9bbb69f518d42ad11710af5f6'
);
recoveryTxn.transactions[2].scanIndex.should.equal(3);
recoveryTxn.transactions[3].serializedTx.should.equal(
'84a4008182582015a1d6db5d3f592aa1cda185b6359ca0e2921c3c51959f64222a6b7d95d3392300018182583900baf55ebcf9ada1b8ecb1640880fba54d2817690f12b3a106afd08004baf55ebcf9ada1b8ecb1640880fba54d2817690f12b3a106afd080041a00960f7f021a00028701031a0250f7eaa10081825820600f86ca22d670f0a990ade4e882c05e654343263494735a31517de0819676735840fe199f8e247a4cfabfeb4f9cb574aa35739a0aa98860ee0a85d720c4ab4fecfac7b4504df310b3e4bea04711f60652d4a8cf5eb41817293b8d29977fe695f704f5f6'
);
recoveryTxn.transactions[3].scanIndex.should.equal(4);
recoveryTxn.lastScanIndex.should.equal(20);
});
it('should recover a txn for non-bitgo recoveries', async function () {
const res = await basecoin.recover({
userKey: wrwUser.userKey,
backupKey: wrwUser.backupKey,
bitgoKey: wrwUser.bitgoKey,
walletPassphrase: wrwUser.walletPassphrase,
recoveryDestination: destAddr,
});
res.should.not.be.empty();
res.should.hasOwnProperty('serializedTx');
sandBox.assert.calledTwice(basecoin.getDataFromNode);
const tx = new Transaction(basecoin);
tx.fromRawTransaction(res.serializedTx);
const txJson = tx.toJson();
const fee = Number(tx.explainTransaction().fee.fee);
should.deepEqual(txJson.inputs[0].transaction_id, testnetUTXO.UTXO_1.tx_hash);
should.deepEqual(txJson.inputs[0].transaction_index, testnetUTXO.UTXO_1.tx_index);
should.deepEqual(txJson.outputs[0].address, destAddr);
should.deepEqual(Number(txJson.outputs[0].amount) + fee, testnetUTXO.UTXO_1.value);
});
it('should recover a txn for unsigned sweep recoveries', async function () {
const res = await basecoin.recover({
bitgoKey: wrwUser.bitgoKey,
recoveryDestination: destAddr,
});
res.should.not.be.empty();
res.txRequests[0].transactions[0].unsignedTx.should.hasOwnProperty('serializedTx');
sandBox.assert.calledTwice(basecoin.getDataFromNode);
const tx = new Transaction(basecoin);
tx.fromRawTransaction(res.txRequests[0].transactions[0].unsignedTx.serializedTx);
const txJson = tx.toJson();
const fee = Number(tx.explainTransaction().fee.fee);
should.deepEqual(txJson.inputs[0].transaction_id, testnetUTXO.UTXO_1.tx_hash);
should.deepEqual(txJson.inputs[0].transaction_index, testnetUTXO.UTXO_1.tx_index);
should.deepEqual(txJson.outputs[0].address, destAddr);
should.deepEqual(Number(txJson.outputs[0].amount) + fee, testnetUTXO.UTXO_1.value);
});
});
describe('Recover Transactions Multiple UTXO:', () => {
const destAddr = address.address2;
const sandBox = sinon.createSandbox();
beforeEach(function () {
const callBack = sandBox.stub(Ada.prototype, 'getDataFromNode' as keyof Ada);
callBack
.withArgs('address_info', {
_addresses: [wrwUser.walletAddress0],
})
.resolves(endpointResponses.addressInfoResponse.TwoUTXO);
callBack.withArgs('tip').resolves(endpointResponses.tipInfoResponse);
});
afterEach(function () {
sandBox.restore();
});
it('should recover a txn for non-bitgo recoveries', async function () {
const res = await basecoin.recover({
userKey: wrwUser.userKey,
backupKey: wrwUser.backupKey,
bitgoKey: wrwUser.bitgoKey,
walletPassphrase: wrwUser.walletPassphrase,
recoveryDestination: destAddr,
});
res.should.not.be.empty();
res.should.hasOwnProperty('serializedTx');
sandBox.assert.calledTwice(basecoin.getDataFromNode);
const tx = new Transaction(basecoin);
tx.fromRawTransaction(res.serializedTx);
const txJson = tx.toJson();
const fee = Number(tx.explainTransaction().fee.fee);
should.deepEqual(txJson.inputs[0].transaction_id, testnetUTXO.UTXO_1.tx_hash);
should.deepEqual(txJson.inputs[0].transaction_index, testnetUTXO.UTXO_1.tx_index);
should.deepEqual(txJson.inputs[1].transaction_id, testnetUTXO.UTXO_2.tx_hash);
should.deepEqual(txJson.inputs[1].transaction_index, testnetUTXO.UTXO_2.tx_index);
should.deepEqual(txJson.outputs[0].address, destAddr);
should.deepEqual(Number(txJson.outputs[0].amount) + fee, testnetUTXO.UTXO_1.value + testnetUTXO.UTXO_2.value);
});
it('should recover a txn for unsigned sweep recoveries', async function () {
const res = await basecoin.recover({
bitgoKey: wrwUser.bitgoKey,
recoveryDestination: destAddr,
});
res.should.not.be.empty();
res.txRequests[0].transactions[0].unsignedTx.should.hasOwnProperty('serializedTx');
sandBox.assert.calledTwice(basecoin.getDataFromNode);
const tx = new Transaction(basecoin);
tx.fromRawTransaction(res.txRequests[0].transactions[0].unsignedTx.serializedTx);
const txJson = tx.toJson();
const fee = Number(tx.explainTransaction().fee.fee);
should.deepEqual(txJson.inputs[0].transaction_id, testnetUTXO.UTXO_1.tx_hash);
should.deepEqual(txJson.inputs[0].transaction_index, testnetUTXO.UTXO_1.tx_index);
should.deepEqual(txJson.inputs[1].transaction_id, testnetUTXO.UTXO_2.tx_hash);
should.deepEqual(txJson.inputs[1].transaction_index, testnetUTXO.UTXO_2.tx_index);
should.deepEqual(txJson.outputs[0].address, destAddr);
should.deepEqual(Number(txJson.outputs[0].amount) + fee, testnetUTXO.UTXO_1.value + testnetUTXO.UTXO_2.value);
});
});
describe('Build Consolidation Recoveries:', () => {
const baseAddr = consolidationWrwUser.walletAddress0;
const sandBox = sinon.createSandbox();
beforeEach(function () {
const callBack = sandBox.stub(Ada.prototype, 'getDataFromNode' as keyof Ada);
callBack
.withArgs('address_info', {
_addresses: [consolidationWrwUser.walletAddress1],
})
.resolves(endpointResponses.addressInfoResponse.ZeroUTXO);
callBack
.withArgs('address_info', {
_addresses: [consolidationWrwUser.walletAddress2],
})
.resolves(endpointResponses.addressInfoResponse.OneUTXO);
callBack
.withArgs('address_info', {
_addresses: [consolidationWrwUser.walletAddress3],
})
.resolves(endpointResponses.addressInfoResponse.OneUTXO2);
callBack.withArgs('tip').resolves(endpointResponses.tipInfoResponse);
});
afterEach(function () {
sandBox.restore();
});
it('should build signed consolidation recoveries', async function () {
const res = await basecoin.recoverConsolidations({
userKey: consolidationWrwUser.userKey,
backupKey: consolidationWrwUser.backupKey,
bitgoKey: consolidationWrwUser.bitgoKey,
walletPassphrase: consolidationWrwUser.walletPassphrase,
startingScanIndex: 1,
endingScanIndex: 4,
});
res.should.not.be.empty();
res.transactions.length.should.equal(2);
res.lastScanIndex.should.equal(3);
const txn1 = res.transactions[0];
const tx1 = new Transaction(basecoin);
tx1.fromRawTransaction(txn1.serializedTx);
const txJson1 = tx1.toJson();
const fee1 = Number(tx1.explainTransaction().fee.fee);
should.deepEqual(txJson1.inputs[0].transaction_id, testnetUTXO.UTXO_1.tx_hash);
should.deepEqual(txJson1.inputs[0].transaction_index, testnetUTXO.UTXO_1.tx_index);
should.deepEqual(txJson1.outputs[0].address, baseAddr);
should.deepEqual(Number(txJson1.outputs[0].amount) + fee1, testnetUTXO.UTXO_1.value);
const txn2 = res.transactions[1];
const tx2 = new Transaction(basecoin);
tx2.fromRawTransaction(txn2.serializedTx);
const txJson2 = tx2.toJson();
const fee2 = Number(tx2.explainTransaction().fee.fee);
should.deepEqual(txJson2.inputs[0].transaction_id, testnetUTXO.UTXO_2.tx_hash);
should.deepEqual(txJson2.inputs[0].transaction_index, testnetUTXO.UTXO_2.tx_index);
should.deepEqual(txJson2.outputs[0].address, baseAddr);
should.deepEqual(Number(txJson2.outputs[0].amount) + fee2, testnetUTXO.UTXO_2.value);
});
it('should skip building consolidate transaction if balance is equal to zero', async function () {
await basecoin
.recoverConsolidations({
userKey: consolidationWrwUser.userKey,
backupKey: consolidationWrwUser.backupKey,
bitgoKey: consolidationWrwUser.bitgoKey,
walletPassphrase: consolidationWrwUser.walletPassphrase,
startingScanIndex: 1,
endingScanIndex: 2,
})
.should.rejectedWith('Did not find an address with funds to recover');
});
it('should throw if startingScanIndex is not ge to 1', async () => {
await basecoin
.recoverConsolidations({
userKey: consolidationWrwUser.userKey,
backupKey: consolidationWrwUser.backupKey,
bitgoKey: consolidationWrwUser.bitgoKey,
startingScanIndex: -1,
})
.should.be.rejectedWith(
'Invalid starting or ending index to scan for addresses. startingScanIndex: -1, endingScanIndex: 19.'
);
});
it('should throw if scan factor is too high', async () => {
await basecoin
.recoverConsolidations({
userKey: consolidationWrwUser.userKey,
backupKey: consolidationWrwUser.backupKey,
bitgoKey: consolidationWrwUser.bitgoKey,
startingScanIndex: 1,
endingScanIndex: 300,
})
.should.be.rejectedWith(
'Invalid starting or ending index to scan for addresses. startingScanIndex: 1, endingScanIndex: 300.'
);
});
});
describe('Recover Transactions Failure:', () => {
const destAddr = address.address2;
const sandBox = sinon.createSandbox();
afterEach(function () {
sandBox.restore();
});
it('should fail to recover due to not finding an address with funds', async function () {
const callBack = sandBox.stub(Ada.prototype, 'getDataFromNode' as keyof Ada);
callBack
.withArgs('address_info', sinon.match.has('_addresses'))
.resolves(endpointResponses.addressInfoResponse.ZeroUTXO);
callBack.withArgs('tip').resolves(endpointResponses.tipInfoResponse);
await basecoin
.recover({
userKey: wrwUser.userKey,
backupKey: wrwUser.backupKey,
bitgoKey: wrwUser.bitgoKey,
walletPassphrase: wrwUser.walletPassphrase,
recoveryDestination: destAddr,
})
.should.rejectedWith('Did not find address with funds to recover');
sandBox.assert.calledOnce(basecoin.getDataFromNode);
});
it('should fail to recover due to not having more than 1 ADA in funds', async function () {
const callBack = sandBox.stub(Ada.prototype, 'getDataFromNode' as keyof Ada);
callBack
.withArgs('address_info', sinon.match.has('_addresses'))
.resolves(endpointResponses.addressInfoResponse.OneSmallUTXO);
callBack.withArgs('tip').resolves(endpointResponses.tipInfoResponse);
await basecoin
.recover({
userKey: wrwUser.userKey,
backupKey: wrwUser.backupKey,
bitgoKey: wrwUser.bitgoKey,
walletPassphrase: wrwUser.walletPassphrase,
recoveryDestination: destAddr,
})
.should.rejectedWith(
'Insufficient funds to recover, minimum required is 1 ADA plus fees, got 9834455 fees: 165545'
);
sandBox.assert.calledTwice(basecoin.getDataFromNode);
});
});
});
Выполнить команду
Для локальной разработки. Не используйте в интернете!