aboutsummaryrefslogtreecommitdiffstats
path: root/packages/base-contract
diff options
context:
space:
mode:
Diffstat (limited to 'packages/base-contract')
-rw-r--r--packages/base-contract/CHANGELOG.json17
-rw-r--r--packages/base-contract/coverage/.gitkeep0
-rw-r--r--packages/base-contract/package.json14
-rw-r--r--packages/base-contract/src/index.ts29
-rw-r--r--packages/base-contract/src/utils.ts25
-rw-r--r--packages/base-contract/test/utils_test.ts108
-rw-r--r--packages/base-contract/tsconfig.json2
7 files changed, 172 insertions, 23 deletions
diff --git a/packages/base-contract/CHANGELOG.json b/packages/base-contract/CHANGELOG.json
index 3147006ea..3b8b22a57 100644
--- a/packages/base-contract/CHANGELOG.json
+++ b/packages/base-contract/CHANGELOG.json
@@ -1,5 +1,22 @@
[
{
+ "version": "0.1.0",
+ "changes": [
+ {
+ "note": "Add tests for traversing ABI tree",
+ "pr": 485
+ },
+ {
+ "note": "Fix ABI tuples traversing",
+ "pr": 485
+ },
+ {
+ "note": "Fix ABI arrays traversing",
+ "pr": 485
+ }
+ ]
+ },
+ {
"timestamp": 1522658513,
"version": "0.0.6",
"changes": [
diff --git a/packages/base-contract/coverage/.gitkeep b/packages/base-contract/coverage/.gitkeep
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/packages/base-contract/coverage/.gitkeep
diff --git a/packages/base-contract/package.json b/packages/base-contract/package.json
index 9de6c01b6..009aa9625 100644
--- a/packages/base-contract/package.json
+++ b/packages/base-contract/package.json
@@ -2,13 +2,18 @@
"name": "@0xproject/base-contract",
"version": "0.0.6",
"description": "0x Base TS contract",
- "main": "lib/index.js",
- "types": "lib/index.d.ts",
+ "main": "lib/src/index.js",
+ "types": "lib/src/index.d.ts",
"scripts": {
"build:watch": "tsc -w",
"build": "tsc && copyfiles -u 2 './lib/monorepo_scripts/**/*' ./scripts",
"clean": "shx rm -rf lib scripts",
- "lint": "tslint --project . 'src/**/*.ts'",
+ "test": "run-s clean build run_mocha",
+ "test:circleci": "yarn test:coverage",
+ "run_mocha": "mocha lib/test/**/*_test.js --bail --exit",
+ "test:coverage": "nyc npm run test --all && yarn coverage:report:lcov",
+ "coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info",
+ "lint": "tslint --project ."
"manual:postpublish": "yarn build; node ./scripts/postpublish.js"
},
"license": "Apache-2.0",
@@ -27,10 +32,13 @@
"copyfiles": "^1.2.0",
"npm-run-all": "^4.1.2",
"shx": "^0.2.2",
+ "chai": "^4.0.1",
+ "mocha": "^4.0.1",
"tslint": "5.8.0",
"typescript": "2.7.1"
},
"dependencies": {
+ "@0xproject/utils": "^0.4.3",
"@0xproject/types": "^0.4.2",
"@0xproject/typescript-typings": "^0.0.2",
"@0xproject/web3-wrapper": "^0.4.0",
diff --git a/packages/base-contract/src/index.ts b/packages/base-contract/src/index.ts
index 961da8842..c8cbd7886 100644
--- a/packages/base-contract/src/index.ts
+++ b/packages/base-contract/src/index.ts
@@ -1,40 +1,31 @@
import { ContractAbi, DataItem, TxData, TxDataPayable } from '@0xproject/types';
+import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as ethersContracts from 'ethers-contracts';
import * as _ from 'lodash';
+import { formatABIDataItem } from './utils';
+
export class BaseContract {
protected _ethersInterface: ethersContracts.Interface;
protected _web3Wrapper: Web3Wrapper;
public abi: ContractAbi;
public address: string;
- protected static _transformABIData(
+ protected static _formatABIDataItemList(
abis: DataItem[],
values: any[],
- transformation: (type: string, value: any) => any,
+ formatter: (type: string, value: any) => any,
): any {
- return _.map(values, (value: any, i: number) =>
- BaseContract._transformTypedData(abis[i].type, value, transformation),
- );
+ return _.map(values, (value: any, i: number) => formatABIDataItem(abis[i], value, formatter));
}
protected static _lowercaseAddress(type: string, value: string): string {
return type === 'address' ? value.toLowerCase() : value;
}
- protected static _bigNumberToString(type: string, value: string): string {
- return _.isObject(value) && (value as any).isBigNumber ? value.toString() : value;
+ protected static _bigNumberToString(type: string, value: any): any {
+ return _.isObject(value) && value.isBigNumber ? value.toString() : value;
}
- private static _transformTypedData(
- type: string,
- values: any,
- transformation: (type: string, value: any) => any,
- ): any {
- const trailingArrayRegex = /\[\d*\]$/;
- if (type.match(trailingArrayRegex)) {
- const arrayItemType = type.replace(trailingArrayRegex, '');
- return _.map(values, value => this._transformTypedData(arrayItemType, value, transformation));
- } else {
- return transformation(type, values);
- }
+ protected static _bnToBigNumber(type: string, value: any): any {
+ return _.isObject(value) && value._bn ? new BigNumber(value.toString()) : value;
}
protected async _applyDefaultsToTxDataAsync<T extends Partial<TxData | TxDataPayable>>(
txData: T,
diff --git a/packages/base-contract/src/utils.ts b/packages/base-contract/src/utils.ts
new file mode 100644
index 000000000..4b86bb1ad
--- /dev/null
+++ b/packages/base-contract/src/utils.ts
@@ -0,0 +1,25 @@
+import { DataItem } from '@0xproject/types';
+import * as _ from 'lodash';
+
+// tslint:disable-next-line:completed-docs
+export function formatABIDataItem(abi: DataItem, value: any, formatter: (type: string, value: any) => any): any {
+ const trailingArrayRegex = /\[\d*\]$/;
+ if (abi.type.match(trailingArrayRegex)) {
+ const arrayItemType = abi.type.replace(trailingArrayRegex, '');
+ return _.map(value, val => {
+ const arrayItemAbi = {
+ ...abi,
+ type: arrayItemType,
+ };
+ return formatABIDataItem(arrayItemAbi, val, formatter);
+ });
+ } else if (abi.type === 'tuple') {
+ const formattedTuple: { [componentName: string]: DataItem } = {};
+ _.forEach(abi.components, componentABI => {
+ formattedTuple[componentABI.name] = formatABIDataItem(componentABI, value[componentABI.name], formatter);
+ });
+ return formattedTuple;
+ } else {
+ return formatter(abi.type, value);
+ }
+}
diff --git a/packages/base-contract/test/utils_test.ts b/packages/base-contract/test/utils_test.ts
new file mode 100644
index 000000000..c083704f4
--- /dev/null
+++ b/packages/base-contract/test/utils_test.ts
@@ -0,0 +1,108 @@
+import { BigNumber } from '@0xproject/utils';
+import * as chai from 'chai';
+import 'mocha';
+
+import { formatABIDataItem } from '../src/utils';
+
+const { expect } = chai;
+
+describe('Utils tests', () => {
+ describe('#formatABIDataItem', () => {
+ it('correctly handles arrays', () => {
+ const calls: Array<{ type: string; value: any }> = [];
+ const abi = {
+ name: 'values',
+ type: 'uint256[]',
+ };
+ const val = [1, 2, 3];
+ const formatted = formatABIDataItem(abi, val, (type: string, value: any) => {
+ calls.push({ type, value });
+ return value; // no-op
+ });
+ expect(formatted).to.be.deep.equal(val);
+ expect(calls).to.be.deep.equal([
+ { type: 'uint256', value: 1 },
+ { type: 'uint256', value: 2 },
+ { type: 'uint256', value: 3 },
+ ]);
+ });
+ it('correctly handles tuples', () => {
+ const calls: Array<{ type: string; value: any }> = [];
+ const abi = {
+ components: [
+ {
+ name: 'to',
+ type: 'address',
+ },
+ {
+ name: 'amount',
+ type: 'uint256',
+ },
+ ],
+ name: 'data',
+ type: 'tuple',
+ };
+ const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';
+ const val = { to: ZERO_ADDRESS, amount: new BigNumber(1) };
+ const formatted = formatABIDataItem(abi, val, (type: string, value: any) => {
+ calls.push({ type, value });
+ return value; // no-op
+ });
+ expect(formatted).to.be.deep.equal(val);
+ expect(calls).to.be.deep.equal([
+ {
+ type: 'address',
+ value: val.to,
+ },
+ {
+ type: 'uint256',
+ value: val.amount,
+ },
+ ]);
+ });
+ it('correctly handles nested arrays of tuples', () => {
+ const calls: Array<{ type: string; value: any }> = [];
+ const abi = {
+ components: [
+ {
+ name: 'to',
+ type: 'address',
+ },
+ {
+ name: 'amount',
+ type: 'uint256',
+ },
+ ],
+ name: 'data',
+ type: 'tuple[2][]',
+ };
+ const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';
+ const val = [
+ [{ to: ZERO_ADDRESS, amount: new BigNumber(1) }, { to: ZERO_ADDRESS, amount: new BigNumber(2) }],
+ ];
+ const formatted = formatABIDataItem(abi, val, (type: string, value: any) => {
+ calls.push({ type, value });
+ return value; // no-op
+ });
+ expect(formatted).to.be.deep.equal(val);
+ expect(calls).to.be.deep.equal([
+ {
+ type: 'address',
+ value: val[0][0].to,
+ },
+ {
+ type: 'uint256',
+ value: val[0][0].amount,
+ },
+ {
+ type: 'address',
+ value: val[0][1].to,
+ },
+ {
+ type: 'uint256',
+ value: val[0][1].amount,
+ },
+ ]);
+ });
+ });
+});
diff --git a/packages/base-contract/tsconfig.json b/packages/base-contract/tsconfig.json
index c56d255d5..8b4cd47a2 100644
--- a/packages/base-contract/tsconfig.json
+++ b/packages/base-contract/tsconfig.json
@@ -3,5 +3,5 @@
"compilerOptions": {
"outDir": "lib"
},
- "include": ["./src/**/*"]
+ "include": ["src/**/*", "test/**/*"]
}