diff options
author | Greg Hysen <hysz@users.noreply.github.com> | 2018-05-22 05:29:56 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-05-22 05:29:56 +0800 |
commit | d460c0e8b9c6f4081803fff4e2d2347be8cd5ce3 (patch) | |
tree | 596681d82624683e76cdd507e31c46ffad4df73b /packages/contracts/src/utils | |
parent | 0fdf32cf6f0f1def41a1733687e977feb3a652f5 (diff) | |
parent | 11b6d290da18ea4690424a2a518413fb39a4a885 (diff) | |
download | dexon-sol-tools-d460c0e8b9c6f4081803fff4e2d2347be8cd5ce3.tar dexon-sol-tools-d460c0e8b9c6f4081803fff4e2d2347be8cd5ce3.tar.gz dexon-sol-tools-d460c0e8b9c6f4081803fff4e2d2347be8cd5ce3.tar.bz2 dexon-sol-tools-d460c0e8b9c6f4081803fff4e2d2347be8cd5ce3.tar.lz dexon-sol-tools-d460c0e8b9c6f4081803fff4e2d2347be8cd5ce3.tar.xz dexon-sol-tools-d460c0e8b9c6f4081803fff4e2d2347be8cd5ce3.tar.zst dexon-sol-tools-d460c0e8b9c6f4081803fff4e2d2347be8cd5ce3.zip |
Merge pull request #572 from 0xProject/feature/contracts/atomicMatching
Atomic Order Matching
Diffstat (limited to 'packages/contracts/src/utils')
-rw-r--r-- | packages/contracts/src/utils/asset_proxy_utils.ts | 107 | ||||
-rw-r--r-- | packages/contracts/src/utils/exchange_wrapper.ts | 22 | ||||
-rw-r--r-- | packages/contracts/src/utils/order_utils.ts | 9 | ||||
-rw-r--r-- | packages/contracts/src/utils/types.ts | 66 |
4 files changed, 196 insertions, 8 deletions
diff --git a/packages/contracts/src/utils/asset_proxy_utils.ts b/packages/contracts/src/utils/asset_proxy_utils.ts index dc31c3497..c042da5d0 100644 --- a/packages/contracts/src/utils/asset_proxy_utils.ts +++ b/packages/contracts/src/utils/asset_proxy_utils.ts @@ -2,12 +2,15 @@ import { BigNumber } from '@0xproject/utils'; import BN = require('bn.js'); import ethUtil = require('ethereumjs-util'); -import { AssetProxyId } from './types'; +import { AssetProxyId, ERC20ProxyData, ERC721ProxyData, ProxyData } from './types'; export const assetProxyUtils = { encodeAssetProxyId(assetProxyId: AssetProxyId): Buffer { return ethUtil.toBuffer(assetProxyId); }, + decodeAssetProxyId(encodedAssetProxyId: Buffer): AssetProxyId { + return ethUtil.bufferToInt(encodedAssetProxyId); + }, encodeAddress(address: string): Buffer { if (!ethUtil.isValidAddress(address)) { throw new Error(`Invalid Address: ${address}`); @@ -15,12 +18,24 @@ export const assetProxyUtils = { const encodedAddress = ethUtil.toBuffer(address); return encodedAddress; }, + decodeAddress(encodedAddress: Buffer): string { + const address = ethUtil.bufferToHex(encodedAddress); + if (!ethUtil.isValidAddress(address)) { + throw new Error(`Invalid Address: ${address}`); + } + return address; + }, encodeUint256(value: BigNumber): Buffer { const formattedValue = new BN(value.toString(10)); const encodedValue = ethUtil.toBuffer(formattedValue); const paddedValue = ethUtil.setLengthLeft(encodedValue, 32); return paddedValue; }, + decodeUint256(encodedValue: Buffer): BigNumber { + const formattedValue = ethUtil.bufferToHex(encodedValue); + const value = new BigNumber(formattedValue, 16); + return value; + }, encodeERC20ProxyData(tokenAddress: string): string { const encodedAssetProxyId = assetProxyUtils.encodeAssetProxyId(AssetProxyId.ERC20); const encodedAddress = assetProxyUtils.encodeAddress(tokenAddress); @@ -28,6 +43,32 @@ export const assetProxyUtils = { const encodedMetadataHex = ethUtil.bufferToHex(encodedMetadata); return encodedMetadataHex; }, + decodeERC20ProxyData(proxyData: string): ERC20ProxyData { + const encodedProxyMetadata = ethUtil.toBuffer(proxyData); + if (encodedProxyMetadata.byteLength !== 21) { + throw new Error( + `Could not decode ERC20 Proxy Data. Expected length of encoded data to be 21. Got ${ + encodedProxyMetadata.byteLength + }`, + ); + } + const encodedAssetProxyId = encodedProxyMetadata.slice(0, 1); + const assetProxyId = assetProxyUtils.decodeAssetProxyId(encodedAssetProxyId); + if (assetProxyId !== AssetProxyId.ERC20) { + throw new Error( + `Could not decode ERC20 Proxy Data. Expected Asset Proxy Id to be ERC20 (${ + AssetProxyId.ERC20 + }), but got ${assetProxyId}`, + ); + } + const encodedTokenAddress = encodedProxyMetadata.slice(1, 21); + const tokenAddress = assetProxyUtils.decodeAddress(encodedTokenAddress); + const erc20ProxyData = { + assetProxyId, + tokenAddress, + }; + return erc20ProxyData; + }, encodeERC721ProxyData(tokenAddress: string, tokenId: BigNumber): string { const encodedAssetProxyId = assetProxyUtils.encodeAssetProxyId(AssetProxyId.ERC721); const encodedAddress = assetProxyUtils.encodeAddress(tokenAddress); @@ -36,4 +77,68 @@ export const assetProxyUtils = { const encodedMetadataHex = ethUtil.bufferToHex(encodedMetadata); return encodedMetadataHex; }, + decodeERC721ProxyData(proxyData: string): ERC721ProxyData { + const encodedProxyMetadata = ethUtil.toBuffer(proxyData); + if (encodedProxyMetadata.byteLength !== 53) { + throw new Error( + `Could not decode ERC20 Proxy Data. Expected length of encoded data to be 53. Got ${ + encodedProxyMetadata.byteLength + }`, + ); + } + const encodedAssetProxyId = encodedProxyMetadata.slice(0, 1); + const assetProxyId = assetProxyUtils.decodeAssetProxyId(encodedAssetProxyId); + if (assetProxyId !== AssetProxyId.ERC721) { + throw new Error( + `Could not decode ERC721 Proxy Data. Expected Asset Proxy Id to be ERC721 (${ + AssetProxyId.ERC721 + }), but got ${assetProxyId}`, + ); + } + const encodedTokenAddress = encodedProxyMetadata.slice(1, 21); + const tokenAddress = assetProxyUtils.decodeAddress(encodedTokenAddress); + const encodedTokenId = encodedProxyMetadata.slice(21, 53); + const tokenId = assetProxyUtils.decodeUint256(encodedTokenId); + const erc721ProxyData = { + assetProxyId, + tokenAddress, + tokenId, + }; + return erc721ProxyData; + }, + decodeProxyDataId(proxyData: string): AssetProxyId { + const encodedProxyMetadata = ethUtil.toBuffer(proxyData); + if (encodedProxyMetadata.byteLength < 1) { + throw new Error( + `Could not decode Proxy Data. Expected length of encoded data to be at least 1. Got ${ + encodedProxyMetadata.byteLength + }`, + ); + } + const encodedAssetProxyId = encodedProxyMetadata.slice(0, 1); + const assetProxyId = assetProxyUtils.decodeAssetProxyId(encodedAssetProxyId); + return assetProxyId; + }, + decodeProxyData(proxyData: string): ProxyData { + const assetProxyId = assetProxyUtils.decodeProxyDataId(proxyData); + switch (assetProxyId) { + case AssetProxyId.ERC20: + const erc20ProxyData = assetProxyUtils.decodeERC20ProxyData(proxyData); + const generalizedERC20ProxyData = { + assetProxyId, + tokenAddress: erc20ProxyData.tokenAddress, + }; + return generalizedERC20ProxyData; + case AssetProxyId.ERC721: + const erc721ProxyData = assetProxyUtils.decodeERC721ProxyData(proxyData); + const generaliedERC721ProxyData = { + assetProxyId, + tokenAddress: erc721ProxyData.tokenAddress, + data: erc721ProxyData.tokenId, + }; + return generaliedERC721ProxyData; + default: + throw new Error(`Unrecognized asset proxy id: ${assetProxyId}`); + } + }, }; diff --git a/packages/contracts/src/utils/exchange_wrapper.ts b/packages/contracts/src/utils/exchange_wrapper.ts index 27fdd698f..46531fa3f 100644 --- a/packages/contracts/src/utils/exchange_wrapper.ts +++ b/packages/contracts/src/utils/exchange_wrapper.ts @@ -9,7 +9,7 @@ import { constants } from './constants'; import { formatters } from './formatters'; import { LogDecoder } from './log_decoder'; import { orderUtils } from './order_utils'; -import { AssetProxyId, SignedOrder, SignedTransaction } from './types'; +import { AssetProxyId, OrderInfo, SignedOrder, SignedTransaction } from './types'; export class ExchangeWrapper { private _exchange: ExchangeContract; @@ -225,6 +225,26 @@ export class ExchangeWrapper { const filledAmount = new BigNumber(await this._exchange.filled.callAsync(orderHashHex)); return filledAmount; } + public async getOrderInfoAsync(signedOrder: SignedOrder): Promise<OrderInfo> { + const orderInfo = (await this._exchange.getOrderInfo.callAsync(signedOrder)) as OrderInfo; + return orderInfo; + } + public async matchOrdersAsync( + signedOrderLeft: SignedOrder, + signedOrderRight: SignedOrder, + from: string, + ): Promise<TransactionReceiptWithDecodedLogs> { + const params = orderUtils.createMatchOrders(signedOrderLeft, signedOrderRight); + const txHash = await this._exchange.matchOrders.sendTransactionAsync( + params.left, + params.right, + params.leftSignature, + params.rightSignature, + { from }, + ); + const tx = await this._getTxWithDecodedExchangeLogsAsync(txHash); + return tx; + } private async _getTxWithDecodedExchangeLogsAsync(txHash: string) { const tx = await this._zeroEx.awaitTransactionMinedAsync(txHash); tx.logs = _.filter(tx.logs, log => log.address === this._exchange.address); diff --git a/packages/contracts/src/utils/order_utils.ts b/packages/contracts/src/utils/order_utils.ts index 10bbf4f7c..7a482ad9e 100644 --- a/packages/contracts/src/utils/order_utils.ts +++ b/packages/contracts/src/utils/order_utils.ts @@ -80,4 +80,13 @@ export const orderUtils = { const orderHashHex = `0x${orderHashBuff.toString('hex')}`; return orderHashHex; }, + createMatchOrders(signedOrderLeft: SignedOrder, signedOrderRight: SignedOrder) { + const fill = { + left: orderUtils.getOrderStruct(signedOrderLeft), + right: orderUtils.getOrderStruct(signedOrderRight), + leftSignature: signedOrderLeft.signature, + rightSignature: signedOrderRight.signature, + }; + return fill; + }, }; diff --git a/packages/contracts/src/utils/types.ts b/packages/contracts/src/utils/types.ts index 234b14ef9..8d81adece 100644 --- a/packages/contracts/src/utils/types.ts +++ b/packages/contracts/src/utils/types.ts @@ -74,12 +74,22 @@ export interface Token { swarmHash: string; } -export enum ExchangeContractErrs { - ERROR_ORDER_EXPIRED, - ERROR_ORDER_FULLY_FILLED, - ERROR_ORDER_CANCELLED, - ERROR_ROUNDING_ERROR_TOO_LARGE, - ERROR_INSUFFICIENT_BALANCE_OR_ALLOWANCE, +export enum ExchangeStatus { + INVALID, + SUCCESS, + ROUNDING_ERROR_TOO_LARGE, + INSUFFICIENT_BALANCE_OR_ALLOWANCE, + TAKER_ASSET_FILL_AMOUNT_TOO_LOW, + INVALID_SIGNATURE, + INVALID_SENDER, + INVALID_TAKER, + INVALID_MAKER, + ORDER_INVALID_MAKER_ASSET_AMOUNT, + ORDER_INVALID_TAKER_ASSET_AMOUNT, + ORDER_FILLABLE, + ORDER_EXPIRED, + ORDER_FULLY_FILLED, + ORDER_CANCELLED, } export enum ContractName { @@ -143,3 +153,47 @@ export interface SignedTransaction { data: string; signature: string; } + +export interface TransferAmountsByMatchOrders { + // Left Maker + amountBoughtByLeftMaker: BigNumber; + amountSoldByLeftMaker: BigNumber; + amountReceivedByLeftMaker: BigNumber; + feePaidByLeftMaker: BigNumber; + // Right Maker + amountBoughtByRightMaker: BigNumber; + amountSoldByRightMaker: BigNumber; + amountReceivedByRightMaker: BigNumber; + feePaidByRightMaker: BigNumber; + // Taker + amountReceivedByTaker: BigNumber; + feePaidByTakerLeft: BigNumber; + feePaidByTakerRight: BigNumber; + totalFeePaidByTaker: BigNumber; + // Fee Recipients + feeReceivedLeft: BigNumber; + feeReceivedRight: BigNumber; +} + +export interface OrderInfo { + orderStatus: number; + orderHash: string; + orderTakerAssetFilledAmount: BigNumber; +} + +export interface ERC20ProxyData { + assetProxyId: AssetProxyId; + tokenAddress: string; +} + +export interface ERC721ProxyData { + assetProxyId: AssetProxyId; + tokenAddress: string; + tokenId: BigNumber; +} + +export interface ProxyData { + assetProxyId: AssetProxyId; + tokenAddress?: string; + data?: any; +} |