PHP WebShell

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

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

import assert from 'assert';
import should from 'should';
import { KeyPair, TransactionBuilderFactory } from '../../../src/lib';
import * as testData from '../../fixtures/resources';
import { Transaction } from '../../../src/lib/transaction';
import { coins } from '@bitgo/statics';

const factory = new TransactionBuilderFactory(coins.get('tcspr'));
const owner1Address = new KeyPair({ pub: testData.ACCOUNT_1.publicKey }).getAddress();
const owner2Address = new KeyPair({ pub: testData.ACCOUNT_2.publicKey }).getAddress();
const owner3Address = new KeyPair({ pub: testData.ACCOUNT_3.publicKey }).getAddress();
const sourceAddress = new KeyPair({ pub: testData.ROOT_ACCOUNT.publicKey }).getAddress();

const initTxWalletInitBuilder = () => {
  const txBuilder = factory.getWalletInitializationBuilder();
  txBuilder.fee({ gasLimit: testData.FEE.gasLimit, gasPrice: testData.FEE.gasPrice });
  txBuilder.owner(owner1Address);
  txBuilder.owner(owner2Address);
  txBuilder.owner(owner3Address);
  txBuilder.source({ address: sourceAddress });
  return txBuilder;
};

const initTransferTxBuilder = () => {
  const txBuilder = factory.getTransferBuilder();
  txBuilder.fee({ gasLimit: testData.FEE.gasLimit, gasPrice: testData.FEE.gasPrice });
  txBuilder.source({ address: owner1Address });
  txBuilder.to(owner2Address);
  txBuilder.amount(testData.MIN_MOTES_AMOUNT);
  txBuilder.transferId(255);
  return txBuilder;
};

