diff --git a/CODEOWNERS b/CODEOWNERS index c45def8b33..221057ee88 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -31,6 +31,7 @@ /modules/account-lib/ @BitGo/ethalt-team /modules/sdk-coin-celo/ @BitGo/ethalt-team /modules/sdk-coin-etc/ @BitGo/ethalt-team +/modules/abstract-eth/ @BitGo/ethalt-team /modules/sdk-coin-eth/ @BitGo/ethalt-team /modules/sdk-coin-eth2/ @BitGo/ethalt-team /modules/sdk-coin-rbtc/ @BitGo/ethalt-team diff --git a/modules/abstract-eth/src/lib/transactionBuilder.ts b/modules/abstract-eth/src/lib/transactionBuilder.ts index e830e86e93..954802429c 100644 --- a/modules/abstract-eth/src/lib/transactionBuilder.ts +++ b/modules/abstract-eth/src/lib/transactionBuilder.ts @@ -626,6 +626,7 @@ export abstract class TransactionBuilder extends BaseTransactionBuilder { throw new BuildTransactionError('Missing transfer information'); } const chainId = this._common.chainIdBN().toString(); + this._transfer.walletVersion(this._walletVersion); // This change is made to support new contracts with different encoding type return this._transfer.signAndBuild(chainId, this.coinUsesNonPackedEncodingForTxData()); } diff --git a/modules/abstract-eth/src/lib/transferBuilder.ts b/modules/abstract-eth/src/lib/transferBuilder.ts index 2e844e4a0c..1742e0fc4f 100644 --- a/modules/abstract-eth/src/lib/transferBuilder.ts +++ b/modules/abstract-eth/src/lib/transferBuilder.ts @@ -20,6 +20,7 @@ export class TransferBuilder { private _coin: Readonly; private _chainId?: string; private _coinUsesNonPackedEncodingForTxData?: boolean; + private _walletVersion?: number; constructor(serializedData?: string) { if (serializedData) { @@ -48,6 +49,11 @@ export class TransferBuilder { return this; } + walletVersion(version: number): TransferBuilder { + this._walletVersion = version; + return this; + } + data(additionalData: string): TransferBuilder { this._signature = this._EMPTY_HEX_VALUE; this._data = additionalData; @@ -95,7 +101,7 @@ export class TransferBuilder { throw new InvalidParameterValueError('Invalid expiration time'); } - signAndBuild(chainId?: string, coinUsesNonPackedEncodingForTxData?: boolean): string { + signAndBuild(chainId: string, coinUsesNonPackedEncodingForTxData?: boolean): string { this._chainId = chainId; // If the coin uses non-packed encoding for tx data, the operation hash is calculated differently @@ -157,11 +163,12 @@ export class TransferBuilder { protected getOperationData(): (string | Buffer)[][] { let operationData; + const prefix = this.getOperationHashPrefix(); if (this._tokenContractAddress !== undefined) { operationData = [ ['string', 'address', 'uint', 'address', 'uint', 'uint'], [ - this.getTokenOperationHashPrefix(), + prefix, new BN(ethUtil.stripHexPrefix(this._toAddress), 16), this._amount, new BN(ethUtil.stripHexPrefix(this._tokenContractAddress), 16), @@ -176,7 +183,7 @@ export class TransferBuilder { operationData = [ ['string', 'address', 'uint', 'bytes', 'uint', 'uint'], [ - this.getNativeOperationHashPrefix(), + prefix, toAddress, this._amount, Buffer.from(ethUtil.padToEven(ethUtil.stripHexPrefix(this._data)) || '', 'hex'), @@ -188,6 +195,13 @@ export class TransferBuilder { return operationData; } + private getOperationHashPrefix(): string { + if (this._walletVersion === 4) { + return this._tokenContractAddress ? `${this._chainId}-ERC20` : `${this._chainId}`; + } + return this._tokenContractAddress ? this.getTokenOperationHashPrefix() : this.getNativeOperationHashPrefix(); + } + /** * Get the prefix used in generating an operation hash for sending tokens * diff --git a/modules/abstract-eth/src/lib/transferBuilders/baseNFTTransferBuilder.ts b/modules/abstract-eth/src/lib/transferBuilders/baseNFTTransferBuilder.ts index 6694da7edd..151624c2d2 100644 --- a/modules/abstract-eth/src/lib/transferBuilders/baseNFTTransferBuilder.ts +++ b/modules/abstract-eth/src/lib/transferBuilders/baseNFTTransferBuilder.ts @@ -17,6 +17,7 @@ export abstract class BaseNFTTransferBuilder { protected _coin: Readonly; protected _nativeCoinOperationHashPrefix?: string; protected _chainId?: string; + protected _walletVersion?: number; public abstract build(): string; @@ -38,6 +39,11 @@ export abstract class BaseNFTTransferBuilder { throw new InvalidParameterValueError('Invalid expiration time'); } + walletVersion(version: number): this { + this._walletVersion = version; + return this; + } + key(signKey: string): this { this._signKey = signKey; return this; @@ -101,6 +107,9 @@ export abstract class BaseNFTTransferBuilder { * @returns the string prefix */ protected getNativeOperationHashPrefix(): string { + if (this._walletVersion === 4) { + return this._chainId ?? 'ETHER'; + } return this._nativeCoinOperationHashPrefix ?? this._chainId ?? 'ETHER'; } diff --git a/modules/abstract-eth/src/lib/transferBuilders/transferBuilderERC1155.ts b/modules/abstract-eth/src/lib/transferBuilders/transferBuilderERC1155.ts index cd1935e32c..b16c471edd 100644 --- a/modules/abstract-eth/src/lib/transferBuilders/transferBuilderERC1155.ts +++ b/modules/abstract-eth/src/lib/transferBuilders/transferBuilderERC1155.ts @@ -53,7 +53,7 @@ export class ERC1155TransferBuilder extends BaseNFTTransferBuilder { return this; } - signAndBuild(chainId?: string): string { + signAndBuild(chainId: string): string { this._chainId = chainId; const hasMandatoryFields = this.hasMandatoryFields(); if (hasMandatoryFields) { diff --git a/modules/abstract-eth/src/lib/transferBuilders/transferBuilderERC721.ts b/modules/abstract-eth/src/lib/transferBuilders/transferBuilderERC721.ts index 41e2712d2c..fec998cb8b 100644 --- a/modules/abstract-eth/src/lib/transferBuilders/transferBuilderERC721.ts +++ b/modules/abstract-eth/src/lib/transferBuilders/transferBuilderERC721.ts @@ -50,7 +50,7 @@ export class ERC721TransferBuilder extends BaseNFTTransferBuilder { return contractCall.serialize(); } - signAndBuild(chainId?: string): string { + signAndBuild(chainId: string): string { this._chainId = chainId; if (this.hasMandatoryFields()) { this._data = this.build(); diff --git a/modules/abstract-eth/test/unit/transferBuilder.ts b/modules/abstract-eth/test/unit/transferBuilder.ts index d8be6eebd0..53dd3317a8 100644 --- a/modules/abstract-eth/test/unit/transferBuilder.ts +++ b/modules/abstract-eth/test/unit/transferBuilder.ts @@ -1,5 +1,6 @@ import assert from 'assert'; import should from 'should'; +import { coins, EthereumNetwork as EthLikeNetwork } from '@bitgo/statics'; import { KeyPair, TransferBuilder } from '../../src'; describe('Eth send multi sig builder', function () { @@ -19,6 +20,7 @@ describe('Eth send multi sig builder', function () { ethLikeCoins.forEach((coin) => { it('should fail with an invalid key', () => { + const staticsCoin = coins.get(coin) as unknown as EthLikeNetwork; const builder = new TransferBuilder() .coin(coin) .expirationTime(1590078260) @@ -27,7 +29,7 @@ describe('Eth send multi sig builder', function () { .contractSequenceId(2) .key('invalidkey'); should(() => { - builder.signAndBuild(); + builder.signAndBuild(`${staticsCoin.chainId}`); }).throw('private key length is invalid'); }); }); @@ -64,17 +66,17 @@ describe('Eth send multi sig builder', function () { it('should fail if a sequenceId param is missing', () => { const builder = new TransferBuilder().amount(amount).to(toAddress).key(key); - assert.throws(() => builder.signAndBuild()); + assert.throws(() => builder.signAndBuild('')); }); it('should fail if a destination param is missing', () => { const builder = new TransferBuilder().amount(amount).contractSequenceId(2).key(key); - assert.throws(() => builder.signAndBuild()); + assert.throws(() => builder.signAndBuild('')); }); it('should fail if a amount param is missing', () => { const builder = new TransferBuilder().to(toAddress).contractSequenceId(2).key(key); - assert.throws(() => builder.signAndBuild()); + assert.throws(() => builder.signAndBuild('')); }); }); }); diff --git a/modules/sdk-coin-arbeth/test/unit/transferBuilder.ts b/modules/sdk-coin-arbeth/test/unit/transferBuilder.ts index 4bf1fd9bd2..5e2c3a6fe1 100644 --- a/modules/sdk-coin-arbeth/test/unit/transferBuilder.ts +++ b/modules/sdk-coin-arbeth/test/unit/transferBuilder.ts @@ -1,4 +1,5 @@ import should from 'should'; +import { coins, EthereumNetwork as EthLikeNetwork } from '@bitgo/statics'; import { KeyPair, TransferBuilder } from '../../src'; import * as testData from '../resources'; @@ -8,7 +9,7 @@ describe('Arbeth send multi sig builder', function () { 'xprv9s21ZrQH143K3D8TXfvAJgHVfTEeQNW5Ys9wZtnUZkqPzFzSjbEJrWC1vZ4GnXCvR7rQL2UFX3RSuYeU9MrERm1XBvACow7c36vnz5iYyj2'; const key = new KeyPair({ prv: xprv }).getKeys().prv as string; const amount = '100000000000000000'; // equivalent to 0.1 ether - + const coin = coins.get('tarbeth') as unknown as EthLikeNetwork; describe('should build', () => { it('native coin transfer should succeed', async () => { const builder = new TransferBuilder() @@ -19,7 +20,7 @@ describe('Arbeth send multi sig builder', function () { .contractSequenceId(2) .key(key) .data('0x'); - const result = builder.signAndBuild(); + const result = builder.signAndBuild(`${coin.chainId}`); should.equal(result, testData.SEND_FUNDS_DATA); }); @@ -32,7 +33,7 @@ describe('Arbeth send multi sig builder', function () { .contractSequenceId(0) .key(key) .data('0x'); - const result = builder.signAndBuild(); + const result = builder.signAndBuild(`${coin.chainId}`); should.equal(result, testData.SEND_FUNDS_SEQUENCE_ZERO_DATA); }); @@ -45,7 +46,7 @@ describe('Arbeth send multi sig builder', function () { .contractSequenceId(2) .key(key) .data('0x'); - const result = builder.signAndBuild(); + const result = builder.signAndBuild(`${coin.chainId}`); should.equal(result, testData.SEND_FUNDS_AMOUNT_ZERO_DATA); }); @@ -57,7 +58,7 @@ describe('Arbeth send multi sig builder', function () { .to(toAddress) .contractSequenceId(2) .key(key); - const result = builder.signAndBuild(); + const result = builder.signAndBuild(`${coin.chainId}`); should.equal(result, testData.SEND_ARBETH_LINK_DATA); }); @@ -69,7 +70,7 @@ describe('Arbeth send multi sig builder', function () { .to(toAddress) .contractSequenceId(0) .key(key); - const result = builder.signAndBuild(); + const result = builder.signAndBuild(`${coin.chainId}`); should.equal(result, testData.SEND_TOKEN_SEQUENCE_ZERO_DATA); }); @@ -81,7 +82,7 @@ describe('Arbeth send multi sig builder', function () { .to(toAddress) .contractSequenceId(2) .key(key); - const result = builder.signAndBuild(); + const result = builder.signAndBuild(`${coin.chainId}`); should.equal(result, testData.SEND_TOKEN_AMOUNT_ZERO_DATA); }); @@ -92,14 +93,14 @@ describe('Arbeth send multi sig builder', function () { .to(toAddress) .contractSequenceId(2) .data('0x'); - const result = builder.signAndBuild(); + const result = builder.signAndBuild(`${coin.chainId}`); should.equal(result, testData.SEND_FUNDS_NO_KEY_DATA); }); it('should build from a non signed serialized data', () => { const builder = new TransferBuilder(testData.SEND_FUNDS_NO_KEY_DATA); builder.coin('tarbeth').key(key); - const result = builder.signAndBuild(); + const result = builder.signAndBuild(`${coin.chainId}`); should.equal(result, testData.SEND_FUNDS_DATA); }); }); diff --git a/modules/sdk-coin-avaxc/test/unit/transferBuilder.ts b/modules/sdk-coin-avaxc/test/unit/transferBuilder.ts index ef39016a85..e0f836e1c0 100644 --- a/modules/sdk-coin-avaxc/test/unit/transferBuilder.ts +++ b/modules/sdk-coin-avaxc/test/unit/transferBuilder.ts @@ -4,6 +4,7 @@ import { getBuilder } from './getBuilder'; import * as testData from '../resources/avaxc'; import { TransactionType } from '@bitgo/sdk-core'; import { decodeTokenTransferData } from '@bitgo/sdk-coin-eth'; +import { coins, EthereumNetwork as EthLikeNetwork } from '@bitgo/statics'; const amount = '20000'; const toAddress = '0x7325A3F7d4f9E86AE62Cf742426078C3755730d5'; @@ -20,7 +21,7 @@ const tokensNames = [ 'avaxc:link', 'tavaxc:link', ]; - +const coin = coins.get('avaxc') as unknown as EthLikeNetwork; let txBuilder: TransactionBuilder; const contractAddress = testData.TEST_ACCOUNT.ethAddress; const initTxBuilder = (): void => { @@ -44,7 +45,7 @@ describe('AVAXERC20 Tokens', () => { .to(toAddress) .contractSequenceId(2) .key(key); - const result = builder.signAndBuild(); + const result = builder.signAndBuild(`${coin.chainId}`); const decode = decodeTokenTransferData(result); should.equal(decode.amount, '20000'); should.equal(decode.expireTime, 1590078260); diff --git a/modules/sdk-coin-celo/test/unit/transferBuilder.ts b/modules/sdk-coin-celo/test/unit/transferBuilder.ts index 79f41e0e59..68afe07d0d 100644 --- a/modules/sdk-coin-celo/test/unit/transferBuilder.ts +++ b/modules/sdk-coin-celo/test/unit/transferBuilder.ts @@ -1,6 +1,7 @@ import should from 'should'; import { KeyPair, TransferBuilder } from '../../src'; import * as testData from '../resources/celo'; +import { coins, EthereumNetwork as EthLikeNetwork } from '@bitgo/statics'; describe('Celo send multi sig builder', function () { const toAddress = '0x7325A3F7d4f9E86AE62Cf742426078C3755730d5'; @@ -8,7 +9,7 @@ describe('Celo send multi sig builder', function () { 'xprv9s21ZrQH143K3D8TXfvAJgHVfTEeQNW5Ys9wZtnUZkqPzFzSjbEJrWC1vZ4GnXCvR7rQL2UFX3RSuYeU9MrERm1XBvACow7c36vnz5iYyj2'; const key = new KeyPair({ prv: xprv }).getKeys().prv as string; const amount = '100000000000000000'; // equivalent to 0.1 ether - + const coin = coins.get('tcelo') as unknown as EthLikeNetwork; describe('should build', () => { it('celo token transfer should succeed', async () => { const builder = new TransferBuilder() @@ -18,7 +19,7 @@ describe('Celo send multi sig builder', function () { .to(toAddress) .contractSequenceId(2) .key(key); - const result = builder.signAndBuild(); + const result = builder.signAndBuild(`${coin.chainId}`); should.equal(result, testData.SEND_TOKEN_DATA); }); @@ -30,7 +31,7 @@ describe('Celo send multi sig builder', function () { .to(toAddress) .contractSequenceId(0) .key(key); - const result = builder.signAndBuild(); + const result = builder.signAndBuild(`${coin.chainId}`); should.equal(result, testData.SEND_TOKEN_SEQUENCE_ZERO_DATA); }); @@ -42,7 +43,7 @@ describe('Celo send multi sig builder', function () { .to(toAddress) .contractSequenceId(2) .key(key); - const result = builder.signAndBuild(); + const result = builder.signAndBuild(`${coin.chainId}`); should.equal(result, testData.SEND_TOKEN_AMOUNT_ZERO_DATA); }); @@ -54,14 +55,14 @@ describe('Celo send multi sig builder', function () { .to(toAddress) .contractSequenceId(2) .data('0x'); - const result = builder.signAndBuild(); + const result = builder.signAndBuild(`${coin.chainId}`); should.equal(result, testData.SEND_FUNDS_NO_KEY_DATA); }); it('should build from a non signed serialized data', () => { const builder = new TransferBuilder(testData.SEND_FUNDS_NO_KEY_DATA); builder.key(key); - const result = builder.signAndBuild(); + const result = builder.signAndBuild(`${coin.chainId}`); should.equal(result, testData.SEND_FUNDS_DATA); }); }); diff --git a/modules/sdk-coin-eth/test/resources/eth.ts b/modules/sdk-coin-eth/test/resources/eth.ts index 6f6395539e..7c957eecbc 100644 --- a/modules/sdk-coin-eth/test/resources/eth.ts +++ b/modules/sdk-coin-eth/test/resources/eth.ts @@ -94,12 +94,12 @@ export const SEND_TERC_DATA = export const CONTRACT_TOKEN_CUSD_ADDRESS = '0xa561131a1C8aC25925FB848bCa45A74aF61e5A38'; export const SEND_TX_BROADCAST_LEGACY = - '0xf901ca02843b9aca0083b8a1a0948f977e912ef500548a0c3be6ddde9899f1199b8180b901643912521500000000000000000000000019645032c7f1533395d44a629462e751084d3e4c000000000000000000000000000000000000000000000000000000003b9aca0000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000005ec67e28000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000417e522e602252e010f97b81b1a83128cf283dcef2ea06c221a236c1c11883adfc222a46f4c9a6ab8cd1d5dd1e963ffa443de88c9cebf755c399702dc00b0b55d61b0000000000000000000000000000000000000000000000000000000000000078a065751b9ff267e551cdc3e304e4314ac395be24b9071b10d90067215414782cb5a0111e39c47d856150fdcf521417aa3c1eea64861f349009be969c835e2bbe0425'; + '0xf901cc02843b9aca0083b8a1a0948f977e912ef500548a0c3be6ddde9899f1199b8180b901643912521500000000000000000000000019645032c7f1533395d44a629462e751084d3e4c000000000000000000000000000000000000000000000000000000003b9aca0000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000005ec67e28000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000417e522e602252e010f97b81b1a83128cf283dcef2ea06c221a236c1c11883adfc222a46f4c9a6ab8cd1d5dd1e963ffa443de88c9cebf755c399702dc00b0b55d61b000000000000000000000000000000000000000000000000000000000000008284f4a0375b0731252b8a4a6f54cd3ee8078e5ba8a89168c8b9b3a49a7a3fb60984b49fa029de0bb07d891c5ad4273016055e474b0c70fa288008eadfaa16ec73b6b78427'; -export const SEND_TX_BROADCAST_EIP1559 = `0x02f901912a02843b9aca00843b9aca0083b8a1a0948f977e912ef500548a0c3be6ddde9899f1199b8180b901643912521500000000000000000000000019645032c7f1533395d44a629462e751084d3e4c000000000000000000000000000000000000000000000000000000003b9aca0000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000005ec67e28000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000417e522e602252e010f97b81b1a83128cf283dcef2ea06c221a236c1c11883adfc222a46f4c9a6ab8cd1d5dd1e963ffa443de88c9cebf755c399702dc00b0b55d61b00000000000000000000000000000000000000000000000000000000000000c0808080`; +export const SEND_TX_BROADCAST_EIP1559 = `0x02f901d282426802830f4240840605234083b8a1a0948f977e912ef500548a0c3be6ddde9899f1199b8180b901643912521500000000000000000000000019645032c7f1533395d44a629462e751084d3e4c000000000000000000000000000000000000000000000000000000003b9aca0000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000005ec67e28000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000417e522e602252e010f97b81b1a83128cf283dcef2ea06c221a236c1c11883adfc222a46f4c9a6ab8cd1d5dd1e963ffa443de88c9cebf755c399702dc00b0b55d61b00000000000000000000000000000000000000000000000000000000000000c080a011efa5a61513c91c611ac1ba2ad1ed35ac90b7541f9c2bcc3fad9f14f156ee09a010be91f8e395e9fb9be5b6afbcbe7982691f149a6e5f3fc2ff5db327b03b74e0`; export const SEND_TX_AMOUNT_ZERO_BROADCAST = - '0xf901ca02843b9aca0083b8a1a0948f977e912ef500548a0c3be6ddde9899f1199b8180b901643912521500000000000000000000000019645032c7f1533395d44a629462e751084d3e4c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000005ec67e28000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000419b75b58d33f058a511267e80e1fb98540e71444e0c66515c66e6c7162d8e8ac6368cb9d0b4eb13bad54c31b2baf69f85fb30d2353901e0948f9fd680d9d94ec31b0000000000000000000000000000000000000000000000000000000000000078a03e187bd1b076a228af9f65fd429217223a9b0cd57a066560e333ef2204c9f67ea06804f35ef1895144edca6ea1f01981cdeec6b31358caaee7d4f495355ffb3b64'; + '0xf901cc02843b9aca0083b8a1a0948f977e912ef500548a0c3be6ddde9899f1199b8180b901643912521500000000000000000000000019645032c7f1533395d44a629462e751084d3e4c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000005ec67e28000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000419b75b58d33f058a511267e80e1fb98540e71444e0c66515c66e6c7162d8e8ac6368cb9d0b4eb13bad54c31b2baf69f85fb30d2353901e0948f9fd680d9d94ec31b000000000000000000000000000000000000000000000000000000000000008284f4a00d784a5037ff8124daeca471c59cfe40f75a4a816b0700dd52d6a4257b66476fa0672040771e698bf30fcc47eefce39f0b9d87381ed2d7df8e803dd5cd7f3efe62'; export const UNSIGNED_ADDRESS_INIT = '0xe3010a8203e8948f977e912ef500548a0c3be6ddde9899f1199b818084a68a76cc808080'; @@ -130,4 +130,4 @@ export const SEND_FUNDS_METHOD_CALL = '0x2e7e33df000000000000000000000000326c977e6efc84e512bb9c30f76e30c160ed06fb000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000'; export const SEND_TOKEN_TX_BROADCAST = - '0xf901aa02843b9aca0083b8a1a094df7decb1baa8f529f0c8982cbb4be5035719529980b901440dcd7a6c00000000000000000000000072c2c8e08bf91d755cd7d26b49a2ee3dc99de1b9000000000000000000000000000000000000000000000000000000000000006400000000000000000000000019f64674d8a5b4e652319f5e239efd3bc969a1fe000000000000000000000000000000000000000000000000000000005ec67e28000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000004118e288f7cefa56b17e878f34566af7103c6fe860a923e5fb1f94d90f9580dacf43c6ba97727a713ed63ac4730bec7b71d9a99fb99d14866ac16756af44d9451a1c0000000000000000000000000000000000000000000000000000000000000078a036705c58646867be2dad8293e4905471892ff6a3086904a2934b4e8a83cb251fa04f1700ea096b7aa1c0c73218f2cc3f68ec1a4d497fd82a2bb589d9ee777417e2'; + '0xf901ac02843b9aca0083b8a1a094df7decb1baa8f529f0c8982cbb4be5035719529980b901440dcd7a6c00000000000000000000000072c2c8e08bf91d755cd7d26b49a2ee3dc99de1b9000000000000000000000000000000000000000000000000000000000000006400000000000000000000000019f64674d8a5b4e652319f5e239efd3bc969a1fe000000000000000000000000000000000000000000000000000000005ec67e28000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000004118e288f7cefa56b17e878f34566af7103c6fe860a923e5fb1f94d90f9580dacf43c6ba97727a713ed63ac4730bec7b71d9a99fb99d14866ac16756af44d9451a1c000000000000000000000000000000000000000000000000000000000000008284f4a0f6e60f6062255b387ff94b702a1496b98a9a421b9ec99cb2b5d252055337bc67a0379f32c3b87445bde443252c6729205d9f880d1e845a7aae69cb27f7b0347d08'; diff --git a/modules/sdk-coin-eth/test/unit/transactionBuilder/send.ts b/modules/sdk-coin-eth/test/unit/transactionBuilder/send.ts index 70eb27f906..3a60e0e3a6 100644 --- a/modules/sdk-coin-eth/test/unit/transactionBuilder/send.ts +++ b/modules/sdk-coin-eth/test/unit/transactionBuilder/send.ts @@ -50,7 +50,7 @@ describe('Eth transaction builder send', () => { beforeEach(() => { contractAddress = '0x8f977e912ef500548a0c3be6ddde9899f1199b81'; - txBuilder = getBuilder('teth') as TransactionBuilder; + txBuilder = getBuilder('hteth') as TransactionBuilder; key = testData.KEYPAIR_PRV.getKeys().prv as string; txBuilder.fee({ fee: '1000000000', @@ -76,7 +76,7 @@ describe('Eth transaction builder send', () => { txBuilder.sign({ key: testData.PRIVATE_KEY }); const tx = await txBuilder.build(); - should.equal(tx.toJson().chainId, 42); + should.equal(tx.toJson().chainId, 17000); should.equal(tx.toBroadcastFormat(), testData.SEND_TX_BROADCAST_LEGACY); should.equal(tx.signature.length, 2); should.equal(tx.inputs.length, 1); @@ -100,6 +100,25 @@ describe('Eth transaction builder send', () => { should.equal(parsedSequenceId, sequenceId); }); + it('should send funds for wallet version 4', async () => { + const recipient = '0x19645032c7f1533395d44a629462e751084d3e4c'; + const amount = '1000000000'; + const expireTime = 1590066728; + const sequenceId = 5; + txBuilder.walletVersion(4); + txBuilder + .transfer() + .amount(amount) + .to(recipient) + .expirationTime(expireTime) + .contractSequenceId(sequenceId) + .key(key); + txBuilder.sign({ key: testData.PRIVATE_KEY }); + await txBuilder.build(); + const operationData = txBuilder.transfer().getOperationData(); + should.equal(operationData[1][0], '17000'); + }); + it('a send funds with amount 0 transaction', async () => { txBuilder .transfer() @@ -195,7 +214,7 @@ describe('Eth transaction builder send', () => { }); it('a send token transactions from serialized', async () => { - const txBuilder = new TransactionBuilder(coins.get('teth')); + const txBuilder = new TransactionBuilder(coins.get('hteth')); txBuilder.from(testData.SEND_TOKEN_TX_BROADCAST); const tx = await txBuilder.build(); should.equal(tx.toBroadcastFormat(), testData.SEND_TOKEN_TX_BROADCAST); @@ -220,7 +239,7 @@ describe('Eth transaction builder send', () => { testParams.map(([txnType, txnHex]) => { it(`should be able to create a send transaction from serialized ${txnType} tx hex`, async () => { - const txBuilder = getBuilder('teth') as TransactionBuilder; + const txBuilder = getBuilder('hteth') as TransactionBuilder; txBuilder.from(txnHex); const signedTx = await txBuilder.build(); should.equal(signedTx.toBroadcastFormat(), txnHex); @@ -229,7 +248,7 @@ describe('Eth transaction builder send', () => { } it('a send funds transaction with amount 0 from serialized', async () => { - const txBuilder = getBuilder('teth') as TransactionBuilder; + const txBuilder = getBuilder('hteth') as TransactionBuilder; txBuilder.from(testData.SEND_TX_AMOUNT_ZERO_BROADCAST); const signedTx = await txBuilder.build(); should.equal(signedTx.toBroadcastFormat(), testData.SEND_TX_AMOUNT_ZERO_BROADCAST); diff --git a/modules/sdk-coin-eth/test/unit/transactionBuilder/sendNFT.ts b/modules/sdk-coin-eth/test/unit/transactionBuilder/sendNFT.ts index dc7c02679a..5cc21f4259 100644 --- a/modules/sdk-coin-eth/test/unit/transactionBuilder/sendNFT.ts +++ b/modules/sdk-coin-eth/test/unit/transactionBuilder/sendNFT.ts @@ -1,4 +1,5 @@ import { TransactionType } from '@bitgo/sdk-core'; +import { coins, EthereumNetwork as EthLikeNetwork } from '@bitgo/statics'; import { ERC1155TransferBuilder, ERC721TransferBuilder, TransactionBuilder } from '../../../src'; import * as testData from '../../resources/eth'; import { ethers } from 'ethers'; @@ -23,6 +24,7 @@ describe('Eth transaction builder sendNFT', () => { const erc721ContractAddress = '0x57f1887a8bf19b14fc0df6fd9b2acc9af147ea85'; // opensea erc1155 const erc1155ContractAddress = '0x495f947276749ce646f68ac8c248420045cb7b5e'; + const coin = coins.get('hteth') as unknown as EthLikeNetwork; let key; beforeEach(() => { @@ -30,7 +32,7 @@ describe('Eth transaction builder sendNFT', () => { }); it('should sign ERC721 properly', async () => { - const txBuilder = getBuilder('teth') as TransactionBuilder; + const txBuilder = getBuilder('hteth') as TransactionBuilder; txBuilder.fee({ fee: '1000000000', gasLimit: '12100000', @@ -59,7 +61,7 @@ describe('Eth transaction builder sendNFT', () => { }); it('should sign and build ERC721 transfer with Builder pattern', async () => { - const txBuilder = getBuilder('teth') as TransactionBuilder; + const txBuilder = getBuilder('hteth') as TransactionBuilder; txBuilder.fee({ fee: '1000000000', gasLimit: '12100000', @@ -83,7 +85,7 @@ describe('Eth transaction builder sendNFT', () => { .tokenId(tokenId) .key(key); - const sendMultisigCallData = erc721Transfer.signAndBuild(); + const sendMultisigCallData = erc721Transfer.signAndBuild(`${coin.chainId}`); const decodedSendMultisigCallData = decodeTransaction(JSON.stringify(walletSimpleABI), sendMultisigCallData); const safeTransferFromCallData = decodedSendMultisigCallData.args[2]; @@ -95,7 +97,7 @@ describe('Eth transaction builder sendNFT', () => { }); it('should sign and build ERC721 transfer with Decoder pattern', async () => { - const txBuilder = getBuilder('teth') as TransactionBuilder; + const txBuilder = getBuilder('hteth') as TransactionBuilder; txBuilder.fee({ fee: '1000000000', gasLimit: '12100000', @@ -107,7 +109,7 @@ describe('Eth transaction builder sendNFT', () => { const tokenId = '1'; const erc721Transfer = txBuilder.transfer(erc721Encoding) as ERC721TransferBuilder; - const sendMultisigCallData = erc721Transfer.signAndBuild(); + const sendMultisigCallData = erc721Transfer.signAndBuild(`${coin.chainId}`); const decodedSendMultisigCallData = decodeTransaction(JSON.stringify(walletSimpleABI), sendMultisigCallData); const safeTransferFromCallData = decodedSendMultisigCallData.args[2]; @@ -119,7 +121,7 @@ describe('Eth transaction builder sendNFT', () => { }); it('should sign and build ERC1155 single transfer with Builder pattern', async () => { - const txBuilder = getBuilder('teth') as TransactionBuilder; + const txBuilder = getBuilder('hteth') as TransactionBuilder; txBuilder.fee({ fee: '1000000000', gasLimit: '12100000', @@ -143,7 +145,7 @@ describe('Eth transaction builder sendNFT', () => { .entry(tokenId, value) .key(key); - const sendMultisigCallData = erc1155Transfer.signAndBuild(); + const sendMultisigCallData = erc1155Transfer.signAndBuild(`${coin.chainId}`); const decodedSendMultisigCallData = decodeTransaction(JSON.stringify(walletSimpleABI), sendMultisigCallData); const safeTransferFromCallData = decodedSendMultisigCallData.args[2]; @@ -159,7 +161,7 @@ describe('Eth transaction builder sendNFT', () => { }); it('should sign and build ERC1155 single transfer with Decoder pattern', async () => { - const txBuilder = getBuilder('teth') as TransactionBuilder; + const txBuilder = getBuilder('hteth') as TransactionBuilder; txBuilder.fee({ fee: '1000000000', gasLimit: '12100000', @@ -172,7 +174,7 @@ describe('Eth transaction builder sendNFT', () => { const value = '10'; const erc1155Transfer = txBuilder.transfer(erc1155SafeTransferEncoding) as ERC1155TransferBuilder; - const sendMultisigCallData = erc1155Transfer.signAndBuild(); + const sendMultisigCallData = erc1155Transfer.signAndBuild(`${coin.chainId}`); const decodedSendMultisigCallData = decodeTransaction(JSON.stringify(walletSimpleABI), sendMultisigCallData); @@ -186,7 +188,7 @@ describe('Eth transaction builder sendNFT', () => { }); it('should sign and build ERC1155 batch transfer with Builder pattern', async () => { - const txBuilder = getBuilder('teth') as TransactionBuilder; + const txBuilder = getBuilder('hteth') as TransactionBuilder; txBuilder.fee({ fee: '1000000000', gasLimit: '12100000', @@ -212,7 +214,7 @@ describe('Eth transaction builder sendNFT', () => { .entry(tokenIds[2], values[2]) .key(key); - const sendMultisigCallData = erc1155Transfer.signAndBuild(); + const sendMultisigCallData = erc1155Transfer.signAndBuild(`${coin.chainId}`); const decodedSendMultisigCallData = decodeTransaction(JSON.stringify(walletSimpleABI), sendMultisigCallData); const safeTransferFromCallData = decodedSendMultisigCallData.args[2]; @@ -231,7 +233,7 @@ describe('Eth transaction builder sendNFT', () => { }); it('should sign and build ERC1155 batch transfer with Decoder pattern', async () => { - const txBuilder = getBuilder('teth') as TransactionBuilder; + const txBuilder = getBuilder('hteth') as TransactionBuilder; txBuilder.fee({ fee: '1000000000', gasLimit: '12100000', @@ -245,7 +247,7 @@ describe('Eth transaction builder sendNFT', () => { const erc1155Transfer = txBuilder.transfer(erc1155BatchTransferEncoding) as ERC1155TransferBuilder; - const sendMultisigCallData = erc1155Transfer.signAndBuild(); + const sendMultisigCallData = erc1155Transfer.signAndBuild(`${coin.chainId}`); const decodedSendMultisigCallData = decodeTransaction(JSON.stringify(walletSimpleABI), sendMultisigCallData); const safeTransferFromCallData = decodedSendMultisigCallData.args[2]; diff --git a/modules/sdk-coin-eth/test/unit/transferBuilder.ts b/modules/sdk-coin-eth/test/unit/transferBuilder.ts index 3fe7789b81..68d36599a2 100644 --- a/modules/sdk-coin-eth/test/unit/transferBuilder.ts +++ b/modules/sdk-coin-eth/test/unit/transferBuilder.ts @@ -1,5 +1,5 @@ import should from 'should'; - +import { coins, EthereumNetwork as EthLikeNetwork } from '@bitgo/statics'; import { KeyPair, TransferBuilder } from '../../src'; import * as testData from '../resources/eth'; @@ -9,7 +9,7 @@ describe('Eth send multi sig builder', function () { 'xprv9s21ZrQH143K3D8TXfvAJgHVfTEeQNW5Ys9wZtnUZkqPzFzSjbEJrWC1vZ4GnXCvR7rQL2UFX3RSuYeU9MrERm1XBvACow7c36vnz5iYyj2'; const key = new KeyPair({ prv: xprv }).getKeys().prv as string; const amount = '100000000000000000'; // equivalent to 0.1 ether - + const coin = coins.get('hteth') as unknown as EthLikeNetwork; describe('should build', () => { it('native coin transfer should succeed', async () => { const builder = new TransferBuilder() @@ -19,7 +19,7 @@ describe('Eth send multi sig builder', function () { .contractSequenceId(2) .key(key) .data('0x'); - const result = builder.signAndBuild(); + const result = builder.signAndBuild(`${coin.chainId}`); should.equal(result, testData.SEND_FUNDS_DATA); }); @@ -32,7 +32,7 @@ describe('Eth send multi sig builder', function () { .contractSequenceId(2) .key(key) .data('0x'); - const result = builder.signAndBuild(); + const result = builder.signAndBuild(`${coin.chainId}`); should.equal(result, testData.SEND_FUNDS_DATA); }); @@ -44,7 +44,7 @@ describe('Eth send multi sig builder', function () { .contractSequenceId(0) .key(key) .data('0x'); - const result = builder.signAndBuild(); + const result = builder.signAndBuild(`${coin.chainId}`); should.equal(result, testData.SEND_FUNDS_SEQUENCE_ZERO_DATA); }); @@ -56,7 +56,7 @@ describe('Eth send multi sig builder', function () { .contractSequenceId(2) .key(key) .data('0x'); - const result = builder.signAndBuild(); + const result = builder.signAndBuild(`${coin.chainId}`); should.equal(result, testData.SEND_FUNDS_AMOUNT_ZERO_DATA); }); @@ -68,7 +68,7 @@ describe('Eth send multi sig builder', function () { .to(toAddress) .contractSequenceId(2) .key(key); - const result = builder.signAndBuild(); + const result = builder.signAndBuild(`${coin.chainId}`); should.equal(result, testData.SEND_TERC_DATA); }); @@ -79,14 +79,14 @@ describe('Eth send multi sig builder', function () { .to(toAddress) .contractSequenceId(2) .data('0x'); - const result = builder.signAndBuild(); + const result = builder.signAndBuild(`${coin.chainId}`); should.equal(result, testData.SEND_FUNDS_NO_KEY_DATA); }); it('should build from a non signed serialized data', () => { const builder = new TransferBuilder(testData.SEND_FUNDS_NO_KEY_DATA); builder.key(key); - const result = builder.signAndBuild(); + const result = builder.signAndBuild(`${coin.chainId}`); should.equal(result, testData.SEND_FUNDS_DATA); }); }); diff --git a/modules/sdk-coin-opeth/test/unit/transferBuilder.ts b/modules/sdk-coin-opeth/test/unit/transferBuilder.ts index 9e7619d0f4..2e39767dd3 100644 --- a/modules/sdk-coin-opeth/test/unit/transferBuilder.ts +++ b/modules/sdk-coin-opeth/test/unit/transferBuilder.ts @@ -1,4 +1,5 @@ import should from 'should'; +import { coins, EthereumNetwork as EthLikeNetwork } from '@bitgo/statics'; import { KeyPair, TransferBuilder } from '../../src'; import * as testData from '../resources'; @@ -9,7 +10,7 @@ describe('Opeth send multi sig builder', function () { 'xprv9s21ZrQH143K3D8TXfvAJgHVfTEeQNW5Ys9wZtnUZkqPzFzSjbEJrWC1vZ4GnXCvR7rQL2UFX3RSuYeU9MrERm1XBvACow7c36vnz5iYyj2'; const key = new KeyPair({ prv: xprv }).getKeys().prv as string; const amount = '100000000000000000'; // equivalent to 0.1 ether - + const coin = coins.get('topeth') as unknown as EthLikeNetwork; describe('should build', () => { it('native coin transfer should succeed', async () => { const builder = new TransferBuilder() @@ -20,7 +21,7 @@ describe('Opeth send multi sig builder', function () { .contractSequenceId(2) .key(key) .data('0x'); - const result = builder.signAndBuild(); + const result = builder.signAndBuild(`${coin.chainId}`); should.equal(result, testData.SEND_FUNDS_DATA); }); @@ -33,7 +34,7 @@ describe('Opeth send multi sig builder', function () { .contractSequenceId(0) .key(key) .data('0x'); - const result = builder.signAndBuild(); + const result = builder.signAndBuild(`${coin.chainId}`); should.equal(result, testData.SEND_FUNDS_SEQUENCE_ZERO_DATA); }); @@ -46,7 +47,7 @@ describe('Opeth send multi sig builder', function () { .contractSequenceId(2) .key(key) .data('0x'); - const result = builder.signAndBuild(); + const result = builder.signAndBuild(`${coin.chainId}`); should.equal(result, testData.SEND_FUNDS_AMOUNT_ZERO_DATA); }); @@ -58,7 +59,7 @@ describe('Opeth send multi sig builder', function () { .to(toAddress) .contractSequenceId(2) .key(key); - const result = builder.signAndBuild(); + const result = builder.signAndBuild(`${coin.chainId}`); should.equal(result, testData.SEND_OPETH_TERC_DATA); }); @@ -70,7 +71,7 @@ describe('Opeth send multi sig builder', function () { .to(toAddress) .contractSequenceId(0) .key(key); - const result = builder.signAndBuild(); + const result = builder.signAndBuild(`${coin.chainId}`); should.equal(result, testData.SEND_TOKEN_SEQUENCE_ZERO_DATA); }); @@ -82,7 +83,7 @@ describe('Opeth send multi sig builder', function () { .to(toAddress) .contractSequenceId(2) .key(key); - const result = builder.signAndBuild(); + const result = builder.signAndBuild(`${coin.chainId}`); should.equal(result, testData.SEND_TOKEN_AMOUNT_ZERO_DATA); }); @@ -93,14 +94,14 @@ describe('Opeth send multi sig builder', function () { .to(toAddress) .contractSequenceId(2) .data('0x'); - const result = builder.signAndBuild(); + const result = builder.signAndBuild(`${coin.chainId}`); should.equal(result, testData.SEND_FUNDS_NO_KEY_DATA); }); it('should build from a non signed serialized data', () => { const builder = new TransferBuilder(testData.SEND_FUNDS_NO_KEY_DATA); builder.coin('topeth').key(key); - const result = builder.signAndBuild(); + const result = builder.signAndBuild(`${coin.chainId}`); should.equal(result, testData.SEND_FUNDS_DATA); }); }); diff --git a/modules/sdk-coin-zketh/test/unit/transferBuilder.ts b/modules/sdk-coin-zketh/test/unit/transferBuilder.ts index cfec435e5c..831dcc0569 100644 --- a/modules/sdk-coin-zketh/test/unit/transferBuilder.ts +++ b/modules/sdk-coin-zketh/test/unit/transferBuilder.ts @@ -1,4 +1,5 @@ import should from 'should'; +import { coins, EthereumNetwork as EthLikeNetwork } from '@bitgo/statics'; import { KeyPair, TransferBuilder } from '../../src'; import * as testData from '../resources'; @@ -9,7 +10,7 @@ describe('Zketh send multi sig builder', function () { 'xprv9s21ZrQH143K3D8TXfvAJgHVfTEeQNW5Ys9wZtnUZkqPzFzSjbEJrWC1vZ4GnXCvR7rQL2UFX3RSuYeU9MrERm1XBvACow7c36vnz5iYyj2'; const key = new KeyPair({ prv: xprv }).getKeys().prv as string; const amount = '100000000000000000'; // equivalent to 0.1 ether - + const coin = coins.get('tzketh') as unknown as EthLikeNetwork; describe('should build', () => { it('native coin transfer should succeed', async () => { const builder = new TransferBuilder() @@ -20,7 +21,7 @@ describe('Zketh send multi sig builder', function () { .contractSequenceId(2) .key(key) .data('0x'); - const result = builder.signAndBuild(); + const result = builder.signAndBuild(`${coin.chainId}`); should.equal(result, testData.SEND_FUNDS_DATA); }); @@ -33,7 +34,7 @@ describe('Zketh send multi sig builder', function () { .contractSequenceId(0) .key(key) .data('0x'); - const result = builder.signAndBuild(); + const result = builder.signAndBuild(`${coin.chainId}`); should.equal(result, testData.SEND_FUNDS_SEQUENCE_ZERO_DATA); }); @@ -46,7 +47,7 @@ describe('Zketh send multi sig builder', function () { .contractSequenceId(2) .key(key) .data('0x'); - const result = builder.signAndBuild(); + const result = builder.signAndBuild(`${coin.chainId}`); should.equal(result, testData.SEND_FUNDS_AMOUNT_ZERO_DATA); }); @@ -58,7 +59,7 @@ describe('Zketh send multi sig builder', function () { .to(toAddress) .contractSequenceId(2) .key(key); - const result = builder.signAndBuild(); + const result = builder.signAndBuild(`${coin.chainId}`); should.equal(result, testData.SEND_ZKETH_LINK_DATA); }); @@ -70,7 +71,7 @@ describe('Zketh send multi sig builder', function () { .to(toAddress) .contractSequenceId(0) .key(key); - const result = builder.signAndBuild(); + const result = builder.signAndBuild(`${coin.chainId}`); should.equal(result, testData.SEND_TOKEN_SEQUENCE_ZERO_DATA); }); @@ -82,7 +83,7 @@ describe('Zketh send multi sig builder', function () { .to(toAddress) .contractSequenceId(2) .key(key); - const result = builder.signAndBuild(); + const result = builder.signAndBuild(`${coin.chainId}`); should.equal(result, testData.SEND_TOKEN_AMOUNT_ZERO_DATA); }); @@ -93,14 +94,14 @@ describe('Zketh send multi sig builder', function () { .to(toAddress) .contractSequenceId(2) .data('0x'); - const result = builder.signAndBuild(); + const result = builder.signAndBuild(`${coin.chainId}`); should.equal(result, testData.SEND_FUNDS_NO_KEY_DATA); }); it('should build from a non signed serialized data', () => { const builder = new TransferBuilder(testData.SEND_FUNDS_NO_KEY_DATA); builder.coin('tzketh').key(key); - const result = builder.signAndBuild(); + const result = builder.signAndBuild(`${coin.chainId}`); should.equal(result, testData.SEND_FUNDS_DATA); }); });