PHP WebShell
Текущая директория: /opt/BitGoJS/modules/sdk-coin-avaxp/test/unit/lib
Просмотр файла: validateTxBuilder.ts
import assert from 'assert';
import 'should';
import utils from '../../../src/lib/utils';
import * as testData from '../../resources/avaxp';
import * as errorMessage from '../../resources/errors';
import { TransactionBuilderFactory, DecodedUtxoObj } from '../../../src/lib';
import { coins } from '@bitgo/statics';
import { BN } from 'avalanche';
describe('AvaxP Validate Tx Builder', () => {
const factory = new TransactionBuilderFactory(coins.get('avaxp'));
describe('validate txBuilder fields', () => {
const txBuilder = factory.getValidatorBuilder();
it('should fail nodeID tag incorrect', () => {
assert.throws(
() => {
txBuilder.validateNodeID(testData.INVALID_NODE_ID_MISSING_NODE_ID);
},
(e: any) => e.message === errorMessage.ERROR_NODE_ID
);
});
it('should fail nodeID length incorrect', () => {
assert.throws(
() => {
txBuilder.validateNodeID(testData.INVALID_NODE_ID_LENGTH);
},
(e: any) => e.message === errorMessage.ERROR_NODE_ID_LENGTH
);
});
it('should suucess nodeID length incorrect', () => {
txBuilder.validateNodeID(testData.NODE_ID_2);
});
it('should fail endTime less than 2 weeks', () => {
assert.throws(
() => {
txBuilder.validateStakeDuration(testData.START_TIME, testData.START_TIME.add(testData.ONE_WEEK));
},
(e: any) => e.message === errorMessage.ERROR_STAKE_DURATION_SHORT_TIME
);
});
it('should fail endTime greater than 1 year', () => {
assert.throws(
() => {
txBuilder.validateStakeDuration(testData.START_TIME, testData.START_TIME.add(testData.TWO_YEAR));
},
(e: any) => e.message === errorMessage.ERROR_STAKE_DURATION_LONG_TIME
);
});
it('should fail startTime too soon', () => {
assert.throws(
() => {
txBuilder.validateStakeDuration(new BN(Date.now()), testData.ONE_WEEK);
},
(e: any) => e.message === errorMessage.ERROR_STAKE_START_TIME_TOO_SHORT
);
});
it('should fail stake amount less than 2000', () => {
assert.throws(
() => {
txBuilder.validateStakeAmount(testData.INVALID_STAKE_AMOUNT);
},
(e: any) => e.message === errorMessage.ERROR_STAKE_AMOUNT
);
});
it('should fail delegationFeeRate too low', () => {
assert.throws(
() => {
txBuilder.validateDelegationFeeRate(testData.INVALID_DELEGATION_FEE);
},
(e: any) => e.message === errorMessage.ERROR_DELEGATION_FEE
);
});
it('should fail validate Utxos empty string', () => {
assert.throws(
() => {
txBuilder.validateUtxos([]);
},
(e: any) => e.message === errorMessage.ERROR_UTXOS_EMPTY
);
});
it('should fail validate Utxos without amount field', () => {
assert.throws(
() => {
txBuilder.validateUtxos([{ outputID: '' } as any as DecodedUtxoObj]);
},
(e: any) => e.message === errorMessage.ERROR_UTXOS_AMOUNT
);
});
});
describe('Utils tests', () => {
it('should fail address is invalid', () => {
utils.isValidAddress(testData.INVALID_ADDRESS).should.be.false();
});
it('should fail blockId is invalid', () => {
utils.isValidBlockId(testData.INVALID_BLOCK_ID).should.be.false();
});
it('should fail blockId length is invalid', () => {
utils.isValidBlockId(testData.INVALID_BLOCK_ID_LENGTH).should.be.false();
});
it('should pass blockId is valid', () => {
utils.isValidBlockId(testData.VALID_BLOCK_ID).should.be.true();
});
it('should pass address is valid', () => {
utils.isValidAddress(testData.VALID_ADDRESS).should.be.true();
});
});
describe('should build ', () => {
it('Should create AddValidator tx for same values', async () => {
const txBuilder = new TransactionBuilderFactory(coins.get('tavaxp'))
.getValidatorBuilder()
.threshold(testData.ADDVALIDATOR_SAMPLES.threshold)
.locktime(testData.ADDVALIDATOR_SAMPLES.locktime)
.fromPubKey(testData.ADDVALIDATOR_SAMPLES.pAddresses)
.startTime(testData.ADDVALIDATOR_SAMPLES.startTime)
.endTime(testData.ADDVALIDATOR_SAMPLES.endTime)
.stakeAmount(testData.ADDVALIDATOR_SAMPLES.minValidatorStake)
.delegationFeeRate(testData.ADDVALIDATOR_SAMPLES.delegationFee)
.nodeID(testData.ADDVALIDATOR_SAMPLES.nodeID)
.utxos(testData.ADDVALIDATOR_SAMPLES.outputs);
const tx = await txBuilder.build();
const rawTx = tx.toBroadcastFormat();
rawTx.should.equal(testData.ADDVALIDATOR_SAMPLES.unsignedTxHex);
});
it('Should create AddValidator tx when change amount is 0', async () => {
const txBuilder = new TransactionBuilderFactory(coins.get('tavaxp'))
.getValidatorBuilder()
.threshold(testData.ADDVALIDATOR_SAMPLES.threshold)
.locktime(testData.ADDVALIDATOR_SAMPLES.locktime)
.fromPubKey(testData.ADDVALIDATOR_SAMPLES.pAddresses)
.startTime(testData.ADDVALIDATOR_SAMPLES.startTime)
.endTime(testData.ADDVALIDATOR_SAMPLES.endTime)
.stakeAmount('24938830298') // stake amount is total amount in outputs
.delegationFeeRate(testData.ADDVALIDATOR_SAMPLES.delegationFee)
.nodeID(testData.ADDVALIDATOR_SAMPLES.nodeID)
.utxos(testData.ADDVALIDATOR_SAMPLES.outputs);
await txBuilder.build().should.not.throw();
});
it('Should recover AddValidator tx from raw tx', async () => {
const txBuilder = new TransactionBuilderFactory(coins.get('tavaxp')).from(
testData.ADDVALIDATOR_SAMPLES.unsignedTxHex
);
const tx = await txBuilder.build();
const rawTx = tx.toBroadcastFormat();
rawTx.should.equal(testData.ADDVALIDATOR_SAMPLES.unsignedTxHex);
});
it('Should create half signed AddValidator tx for same values', async () => {
const txBuilder = new TransactionBuilderFactory(coins.get('tavaxp'))
.getValidatorBuilder()
.threshold(testData.ADDVALIDATOR_SAMPLES.threshold)
.locktime(testData.ADDVALIDATOR_SAMPLES.locktime)
.fromPubKey(testData.ADDVALIDATOR_SAMPLES.pAddresses)
.startTime(testData.ADDVALIDATOR_SAMPLES.startTime)
.endTime(testData.ADDVALIDATOR_SAMPLES.endTime)
.stakeAmount(testData.ADDVALIDATOR_SAMPLES.minValidatorStake)
.delegationFeeRate(testData.ADDVALIDATOR_SAMPLES.delegationFee)
.nodeID(testData.ADDVALIDATOR_SAMPLES.nodeID)
.utxos(testData.ADDVALIDATOR_SAMPLES.outputs);
txBuilder.sign({ key: testData.ADDVALIDATOR_SAMPLES.privKey.prv1 });
const tx = await txBuilder.build();
const rawTx = tx.toBroadcastFormat();
rawTx.should.equal(testData.ADDVALIDATOR_SAMPLES.halfsigntxHex);
});
it('Should recover half signed AddValidator from raw tx', async () => {
const txBuilder = new TransactionBuilderFactory(coins.get('tavaxp')).from(
testData.ADDVALIDATOR_SAMPLES.halfsigntxHex
);
const tx = await txBuilder.build();
const rawTx = tx.toBroadcastFormat();
rawTx.should.equal(testData.ADDVALIDATOR_SAMPLES.halfsigntxHex);
});
it('Should half sign a AddValidator tx from unsigned raw tx', async () => {
const txBuilder = new TransactionBuilderFactory(coins.get('tavaxp')).from(
testData.ADDVALIDATOR_SAMPLES.unsignedTxHex
);
txBuilder.sign({ key: testData.ADDVALIDATOR_SAMPLES.privKey.prv1 });
const tx = await txBuilder.build();
const rawTx = tx.toBroadcastFormat();
rawTx.should.equal(testData.ADDVALIDATOR_SAMPLES.halfsigntxHex);
});
it('Should recover half signed AddValidator from half signed raw tx', async () => {
const txBuilder = new TransactionBuilderFactory(coins.get('tavaxp')).from(
testData.ADDVALIDATOR_SAMPLES.halfsigntxHex
);
const tx = await txBuilder.build();
const rawTx = tx.toBroadcastFormat();
rawTx.should.equal(testData.ADDVALIDATOR_SAMPLES.halfsigntxHex);
});
it('Should recover signed AddValidator from signed raw tx', async () => {
const txBuilder = new TransactionBuilderFactory(coins.get('tavaxp')).from(
testData.ADDVALIDATOR_SAMPLES.fullsigntxHex
);
const tx = await txBuilder.build();
const rawTx = tx.toBroadcastFormat();
rawTx.should.equal(testData.ADDVALIDATOR_SAMPLES.fullsigntxHex);
});
it('Should full sign a AddValidator tx for same values', async () => {
const txBuilder = new TransactionBuilderFactory(coins.get('tavaxp'))
.getValidatorBuilder()
.threshold(testData.ADDVALIDATOR_SAMPLES.threshold)
.locktime(testData.ADDVALIDATOR_SAMPLES.locktime)
.fromPubKey(testData.ADDVALIDATOR_SAMPLES.pAddresses)
.startTime(testData.ADDVALIDATOR_SAMPLES.startTime)
.endTime(testData.ADDVALIDATOR_SAMPLES.endTime)
.stakeAmount(testData.ADDVALIDATOR_SAMPLES.minValidatorStake)
.delegationFeeRate(testData.ADDVALIDATOR_SAMPLES.delegationFee)
.nodeID(testData.ADDVALIDATOR_SAMPLES.nodeID)
.utxos(testData.ADDVALIDATOR_SAMPLES.outputs);
txBuilder.sign({ key: testData.ADDVALIDATOR_SAMPLES.privKey.prv1 });
txBuilder.sign({ key: testData.ADDVALIDATOR_SAMPLES.privKey.prv2 });
const tx = await txBuilder.build();
const rawTx = tx.toBroadcastFormat();
rawTx.should.equal(testData.ADDVALIDATOR_SAMPLES.fullsigntxHex);
});
it('Should full sign a AddValidator tx from half signed raw tx', async () => {
const txBuilder = new TransactionBuilderFactory(coins.get('tavaxp')).from(
testData.ADDVALIDATOR_SAMPLES.halfsigntxHex
);
txBuilder.sign({ key: testData.ADDVALIDATOR_SAMPLES.privKey.prv2 });
const tx = await txBuilder.build();
const rawTx = tx.toBroadcastFormat();
rawTx.should.equal(testData.ADDVALIDATOR_SAMPLES.fullsigntxHex);
});
it('Should full sign a AddValidator tx from unsigned raw tx', async () => {
const txBuilder = new TransactionBuilderFactory(coins.get('tavaxp')).from(
testData.ADDVALIDATOR_SAMPLES.unsignedTxHex
);
txBuilder.sign({ key: testData.ADDVALIDATOR_SAMPLES.privKey.prv1 });
txBuilder.sign({ key: testData.ADDVALIDATOR_SAMPLES.privKey.prv2 });
const tx = await txBuilder.build();
const rawTx = tx.toBroadcastFormat();
rawTx.should.equal(testData.ADDVALIDATOR_SAMPLES.fullsigntxHex);
});
it('Should full sign a AddValidator tx with recovery key for same values', async () => {
const txBuilder = new TransactionBuilderFactory(coins.get('tavaxp'))
.getValidatorBuilder()
.threshold(testData.ADDVALIDATOR_SAMPLES.threshold)
.locktime(testData.ADDVALIDATOR_SAMPLES.locktime)
.fromPubKey(testData.ADDVALIDATOR_SAMPLES.pAddresses)
.startTime(testData.ADDVALIDATOR_SAMPLES.startTime)
.endTime(testData.ADDVALIDATOR_SAMPLES.endTime)
.stakeAmount(testData.ADDVALIDATOR_SAMPLES.minValidatorStake)
.delegationFeeRate(testData.ADDVALIDATOR_SAMPLES.delegationFee)
.nodeID(testData.ADDVALIDATOR_SAMPLES.nodeID)
.utxos(testData.ADDVALIDATOR_SAMPLES.outputs)
.recoverMode();
txBuilder.sign({ key: testData.ADDVALIDATOR_SAMPLES.privKey.prv3 });
txBuilder.sign({ key: testData.ADDVALIDATOR_SAMPLES.privKey.prv2 });
const tx = await txBuilder.build();
const rawTx = tx.toBroadcastFormat();
rawTx.should.equal(testData.ADDVALIDATOR_SAMPLES.recoveryFullsigntxHexWithoutMemo);
});
it('Should recover half sign a AddValidator tx with recovery key from half signed raw tx', async () => {
const txBuilder = new TransactionBuilderFactory(coins.get('tavaxp')).from(
testData.ADDVALIDATOR_SAMPLES.recoveryHalfsigntxHex
);
const tx = await txBuilder.build();
const rawTx = tx.toBroadcastFormat();
rawTx.should.equal(testData.ADDVALIDATOR_SAMPLES.recoveryHalfsigntxHex);
});
it('Should full sign a AddValidator tx with recovery key from half signed raw tx', async () => {
const txBuilder = new TransactionBuilderFactory(coins.get('tavaxp')).from(
testData.ADDVALIDATOR_SAMPLES.recoveryHalfsigntxHex
);
txBuilder.sign({ key: testData.ADDVALIDATOR_SAMPLES.privKey.prv2 });
const tx = await txBuilder.build();
const rawTx = tx.toBroadcastFormat();
rawTx.should.equal(testData.ADDVALIDATOR_SAMPLES.recoveryFullsigntxHex);
});
it('Should full sign a AddValidator tx with recovery key from unsigned raw tx', async () => {
const txBuilder = new TransactionBuilderFactory(coins.get('tavaxp')).from(
testData.ADDVALIDATOR_SAMPLES.recoveryUnsignedTxHex
);
// txBuilder.recoverMode()
txBuilder.sign({ key: testData.ADDVALIDATOR_SAMPLES.privKey.prv3 });
txBuilder.sign({ key: testData.ADDVALIDATOR_SAMPLES.privKey.prv2 });
const tx = await txBuilder.build();
const rawTx = tx.toBroadcastFormat();
rawTx.should.equal(testData.ADDVALIDATOR_SAMPLES.recoveryFullsigntxHexWithMemo);
});
it('Compare size and location of signatures in credentials for halfsign', async () => {
const txBuilder = new TransactionBuilderFactory(coins.get('tavaxp')).from(
testData.ADDVALIDATOR_SAMPLES.unsignedTxHex
);
txBuilder.sign({ key: testData.ADDVALIDATOR_SAMPLES.privKey.prv1 });
// look into credentials make sure that index 0 is signed with user key
});
it('Compare size and location of signatures in credentials for full sign', async () => {
const txBuilder = new TransactionBuilderFactory(coins.get('tavaxp')).from(
testData.ADDVALIDATOR_SAMPLES.unsignedTxHex
);
txBuilder.sign({ key: testData.ADDVALIDATOR_SAMPLES.privKey.prv1 });
txBuilder.sign({ key: testData.ADDVALIDATOR_SAMPLES.privKey.prv1 });
// look into credentials make sure that index 0 and 2 is signed
});
});
describe('Key cannot sign the transaction ', () => {
it('Should full sign a AddValidator tx from unsigned raw tx', () => {
const txBuilder = new TransactionBuilderFactory(coins.get('tavaxp')).from(
testData.ADDVALIDATOR_SAMPLES.unsignedTxHex
);
txBuilder.sign({ key: testData.ADDVALIDATOR_SAMPLES.privKey.prv2 });
txBuilder
.build()
.then(() => assert.fail('it can sign'))
.catch((err) => {
err.message.should.be.equal(errorMessage.ERROR_KEY_CANNOT_SIGN);
});
});
it('Should 2 full sign a AddValidator tx from unsigned raw tx', () => {
const txBuilder = new TransactionBuilderFactory(coins.get('tavaxp')).from(
testData.ADDVALIDATOR_SAMPLES.recoveryUnsignedTxHex
);
txBuilder.sign({ key: testData.ADDVALIDATOR_SAMPLES.privKey.prv1 });
txBuilder
.build()
.then(() => assert.fail('it can sign'))
.catch((err) => {
err.message.should.be.equal(errorMessage.ERROR_KEY_CANNOT_SIGN);
});
});
// HSM expected empty credential, we cannot verify if the next signature is the correct.
it('Should full sign a AddValidator tx from unsigned raw tx', () => {
const txBuilder = new TransactionBuilderFactory(coins.get('tavaxp')).from(
testData.ADDVALIDATOR_SAMPLES.halfsigntxHex
);
txBuilder.sign({ key: testData.ADDVALIDATOR_SAMPLES.privKey.prv2 });
txBuilder
.build()
.then(() => assert.fail('it can sign'))
.catch((err) => {
err.message.should.be.equal(errorMessage.ERROR_KEY_CANNOT_SIGN);
});
});
// HSM expected empty credential, we cannot verify if the next signature is the correct.
it('Should full sign a AddValidator tx from unsigned raw tx', () => {
const txBuilder = new TransactionBuilderFactory(coins.get('tavaxp')).from(
testData.ADDVALIDATOR_SAMPLES.recoveryHalfsigntxHex
);
txBuilder.sign({ key: testData.ADDVALIDATOR_SAMPLES.privKey.prv1 });
txBuilder
.build()
.then(() => assert.fail('it can sign'))
.catch((err) => {
err.message.should.be.equal(errorMessage.ERROR_KEY_CANNOT_SIGN);
});
});
});
});
Выполнить команду
Для локальной разработки. Не используйте в интернете!