Skip to content
This repository has been archived by the owner on Jul 9, 2021. It is now read-only.

Commit

Permalink
Add recursive MultiAsset decoding, store first address in pipeline
Browse files Browse the repository at this point in the history
  • Loading branch information
abandeali1 committed Jan 3, 2019
1 parent e5a9194 commit 702e9b2
Show file tree
Hide file tree
Showing 9 changed files with 64 additions and 23 deletions.
1 change: 1 addition & 0 deletions packages/0x.js/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ export {
ERC20AssetData,
ERC721AssetData,
MultiAssetData,
MultiAssetDataWithRecursiveDecoding,
SignatureType,
OrderRelevantState,
Stats,
Expand Down
29 changes: 28 additions & 1 deletion packages/order-utils/src/asset_data_utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import { AssetProxyId, ERC20AssetData, ERC721AssetData, MultiAssetData, SingleAssetData } from '@0x/types';
import {
AssetProxyId,
ERC20AssetData,
ERC721AssetData,
MultiAssetData,
MultiAssetDataWithRecursiveDecoding,
SingleAssetData,
} from '@0x/types';
import { AbiEncoder, BigNumber } from '@0x/utils';
import { MethodAbi } from 'ethereum-types';
import * as _ from 'lodash';
Expand Down Expand Up @@ -114,6 +121,26 @@ export const assetDataUtils = {
nestedAssetData,
};
},
/**
* Decodes a MultiAsset assetData hex string into it's corresponding amounts and decoded nestedAssetData elements (all nested elements are flattened)
* @param assetData Hex encoded assetData string to decode
* @return An object containing the decoded amounts and nestedAssetData
*/
decodeMultiAssetDataRecursively(assetData: string): MultiAssetDataWithRecursiveDecoding {
const decodedAssetData = assetDataUtils.decodeMultiAssetData(assetData);
const decodedNestedAssetData = _.map(decodedAssetData.nestedAssetData as string[], nestedAssetDataElement => {
const decodedNestedAssetDataElement = assetDataUtils.decodeAssetDataOrThrow(nestedAssetDataElement);
return decodedNestedAssetDataElement.assetProxyId === AssetProxyId.MultiAsset
? assetDataUtils.decodeMultiAssetDataRecursively(nestedAssetDataElement).nestedAssetData
: (decodedNestedAssetDataElement as SingleAssetData);
});
const flattenedDecodedNestedAssetData = _.flattenDeep(decodedNestedAssetData);
return {
assetProxyId: decodedAssetData.assetProxyId,
amounts: decodedAssetData.amounts,
nestedAssetData: flattenedDecodedNestedAssetData as SingleAssetData[],
};
},
/**
* Decode and return the assetProxyId from the assetData
* @param assetData Hex encoded assetData string to decode
Expand Down
2 changes: 1 addition & 1 deletion packages/order-utils/src/exchange_transfer_simulator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ export class ExchangeTransferSimulator {
const amountsElement = decodedAssetData.amounts[index];
const totalAmount = amountInBaseUnits.times(amountsElement);
await this.transferFromAsync(
nestedAssetDataElement,
nestedAssetDataElement as string,
from,
to,
totalAmount,
Expand Down
1 change: 1 addition & 0 deletions packages/order-utils/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export {
ERC20AssetData,
ERC721AssetData,
MultiAssetData,
MultiAssetDataWithRecursiveDecoding,
AssetProxyId,
SignatureType,
OrderStateValid,
Expand Down
2 changes: 1 addition & 1 deletion packages/pipeline/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
"@0x/contract-artifacts": "^1.0.1",
"@0x/contract-wrappers": "^3.0.0",
"@0x/dev-utils": "^1.0.21",
"@0x/order-utils": "^2.0.0",
"@0x/order-utils": "^3.0.7",
"@0x/subproviders": "^2.1.8",
"@0x/types": "^1.4.1",
"@0x/utils": "^2.0.8",
Expand Down
26 changes: 15 additions & 11 deletions packages/pipeline/src/parsers/events/exchange_events.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ExchangeCancelEventArgs, ExchangeCancelUpToEventArgs, ExchangeFillEventArgs } from '@0x/contract-wrappers';
import { assetDataUtils } from '@0x/order-utils';
import { AssetProxyId, ERC20AssetData, ERC721AssetData } from '@0x/types';
import { AssetProxyId, ERC721AssetData, SingleAssetData } from '@0x/types';
import { LogWithDecodedArgs } from 'ethereum-types';
import * as R from 'ramda';

Expand Down Expand Up @@ -62,8 +62,9 @@ export function _convertToExchangeFillEvent(eventLog: LogWithDecodedArgs<Exchang
// HACK(abandeali1): this event schema currently does not support multiple maker/taker assets, so we store a null byte array when decoding assetData from the MultiAssetProxy
exchangeFillEvent.makerTokenAddress =
makerAssetData.assetProxyId === AssetProxyId.MultiAsset
? '0x'
: (makerAssetData as ERC20AssetData | ERC721AssetData).tokenAddress;
? assetDataUtils.decodeMultiAssetDataRecursively(eventLog.args.makerAssetData).nestedAssetData[0]
.tokenAddress
: (makerAssetData as SingleAssetData).tokenAddress;
// tslint has a false positive here. Type assertion is required.
// tslint:disable-next-line:no-unnecessary-type-assertion
exchangeFillEvent.makerTokenId = bigNumbertoStringOrNull((makerAssetData as ERC721AssetData).tokenId);
Expand All @@ -72,9 +73,10 @@ export function _convertToExchangeFillEvent(eventLog: LogWithDecodedArgs<Exchang
exchangeFillEvent.takerAssetProxyId = takerAssetData.assetProxyId;
// HACK(abandeali1): this event schema currently does not support multiple maker/taker assets, so we store a null byte array when decoding assetData from the MultiAssetProxy
exchangeFillEvent.takerTokenAddress =
makerAssetData.assetProxyId === AssetProxyId.MultiAsset
? '0x'
: (takerAssetData as ERC20AssetData | ERC721AssetData).tokenAddress;
takerAssetData.assetProxyId === AssetProxyId.MultiAsset
? assetDataUtils.decodeMultiAssetDataRecursively(eventLog.args.takerAssetData).nestedAssetData[0]
.tokenAddress
: (takerAssetData as SingleAssetData).tokenAddress;
// tslint:disable-next-line:no-unnecessary-type-assertion
exchangeFillEvent.takerTokenId = bigNumbertoStringOrNull((takerAssetData as ERC721AssetData).tokenId);
return exchangeFillEvent;
Expand Down Expand Up @@ -107,18 +109,20 @@ export function _convertToExchangeCancelEvent(
// HACK(abandeali1): this event schema currently does not support multiple maker/taker assets, so we store a null byte array when decoding assetData from the MultiAssetProxy
exchangeCancelEvent.makerTokenAddress =
makerAssetData.assetProxyId === AssetProxyId.MultiAsset
? '0x'
: (makerAssetData as ERC20AssetData | ERC721AssetData).tokenAddress;
? assetDataUtils.decodeMultiAssetDataRecursively(eventLog.args.makerAssetData).nestedAssetData[0]
.tokenAddress
: (makerAssetData as SingleAssetData).tokenAddress;
// tslint:disable-next-line:no-unnecessary-type-assertion
exchangeCancelEvent.makerTokenId = bigNumbertoStringOrNull((makerAssetData as ERC721AssetData).tokenId);
exchangeCancelEvent.rawTakerAssetData = eventLog.args.takerAssetData;
exchangeCancelEvent.takerAssetType = convertAssetProxyIdToType(takerAssetData.assetProxyId as AssetProxyId);
exchangeCancelEvent.takerAssetProxyId = takerAssetData.assetProxyId;
// HACK(abandeali1): this event schema currently does not support multiple maker/taker assets, so we store a null byte array when decoding assetData from the MultiAssetProxy
exchangeCancelEvent.takerTokenAddress =
makerAssetData.assetProxyId === AssetProxyId.MultiAsset
? '0x'
: (takerAssetData as ERC20AssetData | ERC721AssetData).tokenAddress;
takerAssetData.assetProxyId === AssetProxyId.MultiAsset
? assetDataUtils.decodeMultiAssetDataRecursively(eventLog.args.takerAssetData).nestedAssetData[0]
.tokenAddress
: (takerAssetData as SingleAssetData).tokenAddress;
// tslint:disable-next-line:no-unnecessary-type-assertion
exchangeCancelEvent.takerTokenId = bigNumbertoStringOrNull((takerAssetData as ERC721AssetData).tokenId);
return exchangeCancelEvent;
Expand Down
14 changes: 8 additions & 6 deletions packages/pipeline/src/parsers/sra_orders/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { APIOrder, OrdersResponse } from '@0x/connect';
import { assetDataUtils, orderHashUtils } from '@0x/order-utils';
import { AssetProxyId, ERC20AssetData, ERC721AssetData } from '@0x/types';
import { AssetProxyId, ERC721AssetData, SingleAssetData } from '@0x/types';
import * as R from 'ramda';

import { SraOrder } from '../../entities';
Expand Down Expand Up @@ -46,8 +46,9 @@ export function _convertToEntity(apiOrder: APIOrder): SraOrder {
// HACK(abandeali1): this event schema currently does not support multiple maker/taker assets, so we store a null byte array when decoding assetData from the MultiAssetProxy
sraOrder.makerTokenAddress =
makerAssetData.assetProxyId === AssetProxyId.MultiAsset
? '0x'
: (makerAssetData as ERC20AssetData | ERC721AssetData).tokenAddress;
? assetDataUtils.decodeMultiAssetDataRecursively(apiOrder.order.makerAssetData).nestedAssetData[0]
.tokenAddress
: (makerAssetData as SingleAssetData).tokenAddress;
// tslint has a false positive here. Type assertion is required.
// tslint:disable-next-line:no-unnecessary-type-assertion
sraOrder.makerTokenId = bigNumbertoStringOrNull((makerAssetData as ERC721AssetData).tokenId);
Expand All @@ -56,9 +57,10 @@ export function _convertToEntity(apiOrder: APIOrder): SraOrder {
sraOrder.takerAssetProxyId = takerAssetData.assetProxyId;
// HACK(abandeali1): this event schema currently does not support multiple maker/taker assets, so we store a null byte array when decoding assetData from the MultiAssetProxy
sraOrder.takerTokenAddress =
makerAssetData.assetProxyId === AssetProxyId.MultiAsset
? '0x'
: (takerAssetData as ERC20AssetData | ERC721AssetData).tokenAddress;
takerAssetData.assetProxyId === AssetProxyId.MultiAsset
? assetDataUtils.decodeMultiAssetDataRecursively(apiOrder.order.takerAssetData).nestedAssetData[0]
.tokenAddress
: (takerAssetData as SingleAssetData).tokenAddress;
// tslint:disable-next-line:no-unnecessary-type-assertion
sraOrder.takerTokenId = bigNumbertoStringOrNull((takerAssetData as ERC721AssetData).tokenId);

Expand Down
8 changes: 7 additions & 1 deletion packages/types/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,13 +171,19 @@ export interface ERC721AssetData {
tokenId: BigNumber;
}

export type SingleAssetData = ERC20AssetData | ERC721AssetData;

export interface MultiAssetData {
assetProxyId: string;
amounts: BigNumber[];
nestedAssetData: string[];
}

export type SingleAssetData = ERC20AssetData | ERC721AssetData;
export interface MultiAssetDataWithRecursiveDecoding {
assetProxyId: string;
amounts: BigNumber[];
nestedAssetData: SingleAssetData[];
}

// TODO: DRY. These should be extracted from contract code.
export enum RevertReason {
Expand Down
4 changes: 2 additions & 2 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -507,7 +507,7 @@
lodash "^4.17.5"
uuid "^3.1.0"

"@0x/order-utils@^2.0.0", "@0x/order-utils@^2.0.1":
"@0x/order-utils@^2.0.1":
version "2.0.1"
resolved "https://registry.yarnpkg.com/@0x/order-utils/-/order-utils-2.0.1.tgz#8c46d7aeb9e2cce54a0822824c12427cbe5f7eb4"
dependencies:
Expand Down Expand Up @@ -7339,7 +7339,7 @@ ganache-core@0xProject/ganache-core#monorepo-dep:
ethereumjs-tx "0xProject/ethereumjs-tx#fake-tx-include-signature-by-default"
ethereumjs-util "^5.2.0"
ethereumjs-vm "2.3.5"
ethereumjs-wallet "~0.6.0"
ethereumjs-wallet "0.6.0"
fake-merkle-patricia-tree "~1.0.1"
heap "~0.2.6"
js-scrypt "^0.2.0"
Expand Down

0 comments on commit 702e9b2

Please sign in to comment.