From d621428a92c648dca8c688585992e78f61e85ea8 Mon Sep 17 00:00:00 2001 From: Richard Moore Date: Tue, 16 Aug 2022 16:23:58 -0400 Subject: [PATCH] Added ACTION_REJECTED error for UI-based Signers. --- packages/logger/src.ts/index.ts | 8 +++ .../providers/src.ts/json-rpc-provider.ts | 55 ++++++++++++++++--- 2 files changed, 56 insertions(+), 7 deletions(-) diff --git a/packages/logger/src.ts/index.ts b/packages/logger/src.ts/index.ts index 2531013c2d..7a1d0c3b70 100644 --- a/packages/logger/src.ts/index.ts +++ b/packages/logger/src.ts/index.ts @@ -146,6 +146,14 @@ export enum ErrorCode { // - replacement: the full TransactionsResponse for the replacement // - receipt: the receipt of the replacement TRANSACTION_REPLACED = "TRANSACTION_REPLACED", + + + /////////////////// + // Interaction Errors + + // The user rejected the action, such as signing a message or sending + // a transaction + ACTION_REJECTED = "ACTION_REJECTED", }; const HEX = "0123456789abcdef"; diff --git a/packages/providers/src.ts/json-rpc-provider.ts b/packages/providers/src.ts/json-rpc-provider.ts index 866e390d62..94e37e5889 100644 --- a/packages/providers/src.ts/json-rpc-provider.ts +++ b/packages/providers/src.ts/json-rpc-provider.ts @@ -255,6 +255,13 @@ export class JsonRpcSigner extends Signer implements TypedDataSigner { return this.provider.send("eth_sendTransaction", [ hexTx ]).then((hash) => { return hash; }, (error) => { + if (typeof(error.message) === "string" && error.message.match(/user denied/i)) { + logger.throwError("user rejected transaction", Logger.errors.ACTION_REJECTED, { + action: "sendTransaction", + transaction: tx + }); + } + return checkError("sendTransaction", error, hexTx); }); }); @@ -292,15 +299,38 @@ export class JsonRpcSigner extends Signer implements TypedDataSigner { const data = ((typeof(message) === "string") ? toUtf8Bytes(message): message); const address = await this.getAddress(); - return await this.provider.send("personal_sign", [ hexlify(data), address.toLowerCase() ]); + + try { + return await this.provider.send("personal_sign", [ hexlify(data), address.toLowerCase() ]); + } catch (error) { + if (typeof(error.message) === "string" && error.message.match(/user denied/i)) { + logger.throwError("user rejected signing", Logger.errors.ACTION_REJECTED, { + action: "signMessage", + from: address, + message: data + }); + } + throw error; + } } async _legacySignMessage(message: Bytes | string): Promise { const data = ((typeof(message) === "string") ? toUtf8Bytes(message): message); const address = await this.getAddress(); - // https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign - return await this.provider.send("eth_sign", [ address.toLowerCase(), hexlify(data) ]); + try { + // https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign + return await this.provider.send("eth_sign", [ address.toLowerCase(), hexlify(data) ]); + } catch (error) { + if (typeof(error.message) === "string" && error.message.match(/user denied/i)) { + logger.throwError("user rejected signing", Logger.errors.ACTION_REJECTED, { + action: "_legacySignMessage", + from: address, + message: data + }); + } + throw error; + } } async _signTypedData(domain: TypedDataDomain, types: Record>, value: Record): Promise { @@ -311,10 +341,21 @@ export class JsonRpcSigner extends Signer implements TypedDataSigner { const address = await this.getAddress(); - return await this.provider.send("eth_signTypedData_v4", [ - address.toLowerCase(), - JSON.stringify(_TypedDataEncoder.getPayload(populated.domain, types, populated.value)) - ]); + try { + return await this.provider.send("eth_signTypedData_v4", [ + address.toLowerCase(), + JSON.stringify(_TypedDataEncoder.getPayload(populated.domain, types, populated.value)) + ]); + } catch (error) { + if (typeof(error.message) === "string" && error.message.match(/user denied/i)) { + logger.throwError("user rejected signing", Logger.errors.ACTION_REJECTED, { + action: "_signTypedData", + from: address, + message: { domain: populated.domain, types, value: populated.value } + }); + } + throw error; + } } async unlock(password: string): Promise {