Merge pull request #1147 from 0xProject/feature/asset-buyer/signing-request-error

[asset-buyer][contract-wrappers] Throw SignatureRequestDenied and TransactionValueTooLow errors from AssetBuyer
This commit is contained in:
Brandon Millman
2018-10-23 10:33:33 -07:00
committed by GitHub
10 changed files with 66 additions and 17 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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 {

View File

@@ -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

View File

@@ -39,6 +39,7 @@ export { TransactionEncoder } from './utils/transaction_encoder';
export {
ContractWrappersError,
ForwarderWrapperError,
IndexedFilterValues,
BlockRange,
ContractWrappersConfig,

View File

@@ -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 {

View File

@@ -14,4 +14,5 @@ export const constants = {
ZERO_AMOUNT: new BigNumber(0),
ONE_AMOUNT: new BigNumber(1),
ETHER_TOKEN_DECIMALS: 18,
USER_DENIED_SIGNATURE_PATTERN: 'User denied transaction signature',
};

View File

@@ -29,6 +29,14 @@ const schemaErrorTransformer = (error: Error) => {
return error;
};
const signatureRequestErrorTransformer = (error: Error) => {
if (_.includes(error.message, constants.USER_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),

View File

@@ -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
}
]
},

View File

@@ -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.