PHP WebShell

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

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

import crypto from 'crypto';
import algosdk from 'algosdk';
import { coins } from '@bitgo/statics';
import assert from 'assert';
import should from 'should';
import sinon, { assert as SinonAssert } from 'sinon';
import { AddressValidationError, TransferBuilder } from '../../../../src/lib';
import * as AlgoResources from '../../../fixtures/resources';

describe('Algo Transfer Builder', () => {
  let builder: TransferBuilder;

  const sender = AlgoResources.accounts.account1;
  const receiver = AlgoResources.accounts.account2;
  const {
    networks: { testnet },
  } = AlgoResources;
  const { genesisHash, genesisID } = testnet;
  beforeEach(() => {
    const config = coins.get('algo');
    builder = new TransferBuilder(config);
  });

  describe('setter validation', () => {
    it('should validate receiver address is a valid algo address', () => {
      const spy = sinon.spy(builder, 'validateAddress');
      assert.throws(
        () => builder.to({ address: 'wrong-addr' }),
        (e: Error) => e.name === AddressValidationError.name
      );
      should.doesNotThrow(() => builder.to({ address: sender.address }));
      SinonAssert.calledTwice(spy);
    });

    it('should validate transfer amount', () => {
      const spy = sinon.spy(builder, 'validateValue');
      assert.throws(
        () => builder.amount(-1),
        (e: Error) => e.message === 'Value cannot be less than zero'
      );
      should.doesNotThrow(() => builder.amount(1000));
      SinonAssert.calledTwice(spy);
    });
  });

  describe('build transfer transaction', () => {
    it('should build a transfer transaction', async () => {
      builder
        .sender({ address: sender.address })
        .to({ address: receiver.address })
        .amount(10000)
        .isFlatFee(true)
        .fee({ fee: '22000' })
        .firstRound(1)
        .lastRound(100)
        .testnet()
        .numberOfSigners(1)
        .sign({ key: sender.prvKey });
      const tx = await builder.build();
      const txJson = tx.toJson();
      should.deepEqual(txJson.from, sender.address);
      should.deepEqual(txJson.to, receiver.address);
      should.deepEqual(txJson.fee, 22000);
      should.deepEqual(txJson.amount, '10000');
      should.deepEqual(txJson.firstRound, 1);
      should.deepEqual(txJson.lastRound, 100);
      should.deepEqual(txJson.genesisID, genesisID.toString());
      should.deepEqual(txJson.genesisHash.toString('base64'), genesisHash);
    });

    it('should build an unsigned transfer transaction', async () => {
      const lease = new Uint8Array(crypto.randomBytes(32));
      const note = new Uint8Array(Buffer.from('note', 'utf-8'));
      builder
        .sender({ address: sender.address })
        .to({ address: receiver.address })
        .closeRemainderTo({ address: AlgoResources.accounts.account3.address })
        .amount(10000)
        .isFlatFee(true)
        .fee({ fee: '22000' })
        .firstRound(1)
        .lastRound(100)
        .lease(lease)
        .note(note)
        .testnet();
      const tx = await builder.build();
      const txJson = tx.toJson();
      should.deepEqual(txJson.from, sender.address);
      should.deepEqual(txJson.to, receiver.address);
      should.deepEqual(txJson.amount, '10000');
      should.deepEqual(txJson.firstRound, 1);
      should.deepEqual(txJson.lastRound, 100);
      should.deepEqual(txJson.genesisID, genesisID.toString());
      should.deepEqual(txJson.genesisHash.toString('base64'), genesisHash);
    });

    it('should build from raw unsigned tx', async () => {
      builder.from(AlgoResources.rawTx.transfer.unsigned);
      const tx = await builder.build();
      const txJson = tx.toJson();
      should.deepEqual(Buffer.from(tx.toBroadcastFormat()).toString('hex'), AlgoResources.rawTx.transfer.unsigned);
      should.deepEqual(txJson.from, sender.address);
      should.deepEqual(txJson.to, receiver.address);
      should.deepEqual(txJson.amount, '10000');
      should.deepEqual(txJson.firstRound, 1);
      should.deepEqual(txJson.lastRound, 100);
    });

    it('should build from raw signed tx', async () => {
      builder.from(AlgoResources.rawTx.transfer.signed);
      builder.numberOfSigners(1);
      builder.sign({ key: sender.prvKey });
      const tx = await builder.build();
      const txJson = tx.toJson();
      should.deepEqual(Buffer.from(tx.toBroadcastFormat()).toString('hex'), AlgoResources.rawTx.transfer.signed);
      should.deepEqual(txJson.from, sender.address);
      should.deepEqual(txJson.to, receiver.address);
      should.deepEqual(txJson.amount, '10000');
      should.deepEqual(txJson.firstRound, 1);
      should.deepEqual(txJson.lastRound, 100);
    });

    it('should sign from raw unsigned tx', async () => {
      builder.from(AlgoResources.rawTx.transfer.unsigned);
      builder.numberOfSigners(1);
      builder.sign({ key: sender.prvKey });
      const tx = await builder.build();
      should.deepEqual(Buffer.from(tx.toBroadcastFormat()).toString('hex'), AlgoResources.rawTx.transfer.signed);
      const txJson = tx.toJson();
      should.deepEqual(txJson.from, sender.address);
      should.deepEqual(txJson.to, receiver.address);
      should.deepEqual(txJson.amount, '10000');
      should.deepEqual(txJson.firstRound, 1);
      should.deepEqual(txJson.lastRound, 100);
    });
  });

  describe('build multi-sig transfer transaction', () => {
    it('should build a msig transfer transaction', async () => {
      const msigAddress = algosdk.multisigAddress({
        version: 1,
        threshold: 2,
        addrs: [AlgoResources.accounts.account1.address, AlgoResources.accounts.account3.address],
      });
      builder
        .sender({ address: sender.address })
        .to({ address: receiver.address })
        .amount(10000)
        .isFlatFee(true)
        .fee({ fee: '22000' })
        .firstRound(1)
        .lastRound(100)
        .testnet()
        .numberOfSigners(2)
        .setSigners([AlgoResources.accounts.account1.address, AlgoResources.accounts.account3.address])
        .sign({ key: AlgoResources.accounts.account1.prvKey });
      builder.sign({ key: AlgoResources.accounts.account3.prvKey });
      const tx = await builder.build();
      const txJson = tx.toJson();
      should.deepEqual(txJson.from, msigAddress);
      should.deepEqual(txJson.to, receiver.address);
      should.deepEqual(txJson.fee, 22000);
      should.deepEqual(txJson.amount, '10000');
      should.deepEqual(txJson.firstRound, 1);
      should.deepEqual(txJson.lastRound, 100);
      should.deepEqual(txJson.genesisID, genesisID.toString());
      should.deepEqual(txJson.genesisHash.toString('base64'), genesisHash);
    });
    it('should build a half signed transfer transaction', async () => {
      const msigAddress = algosdk.multisigAddress({
        version: 1,
        threshold: 2,
        addrs: [AlgoResources.accounts.account1.address, AlgoResources.accounts.account3.address],
      });
      builder
        .sender({ address: sender.address })
        .to({ address: receiver.address })
        .amount(10000)
        .isFlatFee(true)
        .fee({ fee: '22000' })
        .firstRound(1)
        .lastRound(100)
        .testnet()
        .numberOfSigners(2)
        .setSigners([AlgoResources.accounts.account1.address, AlgoResources.accounts.account3.address])
        .sign({ key: AlgoResources.accounts.account1.prvKey });
      const tx = await builder.build();
      const txJson = tx.toJson();
      should.deepEqual(txJson.from, msigAddress);
      should.deepEqual(txJson.to, receiver.address);
      should.deepEqual(txJson.fee, 22000);
      should.deepEqual(txJson.amount, '10000');
      should.deepEqual(txJson.firstRound, 1);
      should.deepEqual(txJson.lastRound, 100);
      should.deepEqual(txJson.genesisID, genesisID.toString());
      should.deepEqual(txJson.genesisHash.toString('base64'), genesisHash);
    });
    it('should sign a half signed transfer tx', async () => {
      const msigAddress = algosdk.multisigAddress({
        version: 1,
        threshold: 2,
        addrs: [AlgoResources.accounts.account1.address, AlgoResources.accounts.account3.address],
      });
      builder.from(AlgoResources.rawTx.transfer.halfSigned);
      builder
        .numberOfSigners(2)
        .setSigners([AlgoResources.accounts.account1.address, AlgoResources.accounts.account3.address])
        .sign({ key: AlgoResources.accounts.account3.prvKey });
      const tx = await builder.build();
      should.deepEqual(Buffer.from(tx.toBroadcastFormat()).toString('hex'), AlgoResources.rawTx.transfer.multisig);
      const txJson = tx.toJson();
      should.deepEqual(txJson.from, msigAddress);
      should.deepEqual(txJson.to, receiver.address);
      should.deepEqual(txJson.fee, 22000);
      should.deepEqual(txJson.amount, '10000');
      should.deepEqual(txJson.firstRound, 1);
      should.deepEqual(txJson.lastRound, 100);
    });

    it('should build a half signed transfer transaction with 3 signers', async () => {
      const addresses = [
        AlgoResources.accounts.account1.address,
        AlgoResources.accounts.account3.address,
        AlgoResources.accounts.account4.address,
      ];
      const numberOfSigners = 3;
      const msigAddress = algosdk.multisigAddress({
        version: 1,
        threshold: numberOfSigners,
        addrs: addresses,
      });
      builder
        .sender({ address: sender.address })
        .to({ address: receiver.address })
        .amount(10000)
        .isFlatFee(true)
        .fee({ fee: '22000' })
        .firstRound(1)
        .lastRound(100)
        .testnet()
        .numberOfSigners(numberOfSigners)
        .setSigners(addresses)
        .sign({ key: AlgoResources.accounts.account1.prvKey });
      const tx1 = await builder.build();
      const builder2 = new TransferBuilder(coins.get('algo'));
      builder2.from(tx1.toBroadcastFormat());
      builder2
        .numberOfSigners(numberOfSigners)
        .setSigners(addresses)
        .sign({ key: AlgoResources.accounts.account3.prvKey });
      const tx2 = await builder2.build();
      const builder3 = new TransferBuilder(coins.get('algo'));
      builder3.from(tx2.toBroadcastFormat());

      builder3
        .numberOfSigners(numberOfSigners)
        .setSigners(addresses)
        .sign({ key: AlgoResources.accounts.account4.prvKey });
      const tx3 = await builder3.build();
      const txJson = tx3.toJson();
      should.deepEqual(txJson.from, msigAddress);
      should.deepEqual(txJson.to, receiver.address);
      should.deepEqual(txJson.fee, 22000);
      should.deepEqual(txJson.amount, '10000');
      should.deepEqual(txJson.firstRound, 1);
      should.deepEqual(txJson.lastRound, 100);
      should.deepEqual(txJson.genesisID, genesisID.toString());
      should.deepEqual(txJson.genesisHash.toString('base64'), genesisHash);
    });
  });
});

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


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