PHP WebShell

Текущая директория: /opt/BitGoJS/modules/sdk-coin-tao/test/unit

Просмотр файла: tao.ts

import should = require('should');
import { TestBitGo, TestBitGoAPI } from '@bitgo/sdk-test';
import { BitGoAPI } from '@bitgo/sdk-api';
import { Tao, Ttao } from '../../src';
import * as sinon from 'sinon';
import * as testData from './fixtures';
import { txVersion, genesisHash, specVersion } from '../resources';
import { afterEach } from 'mocha';

describe('Tao:', function () {
  let bitgo: TestBitGoAPI;
  let baseCoin;

  before(function () {
    bitgo = TestBitGo.decorate(BitGoAPI, { env: 'mock' });
    bitgo.safeRegister('tao', Tao.createInstance);
    bitgo.safeRegister('ttao', Ttao.createInstance);
    bitgo.initializeTestVars();
    baseCoin = bitgo.coin('ttao') as Ttao;
  });

  describe.skip('Recover Transactions:', function () {
    const sandBox = sinon.createSandbox();
    const recoveryDestination = '5FJ18ywfrWuRifNyc8aPwQ5ium19Fefwmx18H4XYkDc36F2A';
    const nonce = 2;
    let accountInfoCB;
    let headerInfoCB;
    let getFeeCB;

    beforeEach(function () {
      accountInfoCB = sandBox.stub(Tao.prototype, 'getAccountInfo' as keyof Tao);
      headerInfoCB = sandBox.stub(Tao.prototype, 'getHeaderInfo' as keyof Tao);
      getFeeCB = sandBox.stub(Tao.prototype, 'getFee' as keyof Tao);

      getFeeCB.withArgs(recoveryDestination, testData.wrwUser.walletAddress0, 1510000000000).resolves(15783812856); // TODD: use it later
    });

    afterEach(function () {
      sandBox.restore();
    });

    it('should generate unsigned sweep correctly', async function () {
      accountInfoCB.withArgs(testData.unsignedSweepUser.walletAddress0).resolves({ nonce: 1, freeBalance: 2989864739 });
      headerInfoCB.resolves({
        headerNumber: testData.westendBlock.blockNumber,
        headerHash: testData.westendBlock.hash,
      });

      const commonKeyChain =
        'd4a570c1831c7024cb72533e42690cec9d9150b9aac59001c4a5a3a285518263a9e89f1c709bcb1e832f2ff5169fecd496881ba8970f69d5adc977ba4799fedb'; // TODO: add common key chain

      const unsigned = await baseCoin.recover({ bitgoKey: commonKeyChain, recoveryDestination });

      unsigned.txRequests.should.not.be.undefined();
      unsigned.txRequests.length.should.equal(1);
      unsigned.txRequests[0].transactions.length.should.equal(1);
      unsigned.txRequests[0].walletCoin.should.equal('ttao');
      unsigned.txRequests[0].transactions[0].unsignedTx.should.not.be.undefined();
      unsigned.txRequests[0].transactions[0].unsignedTx.serializedTx.should.not.be.undefined();
      unsigned.txRequests[0].transactions[0].unsignedTx.scanIndex.should.equal(0);
      unsigned.txRequests[0].transactions[0].unsignedTx.coin.should.equal('ttao');
      unsigned.txRequests[0].transactions[0].unsignedTx.signableHex.should.not.be.undefined();
      unsigned.txRequests[0].transactions[0].unsignedTx.derivationPath.should.equal('m/0');
      unsigned.txRequests[0].transactions[0].unsignedTx.parsedTx.should.not.be.undefined();
      unsigned.txRequests[0].transactions[0].unsignedTx.parsedTx.inputs.should.not.be.undefined();
      unsigned.txRequests[0].transactions[0].unsignedTx.parsedTx.inputs.length.should.equal(1);
      unsigned.txRequests[0].transactions[0].unsignedTx.parsedTx.inputs[0].address.should.equal(
        '5Ehp6rRKp4zZxW3zh4SUA79zEj5GDXuNhTy7y7g12DT2kh4C'
      );
      unsigned.txRequests[0].transactions[0].unsignedTx.parsedTx.inputs[0].valueString.should.equal('2989864739');
      unsigned.txRequests[0].transactions[0].unsignedTx.parsedTx.inputs[0].value.should.equal(2989864739);
      unsigned.txRequests[0].transactions[0].unsignedTx.parsedTx.outputs.should.not.be.undefined();
      unsigned.txRequests[0].transactions[0].unsignedTx.parsedTx.outputs.length.should.equal(1);
      unsigned.txRequests[0].transactions[0].unsignedTx.parsedTx.outputs[0].address.should.equal(
        '5FJ18ywfrWuRifNyc8aPwQ5ium19Fefwmx18H4XYkDc36F2A'
      );
      unsigned.txRequests[0].transactions[0].unsignedTx.parsedTx.outputs[0].valueString.should.equal('2989864739');
      unsigned.txRequests[0].transactions[0].unsignedTx.parsedTx.outputs[0].coinName.should.equal('ttao');
      unsigned.txRequests[0].transactions[0].unsignedTx.parsedTx.type.should.equal('');
      unsigned.txRequests[0].transactions[0].unsignedTx.feeInfo.should.not.be.undefined();
      unsigned.txRequests[0].transactions[0].unsignedTx.feeInfo.fee.should.equal(0);
      unsigned.txRequests[0].transactions[0].unsignedTx.feeInfo.feeString.should.equal('0');
      unsigned.txRequests[0].transactions[0].unsignedTx.coinSpecific.should.not.be.undefined();
      unsigned.txRequests[0].transactions[0].unsignedTx.coinSpecific.firstValid.should.not.be.undefined();
      unsigned.txRequests[0].transactions[0].unsignedTx.coinSpecific.maxDuration.should.equal(2400);
      unsigned.txRequests[0].transactions[0].unsignedTx.coinSpecific.commonKeychain.should.equal(
        'd4a570c1831c7024cb72533e42690cec9d9150b9aac59001c4a5a3a285518263a9e89f1c709bcb1e832f2ff5169fecd496881ba8970f69d5adc977ba4799fedb'
      );
    });

    it('should recover a tx for non-bitgo recoveries', async function () {
      accountInfoCB.withArgs(testData.wrwUser.walletAddress0).resolves({ nonce: 2, freeBalance: 100001853 });
      headerInfoCB.resolves({
        headerNumber: testData.westendBlock.blockNumber,
        headerHash: testData.westendBlock.hash,
      });

      const res = await baseCoin.recover({
        userKey: testData.wrwUser.userKey,
        backupKey: testData.wrwUser.backupKey,
        bitgoKey: testData.wrwUser.bitgoKey,
        walletPassphrase: testData.wrwUser.walletPassphrase,
        recoveryDestination: recoveryDestination,
      });

      res.should.not.be.empty();
      res.should.hasOwnProperty('serializedTx');
      res.should.hasOwnProperty('scanIndex');
      // sandBox.assert.calledOnce(baseCoin.getAccountInfo);
      // sandBox.assert.calledOnce(baseCoin.getHeaderInfo);

      const txBuilder = baseCoin.getBuilder().from(res.serializedTx);
      txBuilder
        .validity({
          firstValid: testData.westendBlock.blockNumber,
          maxDuration: baseCoin.SWEEP_TXN_DURATION,
        })
        .referenceBlock(testData.westendBlock.hash);

      const tx = await txBuilder.build();
      const txJson = tx.toJson();
      should.deepEqual(txJson.sender, testData.wrwUser.walletAddress0);
      should.deepEqual(txJson.blockNumber, testData.westendBlock.blockNumber);
      should.deepEqual(txJson.referenceBlock, testData.westendBlock.hash);
      should.deepEqual(txJson.genesisHash, genesisHash);
      should.deepEqual(txJson.specVersion, specVersion);
      should.deepEqual(txJson.nonce, nonce);
      should.deepEqual(txJson.tip, 0);
      should.deepEqual(txJson.transactionVersion, txVersion);
      // should.deepEqual(txJson.chainName, chainName);
      should.deepEqual(txJson.eraPeriod, baseCoin.SWEEP_TXN_DURATION);
    });

    it('should recover a txn for unsigned-sweep recoveries', async function () {
      accountInfoCB.withArgs(testData.unsignedSweepUser.walletAddress0).resolves({ nonce: 1, freeBalance: 2989864739 });
      headerInfoCB.resolves({
        headerNumber: testData.westendBlock.blockNumber,
        headerHash: testData.westendBlock.hash,
      });

      const res = await baseCoin.recover({
        bitgoKey: testData.unsignedSweepUser.bitgoKey,
        recoveryDestination: recoveryDestination,
      });

      res.should.not.be.empty();
      res.txRequests[0].transactions[0].unsignedTx.should.hasOwnProperty('serializedTx');
      res.txRequests[0].transactions[0].unsignedTx.should.hasOwnProperty('scanIndex');
      // sandBox.assert.calledOnce(baseCoin.getAccountInfo);
      // sandBox.assert.calledOnce(baseCoin.getHeaderInfo);

      const txBuilder = baseCoin.getBuilder().from(res.txRequests[0].transactions[0].unsignedTx.serializedTx);
      txBuilder
        .validity({
          firstValid: testData.westendBlock.blockNumber,
          maxDuration: baseCoin.SWEEP_TXN_DURATION,
        })
        .referenceBlock(testData.westendBlock.hash)
        .sender({ address: testData.unsignedSweepUser.walletAddress0 });

      const tx = await txBuilder.build();
      const txJson = tx.toJson();
      should.deepEqual(txJson.sender, testData.unsignedSweepUser.walletAddress0);
      should.deepEqual(txJson.blockNumber, testData.westendBlock.blockNumber);
      should.deepEqual(txJson.referenceBlock, testData.westendBlock.hash);
      should.deepEqual(txJson.genesisHash, genesisHash);
      should.deepEqual(txJson.specVersion, specVersion);
      should.deepEqual(txJson.nonce, 1);
      should.deepEqual(txJson.tip, 0);
      should.deepEqual(txJson.transactionVersion, txVersion);
      // should.deepEqual(txJson.chainName, chainName);
      should.deepEqual(txJson.eraPeriod, baseCoin.SWEEP_TXN_DURATION);
    });
  });

  describe.skip('Build Consolidation Recoveries', function () {
    const sandbox = sinon.createSandbox();
    const baseAddr = testData.consolidationWrwUser.walletAddress0;
    const nonce = 123;

    beforeEach(function () {
      const accountInfoCB = sandbox.stub(Tao.prototype, 'getAccountInfo' as keyof Tao);
      accountInfoCB.withArgs(testData.consolidationWrwUser.walletAddress1).resolves({
        nonce: nonce,
        freeBalance: 10000000000,
      });
      accountInfoCB.withArgs(testData.consolidationWrwUser.walletAddress2).resolves({
        nonce: nonce,
        freeBalance: 1510000000000,
      });
      accountInfoCB.withArgs(testData.consolidationWrwUser.walletAddress3).resolves({
        nonce: nonce,
        freeBalance: 1510000000000,
      });
      const headerInfoCB = sandbox.stub(Tao.prototype, 'getHeaderInfo' as keyof Tao);
      headerInfoCB.resolves({
        headerNumber: testData.westendBlock.blockNumber,
        headerHash: testData.westendBlock.hash,
      });
      const getFeeCB = sandbox.stub(Tao.prototype, 'getFee' as keyof Tao);
      getFeeCB.withArgs(baseAddr, testData.consolidationWrwUser.walletAddress1, 10000000000).resolves(15783812856);
      getFeeCB.withArgs(baseAddr, testData.consolidationWrwUser.walletAddress2, 1510000000000).resolves(15783812856);
      getFeeCB.withArgs(baseAddr, testData.consolidationWrwUser.walletAddress3, 1510000000000).resolves(15783812856);
    });

    afterEach(function () {
      sandbox.restore();
    });

    it('should build signed consolidation recovery', async function () {
      const res = await baseCoin.recoverConsolidations({
        userKey: testData.consolidationWrwUser.userKey,
        backupKey: testData.consolidationWrwUser.backupKey,
        bitgoKey: testData.consolidationWrwUser.bitgoKey,
        walletPassphrase: testData.consolidationWrwUser.walletPassphrase,
        startingScanIndex: 1,
        endingScanIndex: 4,
      });

      res.should.not.be.empty();
      res.transactions.length.should.equal(2);
      // sandbox.assert.calledThrice(baseCoin.getAccountInfo);
      // sandbox.assert.calledTwice(baseCoin.getHeaderInfo);

      const txn1 = res.transactions[0];
      txn1.should.hasOwnProperty('serializedTx');
      txn1.should.hasOwnProperty('scanIndex');
      txn1.scanIndex.should.equal(2);
      const txBuilder1 = baseCoin.getBuilder().from(txn1.serializedTx);
      txBuilder1
        .validity({
          firstValid: testData.westendBlock.blockNumber,
          maxDuration: baseCoin.MAX_VALIDITY_DURATION,
        })
        .referenceBlock(testData.westendBlock.hash);
      const tx1 = await txBuilder1.build();
      const txJson1 = tx1.toJson();
      should.deepEqual(txJson1.sender, testData.consolidationWrwUser.walletAddress2);
      should.deepEqual(txJson1.blockNumber, testData.westendBlock.blockNumber);
      should.deepEqual(txJson1.referenceBlock, testData.westendBlock.hash);
      should.deepEqual(txJson1.genesisHash, genesisHash);
      should.deepEqual(txJson1.specVersion, specVersion);
      should.deepEqual(txJson1.nonce, nonce);
      should.deepEqual(txJson1.tip, 0);
      should.deepEqual(txJson1.transactionVersion, txVersion);
      // should.deepEqual(txJson1.chainName, chainName);
      // eraPeriod will always round to the next upper power of 2 for any input value, in this case 2400.
      // 4096 is the "highest" value you can set, but the txn still may fail after 2400 blocks.
      const eraPeriod = 4096;
      should.deepEqual(txJson1.eraPeriod, eraPeriod);
      should.deepEqual(txJson1.to, baseAddr);

      res.lastScanIndex.should.equal(3);
      const txn2 = res.transactions[1];
      txn2.should.hasOwnProperty('serializedTx');
      txn2.should.hasOwnProperty('scanIndex');
      txn2.scanIndex.should.equal(3);
      const txBuilder2 = baseCoin.getBuilder().from(txn2.serializedTx);
      txBuilder2
        .validity({
          firstValid: testData.westendBlock.blockNumber,
          maxDuration: baseCoin.MAX_VALIDITY_DURATION,
        })
        .referenceBlock(testData.westendBlock.hash);
      const tx2 = await txBuilder2.build();
      const txJson2 = tx2.toJson();
      should.deepEqual(txJson2.sender, testData.consolidationWrwUser.walletAddress3);
      should.deepEqual(txJson2.blockNumber, testData.westendBlock.blockNumber);
      should.deepEqual(txJson2.referenceBlock, testData.westendBlock.hash);
      should.deepEqual(txJson2.genesisHash, genesisHash);
      should.deepEqual(txJson2.specVersion, specVersion);
      should.deepEqual(txJson2.nonce, nonce);
      should.deepEqual(txJson2.tip, 0);
      should.deepEqual(txJson2.transactionVersion, txVersion);
      // should.deepEqual(txJson2.chainName, chainName);
      should.deepEqual(txJson2.eraPeriod, eraPeriod);
      should.deepEqual(txJson2.to, baseAddr);
    });

    it('should build unsigned consolidation recoveries', async function () {
      const res = await baseCoin.recoverConsolidations({
        bitgoKey: testData.consolidationWrwUser.bitgoKey,
        startingScanIndex: 1,
        endingScanIndex: 4,
      });
      res.should.not.be.empty();
      res.txRequests.length.should.equal(2);
      sandbox.assert.calledThrice(baseCoin.getAccountInfo);
      sandbox.assert.calledTwice(baseCoin.getHeaderInfo);

      const txn1 = res.txRequests[0].transactions[0].unsignedTx;
      txn1.should.hasOwnProperty('serializedTx');
      txn1.should.hasOwnProperty('signableHex');
      txn1.should.hasOwnProperty('scanIndex');
      txn1.scanIndex.should.equal(2);
      txn1.should.hasOwnProperty('coin');
      txn1.coin.should.equal('ttao');
      txn1.should.hasOwnProperty('derivationPath');
      txn1.derivationPath.should.equal('m/2');

      txn1.should.hasOwnProperty('coinSpecific');
      const coinSpecific1 = txn1.coinSpecific;
      coinSpecific1.should.hasOwnProperty('commonKeychain');
      coinSpecific1.should.hasOwnProperty('firstValid');
      coinSpecific1.firstValid.should.equal(testData.westendBlock.blockNumber);
      coinSpecific1.should.hasOwnProperty('maxDuration');
      coinSpecific1.maxDuration.should.equal(baseCoin.MAX_VALIDITY_DURATION);

      // deserialize the txn and verify the fields are what we expect
      const txBuilder1 = baseCoin.getBuilder().from(txn1.serializedTx);
      // some information isn't deserialized by the from method, so we will
      // supply it again in order to re-build the txn
      txBuilder1
        .validity({
          firstValid: testData.westendBlock.blockNumber,
          maxDuration: baseCoin.MAX_VALIDITY_DURATION,
        })
        .referenceBlock(testData.westendBlock.hash)
        .sender({ address: testData.consolidationWrwUser.walletAddress2 });
      const tx1 = await txBuilder1.build();
      const txJson1 = tx1.toJson();
      should.deepEqual(txJson1.sender, testData.consolidationWrwUser.walletAddress2);
      should.deepEqual(txJson1.blockNumber, testData.westendBlock.blockNumber);
      should.deepEqual(txJson1.referenceBlock, testData.westendBlock.hash);
      should.deepEqual(txJson1.genesisHash, genesisHash);
      should.deepEqual(txJson1.specVersion, specVersion);
      should.deepEqual(txJson1.nonce, nonce);
      should.deepEqual(txJson1.tip, 0);
      should.deepEqual(txJson1.transactionVersion, txVersion);
      // should.deepEqual(txJson1.chainName, chainName);
      // eraPeriod will always round to the next upper power of 2 for any input value, in this case 2400.
      // 4096 is the "highest" value you can set, but the txn still may fail after 2400 blocks.
      const eraPeriod = 4096;
      should.deepEqual(txJson1.eraPeriod, eraPeriod);
      should.deepEqual(txJson1.to, baseAddr);

      const txn2 = res.txRequests[1].transactions[0].unsignedTx;
      txn2.should.hasOwnProperty('serializedTx');
      txn2.should.hasOwnProperty('signableHex');
      txn2.should.hasOwnProperty('scanIndex');
      txn2.scanIndex.should.equal(3);
      txn2.should.hasOwnProperty('coin');
      txn2.coin.should.equal('ttao');
      txn2.should.hasOwnProperty('derivationPath');
      txn2.derivationPath.should.equal('m/3');

      txn2.should.hasOwnProperty('coinSpecific');
      const coinSpecific2 = txn2.coinSpecific;
      coinSpecific2.should.hasOwnProperty('commonKeychain');
      coinSpecific2.should.hasOwnProperty('firstValid');
      coinSpecific2.firstValid.should.equal(testData.westendBlock.blockNumber);
      coinSpecific2.should.hasOwnProperty('maxDuration');
      coinSpecific2.maxDuration.should.equal(baseCoin.MAX_VALIDITY_DURATION);
      coinSpecific2.should.hasOwnProperty('commonKeychain');
      coinSpecific2.should.hasOwnProperty('lastScanIndex');
      coinSpecific2.lastScanIndex.should.equal(3);

      // deserialize the txn and verify the fields are what we expect
      const txBuilder2 = baseCoin.getBuilder().from(txn2.serializedTx);
      // some information isn't deserialized by the from method, so we will
      // supply it again in order to re-build the txn
      txBuilder2
        .validity({
          firstValid: testData.westendBlock.blockNumber,
          maxDuration: baseCoin.MAX_VALIDITY_DURATION,
        })
        .referenceBlock(testData.westendBlock.hash)
        .sender({ address: testData.consolidationWrwUser.walletAddress3 });
      const tx2 = await txBuilder2.build();
      const txJson2 = tx2.toJson();
      should.deepEqual(txJson2.sender, testData.consolidationWrwUser.walletAddress3);
      should.deepEqual(txJson2.blockNumber, testData.westendBlock.blockNumber);
      should.deepEqual(txJson2.referenceBlock, testData.westendBlock.hash);
      should.deepEqual(txJson2.genesisHash, genesisHash);
      should.deepEqual(txJson2.specVersion, specVersion);
      should.deepEqual(txJson2.nonce, nonce);
      should.deepEqual(txJson2.tip, 0);
      should.deepEqual(txJson2.transactionVersion, txVersion);
      // should.deepEqual(txJson2.chainName, chainName);
      should.deepEqual(txJson2.eraPeriod, eraPeriod);
      should.deepEqual(txJson2.to, baseAddr);
    });

    it('should skip building consolidate transaction if balance is equal to zero', async function () {
      await baseCoin
        .recoverConsolidations({
          userKey: testData.consolidationWrwUser.userKey,
          backupKey: testData.consolidationWrwUser.backupKey,
          bitgoKey: testData.consolidationWrwUser.bitgoKey,
          walletPassphrase: testData.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: testData.consolidationWrwUser.userKey,
          backupKey: testData.consolidationWrwUser.backupKey,
          bitgoKey: testData.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: testData.consolidationWrwUser.userKey,
          backupKey: testData.consolidationWrwUser.backupKey,
          bitgoKey: testData.consolidationWrwUser.bitgoKey,
          startingScanIndex: 1,
          endingScanIndex: 300,
        })
        .should.be.rejectedWith(
          'Invalid starting or ending index to scan for addresses. startingScanIndex: 1, endingScanIndex: 300.'
        );
    });
  });
});

Выполнить команду


Для локальной разработки. Не используйте в интернете!