From b75fe10c790a60c875914a2a79ae8c4761b78bb9 Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Wed, 17 Oct 2018 00:49:48 -0700 Subject: feat(contract-wrappers): export ForwarderWrapperError and ContractWrapperError.SignatureRequestDenied --- packages/contract-wrappers/CHANGELOG.json | 8 ++++++++ packages/contract-wrappers/src/index.ts | 1 + packages/contract-wrappers/src/types.ts | 5 +++++ packages/contract-wrappers/src/utils/constants.ts | 1 + packages/contract-wrappers/src/utils/decorators.ts | 14 +++++++++++++- 5 files changed, 28 insertions(+), 1 deletion(-) diff --git a/packages/contract-wrappers/CHANGELOG.json b/packages/contract-wrappers/CHANGELOG.json index f66be3f0a..c3d986b4a 100644 --- a/packages/contract-wrappers/CHANGELOG.json +++ b/packages/contract-wrappers/CHANGELOG.json @@ -37,6 +37,14 @@ "note": "Removed ContractNotFound errors. Checking for this error was somewhat ineffecient. Relevant methods/functions now return the default error from web3-wrapper, which we feel provides enough information.", "pr": 1105 + }, + { + "note": "Add `ForwarderWrapperError` to public interface", + "pr": 1147 + }, + { + "note": "Add `ContractWrapperError.SignatureRequestDenied` to public interface", + "pr": 1147 } ], "timestamp": 1539871071 diff --git a/packages/contract-wrappers/src/index.ts b/packages/contract-wrappers/src/index.ts index a38bd122b..d66ff5c9c 100644 --- a/packages/contract-wrappers/src/index.ts +++ b/packages/contract-wrappers/src/index.ts @@ -39,6 +39,7 @@ export { TransactionEncoder } from './utils/transaction_encoder'; export { ContractWrappersError, + ForwarderWrapperError, IndexedFilterValues, BlockRange, ContractWrappersConfig, diff --git a/packages/contract-wrappers/src/types.ts b/packages/contract-wrappers/src/types.ts index 60750179f..5a5bdd530 100644 --- a/packages/contract-wrappers/src/types.ts +++ b/packages/contract-wrappers/src/types.ts @@ -18,6 +18,10 @@ export enum ExchangeWrapperError { AssetDataMismatch = 'ASSET_DATA_MISMATCH', } +export enum ForwarderWrapperError { + CompleteFillFailed = 'COMPLETE_FILL_FAILED', +} + export enum ContractWrappersError { ContractNotDeployedOnNetwork = 'CONTRACT_NOT_DEPLOYED_ON_NETWORK', InsufficientAllowanceForTransfer = 'INSUFFICIENT_ALLOWANCE_FOR_TRANSFER', @@ -30,6 +34,7 @@ export enum ContractWrappersError { SubscriptionAlreadyPresent = 'SUBSCRIPTION_ALREADY_PRESENT', ERC721OwnerNotFound = 'ERC_721_OWNER_NOT_FOUND', ERC721NoApproval = 'ERC_721_NO_APPROVAL', + SignatureRequestDenied = 'SIGNATURE_REQUEST_DENIED', } export enum InternalContractWrappersError { diff --git a/packages/contract-wrappers/src/utils/constants.ts b/packages/contract-wrappers/src/utils/constants.ts index 9ff61f62a..b89438592 100644 --- a/packages/contract-wrappers/src/utils/constants.ts +++ b/packages/contract-wrappers/src/utils/constants.ts @@ -14,4 +14,5 @@ export const constants = { ZERO_AMOUNT: new BigNumber(0), ONE_AMOUNT: new BigNumber(1), ETHER_TOKEN_DECIMALS: 18, + METAMASK_DENIED_SIGNATURE_PATTERN: 'MetaMask Tx Signature: User denied transaction signature', }; diff --git a/packages/contract-wrappers/src/utils/decorators.ts b/packages/contract-wrappers/src/utils/decorators.ts index e17246015..932b11785 100644 --- a/packages/contract-wrappers/src/utils/decorators.ts +++ b/packages/contract-wrappers/src/utils/decorators.ts @@ -29,6 +29,14 @@ const schemaErrorTransformer = (error: Error) => { return error; }; +const signatureRequestErrorTransformer = (error: Error) => { + if (_.includes(error.message, constants.METAMASK_DENIED_SIGNATURE_PATTERN)) { + const errMsg = ContractWrappersError.SignatureRequestDenied; + return new Error(errMsg); + } + return error; +}; + /** * Source: https://stackoverflow.com/a/29837695/3546986 */ @@ -87,7 +95,11 @@ const syncErrorHandlerFactory = (errorTransformer: ErrorTransformer) => { }; // _.flow(f, g) = f ∘ g -const zeroExErrorTransformer = _.flow(schemaErrorTransformer, contractCallErrorTransformer); +const zeroExErrorTransformer = _.flow( + schemaErrorTransformer, + contractCallErrorTransformer, + signatureRequestErrorTransformer, +); export const decorators = { asyncZeroExErrorHandler: asyncErrorHandlerFactory(zeroExErrorTransformer), -- cgit v1.2.3 From dcd428a4a299de0daf6bbfb8e8a7c15685b673cf Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Wed, 17 Oct 2018 09:54:41 -0700 Subject: feat(monorepo-scripts): add ForwarderWrapperError to IGNORED_EXCESSIVE_TYPES in docGenConfigs --- packages/monorepo-scripts/CHANGELOG.json | 4 ++++ packages/monorepo-scripts/src/doc_gen_configs.ts | 1 + 2 files changed, 5 insertions(+) diff --git a/packages/monorepo-scripts/CHANGELOG.json b/packages/monorepo-scripts/CHANGELOG.json index 4797fd929..170a97a33 100644 --- a/packages/monorepo-scripts/CHANGELOG.json +++ b/packages/monorepo-scripts/CHANGELOG.json @@ -9,6 +9,10 @@ { "note": "Add AssetBuyerError to the IGNORED_EXCESSIVE_TYPES array", "pr": 1139 + }, + { + "note": "Add ForwarderError to the IGNORED_EXCESSIVE_TYPES array", + "pr": 1147 } ] }, diff --git a/packages/monorepo-scripts/src/doc_gen_configs.ts b/packages/monorepo-scripts/src/doc_gen_configs.ts index 0aaf5a6a5..7a14f8664 100644 --- a/packages/monorepo-scripts/src/doc_gen_configs.ts +++ b/packages/monorepo-scripts/src/doc_gen_configs.ts @@ -56,6 +56,7 @@ export const docGenConfigs: DocGenConfigs = { 'ContractWrappersError', 'OrderError', 'AssetBuyerError', + 'ForwarderWrapperError', ], // Some libraries only export types. In those cases, we cannot check if the exported types are part of the // "exported public interface". Thus we add them here and skip those checks. -- cgit v1.2.3 From 117ee19370e56f3559b9b11b04becc5ad9c7d634 Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Wed, 17 Oct 2018 10:03:46 -0700 Subject: feat(asset-buyer): throw SignatureRequestDenied and TransactionValueTooLow errors when executing buy --- packages/asset-buyer/CHANGELOG.json | 4 +++ packages/asset-buyer/src/asset_buyer.ts | 43 +++++++++++++++++++++------------ packages/asset-buyer/src/types.ts | 2 ++ 3 files changed, 33 insertions(+), 16 deletions(-) diff --git a/packages/asset-buyer/CHANGELOG.json b/packages/asset-buyer/CHANGELOG.json index 5ebe2aa24..7ebcd8c2f 100644 --- a/packages/asset-buyer/CHANGELOG.json +++ b/packages/asset-buyer/CHANGELOG.json @@ -25,6 +25,10 @@ { "note": "Add missing types to public interface", "pr": 1139 + }, + { + "note": "Throw `SignatureRequestDenied` and `TransactionValueTooLow` errors when executing buy", + "pr": 1147 } ], "timestamp": 1539871071 diff --git a/packages/asset-buyer/src/asset_buyer.ts b/packages/asset-buyer/src/asset_buyer.ts index 2fe8f6deb..2f9a3108e 100644 --- a/packages/asset-buyer/src/asset_buyer.ts +++ b/packages/asset-buyer/src/asset_buyer.ts @@ -1,4 +1,4 @@ -import { ContractWrappers } from '@0x/contract-wrappers'; +import { ContractWrappers, ContractWrappersError, ForwarderWrapperError } from '@0x/contract-wrappers'; import { schemas } from '@0x/json-schemas'; import { SignedOrder } from '@0x/order-utils'; import { ObjectMap } from '@0x/types'; @@ -210,21 +210,32 @@ export class AssetBuyer { throw new Error(AssetBuyerError.NoAddressAvailable); } } - // if no ethAmount is provided, default to the worst ethAmount from buyQuote - const txHash = await this._contractWrappers.forwarder.marketBuyOrdersWithEthAsync( - orders, - assetBuyAmount, - finalTakerAddress, - ethAmount || worstCaseQuoteInfo.totalEthAmount, - feeOrders, - feePercentage, - feeRecipient, - { - gasLimit, - gasPrice, - }, - ); - return txHash; + try { + // if no ethAmount is provided, default to the worst ethAmount from buyQuote + const txHash = await this._contractWrappers.forwarder.marketBuyOrdersWithEthAsync( + orders, + assetBuyAmount, + finalTakerAddress, + ethAmount || worstCaseQuoteInfo.totalEthAmount, + feeOrders, + feePercentage, + feeRecipient, + { + gasLimit, + gasPrice, + shouldValidate: true, + }, + ); + return txHash; + } catch (err) { + if (_.includes(err.message, ContractWrappersError.SignatureRequestDenied)) { + throw new Error(AssetBuyerError.SignatureRequestDenied); + } else if (_.includes(err.message, ForwarderWrapperError.CompleteFillFailed)) { + throw new Error(AssetBuyerError.TransactionValueTooLow); + } else { + throw err; + } + } } /** * Grab orders from the map, if there is a miss or it is time to refresh, fetch and process the orders diff --git a/packages/asset-buyer/src/types.ts b/packages/asset-buyer/src/types.ts index 0d8e732d7..f15e7e934 100644 --- a/packages/asset-buyer/src/types.ts +++ b/packages/asset-buyer/src/types.ts @@ -112,6 +112,8 @@ export enum AssetBuyerError { NoAddressAvailable = 'NO_ADDRESS_AVAILABLE', InvalidOrderProviderResponse = 'INVALID_ORDER_PROVIDER_RESPONSE', AssetUnavailable = 'ASSET_UNAVAILABLE', + SignatureRequestDenied = 'SIGNATURE_REQUEST_DENIED', + TransactionValueTooLow = 'TRANSACTION_VALUE_TOO_LOW', } export interface OrdersAndFillableAmounts { -- cgit v1.2.3 From af2bf053bc9cfe80618109dc10a90515d780cd25 Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Mon, 22 Oct 2018 22:23:32 -0700 Subject: feat(contract-wrappers): relax requirement for throwing `ContractWrappersError.SignatureRequestDenied` --- packages/contract-wrappers/src/utils/constants.ts | 2 +- packages/contract-wrappers/src/utils/decorators.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/contract-wrappers/src/utils/constants.ts b/packages/contract-wrappers/src/utils/constants.ts index b89438592..c587ba526 100644 --- a/packages/contract-wrappers/src/utils/constants.ts +++ b/packages/contract-wrappers/src/utils/constants.ts @@ -14,5 +14,5 @@ export const constants = { ZERO_AMOUNT: new BigNumber(0), ONE_AMOUNT: new BigNumber(1), ETHER_TOKEN_DECIMALS: 18, - METAMASK_DENIED_SIGNATURE_PATTERN: 'MetaMask Tx Signature: User denied transaction signature', + USER_DENIED_SIGNATURE_PATTERN: 'User denied transaction signature', }; diff --git a/packages/contract-wrappers/src/utils/decorators.ts b/packages/contract-wrappers/src/utils/decorators.ts index 932b11785..a4207ae4c 100644 --- a/packages/contract-wrappers/src/utils/decorators.ts +++ b/packages/contract-wrappers/src/utils/decorators.ts @@ -30,7 +30,7 @@ const schemaErrorTransformer = (error: Error) => { }; const signatureRequestErrorTransformer = (error: Error) => { - if (_.includes(error.message, constants.METAMASK_DENIED_SIGNATURE_PATTERN)) { + if (_.includes(error.message, constants.USER_DENIED_SIGNATURE_PATTERN)) { const errMsg = ContractWrappersError.SignatureRequestDenied; return new Error(errMsg); } -- cgit v1.2.3