PHP WebShell
Текущая директория: /opt/BitGoJS/modules/sdk-coin-hbar/test/unit/transactionBuilder
Просмотр файла: tokenTransferBuilder.ts
import assert from 'assert';
import * as should from 'should';
import { getBuilderFactory } from '../getBuilderFactory';
import * as testData from '../../resources/hbar';
import { TransactionType } from '@bitgo/sdk-core';
describe('HBAR Token Transfer Builder', () => {
const factory = getBuilderFactory('thbar');
const TOKEN_NAME = 'thbar:usdc';
const initTxBuilder = (amount = '10') => {
const txBuilder = factory.getTokenTransferBuilder();
txBuilder.fee({ fee: testData.FEE });
txBuilder.source({ address: testData.ACCOUNT_1.accountId });
txBuilder.send({
address: testData.ACCOUNT_2.accountId,
amount: amount,
tokenName: TOKEN_NAME,
});
return txBuilder;
};
describe('should build ', () => {
describe('non serialized transactions', () => {
it('a signed transfer transaction', async () => {
const builder = initTxBuilder();
builder.validDuration(1000000);
builder.node({ nodeId: '0.0.2345' });
builder.startTime('1596110493.372646570');
builder.sign({ key: testData.ACCOUNT_1.prvKeyWithPrefix });
const tx = await builder.build();
const txJson = tx.toJson();
should.deepEqual(tx.signature.length, 1);
txJson.instructionsData.params.recipients.length.should.equal(1);
txJson.instructionsData.params.recipients[0].should.deepEqual({
address: testData.ACCOUNT_2.accountId,
amount: '10',
tokenName: TOKEN_NAME,
});
should.deepEqual(txJson.from, testData.ACCOUNT_1.accountId);
should.deepEqual(txJson.fee.toString(), testData.FEE);
should.deepEqual(tx.toBroadcastFormat(), testData.SIGNED_TOKEN_TRANSFER_TRANSACTION);
tx.type.should.equal(TransactionType.Send);
tx.outputs.length.should.equal(1);
tx.outputs[0].should.deepEqual({
address: testData.ACCOUNT_2.accountId,
value: '10',
coin: TOKEN_NAME,
});
tx.inputs.length.should.equal(1);
tx.inputs[0].should.deepEqual({
address: testData.ACCOUNT_1.accountId,
value: '10',
coin: TOKEN_NAME,
});
});
it('a token transfer transaction with amount 0', async () => {
const builder = initTxBuilder('0');
const tx = await builder.build();
const txJson = tx.toJson();
txJson.instructionsData.params.recipients.length.should.equal(1);
txJson.instructionsData.params.recipients[0].should.deepEqual({
address: testData.ACCOUNT_2.accountId,
amount: '0',
tokenName: TOKEN_NAME,
});
should.deepEqual(txJson.from, testData.ACCOUNT_1.accountId);
should.deepEqual(txJson.fee.toString(), testData.FEE);
});
it('a token transfer transaction with memo', async () => {
const builder = initTxBuilder();
builder.memo('This is an example');
const tx = await builder.build();
const txJson = tx.toJson();
txJson.instructionsData.params.recipients.length.should.equal(1);
txJson.instructionsData.params.recipients[0].should.deepEqual({
address: testData.ACCOUNT_2.accountId,
amount: '10',
tokenName: TOKEN_NAME,
});
should.deepEqual(txJson.memo, 'This is an example');
should.deepEqual(txJson.from, testData.ACCOUNT_1.accountId);
should.deepEqual(txJson.fee.toString(), testData.FEE);
});
it('a non signed token transfer transaction', async () => {
const builder = initTxBuilder();
builder.startTime('1596110493.372646570');
builder.validDuration(1000000);
builder.node({ nodeId: '0.0.2345' });
const tx = await builder.build();
const txJson = tx.toJson();
txJson.instructionsData.params.recipients.length.should.equal(1);
txJson.instructionsData.params.recipients[0].should.deepEqual({
address: testData.ACCOUNT_2.accountId,
amount: '10',
tokenName: TOKEN_NAME,
});
should.deepEqual(txJson.from, testData.ACCOUNT_1.accountId);
should.deepEqual(txJson.fee.toString(), testData.FEE);
should.deepEqual(tx.toBroadcastFormat(), testData.NON_SIGNED_TOKEN_TRANSFER_TRANSACTION);
});
it('a token transaction between accounts with realm and shard non zero', async () => {
const builder = factory.getTokenTransferBuilder();
builder.fee({ fee: testData.FEE });
builder.source({ address: '2.3.456' });
builder.send({
address: '3.4.567',
amount: '10',
tokenName: TOKEN_NAME,
});
builder.node({ nodeId: '5.2.2345' });
const tx = await builder.build();
const txJson = tx.toJson();
txJson.instructionsData.params.recipients.length.should.equal(1);
txJson.instructionsData.params.recipients[0].should.deepEqual({
address: '3.4.567',
amount: '10',
tokenName: TOKEN_NAME,
});
should.deepEqual(txJson.node, '5.2.2345');
should.deepEqual(txJson.from, '2.3.456');
});
it('a token transaction between accounts without realm and shard', async () => {
const builder = factory.getTokenTransferBuilder();
builder.fee({ fee: testData.FEE });
builder.source({ address: '456' });
builder.send({
address: '567',
amount: '10',
tokenName: TOKEN_NAME,
});
builder.node({ nodeId: '2345' });
const tx = await builder.build();
const txJson = tx.toJson();
txJson.instructionsData.params.recipients.length.should.equal(1);
txJson.instructionsData.params.recipients[0].should.deepEqual({
address: '0.0.567',
amount: '10',
tokenName: TOKEN_NAME,
});
should.deepEqual(txJson.node, '0.0.2345');
should.deepEqual(txJson.from, '0.0.456');
});
it('a transfer transaction with multiple recipients', async () => {
const builder = initTxBuilder();
builder.validDuration(1000000);
builder.node({ nodeId: '0.0.2345' });
builder.startTime('1596110493.372646570');
builder.send({
address: testData.ACCOUNT_3.accountId,
amount: '15',
tokenName: TOKEN_NAME,
});
const tx = await builder.build();
const txJson = tx.toJson();
txJson.instructionsData.params.recipients.length.should.equal(2);
txJson.instructionsData.params.recipients[0].should.deepEqual({
address: testData.ACCOUNT_2.accountId,
amount: '10',
tokenName: TOKEN_NAME,
});
txJson.instructionsData.params.recipients[1].should.deepEqual({
address: testData.ACCOUNT_3.accountId,
amount: '15',
tokenName: TOKEN_NAME,
});
should.deepEqual(txJson.from, testData.ACCOUNT_1.accountId);
should.deepEqual(txJson.fee.toString(), testData.FEE);
tx.outputs.length.should.equal(2);
tx.outputs[0].should.deepEqual({
address: testData.ACCOUNT_2.accountId,
value: '10',
coin: TOKEN_NAME,
});
tx.outputs[1].should.deepEqual({
address: testData.ACCOUNT_3.accountId,
value: '15',
coin: TOKEN_NAME,
});
tx.inputs.length.should.equal(1);
tx.inputs[0].should.deepEqual({
address: testData.ACCOUNT_1.accountId,
value: '25',
coin: TOKEN_NAME,
});
should.deepEqual(tx.toBroadcastFormat(), testData.NON_SIGNED_TOKEN_MULTI_TRANSFER_TRANSACTION);
});
});
describe('serialized token transactions', () => {
it('a non signed token transfer transaction from serialized', async () => {
const builder = factory.from(testData.NON_SIGNED_TOKEN_TRANSFER_TRANSACTION);
builder.sign({ key: testData.ACCOUNT_1.prvKeyWithPrefix });
const tx2 = await builder.build();
should.deepEqual(tx2.toBroadcastFormat(), testData.SIGNED_TOKEN_TRANSFER_TRANSACTION);
tx2.type.should.equal(TransactionType.Send);
});
it('a non signed multirecipients token transfer transaction from serialized', async () => {
const builder = factory.from(testData.NON_SIGNED_TOKEN_MULTI_TRANSFER_TRANSACTION);
builder.sign({ key: testData.ACCOUNT_1.prvKeyWithPrefix });
const tx2 = await builder.build();
should.deepEqual(tx2.toBroadcastFormat(), testData.NON_SIGNED_TOKEN_MULTI_TRANSFER_TRANSACTION_SERIALIZED);
tx2.type.should.equal(TransactionType.Send);
});
it('an offline multisig token transfer transaction', async () => {
const builder = initTxBuilder();
builder.startTime('1596110493.372646570');
builder.sign({ key: testData.ACCOUNT_1.prvKeyWithPrefix });
const tx = await builder.build();
should.deepEqual(tx.signature.length, 1);
const builder2 = factory.from(tx.toBroadcastFormat());
builder2.sign({ key: testData.ACCOUNT_2.privateKey });
const tx2 = await builder2.build();
should.deepEqual(tx2.signature.length, 2);
const builder3 = factory.from(tx2.toBroadcastFormat());
builder3.sign({ key: testData.ACCOUNT_3.privateKey });
const tx3 = await builder3.build();
should.deepEqual(tx3.signature.length, 3);
should.deepEqual(tx3.toBroadcastFormat(), testData.THREE_TIMES_SIGNED_TOKEN_TRANSACTION);
});
});
});
describe('should fail', () => {
it('a token transfer transaction with an invalid key', () => {
const builder = initTxBuilder();
assert.throws(
() => builder.sign({ key: '5bb72603f237c0993f7973d37fdade32c71aa94aee686aa79d260acba1882d90AA' }),
(e: any) => e.message === 'Invalid private key'
);
});
it('a token transfer transaction with more signatures than allowed', () => {
const builder = initTxBuilder();
builder.sign({ key: testData.ACCOUNT_2.privateKey });
builder.sign({ key: testData.ACCOUNT_1.prvKeyWithPrefix });
builder.sign({ key: testData.ACCOUNT_3.privateKey });
assert.throws(
() => builder.sign({ key: '5bb72603f237c0993f7973d37fdade32c71aa94aee686aa79d260acba1882d90' }),
(e: any) => e.message === 'A maximum of 3 can sign the transaction.'
);
});
it('a transfer transaction with repeated sign', () => {
const builder = initTxBuilder();
builder.sign({ key: testData.ACCOUNT_1.prvKeyWithPrefix });
assert.throws(
() => builder.sign({ key: testData.ACCOUNT_1.prvKeyWithPrefix }),
(e: any) =>
e.message ===
'Repeated sign: 302e020100300506032b65700422042062b0b669de0ab5e91b4328e1431859a5ca47e7426e701019272f5c2d52825b01'
);
});
it('a token transfer transaction with an invalid destination address', () => {
const txBuilder = factory.getTokenTransferBuilder();
assert.throws(
() =>
txBuilder.send({
address: 'invalidaddress',
amount: '10',
tokenName: TOKEN_NAME,
}),
(e: any) => e.message === 'Invalid address'
);
});
it('a token transfer transaction with an invalid amount: text value', () => {
const txBuilder = factory.getTokenTransferBuilder();
assert.throws(
() =>
txBuilder.send({
address: testData.ACCOUNT_2.accountId,
amount: 'invalidamount',
tokenName: TOKEN_NAME,
}),
(e: any) => e.message === 'Invalid amount'
);
});
it('a token transfer transaction with an invalid amount: negative value', () => {
const txBuilder = factory.getTokenTransferBuilder();
assert.throws(
() =>
txBuilder.send({
address: testData.ACCOUNT_2.accountId,
amount: '-5',
tokenName: TOKEN_NAME,
}),
(e: any) => e.message === 'Invalid amount'
);
});
it('a token transfer transaction with an invalid destination memo', () => {
const txBuilder = factory.getTokenTransferBuilder();
assert.throws(
() =>
txBuilder.memo(
'This sentence has more than 100 bytes allowed for the memo, this should throw error -----------------'
),
(e: any) => e.message === 'Memo must not be longer than 100 bytes'
);
});
it('a token transfer transaction with an invalid token name', () => {
const txBuilder = factory.getTokenTransferBuilder();
assert.throws(
() =>
txBuilder.send({
address: testData.ACCOUNT_2.accountId,
amount: '10',
tokenName: 'invalidtokenname',
}),
(e: any) => e.message === 'Invalid token name: invalidtokenname'
);
});
it('a token transfer transaction without token name', async () => {
const txBuilder = factory.getTokenTransferBuilder();
assert.throws(
() =>
txBuilder.send({
address: testData.ACCOUNT_2.accountId,
amount: '10',
}),
(e: any) => e.message === 'Invalid missing token name'
);
});
it('a token transfer transaction with invalid start time', () => {
const txBuilder = factory.getTokenTransferBuilder();
assert.throws(
() => txBuilder.startTime('invalid start time'),
(e: any) => e.message === 'Invalid value for time parameter'
);
assert.throws(
() => txBuilder.startTime('-5'),
(e: any) => e.message === 'Invalid value for time parameter'
);
});
it('a token transfer transaction with invalid node', () => {
const txBuilder = factory.getTokenTransferBuilder();
assert.throws(
() => txBuilder.node({ nodeId: 'invalid node' }),
(e: any) => e.message === 'Invalid Hedera node address'
);
});
});
});
Выполнить команду
Для локальной разработки. Не используйте в интернете!