PHP WebShell

Текущая директория: /usr/lib/node_modules/bitgo/node_modules/@bitgo-forks/avalanchejs/src/vms/utils/calculateSpend

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

import { BigIntPr, Int } from '../../../serializable/primitives';
import { testContext } from '../../../fixtures/context';
import {
  fromAddressBytes,
  getLockedUTXO,
  getStakeableLockoutOutput,
  getValidUtxo,
  testAvaxAssetID,
  testUTXOID1,
  testUTXOID2,
  testUTXOID3,
  testUtxos,
} from '../../../fixtures/transactions';
import { addressesFromBytes } from '../../../utils';
import { calculateUTXOSpend } from './calculateSpend';
import {
  useSpendableLockedUTXOs,
  useUnlockedUTXOs,
} from '../../pvm/utxoCalculationFns';
import { compareTransferableOutputs } from '../../../utils/sort';
import {
  OutputOwners,
  TransferableOutput,
  TransferInput,
  TransferOutput,
} from '../../../serializable';
import { TransferableInput } from '../../../serializable';
import { Address, Id } from '../../../serializable/fxs/common';
import { NoSigMatchError } from './utils';
import { useAvmAndCorethUTXOs } from '../../../vms/avm/utxoCalculationFns';
import type { StakeableLockOut } from '../../../serializable/pvm';
import { StakeableLockIn } from '../../../serializable/pvm';
import { UTXOID } from '../../../serializable/avax';