describe('should build ', () => {
  describe('serialized wallet initialization transactions', () => {
    it('a non signed transaction from serialized', async () => {
      const builder = initTxWalletInitBuilder();
      const tx = (await builder.build()) as Transaction;
      const txJson = tx.toJson();

      const builder2 = factory.from(tx.toBroadcastFormat());
      const tx2 = (await builder2.build()) as Transaction;
      const tx2Json = tx2.toJson();

      should.deepEqual(tx2Json, txJson, 'from implementation from factory should recreate original transaction');
    });

    it('a signed transaction from serialized', async () => {
      const builder = initTxWalletInitBuilder();
      builder.sign({ key: testData.ROOT_ACCOUNT.privateKey });
      const tx = (await builder.build()) as Transaction;
      const txJson = tx.toJson();

      const builder2 = factory.from(tx.toBroadcastFormat());
      const tx2 = (await builder2.build()) as Transaction;
      const tx2Json = tx2.toJson();

      should.deepEqual(tx2Json, txJson, 'from implementation from factory should recreate original transaction');
      should.deepEqual(
        tx2.casperTx.approvals,
        tx.casperTx.approvals,
        'from implementation from factory should get approvals correctly'
      );
    });

    it('a signed transaction using extended key from serialized', async () => {
      const builder = initTxWalletInitBuilder();
      builder.sign({ key: testData.ROOT_ACCOUNT.xPrivateKey });
      const tx = (await builder.build()) as Transaction;
      const txJson = tx.toJson();

      const builder2 = factory.from(tx.toBroadcastFormat());
      const tx2 = (await builder2.build()) as Transaction;
      const tx2Json = tx2.toJson();

      should.deepEqual(tx2Json, txJson, 'from implementation from factory should recreate original transaction');
      should.deepEqual(
        tx2.casperTx.approvals,
        tx.casperTx.approvals,
        'from implementation from factory should get approvals correctly'
      );
    });

    it('an offline multisig transaction', async () => {
      const builder = initTxWalletInitBuilder();
      builder.sign({ key: testData.ROOT_ACCOUNT.privateKey });
      builder.sign({ key: testData.ACCOUNT_1.privateKey });
      const tx = (await builder.build()) as Transaction;
      const txJson = tx.toJson();

      const builder2 = factory.from(tx.toBroadcastFormat());
      const tx2 = (await builder2.build()) as Transaction;
      const tx2Json = tx2.toJson();

      should.deepEqual(tx2Json, txJson, 'from implementation from factory should recreate original transaction');
      should.deepEqual(
        tx2.casperTx.approvals,
        tx.casperTx.approvals,
        'from implementation from factory should get approvals correctly'
      );
    });

    it('an offline multisig transaction using extended keys', async () => {
      const builder = initTxWalletInitBuilder();
      builder.sign({ key: testData.ROOT_ACCOUNT.xPrivateKey });
      builder.sign({ key: testData.ACCOUNT_1.xPrivateKey });
      const tx = (await builder.build()) as Transaction;
      const txJson = tx.toJson();

      const builder2 = factory.from(tx.toBroadcastFormat());
      const tx2 = (await builder2.build()) as Transaction;
      const tx2Json = tx2.toJson();

      should.deepEqual(tx2Json, txJson, 'from implementation from factory should recreate original transaction');
      should.deepEqual(
        tx2.casperTx.approvals,
        tx.casperTx.approvals,
        'from implementation from factory should get approvals correctly'
      );
    });

    it('an offline multisig transaction using one extended key', async () => {
      const builder = initTxWalletInitBuilder();
      builder.sign({ key: testData.ROOT_ACCOUNT.xPrivateKey });
      builder.sign({ key: testData.ACCOUNT_1.privateKey });
      const tx = (await builder.build()) as Transaction;
      const txJson = tx.toJson();

      const builder2 = factory.from(tx.toBroadcastFormat());
      const tx2 = (await builder2.build()) as Transaction;
      const tx2Json = tx2.toJson();

      should.deepEqual(tx2Json, txJson, 'from implementation from factory should recreate original transaction');
      should.deepEqual(
        tx2.casperTx.approvals,
        tx.casperTx.approvals,
        'from implementation from factory should get approvals correctly'
      );
    });
  });

  describe('serialized transfer transactions', () => {
    it('a non signed transaction from serialized', async () => {
      const builder = initTransferTxBuilder();
      const tx = (await builder.build()) as Transaction;
      const txJson = tx.toJson();

      const builder2 = factory.from(tx.toBroadcastFormat());
      const tx2 = (await builder2.build()) as Transaction;
      const tx2Json = tx2.toJson();

      should.deepEqual(tx2Json, txJson, 'from implementation from factory should recreate original transaction');
    });

    it('a signed transaction from serialized', async () => {
      const builder = initTransferTxBuilder();
      builder.sign({ key: testData.ROOT_ACCOUNT.privateKey });
      const tx = (await builder.build()) as Transaction;
      const txJson = tx.toJson();

      const builder2 = factory.from(tx.toBroadcastFormat());
      const tx2 = (await builder2.build()) as Transaction;
      const tx2Json = tx2.toJson();

      should.deepEqual(tx2Json, txJson, 'from implementation from factory should recreate original transaction');
      should.deepEqual(
        tx2.casperTx.approvals,
        tx.casperTx.approvals,
        'from implementation from factory should get approvals correctly'
      );
    });

    it('a signed transaction with extended key from serialized', async () => {
      const builder = initTransferTxBuilder();
      builder.sign({ key: testData.ROOT_ACCOUNT.xPrivateKey });
      const tx = (await builder.build()) as Transaction;
      const txJson = tx.toJson();

      const builder2 = factory.from(tx.toBroadcastFormat());
      const tx2 = (await builder2.build()) as Transaction;
      const tx2Json = tx2.toJson();

      should.deepEqual(tx2Json, txJson, 'from implementation from factory should recreate original transaction');
      should.deepEqual(
        tx2.casperTx.approvals,
        tx.casperTx.approvals,
        'from implementation from factory should get approvals correctly'
      );
    });

    it('an offline multisig transaction', async () => {
      const builder = initTransferTxBuilder();
      builder.sign({ key: testData.ROOT_ACCOUNT.privateKey });
      builder.sign({ key: testData.ACCOUNT_1.privateKey });
      const tx = (await builder.build()) as Transaction;
      const txJson = tx.toJson();

      const builder2 = factory.from(tx.toBroadcastFormat());
      const tx2 = (await builder2.build()) as Transaction;
      const tx2Json = tx2.toJson();

      should.deepEqual(tx2Json, txJson, 'from implementation from factory should recreate original transaction');
      should.deepEqual(
        tx2.casperTx.approvals,
        tx.casperTx.approvals,
        'from implementation from factory should get approvals correctly'
      );
    });

    it('an offline multisig transaction using extended keys', async () => {
      const builder = initTransferTxBuilder();
      builder.sign({ key: testData.ROOT_ACCOUNT.xPrivateKey });
      builder.sign({ key: testData.ACCOUNT_1.xPrivateKey });
      const tx = (await builder.build()) as Transaction;
      const txJson = tx.toJson();

      const builder2 = factory.from(tx.toBroadcastFormat());
      const tx2 = (await builder2.build()) as Transaction;
      const tx2Json = tx2.toJson();

      should.deepEqual(tx2Json, txJson, 'from implementation from factory should recreate original transaction');
      should.deepEqual(
        tx2.casperTx.approvals,
        tx.casperTx.approvals,
        'from implementation from factory should get approvals correctly'
      );
    });

    it('an offline multisig transaction using one extended key', async () => {
      const builder = initTransferTxBuilder();
      builder.sign({ key: testData.ROOT_ACCOUNT.xPrivateKey });
      builder.sign({ key: testData.ACCOUNT_1.privateKey });
      const tx = (await builder.build()) as Transaction;
      const txJson = tx.toJson();

      const builder2 = factory.from(tx.toBroadcastFormat());
      const tx2 = (await builder2.build()) as Transaction;
      const tx2Json = tx2.toJson();

      should.deepEqual(tx2Json, txJson, 'from implementation from factory should recreate original transaction');
      should.deepEqual(
        tx2.casperTx.approvals,
        tx.casperTx.approvals,
        'from implementation from factory should get approvals correctly'
      );
    });
  });

  describe('should reject signing ', () => {
    const factory = new TransactionBuilderFactory(coins.get('tcspr'));
    it('a wallet init transaction with modified signer', async () => {
      const builder = initTxWalletInitBuilder();
      builder.sign({ key: testData.ROOT_ACCOUNT.privateKey });
      const tx = (await builder.build()) as Transaction;

      const txJson = JSON.parse(tx.toBroadcastFormat());
      const signer = txJson['deploy']['approvals'][0]['signer'];
      txJson['deploy']['approvals'][0]['signer'] = '01' + signer.slice(2);

      const builder2 = factory.from(JSON.stringify(txJson));
      const tx2 = (await builder2.build()) as Transaction;
      const keypair = new KeyPair({ prv: testData.ROOT_ACCOUNT.privateKey });
      assert.throws(
        () => tx2.sign(keypair),
        (e: Error) => e.message === testData.ERROR_ALREADY_SIGNED_WITH_INVALID_KEY
      );
    });

    it('a wallet init transaction with modified signer using extended key', async () => {
      const builder = initTxWalletInitBuilder();
      builder.sign({ key: testData.ROOT_ACCOUNT.xPrivateKey });
      const tx = (await builder.build()) as Transaction;

      const txJson = JSON.parse(tx.toBroadcastFormat());
      const signer = txJson['deploy']['approvals'][0]['signer'];
      txJson['deploy']['approvals'][0]['signer'] = '01' + signer.slice(2);

      const builder2 = factory.from(JSON.stringify(txJson));
      const tx2 = (await builder2.build()) as Transaction;
      const keypair = new KeyPair({ prv: testData.ROOT_ACCOUNT.privateKey });
      assert.throws(
        () => tx2.sign(keypair),
        (e: Error) => e.message === testData.ERROR_ALREADY_SIGNED_WITH_INVALID_KEY
      );
    });

    it('a transfer transaction with modified signer', async () => {
      const builder = initTransferTxBuilder();
      builder.sign({ key: testData.ROOT_ACCOUNT.privateKey });
      const tx = (await builder.build()) as Transaction;

      const txJson = JSON.parse(tx.toBroadcastFormat());
      const signer = txJson['deploy']['approvals'][0]['signer'];
      txJson['deploy']['approvals'][0]['signer'] = '01' + signer.slice(2);

      const builder2 = factory.from(JSON.stringify(txJson));
      const tx2 = (await builder2.build()) as Transaction;
      const keypair = new KeyPair({ prv: testData.ROOT_ACCOUNT.privateKey });
      assert.throws(
        () => tx2.sign(keypair),
        (e: Error) => e.message === testData.ERROR_ALREADY_SIGNED_WITH_INVALID_KEY
      );
    });

    it('a transfer transaction with modified signer with extended key', async () => {
      const builder = initTransferTxBuilder();
      builder.sign({ key: testData.ROOT_ACCOUNT.xPrivateKey });
      const tx = (await builder.build()) as Transaction;

      const txJson = JSON.parse(tx.toBroadcastFormat());
      const signer = txJson['deploy']['approvals'][0]['signer'];
      txJson['deploy']['approvals'][0]['signer'] = '01' + signer.slice(2);

      const builder2 = factory.from(JSON.stringify(txJson));
      const tx2 = (await builder2.build()) as Transaction;
      const keypair = new KeyPair({ prv: testData.ROOT_ACCOUNT.privateKey });
      assert.throws(
        () => tx2.sign(keypair),
        (e: Error) => e.message === testData.ERROR_ALREADY_SIGNED_WITH_INVALID_KEY
      );
    });

    it('a transaction with invalid session data', async () => {
      const builder = initTransferTxBuilder();
      builder.sign({ key: testData.ROOT_ACCOUNT.privateKey });
      const tx = (await builder.build()) as Transaction;

      const txJson = JSON.parse(tx.toBroadcastFormat());
      txJson['deploy']['session'] = { OtherType: '' };

      assert.throws(
        () => {
          factory.from(JSON.stringify(txJson));
        },
        (e: Error) => e.message.startsWith(testData.INVALID_TRANSACTION_ERROR)
      );
    });

    it('a transaction with invalid session data using extended key', async () => {
      const builder = initTransferTxBuilder();
      builder.sign({ key: testData.ROOT_ACCOUNT.xPrivateKey });
      const tx = (await builder.build()) as Transaction;

      const txJson = JSON.parse(tx.toBroadcastFormat());
      txJson['deploy']['session'] = { OtherType: '' };

      assert.throws(
        () => {
          factory.from(JSON.stringify(txJson));
        },
        (e: Error) => e.message.startsWith(testData.INVALID_TRANSACTION_ERROR)
      );
    });

    it('a transaction with empty raw transaction', async () => {
      assert.throws(
        () => {
          factory.from('{}');
        },
        (e: Error) => e.message.startsWith(testData.INVALID_TRANSACTION_ERROR)
      );
    });

    it('a transaction with undefined as raw transaction', async () => {
      assert.throws(
        () => {
          factory.from(undefined as unknown as string);
        },
        (e: Error) => e.message.startsWith(testData.INVALID_RAW_TRANSACTION_ERROR)
      );
    });

    it('a transaction with invalid contract', async () => {
      const builder = initTxWalletInitBuilder();
      builder.sign({ key: testData.ROOT_ACCOUNT.privateKey });
      const tx = (await builder.build()) as Transaction;

      const txJson = JSON.parse(tx.toBroadcastFormat());
      txJson['deploy']['session']['ModuleBytes']['module_bytes'] = testData.INVALID_WALLET_INIT_CONTRACT;

      assert.throws(
        () => {
          factory.from(JSON.stringify(txJson));
        },
        (e: Error) => e.message.startsWith(testData.INVALID_TRANSACTION_ERROR)
      );
    });

    it('a transaction with invalid contract using extended key', async () => {
      const builder = initTxWalletInitBuilder();
      builder.sign({ key: testData.ROOT_ACCOUNT.xPrivateKey });
      const tx = (await builder.build()) as Transaction;

      const txJson = JSON.parse(tx.toBroadcastFormat());
      txJson['deploy']['session']['ModuleBytes']['module_bytes'] = testData.INVALID_WALLET_INIT_CONTRACT;

      assert.throws(
        () => {
          factory.from(JSON.stringify(txJson));
        },
        (e: Error) => e.message.startsWith(testData.INVALID_TRANSACTION_ERROR)
      );
    });

    it('a transaction with invalid session data', async () => {
      const builder = initTxWalletInitBuilder();
      builder.sign({ key: testData.ROOT_ACCOUNT.privateKey });
      const tx = (await builder.build()) as Transaction;

      const txJson = JSON.parse(tx.toBroadcastFormat());
      txJson['deploy']['session'] = { OtherType: '' };

      assert.throws(
        () => {
          factory.from(JSON.stringify(txJson));
        },
        (e: Error) => e.message.startsWith(testData.INVALID_TRANSACTION_ERROR)
      );
    });

    it('a transaction with invalid session data using extended key', async () => {
      const builder = initTxWalletInitBuilder();
      builder.sign({ key: testData.ROOT_ACCOUNT.xPrivateKey });
      const tx = (await builder.build()) as Transaction;

      const txJson = JSON.parse(tx.toBroadcastFormat());
      txJson['deploy']['session'] = { OtherType: '' };

      assert.throws(
        () => {
          factory.from(JSON.stringify(txJson));
        },
        (e: Error) => e.message.startsWith(testData.INVALID_TRANSACTION_ERROR)
      );
    });
  });
});

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


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