Skip to content

Commit

Permalink
feat(abstract-eth): add chain id as network identifier
Browse files Browse the repository at this point in the history
  • Loading branch information
gianchandania committed Jan 2, 2024
1 parent 2590e01 commit 73e9551
Show file tree
Hide file tree
Showing 27 changed files with 667 additions and 207 deletions.
15 changes: 12 additions & 3 deletions modules/abstract-eth/src/abstractEthLikeNewCoins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1003,7 +1003,10 @@ export abstract class AbstractEthLikeNewCoins extends AbstractEthLikeCoin {
}
const txBuilder = this.getTransactionBuilder();
txBuilder.from(params.txPrebuild.txHex);
txBuilder.transfer().key(new KeyPairLib({ prv: params.prv }).getKeys().prv!);
txBuilder
.transfer()
.coin(this.staticsCoin?.name as string)
.key(new KeyPairLib({ prv: params.prv }).getKeys().prv!);
const transaction = await txBuilder.build();

const recipients = transaction.outputs.map((output) => ({ address: output.address, amount: output.value }));
Expand Down Expand Up @@ -1415,6 +1418,7 @@ export abstract class AbstractEthLikeNewCoins extends AbstractEthLikeCoin {
});
const transferBuilder = txBuilder.transfer() as TransferBuilder;
transferBuilder
.coin(this.staticsCoin?.name as string)
.amount(recipients[0].amount)
.contractSequenceId(sequenceId)
.expirationTime(this.getDefaultExpireTime())
Expand All @@ -1440,7 +1444,10 @@ export abstract class AbstractEthLikeNewCoins extends AbstractEthLikeCoin {
return response;
}

txBuilder.transfer().key(new KeyPairLib({ prv: userKey }).getKeys().prv as string);
txBuilder
.transfer()
.coin(this.staticsCoin?.name as string)
.key(new KeyPairLib({ prv: userKey }).getKeys().prv as string);
txBuilder.sign({ key: backupSigningKey });

