aboutsummaryrefslogtreecommitdiffstats
path: root/packages/order-utils/test/abi/data_type.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/order-utils/test/abi/data_type.ts')
-rw-r--r--packages/order-utils/test/abi/data_type.ts98
1 files changed, 55 insertions, 43 deletions
diff --git a/packages/order-utils/test/abi/data_type.ts b/packages/order-utils/test/abi/data_type.ts
index f74621085..1a4610f7c 100644
--- a/packages/order-utils/test/abi/data_type.ts
+++ b/packages/order-utils/test/abi/data_type.ts
@@ -1,4 +1,4 @@
-import { Calldata, CalldataBlock, PayloadCalldataBlock, DependentCalldataBlock } from "./calldata";
+import { Calldata, CalldataBlock, PayloadCalldataBlock, DependentCalldataBlock, MemberCalldataBlock } from "./calldata";
import { MethodAbi, DataItem } from 'ethereum-types';
import { BigNumber } from '@0x/utils';
import ethUtil = require('ethereumjs-util');
@@ -17,7 +17,7 @@ export abstract class DataType {
return this.dataItem;
}
- protected abstract createCalldataBlock(): CalldataBlock;
+ public abstract generateCalldataBlock(value: any, parentBlock?: CalldataBlock): CalldataBlock;
public abstract encode(value: any, calldata: Calldata): void;
public abstract getSignature(): string;
public abstract isStatic(): boolean;
@@ -31,19 +31,27 @@ export abstract class PayloadDataType extends DataType {
this.hasConstantSize = hasConstantSize;
}
- protected generateCalldataBlock(payload: Buffer, calldata: Calldata): void {
+ public generateCalldataBlocks(value: any, parentBlock?: CalldataBlock): PayloadCalldataBlock {
+ const encodedValue = this.encodeValue(value);
const name = this.getDataItem().name;
const signature = this.getSignature();
- const offsetInBytes = calldata.getSizeInBytes();
+ // const offsetInBytes = calldata.getSizeInBytes();
const relocatable = false;
- const block = new PayloadCalldataBlock(name, signature, offsetInBytes, relocatable, payload);
- calldata.pushBlock(block);
+ const block = new PayloadCalldataBlock(name, signature, /*offsetInBytes,*/ relocatable, encodedValue);
+ return block;
+ }
+
+ public encode(value: any, calldata: Calldata): void {
+ const block = this.generateCalldataBlock(value);
+ calldata.setRoot(block);
}
public isStatic(): boolean {
// If a payload has a constant size then it's static
return this.hasConstantSize;
}
+
+ public abstract encodeValue(value: any): Buffer;
}
export abstract class DependentDataType extends DataType {
@@ -56,20 +64,21 @@ export abstract class DependentDataType extends DataType {
this.parent = parent;
}
- protected generateCalldataBlock(offsetInBytes: number, calldata: Calldata): CalldataBlock {
+ public generateCalldataBlock(value: any, parentBlock?: CalldataBlock): DependentCalldataBlock {
+ if (parentBlock === undefined) {
+ throw new Error(`DependentDataType requires a parent block to generate its block`);
+ }
+ const dependencyBlock = this.dependency.generateCalldataBlock(value);
const name = this.getDataItem().name;
const signature = this.getSignature();
const relocatable = false;
- const parentBlock = calldata.lookupBlockByName(this.parent.getDataItem().name);
- const dependencyBlock = calldata.lookupBlockByName(this.parent.getDataItem().name);
- const block = new DependentCalldataBlock(name, signature, offsetInBytes, relocatable, dependencyBlock, parentBlock);
- calldata.pushBlock(block);
+ const block = new DependentCalldataBlock(name, signature, /*offsetInBytes,*/ relocatable, dependencyBlock, parentBlock);
+ return block;
}
public encode(value: any, calldata: Calldata = new Calldata()): void {
- const offsetInBytes = calldata.reserveSpace(DependentCalldataBlock.DEPENDENT_PAYLOAD_SIZE_IN_BYTES);
- this.dependency.encode(value, calldata);
- this.generateCalldataBlock(offsetInBytes, calldata);
+ const block = this.generateCalldataBlock(value);
+ calldata.setRoot(block);
}
public isStatic(): boolean {
@@ -96,7 +105,7 @@ export abstract class MemberDataType extends DataType {
this.isArray = isArray;
this.arrayLength = arrayLength;
if (isArray && arrayLength !== undefined) {
- [this.members, this.memberMap] = MemberDataType.createMembersWithLength(arrayLength);
+ [this.members, this.memberMap] = MemberDataType.createMembersWithLength(dataItem, arrayLength);
} else if (!isArray) {
[this.members, this.memberMap] = MemberDataType.createMembersWithKeys(dataItem);
}
@@ -129,7 +138,7 @@ export abstract class MemberDataType extends DataType {
const range = _.range(length);
_.each(range, (idx: number) => {
const childDataItem = {
- type: this.type,
+ type: dataItem.type,
name: `${dataItem.name}[${idx.toString(10)}]`,
} as DataItem;
const components = dataItem.components;
@@ -144,57 +153,60 @@ export abstract class MemberDataType extends DataType {
return [members, memberMap];
}
- protected encodeFromArray(value: any[], calldata: Calldata) {
+ protected generateCalldataBlockFromArray(value: any[]): MemberCalldataBlock {
// Sanity check length
- const valueLength = new BigNumber(value.length);
- if (this.length !== SolArray.UNDEFINED_LENGTH && valueLength.equals(this.length) === false) {
+ if (this.arrayLength !== undefined && value.length !== this.arrayLength) {
throw new Error(
`Expected array of ${JSON.stringify(
- this.length,
- )} elements, but got array of length ${JSON.stringify(valueLength)}`,
+ this.arrayLength,
+ )} elements, but got array of length ${JSON.stringify(value.length)}`,
);
}
- // Assign values to children
- for (let idx = new BigNumber(0); idx.lessThan(this.length); idx = idx.plus(1)) {
- const idxNumber = idx.toNumber();
- this.members[idxNumber].assignValue(value[idxNumber]);
+ let members = this.members;
+ if (this.arrayLength === undefined) {
+ [members,] = MemberDataType.createMembersWithLength(this.getDataItem(), value.length);
}
+
+ const methodBlock: MemberCalldataBlock = new MemberCalldataBlock(this.getDataItem().name, this.getSignature(), false);
+ const memberBlocks: CalldataBlock[] = [];
+ _.each(members, (member: DataType) => {
+ const block = member.generateCalldataBlock(value, methodBlock);
+ memberBlocks.push(block);
+ });
+ methodBlock.setMembers(memberBlocks);
+ return methodBlock;
}
- protected encodeFromObject(obj: object, calldata: Calldata) {
+ protected generateCalldataBlockFromObject(obj: object): MemberCalldataBlock {
+ const methodBlock: MemberCalldataBlock = new MemberCalldataBlock(this.getDataItem().name, this.getSignature(), false);
+ const memberBlocks: CalldataBlock[] = [];
let childMap = _.cloneDeep(this.memberMap);
_.forOwn(obj, (value: any, key: string) => {
if (key in childMap === false) {
throw new Error(`Could not assign tuple to object: unrecognized key '${key}'`);
}
- this.members[this.childMap[key]].assignValue(value);
+ const block = this.members[this.memberMap[key]].generateCalldataBlock(value, methodBlock);
+ memberBlocks.push(block);
delete childMap[key];
});
if (Object.keys(childMap).length !== 0) {
throw new Error(`Could not assign tuple to object: missing keys ${Object.keys(childMap)}`);
}
+
+ methodBlock.setMembers(memberBlocks);
+ return methodBlock;
}
- public encode(value: any[] | object, calldata = new Calldata()) {
- if (value instanceof Array) {
- this.encodeFromArray(value, calldata);
- } else if (typeof value === 'object') {
- this.encodeFromObject(value, encodeFromObject);
- } else {
- throw new Error(`Unexpected type for ${value}`);
- }
+ public generateCalldataBlock(value: any[] | object, parentBlock?: CalldataBlock): MemberCalldataBlock {
+ const block = (value instanceof Array) ? this.generateCalldataBlockFromArray(value) : this.generateCalldataBlockFromObject(value, calldata);
+ return block;
}
- protected generateCalldataBlock(offsetInBytes: number, calldata: Calldata): CalldataBlock {
- const name = this.getDataItem().name;
- const signature = this.getSignature();
- const relocatable = false;
- const parentBlock = calldata.lookupBlockByName(this.parent.getDataItem().name);
- const dependencyBlock = calldata.lookupBlockByName(this.parent.getDataItem().name);
- const block = new DependentCalldataBlock(name, signature, offsetInBytes, relocatable, dependencyBlock, parentBlock);
- calldata.pushBlock(block);
+ public encode(value: any, calldata: Calldata = new Calldata()): void {
+ const block = this.generateCalldataBlock(value);
+ calldata.setRoot(block);
}
protected computeSignatureOfMembers(): string {