describe('src/vms/pvm/spend/calculateSpend.spec.ts', () => {
  it('should pay down burn and stake from utxos', () => {
    const burnAmount = 100n;
    const unlockedUTXOAmount = 200n;
    const stakeAmount = 1000000n;

    const stakeAmount1 = 500000n;
    const stakeAmount2 = 600000n;
    const lockTime1 = BigInt(Math.floor(new Date().getTime() / 1000)) + 100000n;
    const lockTime2 = BigInt(Math.floor(new Date().getTime() / 1000)) + 200000n;

    const { stakeOutputs, changeOutputs, inputs } = calculateUTXOSpend(
      new Map([[testContext.avaxAssetID, burnAmount]]),
      new Map([[testContext.avaxAssetID, stakeAmount]]),
      [
        getValidUtxo(new BigIntPr(unlockedUTXOAmount)),
        getStakeableLockoutOutput(testUTXOID1, stakeAmount1, lockTime1),
        getStakeableLockoutOutput(testUTXOID2, stakeAmount2, lockTime2),
      ],
      addressesFromBytes(fromAddressBytes),
      { changeAddresses: fromAddressBytes, minIssuanceTime: 0n } as any,
      [useSpendableLockedUTXOs, useUnlockedUTXOs],
    );

    const getExpectedStakeOut = (lockTime: bigint, amount: bigint) =>
      new TransferableOutput(
        testAvaxAssetID,
        getStakeableLockoutOutput(
          Id.fromHex(''), // does not matter, we only need the output of the UTXO
          amount,
          lockTime,
        ).output as StakeableLockOut,
      );

    const getExpectedStakeInput = (
      utxoID: UTXOID,
      amount: bigint,
      lockTime: bigint,
    ) =>
      new TransferableInput(
        utxoID,
        testAvaxAssetID,
        new StakeableLockIn(
          new BigIntPr(lockTime),
          TransferInput.fromNative(amount, [0]),
        ),
      );

    // sorted stake outputs
    expect(stakeOutputs.length).toEqual(2);

    expect(stakeOutputs[0]).toStrictEqual(
      getExpectedStakeOut(lockTime1, 500000n),
    );
    expect(stakeOutputs[1]).toStrictEqual(
      getExpectedStakeOut(lockTime2, 500000n),
    );

    // sorted inputs
    expect(inputs.length).toEqual(3);

    expect(inputs[0]).toStrictEqual(
      getExpectedStakeInput(
        new UTXOID(testUTXOID1, new Int(0)),
        stakeAmount1,
        lockTime1,
      ),
    );
    expect(inputs[1]).toStrictEqual(
      new TransferableInput(
        new UTXOID(testUTXOID3, new Int(0)),
        testAvaxAssetID,
        TransferInput.fromNative(unlockedUTXOAmount, [0]),
      ),
    );
    expect(inputs[2]).toStrictEqual(
      getExpectedStakeInput(
        new UTXOID(testUTXOID2, new Int(0)),
        stakeAmount2,
        lockTime2,
      ),
    );

    // sorted change outputs
    expect(changeOutputs.length).toEqual(2);

    expect(changeOutputs[0]).toStrictEqual(
      new TransferableOutput(
        testAvaxAssetID,
        new TransferOutput(
          new BigIntPr(unlockedUTXOAmount - burnAmount),
          new OutputOwners(
            new BigIntPr(0n),
            new Int(1),
            addressesFromBytes(fromAddressBytes),
          ),
        ),
      ),
    );
    expect(changeOutputs[1]).toStrictEqual(
      getExpectedStakeOut(lockTime2, stakeAmount1 + stakeAmount2 - stakeAmount),
    );
  });
  it('Should verify if the changeOutputs, inputs and stakeOutputs have been sorted', () => {
    const burnAmount = 100n;
    const unlockedUTXOAmount = 200n;
    const lockedUTXOAmount = 1000000n;
    const stakeUTXOAmount = 1000000n;

    const { stakeOutputs, changeOutputs, inputs } = calculateUTXOSpend(
      new Map([[testContext.avaxAssetID, burnAmount]]),
      new Map([[testContext.avaxAssetID, stakeUTXOAmount]]),
      [
        getValidUtxo(new BigIntPr(unlockedUTXOAmount)),
        getLockedUTXO(new BigIntPr(lockedUTXOAmount)),
      ],
      addressesFromBytes(fromAddressBytes),
      { changeAddresses: fromAddressBytes } as any,
      [useSpendableLockedUTXOs, useUnlockedUTXOs],
    );

    expect(stakeOutputs).toEqual(
      [...stakeOutputs].sort(compareTransferableOutputs),
    );
    expect(changeOutputs).toEqual(
      [...changeOutputs].sort(compareTransferableOutputs),
    );
    expect(inputs).toEqual([...inputs].sort(TransferableInput.compare));
  });

  it('Should throw an error when the UTXO owner "fromAddress" doesnt match any UTXOs', () => {
    const tryUseFunctionAndThrowMismatchError = (useFn: (() => any)[]) => {
      return calculateUTXOSpend(
        new Map([[testContext.avaxAssetID, 100n]]),
        new Map([[testContext.avaxAssetID, 10000n]]),
        [
          getValidUtxo(new BigIntPr(10000n)),
          getLockedUTXO(new BigIntPr(10000n)),
          getStakeableLockoutOutput(testUTXOID1, 300n),
          getStakeableLockoutOutput(testUTXOID2, 10000n),
          ...testUtxos(),
        ],
        // use random address that doesnt belong to any utxos we have in the test
        addressesFromBytes([
          Address.fromString(
            'X-fuji1xwdz5ca4pl443ghm6ez63m7yr64wu6u7qhksa2',
          ).toBytes(),
        ]),
        {
          changeAddresses: fromAddressBytes,
          minIssuanceTime: 1000000000000n,
        } as any,
        // eslint-disable-next-line @typescript-eslint/ban-ts-comment
        // @ts-ignore
        [...useFn],
      );
    };

    function catchAndEqualNoSigMatch(useFns) {
      try {
        tryUseFunctionAndThrowMismatchError(useFns);
      } catch (err) {
        expect(err).toEqual(NoSigMatchError);
      }
    }

    catchAndEqualNoSigMatch([useUnlockedUTXOs]);
    catchAndEqualNoSigMatch([useSpendableLockedUTXOs, useUnlockedUTXOs]);
    catchAndEqualNoSigMatch([useAvmAndCorethUTXOs]);
  });
});

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


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