const signedTx = await txBuilder.build();
Expand Down Expand Up @@ -1594,14 +1601,15 @@ export abstract class AbstractEthLikeNewCoins extends AbstractEthLikeCoin {
const transferBuilder = txBuilder.transfer() as TransferBuilder;

transferBuilder
.coin(this.staticsCoin?.name as string)
.amount(batchExecutionInfo.totalAmount)
.contractSequenceId(sequenceId)
.expirationTime(this.getDefaultExpireTime())
.to(batcherContractAddress)
.data(batchData);

if (params.walletPassphrase) {
txBuilder.transfer().key(userSigningKey);
transferBuilder.key(userSigningKey);
}

const tx = await txBuilder.build();
Expand Down Expand Up @@ -1731,6 +1739,7 @@ export abstract class AbstractEthLikeNewCoins extends AbstractEthLikeCoin {
const token = getToken(params.tokenContractAddress as string, network as EthLikeNetwork)?.name as string;

transferBuilder
.coin(token)
.amount(txAmount)
.contractSequenceId(sequenceId)
.expirationTime(this.getDefaultExpireTime())
Expand Down
17 changes: 12 additions & 5 deletions modules/abstract-eth/src/lib/transferBuilder.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as ethUtil from 'ethereumjs-util';
import EthereumAbi from 'ethereumjs-abi';
import BN from 'bn.js';
import { coins, BaseCoin, ContractAddressDefinedToken } from '@bitgo/statics';
import { coins, BaseCoin, ContractAddressDefinedToken, EthereumNetwork as EthLikeNetwork } from '@bitgo/statics';
import { BuildTransactionError, InvalidParameterValueError } from '@bitgo/sdk-core';
import { decodeTransferData, sendMultiSigData, sendMultiSigTokenData, isValidEthAddress, isValidAmount } from './utils';

Expand All @@ -17,6 +17,9 @@ export class TransferBuilder {
private _data: string;
private _tokenContractAddress?: string;
private _coin: Readonly<BaseCoin>;
private _network: EthLikeNetwork;
private _nativeCoinOperationHashPrefix?: string;
private _tokenOperationHashPrefix?: string;

constructor(serializedData?: string) {
if (serializedData) {
Expand All @@ -30,17 +33,20 @@ export class TransferBuilder {
}

/**
* A method to set the ERC20 token to be transferred.
* A method to set the native coin or ERC20 token to be transferred.
* This ERC20 token may not be compatible with the network.
*
* @param {string} coin the ERC20 coin to be set
* @param {string} coin - the native coin or ERC20 token to be set
* @returns {TransferBuilder} the transfer builder instance modified
*/
coin(coin: string): TransferBuilder {
this._coin = coins.get(coin);
this._network = this._coin.network as EthLikeNetwork;
this._nativeCoinOperationHashPrefix = this._network.nativeCoinOperationHashPrefix;

if (this._coin instanceof ContractAddressDefinedToken) {
this._tokenContractAddress = this._coin.contractAddress.toString();
this._tokenOperationHashPrefix = this._network.tokenOperationHashPrefix;
}

return this;
Expand Down Expand Up @@ -137,11 +143,12 @@ export class TransferBuilder {

protected getOperationData(): (string | Buffer)[][] {
let operationData;

if (this._tokenContractAddress !== undefined) {
operationData = [
['string', 'address', 'uint', 'address', 'uint', 'uint'],
[
this.getTokenOperationHashPrefix(),
this._tokenOperationHashPrefix ?? this.getTokenOperationHashPrefix(),
new BN(ethUtil.stripHexPrefix(this._toAddress), 16),
this._amount,
new BN(ethUtil.stripHexPrefix(this._tokenContractAddress), 16),
Expand All @@ -153,7 +160,7 @@ export class TransferBuilder {
operationData = [
['string', 'address', 'uint', 'bytes', 'uint', 'uint'],
[
this.getNativeOperationHashPrefix(),
this._nativeCoinOperationHashPrefix ?? this.getNativeOperationHashPrefix(),
new BN(ethUtil.stripHexPrefix(this._toAddress), 16),
this._amount,
Buffer.from(ethUtil.padToEven(ethUtil.stripHexPrefix(this._data)) || '', 'hex'),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { InvalidParameterValueError, InvalidSignatureError } from '@bitgo/sdk-core';
import { isValidEthAddress } from '../utils';
import { joinSignature, solidityKeccak256, SigningKey } from 'ethers/lib/utils';
import { BaseCoin, EthereumNetwork as EthLikeNetwork } from '@bitgo/statics';

export abstract class BaseNFTTransferBuilder {
protected readonly _EMPTY_HEX_VALUE = '0x';
Expand All @@ -13,6 +14,9 @@ export abstract class BaseNFTTransferBuilder {
protected _signature: string;
protected _data: string;
protected _tokenContractAddress: string;
protected _coin: Readonly<BaseCoin>;
protected _network: EthLikeNetwork;
protected _nativeCoinOperationHashPrefix?: string;

public abstract build(): string;

Expand Down Expand Up @@ -85,7 +89,7 @@ export abstract class BaseNFTTransferBuilder {
if (this._signKey) {
this._signature = this.ethSignMsgHash();
}
if (this._signature == null) {
if (this._signature === null) {
throw new InvalidSignatureError('Null signature value');
}
return this._signature;
Expand All @@ -110,7 +114,7 @@ export abstract class BaseNFTTransferBuilder {
const hash = solidityKeccak256(
['string', 'address', 'uint', 'bytes', 'uint', 'uint'],
[
this.getNativeOperationHashPrefix(),
this._nativeCoinOperationHashPrefix ?? this.getNativeOperationHashPrefix(),
this._toAddress,
'0', // dummy amount value
this._data,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
ERC1155SafeTransferTypeMethodId,
} from '../walletUtil';
import { BaseNFTTransferBuilder } from './baseNFTTransferBuilder';
import { coins, EthereumNetwork as EthLikeNetwork } from '@bitgo/statics';

export class ERC1155TransferBuilder extends BaseNFTTransferBuilder {
private _tokenIds: string[];
Expand All @@ -27,6 +28,13 @@ export class ERC1155TransferBuilder extends BaseNFTTransferBuilder {
}
}

coin(coin: string): ERC1155TransferBuilder {
this._coin = coins.get(coin);
this._network = this._coin.network as EthLikeNetwork;
this._nativeCoinOperationHashPrefix = this._network.nativeCoinOperationHashPrefix;
return this;
}

tokenContractAddress(address: string): ERC1155TransferBuilder {
if (isValidEthAddress(address)) {
this._tokenContractAddress = address;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { ContractCall } from '../contractCall';
import { decodeERC721TransferData, isValidEthAddress, sendMultiSigData } from '../utils';
import { BaseNFTTransferBuilder } from './baseNFTTransferBuilder';
import { ERC721SafeTransferTypeMethodId, ERC721SafeTransferTypes } from '../walletUtil';
import { coins, EthereumNetwork as EthLikeNetwork } from '@bitgo/statics';

export class ERC721TransferBuilder extends BaseNFTTransferBuilder {
private _tokenId: string;
Expand All @@ -18,6 +19,13 @@ export class ERC721TransferBuilder extends BaseNFTTransferBuilder {
}
}

coin(coin: string): ERC721TransferBuilder {
this._coin = coins.get(coin);
this._network = this._coin.network as EthLikeNetwork;
this._nativeCoinOperationHashPrefix = this._network.nativeCoinOperationHashPrefix;
return this;
}

tokenContractAddress(address: string): ERC721TransferBuilder {
if (isValidEthAddress(address)) {
this._tokenContractAddress = address;
Expand Down
3 changes: 2 additions & 1 deletion modules/sdk-coin-arbeth/src/lib/transactionBuilder.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { BaseCoin as CoinConfig } from '@bitgo/statics';
import { BuildTransactionError, TransactionType } from '@bitgo/sdk-core';
import { KeyPair, Transaction, TransactionBuilder as EthLikeTransactionBuilder } from '@bitgo/abstract-eth';
import { getCommon } from './utils';

import { TransferBuilder } from './transferBuilder';
import { getCommon } from './utils';
import { walletSimpleByteCode } from './walletUtil';

export class TransactionBuilder extends EthLikeTransactionBuilder {
Expand Down
24 changes: 1 addition & 23 deletions modules/sdk-coin-arbeth/src/lib/transferBuilder.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1 @@
import { TransferBuilder as EthTransferBuilder } from '@bitgo/abstract-eth';

export class TransferBuilder extends EthTransferBuilder {
/**
* Get the prefix used in generating an operation hash for sending native coins
* See https://github.com/BitGo/eth-multisig-v4/blob/master/contracts/coins/ArbethWalletSimple.sol
*
* @returns the string prefix
*/
protected getNativeOperationHashPrefix(): string {
return 'ARBETH';
}

/**
* Get the prefix used in generating an operation hash for sending tokens
* See https://github.com/BitGo/eth-multisig-v4/blob/master/contracts/coins/ArbethWalletSimple.sol
*
* @returns the string prefix
*/
protected getTokenOperationHashPrefix(): string {
return 'ARBETH-ERC20';
}
}
export { TransferBuilder } from '@bitgo/abstract-eth';
21 changes: 21 additions & 0 deletions modules/sdk-coin-arbeth/test/resources.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,24 @@ export const PRIVATE_KEY_2 =

export const PUBLIC_KEY_2 =
'xpub661MyMwAqRbcFXrZT6GpipqTPdFdhYX5DFDGv5ws1iW8ViCWSTK3zVhVntpiKDjPqXrqP1hhQscJZhVpbmZt9qygxgPdmN9RAZVKqovPfLw';

export const SEND_FUNDS_DATA =
'0x391252150000000000000000000000007325a3f7d4f9e86ae62cf742426078c3755730d5000000000000000000000000000000000000000000000000016345785d8a000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000005ec6ab34000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041d8decc5aa3e56cba81cb5405cdd187a01885fd118ca3add06fc10c471d86b94459fe0c0b7a906e2147f64d948616236241288d8bf775873692b9963803ac608c1c00000000000000000000000000000000000000000000000000000000000000';

export const SEND_FUNDS_SEQUENCE_ZERO_DATA =
'0x391252150000000000000000000000007325a3f7d4f9e86ae62cf742426078c3755730d5000000000000000000000000000000000000000000000000016345785d8a000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000005ec6ab34000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041cb8ce1d2f2e482a7c6e50ad9c7cc6df33f30a0ef6e6792100d20d08181b054d034eae3fc8a18e7d48344d193c14786fbc91483f395e6e89cbeb36e9ced6429291b00000000000000000000000000000000000000000000000000000000000000';

export const SEND_FUNDS_AMOUNT_ZERO_DATA =
'0x391252150000000000000000000000007325a3f7d4f9e86ae62cf742426078c3755730d5000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000005ec6ab34000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041aac0763277264c9be1e79a7b4bf056f3011a545ca2ead9fe76aa6efaa80b35db1b9769bf44693896ca655eb845b8e796f71073096e00f4ab8eddf1c46b8d7e401c00000000000000000000000000000000000000000000000000000000000000';

export const SEND_ARBETH_LINK_DATA =
'0x0dcd7a6c0000000000000000000000007325a3f7d4f9e86ae62cf742426078c3755730d5000000000000000000000000000000000000000000000000016345785d8a0000000000000000000000000000143e1dae4f018ff86051a01d44a1b49b13704056000000000000000000000000000000000000000000000000000000005ec6ab34000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000041c6f5ab6c29ea92fec02229e8f87981fdb0863bf465f3d4f08df81d66d12d771a588acaf9d2313704dfb120da5e50a3a6089abbe610fca825d1a1fc9f3287ab8a1c00000000000000000000000000000000000000000000000000000000000000';

export const SEND_TOKEN_SEQUENCE_ZERO_DATA =
'0x0dcd7a6c0000000000000000000000007325a3f7d4f9e86ae62cf742426078c3755730d5000000000000000000000000000000000000000000000000016345785d8a0000000000000000000000000000143e1dae4f018ff86051a01d44a1b49b13704056000000000000000000000000000000000000000000000000000000005ec6ab34000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000041c92569648e4bb36f8890254998b71359992f6afa97bba96975297cff3272dc402bfae501804561ca3bed0f38057ca6cc896950c50a35322b6062a5f132c653711b00000000000000000000000000000000000000000000000000000000000000';

export const SEND_TOKEN_AMOUNT_ZERO_DATA =
'0x0dcd7a6c0000000000000000000000007325a3f7d4f9e86ae62cf742426078c3755730d50000000000000000000000000000000000000000000000000000000000000000000000000000000000000000143e1dae4f018ff86051a01d44a1b49b13704056000000000000000000000000000000000000000000000000000000005ec6ab34000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000041f159de6649d213fe6b882444d525ac3f9a7393618d510506f250931a28f6c34b50bab2af7f77e893e281ab3d0f629190d70ab271e491b4b41fa75b4dbf97cd191c00000000000000000000000000000000000000000000000000000000000000';

export const SEND_FUNDS_NO_KEY_DATA =
'0x391252150000000000000000000000007325a3f7d4f9e86ae62cf742426078c3755730d5000000000000000000000000000000000000000000000000016345785d8a000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000005ec6ab34000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000';
6 changes: 4 additions & 2 deletions modules/sdk-coin-arbeth/test/unit/arbeth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,8 @@ describe('Arbitrum', function () {
builder.counter(1);
builder.type(TransactionType.Send);
builder.contract(account_1.address);
builder.transfer().amount('1').to(account_2.address).expirationTime(10000).contractSequenceId(1);
const transferBuilder = builder.transfer() as TransferBuilder;
transferBuilder.coin('tarbeth').amount('1').to(account_2.address).expirationTime(10000).contractSequenceId(1);

const unsignedTx = await builder.build();
const unsignedTxForBroadcasting = unsignedTx.toBroadcastFormat();
Expand Down Expand Up @@ -207,7 +208,8 @@ describe('Arbitrum', function () {
builder.counter(1);
builder.type(TransactionType.Send);
builder.contract(account_1.address);
builder.transfer().amount('1').to(account_2.address).expirationTime(10000).contractSequenceId(1);
const transferBuilder = builder.transfer() as TransferBuilder;
transferBuilder.coin('tarbeth').amount('1').to(account_2.address).expirationTime(10000).contractSequenceId(1);

const unsignedTx = await builder.build();
const unsignedTxForBroadcasting = unsignedTx.toBroadcastFormat();
Expand Down
Loading

0 comments on commit 73e9551

Please sign in to comment.