aboutsummaryrefslogtreecommitdiffstats
path: root/packages/web3-wrapper/src/marshaller.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/web3-wrapper/src/marshaller.ts')
-rw-r--r--packages/web3-wrapper/src/marshaller.ts177
1 files changed, 177 insertions, 0 deletions
diff --git a/packages/web3-wrapper/src/marshaller.ts b/packages/web3-wrapper/src/marshaller.ts
new file mode 100644
index 000000000..06556ce90
--- /dev/null
+++ b/packages/web3-wrapper/src/marshaller.ts
@@ -0,0 +1,177 @@
+import { addressUtils, BigNumber } from '@0xproject/utils';
+import {
+ BlockParam,
+ BlockParamLiteral,
+ BlockWithoutTransactionData,
+ BlockWithTransactionData,
+ CallData,
+ CallTxDataBase,
+ LogEntry,
+ RawLogEntry,
+ Transaction,
+ TxData,
+} from 'ethereum-types';
+import ethUtil = require('ethereumjs-util');
+import * as _ from 'lodash';
+import web3Utils = require('web3-utils');
+
+import { utils } from './utils';
+
+import {
+ AbstractBlockRPC,
+ BlockWithoutTransactionDataRPC,
+ BlockWithTransactionDataRPC,
+ CallDataRPC,
+ CallTxDataBaseRPC,
+ TransactionRPC,
+ TxDataRPC,
+} from './types';
+
+export const marshaller = {
+ unmarshalIntoBlockWithoutTransactionData(
+ blockWithHexValues: BlockWithoutTransactionDataRPC,
+ ): BlockWithoutTransactionData {
+ const block = {
+ ...blockWithHexValues,
+ gasLimit: web3Utils.toDecimal(blockWithHexValues.gasLimit),
+ gasUsed: web3Utils.toDecimal(blockWithHexValues.gasUsed),
+ size: web3Utils.toDecimal(blockWithHexValues.size),
+ timestamp: web3Utils.toDecimal(blockWithHexValues.timestamp),
+ number: _.isNull(blockWithHexValues.number) ? null : web3Utils.toDecimal(blockWithHexValues.number),
+ difficulty: this._convertAmountToBigNumber(blockWithHexValues.difficulty),
+ totalDifficulty: this._convertAmountToBigNumber(blockWithHexValues.totalDifficulty),
+ };
+ return block;
+ },
+ unmarshalIntoBlockWithTransactionData(blockWithHexValues: BlockWithTransactionDataRPC): BlockWithTransactionData {
+ const block = {
+ ...blockWithHexValues,
+ gasLimit: web3Utils.toDecimal(blockWithHexValues.gasLimit),
+ gasUsed: web3Utils.toDecimal(blockWithHexValues.gasUsed),
+ size: web3Utils.toDecimal(blockWithHexValues.size),
+ timestamp: web3Utils.toDecimal(blockWithHexValues.timestamp),
+ number: _.isNull(blockWithHexValues.number) ? null : web3Utils.toDecimal(blockWithHexValues.number),
+ difficulty: this._convertAmountToBigNumber(blockWithHexValues.difficulty),
+ totalDifficulty: this._convertAmountToBigNumber(blockWithHexValues.totalDifficulty),
+ transactions: [] as Transaction[],
+ };
+ block.transactions = _.map(blockWithHexValues.transactions, (tx: TransactionRPC) => {
+ const transaction = this.unmarshalTransaction(tx);
+ return transaction;
+ });
+ return block;
+ },
+ unmarshalTransaction(txRpc: TransactionRPC): Transaction {
+ const tx = {
+ ...txRpc,
+ blockNumber: !_.isNull(txRpc.blockNumber) ? web3Utils.toDecimal(txRpc.blockNumber) : null,
+ transactionIndex: !_.isNull(txRpc.transactionIndex) ? web3Utils.toDecimal(txRpc.transactionIndex) : null,
+ nonce: web3Utils.toDecimal(txRpc.nonce),
+ gas: web3Utils.toDecimal(txRpc.gas),
+ gasPrice: this._convertAmountToBigNumber(txRpc.gasPrice),
+ value: this._convertAmountToBigNumber(txRpc.value),
+ };
+ return tx;
+ },
+ marshalTxData(txData: Partial<TxData>): Partial<TxDataRPC> {
+ if (_.isUndefined(txData.from)) {
+ throw new Error(`txData is missing required "from" address.`);
+ }
+ const callTxDataBase = {
+ ...txData,
+ };
+ delete callTxDataBase.from;
+ const callTxDataBaseRPC = this._marshalCallTxDataBase(callTxDataBase);
+ const txDataRPC = {
+ ...callTxDataBaseRPC,
+ from: this.marshalAddress(txData.from),
+ };
+ const prunableIfUndefined = ['gasPrice', 'gas', 'value', 'nonce'];
+ _.each(txDataRPC, (value: any, key: string) => {
+ if (_.isUndefined(value) && _.includes(prunableIfUndefined, key)) {
+ delete (txDataRPC as any)[key];
+ }
+ });
+ return txDataRPC;
+ },
+ marshalCallData(callData: Partial<CallData>): Partial<CallDataRPC> {
+ const callTxDataBase = {
+ ...callData,
+ };
+ delete callTxDataBase.from;
+ const callTxDataBaseRPC = this._marshalCallTxDataBase(callTxDataBase);
+ const callDataRPC = {
+ ...callTxDataBaseRPC,
+ from: _.isUndefined(callData.from) ? undefined : this.marshalAddress(callData.from),
+ };
+ return callDataRPC;
+ },
+ marshalAddress(address: string): string {
+ if (addressUtils.isAddress(address)) {
+ return ethUtil.addHexPrefix(address);
+ }
+ throw new Error(`Invalid address encountered: ${address}`);
+ },
+ marshalBlockParam(blockParam: BlockParam | string | number | undefined): string | undefined {
+ if (_.isUndefined(blockParam)) {
+ return BlockParamLiteral.Latest;
+ }
+ const encodedBlockParam = _.isNumber(blockParam) ? web3Utils.toHex(blockParam) : blockParam;
+ return encodedBlockParam;
+ },
+ unmarshalLog(rawLog: RawLogEntry): LogEntry {
+ const formattedLog = {
+ ...rawLog,
+ logIndex: this.convertHexToNumberOrNull(rawLog.logIndex),
+ blockNumber: this.convertHexToNumberOrNull(rawLog.blockNumber),
+ transactionIndex: this.convertHexToNumberOrNull(rawLog.transactionIndex),
+ };
+ return formattedLog;
+ },
+ _marshalCallTxDataBase(callTxDataBase: Partial<CallTxDataBase>): Partial<CallTxDataBaseRPC> {
+ const callTxDataBaseRPC = {
+ ...callTxDataBase,
+ to: _.isUndefined(callTxDataBase.to) ? undefined : this.marshalAddress(callTxDataBase.to),
+ gasPrice: _.isUndefined(callTxDataBase.gasPrice)
+ ? undefined
+ : this._encodeAmountAsHexString(callTxDataBase.gasPrice),
+ gas: _.isUndefined(callTxDataBase.gas) ? undefined : this._encodeAmountAsHexString(callTxDataBase.gas),
+ value: _.isUndefined(callTxDataBase.value)
+ ? undefined
+ : this._encodeAmountAsHexString(callTxDataBase.value),
+ nonce: _.isUndefined(callTxDataBase.nonce)
+ ? undefined
+ : this._encodeAmountAsHexString(callTxDataBase.nonce),
+ };
+
+ return callTxDataBaseRPC;
+ },
+ convertHexToNumberOrNull(hex: string | null): number | null {
+ if (_.isNull(hex)) {
+ return null;
+ }
+ const decimal = web3Utils.toDecimal(hex);
+ return decimal;
+ },
+ _convertAmountToBigNumber(value: string | number | BigNumber): BigNumber {
+ const num = value || 0;
+ const isBigNumber = utils.isBigNumber(num);
+ if (isBigNumber) {
+ return num as BigNumber;
+ }
+
+ if (_.isString(num) && (num.indexOf('0x') === 0 || num.indexOf('-0x') === 0)) {
+ return new BigNumber(num.replace('0x', ''), 16);
+ }
+
+ const baseTen = 10;
+ return new BigNumber((num as number).toString(baseTen), baseTen);
+ },
+ _encodeAmountAsHexString(value: string | number | BigNumber): string {
+ const valueBigNumber = this._convertAmountToBigNumber(value);
+ const hexBase = 16;
+ const valueHex = valueBigNumber.toString(hexBase);
+
+ return valueBigNumber.lessThan(0) ? '-0x' + valueHex.substr(1) : '0x' + valueHex;
+ },
+};