@rango-dev/signer-evm 0.5.1-next.5 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,14 @@
1
+ # [0.6.0](https://github.com/rango-exchange/rango-client/compare/signer-evm@0.5.0...signer-evm@0.6.0) (2023-07-11)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * better parsing of evm rpc errors ([f23031a](https://github.com/rango-exchange/rango-client/commit/f23031ae14e6e841ee488591bd1bf58cfa7ca15b))
7
+ * fix signer wait change network issues ([e453db6](https://github.com/rango-exchange/rango-client/commit/e453db6ccf7736e36e5ada0c29502be32254fe9c))
8
+ * show tenderly error on call exception ([c218f49](https://github.com/rango-exchange/rango-client/commit/c218f49f3330706d9262b0cf3ec8e293e91e3729))
9
+
10
+
11
+
1
12
  # [0.5.0](https://github.com/rango-exchange/rango-client/compare/signer-evm@0.4.0...signer-evm@0.5.0) (2023-05-31)
2
13
 
3
14
 
@@ -1 +1 @@
1
- {"version":3,"file":"helper.d.ts","sourceRoot":"","sources":["../src/helper.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,IAAI,eAAe,EAAE,MAAM,aAAa,CAAC;AAGlE,eAAO,MAAM,aAAa,UAAW,GAAG,KAAG,eAsB1C,CAAC;AAMF,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAc7B"}
1
+ {"version":3,"file":"helper.d.ts","sourceRoot":"","sources":["../src/helper.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,IAAI,eAAe,EAAE,MAAM,aAAa,CAAC;AAQlE,eAAO,MAAM,aAAa,UAAW,GAAG,KAAG,eAyF1C,CAAC;AAMF,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAc7B"}
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- var y=Object.defineProperty;var c=(t,r)=>y(t,"name",{value:r,configurable:!0});import{providers as E}from"ethers";import{SignerError as f,SignerErrorCode as u}from"rango-types";var h=c(t=>{let r;if(t&&Object.prototype.hasOwnProperty.call(t,"message")&&Object.prototype.hasOwnProperty.call(t,"code")&&Object.prototype.hasOwnProperty.call(t,"reason"))r=`Error sending the tx (code: ${t.code})`;else if(t&&Object.prototype.hasOwnProperty.call(t,"code")&&Object.prototype.hasOwnProperty.call(t,"message")&&t?.code===-32603)return new f(u.SEND_TX_ERROR,void 0,t.message);return new f(u.SEND_TX_ERROR,r,t)},"cleanEvmError");async function w(t,r){if(!t||!r)return;let n=parseInt(t);try{let e=`https://api.tenderly.co/api/v1/public-contract/${n}/tx/${r}`,s=await fetch(e,{method:"GET"});return s.ok?(await s.json())?.error_message:void 0}catch{return}}c(w,"getTenderlyError");import{SignerError as g,SignerErrorCode as d}from"rango-types";var P=c(t=>new Promise(r=>setTimeout(r,t)),"waitMs"),R=c(async(t,r,n,e)=>{let s=!1;return await Promise.race([(async()=>{await r.wait(e),s=!0})(),(async()=>{for(;!s;){if(await P(3e3),s)return null;try{if(!await t.getTransaction(n))return null}catch(o){return console.log({error:o}),null}}return null})()])},"waitWithMempoolCheck"),p=class{constructor(r){this.provider=new E.Web3Provider(r),this.signer=this.provider.getSigner()}async signMessage(r){try{return await this.signer.signMessage(r)}catch(n){throw new g(d.SIGN_TX_ERROR,void 0,n)}}async signAndSendTx(r,n,e){try{this.signer=this.provider.getSigner(r.from??void 0);let s=p.buildTx(r),o=await this.signer.getChainId(),i=await this.signer.getAddress();if(e&&o&&o!==parseInt(e))throw new g(d.UNEXPECTED_BEHAVIOUR,`Signer chainId: '${o}' doesn't match with required chainId: '${e}' for tx.`);if(i&&n&&i.toLowerCase()!==n.toLowerCase())throw new g(d.UNEXPECTED_BEHAVIOUR,`Signer address: '${i.toLowerCase()}' doesn't match with required address: '${n.toLowerCase()}' for tx.`);try{let a=await this.signer.sendTransaction(s);return{hash:a.hash,response:a}}catch(a){if(a?.message&&typeof a.message=="string"&&a.message.indexOf("EIP-1559")!==-1){console.log("retrying EIP-1559 error without v2 fields ...");let m=p.buildTx(r,!0),l=await this.signer.sendTransaction(m);return{hash:l.hash,response:l}}else throw a}}catch(s){throw h(s)}}async wait(r,n,e,s){try{if(e)return await e?.wait(s),{hash:r};if(!this.provider)return{hash:r};if(this.signer=this.provider.getSigner(),!n)return{hash:r};let o=await this.signer.getChainId();if(!o||parseInt(n)!=o)return{hash:r};let i=await this.provider.getTransaction(r);if(!i)throw Error(`Transaction hash '${r}' not found in blockchain.`);return await R(this.provider,i,r,s),{hash:r}}catch(o){let i=o;if(i?.code==="TRANSACTION_REPLACED"&&i?.replacement)return{hash:i?.replacement?.hash,response:i?.replacement};if(i?.code==="CALL_EXCEPTION"){let a=await w(n,r);if(a)throw new g(d.SEND_TX_ERROR,"Trannsaction failed in blockchain",a)}throw h(i)}}static buildTx(r,n=!1){let e={};return r.from&&(e={...e,from:r.from}),r.to&&(e={...e,to:r.to}),r.data&&(e={...e,data:r.data}),r.value&&(e={...e,value:r.value}),r.nonce&&(e={...e,nonce:r.nonce}),r.gasLimit&&(e={...e,gasLimit:r.gasLimit}),r.gasPrice&&(e={...e,gasPrice:"0x"+parseInt(r.gasPrice).toString(16)}),r.maxFeePerGas&&!n&&(e={...e,maxFeePerGas:r.maxFeePerGas}),r.maxPriorityFeePerGas&&!n&&(e={...e,maxPriorityFeePerGas:r.maxPriorityFeePerGas}),e}};c(p,"DefaultEvmSigner");export{p as DefaultEvmSigner};
1
+ var T=Object.defineProperty;var E=(n,e)=>T(n,"name",{value:e,configurable:!0});import{providers as O}from"ethers";import{getMessageFromCode as m}from"eth-rpc-errors";import{RPCErrorCode as u,SignerError as c,SignerErrorCode as d}from"rango-types";var R={rpc:{invalidInput:-32e3,resourceNotFound:-32001,resourceUnavailable:-32002,transactionRejected:-32003,methodNotSupported:-32004,limitExceeded:-32005,parse:-32700,invalidRequest:-32600,methodNotFound:-32601,invalidParams:-32602,internal:-32603},provider:{userRejectedRequest:4001,unauthorized:4100,unsupportedMethod:4200,disconnected:4900,chainDisconnected:4901}};var f=E(n=>{if(!n)return new c(d.SEND_TX_ERROR);if(c.isSignerError(n))return n;let e=Object.prototype.hasOwnProperty.call(n,"message"),i=Object.prototype.hasOwnProperty.call(n,"code");if(e&&i){let{message:r,code:t}=n;if("ACTION_REJECTED"===t||R.provider.userRejectedRequest===t)return new c(d.REJECTED_BY_USER,void 0,n,u.REJECTION,n);if(typeof t=="number"){if(Object.values(R.provider).includes(t)){let s=m(t);return new c(d.SEND_TX_ERROR,void 0,s,u.UNKNOWN_ERROR,n)}else if(Object.values(R.rpc).includes(t)){if(t===R.rpc.internal&&(r?.includes("underpriced")||r?.includes("replacement fee too low")))return new c(d.SEND_TX_ERROR,void 0,"Transaction is underpriced.",u.UNDER_PRICED,n);if(r?.includes("intrinsic gas too low")||r?.includes("out of gas"))return new c(d.SEND_TX_ERROR,void 0,"Gas limit is low.",u.OUT_OF_GAS,n);let s=m(t);return new c(d.SEND_TX_ERROR,void 0,s??n,u.UNKNOWN_ERROR,n)}}switch(t){case"INVALID_ARGUMENT":{let s=(n.reason||n.message)??n;return new c(d.SEND_TX_ERROR,void 0,s,u.UNKNOWN_ERROR,n)}}}return new c(d.SEND_TX_ERROR,void 0,n,u.UNKNOWN_ERROR,n)},"cleanEvmError");async function N(n,e){if(!n||!e)return;let i=parseInt(n);try{let r=`https://api.tenderly.co/api/v1/public-contract/${i}/tx/${e}`,t=await fetch(r,{method:"GET"});return t.ok?(await t.json())?.error_message:void 0}catch{return}}E(N,"getTenderlyError");import{RPCErrorCode as C,SignerError as g,SignerErrorCode as h}from"rango-types";var I=E(n=>new Promise(e=>setTimeout(e,n)),"waitMs"),S=E(async(n,e,i,r)=>{let t=!1;return await Promise.race([(async()=>{await e.wait(r),t=!0})(),(async()=>{for(;!t;){if(await I(3e3),t)return null;try{if(!await n.getTransaction(i))return null}catch(s){return console.log({error:s}),null}}return null})()])},"waitWithMempoolCheck"),p=class{constructor(e){this.provider=new O.Web3Provider(e),this.signer=this.provider.getSigner()}async signMessage(e){try{return await this.signer.signMessage(e)}catch(i){throw new g(h.SIGN_TX_ERROR,void 0,i)}}async signAndSendTx(e,i,r){try{this.signer=this.provider.getSigner(e.from??void 0);let t=p.buildTx(e),s=await this.signer.getChainId(),o=await this.signer.getAddress();if(r&&s&&s!==parseInt(r))throw new g(h.UNEXPECTED_BEHAVIOUR,void 0,`Signer chainId: '${s}' doesn't match with required chainId: '${r}' for tx.`);if(o&&i&&o.toLowerCase()!==i.toLowerCase())throw new g(h.UNEXPECTED_BEHAVIOUR,void 0,`Signer address: '${o.toLowerCase()}' doesn't match with required address: '${i.toLowerCase()}' for tx.`);try{let a=await this.signer.sendTransaction(t);return{hash:a.hash,response:a}}catch(a){if(a?.message&&typeof a.message=="string"&&a.message.indexOf("EIP-1559")!==-1){console.log("retrying EIP-1559 error without v2 fields ...");let _=p.buildTx(e,!0),l=await this.signer.sendTransaction(_);return{hash:l.hash,response:l}}else throw a}}catch(t){throw f(t)}}async wait(e,i,r,t){try{if(r)return await r?.wait(t),{hash:e};if(!this.provider)return{hash:e};if(this.signer=this.provider.getSigner(),!i)return{hash:e};let s=await this.signer.getChainId();if(!s||parseInt(i)!=s)return{hash:e};let o=await this.provider.getTransaction(e);if(!o)throw Error(`Transaction hash '${e}' not found in blockchain.`);return await S(this.provider,o,e,t),{hash:e}}catch(s){let o=s;if(o?.code==="TRANSACTION_REPLACED"&&o?.replacement)return{hash:o?.replacement?.hash,response:o?.replacement};if(o?.code==="CALL_EXCEPTION"){let a=await N(i,e);if(a)throw new g(h.TX_FAILED_IN_BLOCKCHAIN,"Trannsaction failed in blockchain",a,C.CALL_EXCEPTION,o);return{hash:e}}throw f(o)}}static buildTx(e,i=!1){let r={};return e.from&&(r={...r,from:e.from}),e.to&&(r={...r,to:e.to}),e.data&&(r={...r,data:e.data}),e.value&&(r={...r,value:e.value}),e.nonce&&(r={...r,nonce:e.nonce}),e.gasLimit&&(r={...r,gasLimit:e.gasLimit}),e.gasPrice&&(r={...r,gasPrice:"0x"+parseInt(e.gasPrice).toString(16)}),e.maxFeePerGas&&!i&&(r={...r,maxFeePerGas:e.maxFeePerGas}),e.maxPriorityFeePerGas&&!i&&(r={...r,maxPriorityFeePerGas:e.maxPriorityFeePerGas}),r}};E(p,"DefaultEvmSigner");export{p as DefaultEvmSigner};
2
2
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/signer.ts", "../src/helper.ts"],
4
- "sourcesContent": ["import {\n TransactionRequest,\n TransactionResponse,\n} from '@ethersproject/abstract-provider';\nimport type { GenericSigner } from 'rango-types';\nimport { EvmTransaction } from 'rango-types/lib/api/main';\nimport { providers } from 'ethers';\nimport { cleanEvmError, getTenderlyError } from './helper';\nimport { SignerError, SignerErrorCode } from 'rango-types';\n\nconst waitMs = (ms: number) =>\n new Promise((resolve) => setTimeout(resolve, ms));\n\nconst waitWithMempoolCheck = async (\n provider: providers.Web3Provider,\n tx: TransactionResponse,\n txHash: string,\n confirmations?: number\n) => {\n let finished = false;\n return await Promise.race([\n (async () => {\n await tx.wait(confirmations);\n finished = true;\n })(),\n (async () => {\n while (!finished) {\n await waitMs(3_000);\n if (finished) return null;\n try {\n const mempoolTx = await provider.getTransaction(txHash);\n if (!mempoolTx) return null;\n } catch (error) {\n console.log({ error });\n return null;\n }\n }\n return null;\n })(),\n ]);\n};\n\nexport class DefaultEvmSigner implements GenericSigner<EvmTransaction> {\n private signer: providers.JsonRpcSigner;\n private provider: providers.Web3Provider;\n\n constructor(provider: providers.ExternalProvider) {\n this.provider = new providers.Web3Provider(provider);\n this.signer = this.provider.getSigner();\n }\n\n async signMessage(msg: string): Promise<string> {\n try {\n return await this.signer.signMessage(msg);\n } catch (error) {\n throw new SignerError(SignerErrorCode.SIGN_TX_ERROR, undefined, error);\n }\n }\n\n async signAndSendTx(\n tx: EvmTransaction,\n address: string,\n chainId: string | null\n ): Promise<{ hash: string; response: TransactionResponse }> {\n try {\n this.signer = this.provider.getSigner(tx.from ?? undefined);\n const transaction = DefaultEvmSigner.buildTx(tx);\n const signerChainId = await this.signer.getChainId();\n const signerAddress = await this.signer.getAddress();\n if (!!chainId && !!signerChainId && signerChainId !== parseInt(chainId)) {\n throw new SignerError(\n SignerErrorCode.UNEXPECTED_BEHAVIOUR,\n `Signer chainId: '${signerChainId}' doesn't match with required chainId: '${chainId}' for tx.`\n );\n }\n if (\n !!signerAddress &&\n !!address &&\n signerAddress.toLowerCase() !== address.toLowerCase()\n ) {\n throw new SignerError(\n SignerErrorCode.UNEXPECTED_BEHAVIOUR,\n `Signer address: '${signerAddress.toLowerCase()}' doesn't match with required address: '${address.toLowerCase()}' for tx.`\n );\n }\n try {\n const response = await this.signer.sendTransaction(transaction);\n return { hash: response.hash, response };\n } catch (error: any) {\n // retrying EIP-1559 without v2 related fields\n if (\n !!error?.message &&\n typeof error.message === 'string' &&\n error.message.indexOf('EIP-1559') !== -1\n ) {\n console.log('retrying EIP-1559 error without v2 fields ...');\n const transaction = DefaultEvmSigner.buildTx(tx, true);\n const response = await this.signer.sendTransaction(transaction);\n return { hash: response.hash, response };\n } else {\n throw error;\n }\n }\n } catch (error) {\n throw cleanEvmError(error);\n }\n }\n\n async wait(\n txHash: string,\n chainId?: string,\n txResponse?: TransactionResponse,\n confirmations?: number\n ): Promise<{ hash: string; response?: TransactionResponse }> {\n try {\n // if we have transaction response, use that to wait\n // otherwise, try to get tx response from the wallet provider\n if (txResponse) {\n // if we use waitWithMempoolCheck here, we can't detect replaced tx anymore\n await txResponse?.wait(confirmations);\n return { hash: txHash };\n }\n\n // ignore wait if wallet not connected yet\n if (!this.provider) return { hash: txHash };\n this.signer = this.provider.getSigner();\n\n // don't proceed if signer chain changed or chain id is not specified\n // because if user change the wallet network, we receive null on getTransaction\n if (!chainId) return { hash: txHash };\n const signerChainId = await this.signer.getChainId();\n if (!signerChainId || parseInt(chainId) != signerChainId)\n return { hash: txHash };\n\n const tx = await this.provider.getTransaction(txHash);\n if (!tx)\n throw Error(`Transaction hash '${txHash}' not found in blockchain.`);\n\n await waitWithMempoolCheck(this.provider, tx, txHash, confirmations);\n return { hash: txHash };\n } catch (err) {\n const error = err as any; // TODO find a proper type\n if (error?.code === 'TRANSACTION_REPLACED' && error?.replacement)\n return { hash: error?.replacement?.hash, response: error?.replacement };\n else if (error?.code === 'CALL_EXCEPTION') {\n const tError = await getTenderlyError(chainId, txHash);\n if (!!tError)\n // TODO different Signer Error Code\n throw new SignerError(\n SignerErrorCode.SEND_TX_ERROR,\n 'Trannsaction failed in blockchain',\n tError\n );\n }\n throw cleanEvmError(error);\n }\n }\n\n static buildTx(evmTx: EvmTransaction, disableV2 = false): TransactionRequest {\n let tx: TransactionRequest = {};\n if (evmTx.from) tx = { ...tx, from: evmTx.from };\n if (evmTx.to) tx = { ...tx, to: evmTx.to };\n if (evmTx.data) tx = { ...tx, data: evmTx.data };\n if (evmTx.value) tx = { ...tx, value: evmTx.value };\n if (evmTx.nonce) tx = { ...tx, nonce: evmTx.nonce };\n if (evmTx.gasLimit) tx = { ...tx, gasLimit: evmTx.gasLimit };\n if (evmTx.gasPrice)\n tx = {\n ...tx,\n gasPrice: '0x' + parseInt(evmTx.gasPrice).toString(16),\n };\n if (evmTx.maxFeePerGas && !disableV2)\n tx = { ...tx, maxFeePerGas: evmTx.maxFeePerGas };\n if (evmTx.maxPriorityFeePerGas && !disableV2)\n tx = { ...tx, maxPriorityFeePerGas: evmTx.maxPriorityFeePerGas };\n return tx;\n }\n}\n", "import type { SignerError as SignerErrorType } from 'rango-types';\nimport { SignerError, SignerErrorCode } from 'rango-types';\n\nexport const cleanEvmError = (error: any): SignerErrorType => {\n let message = undefined;\n if (\n error &&\n Object.prototype.hasOwnProperty.call(error, 'message') &&\n Object.prototype.hasOwnProperty.call(error, 'code') &&\n Object.prototype.hasOwnProperty.call(error, 'reason')\n ) {\n message = `Error sending the tx (code: ${(error as any).code})`;\n } else if (\n error &&\n Object.prototype.hasOwnProperty.call(error, 'code') &&\n Object.prototype.hasOwnProperty.call(error, 'message') &&\n (error as any)?.code === -32603\n ) {\n return new SignerError(\n SignerErrorCode.SEND_TX_ERROR,\n undefined,\n (error as any).message\n );\n }\n return new SignerError(SignerErrorCode.SEND_TX_ERROR, message, error);\n};\n\ninterface TenderlyResponse {\n error_message: string;\n}\n\nexport async function getTenderlyError(\n chainId: string | undefined,\n txHash: string\n): Promise<string | undefined> {\n if (!chainId || !txHash) return;\n const chainIdInt = parseInt(chainId);\n try {\n const url = `https://api.tenderly.co/api/v1/public-contract/${chainIdInt}/tx/${txHash}`;\n const response = await fetch(url, {\n method: 'GET',\n });\n if (!response.ok) return;\n const data: TenderlyResponse = await response.json();\n return data?.error_message;\n } catch (error) {\n return;\n }\n}\n"],
5
- "mappings": "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",
6
- "names": ["providers", "SignerError", "SignerErrorCode", "cleanEvmError", "__name", "error", "message", "SignerError", "SignerErrorCode", "getTenderlyError", "chainId", "txHash", "chainIdInt", "url", "response", "SignerError", "SignerErrorCode", "waitMs", "__name", "ms", "resolve", "waitWithMempoolCheck", "provider", "tx", "txHash", "confirmations", "finished", "error", "DefaultEvmSigner", "providers", "msg", "SignerError", "SignerErrorCode", "address", "chainId", "transaction", "signerChainId", "signerAddress", "response", "cleanEvmError", "txResponse", "err", "tError", "getTenderlyError", "evmTx", "disableV2"]
3
+ "sources": ["../src/signer.ts", "../src/helper.ts", "../src/types.ts"],
4
+ "sourcesContent": ["import {\n TransactionRequest,\n TransactionResponse,\n} from '@ethersproject/abstract-provider';\nimport type { GenericSigner } from 'rango-types';\nimport { EvmTransaction } from 'rango-types/lib/api/main';\nimport { providers } from 'ethers';\nimport { cleanEvmError, getTenderlyError } from './helper';\nimport {\n RPCErrorCode as RangoRPCErrorCode,\n SignerError,\n SignerErrorCode,\n} from 'rango-types';\nimport { RPCErrorCode } from './types';\n\nconst waitMs = (ms: number) =>\n new Promise((resolve) => setTimeout(resolve, ms));\n\nconst waitWithMempoolCheck = async (\n provider: providers.Web3Provider,\n tx: TransactionResponse,\n txHash: string,\n confirmations?: number\n) => {\n let finished = false;\n return await Promise.race([\n (async () => {\n await tx.wait(confirmations);\n finished = true;\n })(),\n (async () => {\n while (!finished) {\n await waitMs(3_000);\n if (finished) return null;\n try {\n const mempoolTx = await provider.getTransaction(txHash);\n if (!mempoolTx) return null;\n } catch (error) {\n console.log({ error });\n return null;\n }\n }\n return null;\n })(),\n ]);\n};\n\nexport class DefaultEvmSigner implements GenericSigner<EvmTransaction> {\n private signer: providers.JsonRpcSigner;\n private provider: providers.Web3Provider;\n\n constructor(provider: providers.ExternalProvider) {\n this.provider = new providers.Web3Provider(provider);\n this.signer = this.provider.getSigner();\n }\n\n async signMessage(msg: string): Promise<string> {\n try {\n return await this.signer.signMessage(msg);\n } catch (error) {\n throw new SignerError(SignerErrorCode.SIGN_TX_ERROR, undefined, error);\n }\n }\n\n async signAndSendTx(\n tx: EvmTransaction,\n address: string,\n chainId: string | null\n ): Promise<{ hash: string; response: TransactionResponse }> {\n try {\n this.signer = this.provider.getSigner(tx.from ?? undefined);\n const transaction = DefaultEvmSigner.buildTx(tx);\n const signerChainId = await this.signer.getChainId();\n const signerAddress = await this.signer.getAddress();\n if (!!chainId && !!signerChainId && signerChainId !== parseInt(chainId)) {\n throw new SignerError(\n SignerErrorCode.UNEXPECTED_BEHAVIOUR,\n undefined,\n `Signer chainId: '${signerChainId}' doesn't match with required chainId: '${chainId}' for tx.`\n );\n }\n if (\n !!signerAddress &&\n !!address &&\n signerAddress.toLowerCase() !== address.toLowerCase()\n ) {\n throw new SignerError(\n SignerErrorCode.UNEXPECTED_BEHAVIOUR,\n undefined,\n `Signer address: '${signerAddress.toLowerCase()}' doesn't match with required address: '${address.toLowerCase()}' for tx.`\n );\n }\n try {\n const response = await this.signer.sendTransaction(transaction);\n return { hash: response.hash, response };\n } catch (error: any) {\n // retrying EIP-1559 without v2 related fields\n if (\n !!error?.message &&\n typeof error.message === 'string' &&\n error.message.indexOf('EIP-1559') !== -1\n ) {\n console.log('retrying EIP-1559 error without v2 fields ...');\n const transaction = DefaultEvmSigner.buildTx(tx, true);\n const response = await this.signer.sendTransaction(transaction);\n return { hash: response.hash, response };\n } else {\n throw error;\n }\n }\n } catch (error) {\n throw cleanEvmError(error);\n }\n }\n\n async wait(\n txHash: string,\n chainId?: string,\n txResponse?: TransactionResponse,\n confirmations?: number\n ): Promise<{ hash: string; response?: TransactionResponse }> {\n try {\n // if we have transaction response, use that to wait\n // otherwise, try to get tx response from the wallet provider\n if (txResponse) {\n // if we use waitWithMempoolCheck here, we can't detect replaced tx anymore\n await txResponse?.wait(confirmations);\n return { hash: txHash };\n }\n\n // ignore wait if wallet not connected yet\n if (!this.provider) return { hash: txHash };\n this.signer = this.provider.getSigner();\n\n // don't proceed if signer chain changed or chain id is not specified\n // because if user change the wallet network, we receive null on getTransaction\n if (!chainId) return { hash: txHash };\n const signerChainId = await this.signer.getChainId();\n if (!signerChainId || parseInt(chainId) != signerChainId)\n return { hash: txHash };\n\n const tx = await this.provider.getTransaction(txHash);\n if (!tx)\n throw Error(`Transaction hash '${txHash}' not found in blockchain.`);\n\n await waitWithMempoolCheck(this.provider, tx, txHash, confirmations);\n return { hash: txHash };\n } catch (err) {\n const error = err as any; // TODO find a proper type\n if (\n error?.code === RPCErrorCode.TRANSACTION_REPLACED &&\n error?.replacement\n )\n return { hash: error?.replacement?.hash, response: error?.replacement };\n else if (error?.code === RPCErrorCode.CALL_EXCEPTION) {\n const tError = await getTenderlyError(chainId, txHash);\n if (!!tError) {\n throw new SignerError(\n SignerErrorCode.TX_FAILED_IN_BLOCKCHAIN,\n 'Trannsaction failed in blockchain',\n tError,\n RangoRPCErrorCode.CALL_EXCEPTION,\n error\n );\n } else {\n /**\n * In cases where the is no error returen from tenderly, we could ignore\n * the error and proceed with check status flow.\n * */\n return { hash: txHash };\n }\n }\n throw cleanEvmError(error);\n }\n }\n\n static buildTx(evmTx: EvmTransaction, disableV2 = false): TransactionRequest {\n let tx: TransactionRequest = {};\n if (evmTx.from) tx = { ...tx, from: evmTx.from };\n if (evmTx.to) tx = { ...tx, to: evmTx.to };\n if (evmTx.data) tx = { ...tx, data: evmTx.data };\n if (evmTx.value) tx = { ...tx, value: evmTx.value };\n if (evmTx.nonce) tx = { ...tx, nonce: evmTx.nonce };\n if (evmTx.gasLimit) tx = { ...tx, gasLimit: evmTx.gasLimit };\n if (evmTx.gasPrice)\n tx = {\n ...tx,\n gasPrice: '0x' + parseInt(evmTx.gasPrice).toString(16),\n };\n if (evmTx.maxFeePerGas && !disableV2)\n tx = { ...tx, maxFeePerGas: evmTx.maxFeePerGas };\n if (evmTx.maxPriorityFeePerGas && !disableV2)\n tx = { ...tx, maxPriorityFeePerGas: evmTx.maxPriorityFeePerGas };\n return tx;\n }\n}\n", "import { getMessageFromCode } from 'eth-rpc-errors';\nimport type { SignerError as SignerErrorType } from 'rango-types';\nimport {\n RPCErrorCode as RangoRPCErrorCode,\n SignerError,\n SignerErrorCode,\n} from 'rango-types';\nimport { MetamaskErrorCodes, RPCErrorCode, RPCErrorMessage } from './types';\n\nexport const cleanEvmError = (error: any): SignerErrorType => {\n if (!error) return new SignerError(SignerErrorCode.SEND_TX_ERROR);\n if (SignerError.isSignerError(error)) return error;\n const hasMessage = Object.prototype.hasOwnProperty.call(error, 'message');\n const hasCode = Object.prototype.hasOwnProperty.call(error, 'code');\n if (hasMessage && hasCode) {\n const { message: errorMessage, code: errorCode } = error;\n // rejection error\n if (\n RPCErrorCode.ACTION_REJECTED === errorCode ||\n MetamaskErrorCodes.provider.userRejectedRequest === errorCode\n )\n return new SignerError(\n SignerErrorCode.REJECTED_BY_USER,\n undefined,\n error,\n RangoRPCErrorCode.REJECTION,\n error\n );\n if (typeof errorCode === 'number') {\n // provider errors\n if (Object.values(MetamaskErrorCodes.provider).includes(errorCode)) {\n const msg = getMessageFromCode(errorCode);\n return new SignerError(\n SignerErrorCode.SEND_TX_ERROR,\n undefined,\n msg,\n RangoRPCErrorCode.UNKNOWN_ERROR,\n error\n );\n }\n // rpc errors\n else if (Object.values(MetamaskErrorCodes.rpc).includes(errorCode)) {\n // underpriced errors are sent as internal errors\n if (\n errorCode === MetamaskErrorCodes.rpc.internal &&\n (errorMessage?.includes(RPCErrorMessage.UNDER_PRICED) ||\n errorMessage?.includes(RPCErrorMessage.REPLACEMENT_FEE_TOO_LOW))\n )\n return new SignerError(\n SignerErrorCode.SEND_TX_ERROR,\n undefined,\n 'Transaction is underpriced.',\n RangoRPCErrorCode.UNDER_PRICED,\n error\n );\n // gas limit errors are sent as internal errors\n if (\n errorMessage?.includes(RPCErrorMessage.INTRINSIC_GAS_TOO_LOW) ||\n errorMessage?.includes(RPCErrorMessage.OUT_OF_GAS)\n )\n return new SignerError(\n SignerErrorCode.SEND_TX_ERROR,\n undefined,\n 'Gas limit is low.',\n RangoRPCErrorCode.OUT_OF_GAS,\n error\n );\n\n const msg = getMessageFromCode(errorCode);\n return new SignerError(\n SignerErrorCode.SEND_TX_ERROR,\n undefined,\n msg ?? error,\n RangoRPCErrorCode.UNKNOWN_ERROR,\n error\n );\n }\n }\n switch (errorCode) {\n case RPCErrorCode.INVALID_ARGUMENT: {\n const msg = (error.reason || error.message) ?? error;\n return new SignerError(\n SignerErrorCode.SEND_TX_ERROR,\n undefined,\n msg,\n RangoRPCErrorCode.UNKNOWN_ERROR,\n error\n );\n }\n }\n }\n return new SignerError(\n SignerErrorCode.SEND_TX_ERROR,\n undefined,\n error,\n RangoRPCErrorCode.UNKNOWN_ERROR,\n error\n );\n};\n\ninterface TenderlyResponse {\n error_message: string;\n}\n\nexport async function getTenderlyError(\n chainId: string | undefined,\n txHash: string\n): Promise<string | undefined> {\n if (!chainId || !txHash) return;\n const chainIdInt = parseInt(chainId);\n try {\n const url = `https://api.tenderly.co/api/v1/public-contract/${chainIdInt}/tx/${txHash}`;\n const response = await fetch(url, {\n method: 'GET',\n });\n if (!response.ok) return;\n const data: TenderlyResponse = await response.json();\n return data?.error_message;\n } catch (error) {\n return;\n }\n}\n", "export const MetamaskErrorCodes = {\n rpc: {\n invalidInput: -32000,\n resourceNotFound: -32001,\n resourceUnavailable: -32002,\n transactionRejected: -32003,\n methodNotSupported: -32004,\n limitExceeded: -32005,\n parse: -32700,\n invalidRequest: -32600,\n methodNotFound: -32601,\n invalidParams: -32602,\n internal: -32603,\n },\n provider: {\n userRejectedRequest: 4001,\n unauthorized: 4100,\n unsupportedMethod: 4200,\n disconnected: 4900,\n chainDisconnected: 4901,\n },\n};\n\nexport enum RPCErrorCode {\n ACTION_REJECTED = 'ACTION_REJECTED',\n INVALID_ARGUMENT = 'INVALID_ARGUMENT',\n CALL_EXCEPTION = 'CALL_EXCEPTION',\n INSUFFICIENT_FUNDS = 'INSUFFICIENT_FUNDS',\n TRANSACTION_REPLACED = 'TRANSACTION_REPLACED',\n}\n\nexport enum RPCErrorMessage {\n UNDER_PRICED = 'underpriced',\n REPLACEMENT_FEE_TOO_LOW = 'replacement fee too low',\n INTRINSIC_GAS_TOO_LOW = 'intrinsic gas too low',\n OUT_OF_GAS = 'out of gas',\n INTERNAL_ERROR = 'Internal JSON-RPC error',\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["providers", "getMessageFromCode", "RangoRPCErrorCode", "SignerError", "SignerErrorCode", "MetamaskErrorCodes", "cleanEvmError", "__name", "error", "SignerError", "SignerErrorCode", "hasMessage", "hasCode", "errorMessage", "errorCode", "MetamaskErrorCodes", "RangoRPCErrorCode", "msg", "getMessageFromCode", "getTenderlyError", "chainId", "txHash", "chainIdInt", "url", "response", "RangoRPCErrorCode", "SignerError", "SignerErrorCode", "waitMs", "__name", "ms", "resolve", "waitWithMempoolCheck", "provider", "tx", "txHash", "confirmations", "finished", "error", "DefaultEvmSigner", "providers", "msg", "SignerError", "SignerErrorCode", "address", "chainId", "transaction", "signerChainId", "signerAddress", "response", "cleanEvmError", "txResponse", "err", "tError", "getTenderlyError", "RangoRPCErrorCode", "evmTx", "disableV2"]
7
7
  }
@@ -1 +1 @@
1
- {"version":3,"file":"signer.d.ts","sourceRoot":"","sources":["../src/signer.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACpB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAoCnC,qBAAa,gBAAiB,YAAW,aAAa,CAAC,cAAc,CAAC;IACpE,OAAO,CAAC,MAAM,CAA0B;IACxC,OAAO,CAAC,QAAQ,CAAyB;gBAE7B,QAAQ,EAAE,SAAS,CAAC,gBAAgB;IAK1C,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAQzC,aAAa,CACjB,EAAE,EAAE,cAAc,EAClB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,GAAG,IAAI,GACrB,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,mBAAmB,CAAA;KAAE,CAAC;IA6CrD,IAAI,CACR,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,MAAM,EAChB,UAAU,CAAC,EAAE,mBAAmB,EAChC,aAAa,CAAC,EAAE,MAAM,GACrB,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,mBAAmB,CAAA;KAAE,CAAC;IA6C5D,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,cAAc,EAAE,SAAS,UAAQ,GAAG,kBAAkB;CAmB7E"}
1
+ {"version":3,"file":"signer.d.ts","sourceRoot":"","sources":["../src/signer.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACpB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAyCnC,qBAAa,gBAAiB,YAAW,aAAa,CAAC,cAAc,CAAC;IACpE,OAAO,CAAC,MAAM,CAA0B;IACxC,OAAO,CAAC,QAAQ,CAAyB;gBAE7B,QAAQ,EAAE,SAAS,CAAC,gBAAgB;IAK1C,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAQzC,aAAa,CACjB,EAAE,EAAE,cAAc,EAClB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,GAAG,IAAI,GACrB,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,mBAAmB,CAAA;KAAE,CAAC;IA+CrD,IAAI,CACR,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,MAAM,EAChB,UAAU,CAAC,EAAE,mBAAmB,EAChC,aAAa,CAAC,EAAE,MAAM,GACrB,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,mBAAmB,CAAA;KAAE,CAAC;IAwD5D,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,cAAc,EAAE,SAAS,UAAQ,GAAG,kBAAkB;CAmB7E"}
@@ -0,0 +1,37 @@
1
+ export declare const MetamaskErrorCodes: {
2
+ rpc: {
3
+ invalidInput: number;
4
+ resourceNotFound: number;
5
+ resourceUnavailable: number;
6
+ transactionRejected: number;
7
+ methodNotSupported: number;
8
+ limitExceeded: number;
9
+ parse: number;
10
+ invalidRequest: number;
11
+ methodNotFound: number;
12
+ invalidParams: number;
13
+ internal: number;
14
+ };
15
+ provider: {
16
+ userRejectedRequest: number;
17
+ unauthorized: number;
18
+ unsupportedMethod: number;
19
+ disconnected: number;
20
+ chainDisconnected: number;
21
+ };
22
+ };
23
+ export declare enum RPCErrorCode {
24
+ ACTION_REJECTED = "ACTION_REJECTED",
25
+ INVALID_ARGUMENT = "INVALID_ARGUMENT",
26
+ CALL_EXCEPTION = "CALL_EXCEPTION",
27
+ INSUFFICIENT_FUNDS = "INSUFFICIENT_FUNDS",
28
+ TRANSACTION_REPLACED = "TRANSACTION_REPLACED"
29
+ }
30
+ export declare enum RPCErrorMessage {
31
+ UNDER_PRICED = "underpriced",
32
+ REPLACEMENT_FEE_TOO_LOW = "replacement fee too low",
33
+ INTRINSIC_GAS_TOO_LOW = "intrinsic gas too low",
34
+ OUT_OF_GAS = "out of gas",
35
+ INTERNAL_ERROR = "Internal JSON-RPC error"
36
+ }
37
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;CAqB9B,CAAC;AAEF,oBAAY,YAAY;IACtB,eAAe,oBAAoB;IACnC,gBAAgB,qBAAqB;IACrC,cAAc,mBAAmB;IACjC,kBAAkB,uBAAuB;IACzC,oBAAoB,yBAAyB;CAC9C;AAED,oBAAY,eAAe;IACzB,YAAY,gBAAgB;IAC5B,uBAAuB,4BAA4B;IACnD,qBAAqB,0BAA0B;IAC/C,UAAU,eAAe;IACzB,cAAc,4BAA4B;CAC3C"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rango-dev/signer-evm",
3
- "version": "0.5.1-next.5",
3
+ "version": "0.6.0",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "module": "./dist/index.js",
@@ -21,6 +21,7 @@
21
21
  },
22
22
  "dependencies": {
23
23
  "@ethersproject/abstract-provider": "^5.7.0",
24
+ "eth-rpc-errors": "^4.0.3",
24
25
  "ethers": "^5.7.2",
25
26
  "rango-types": "^0.1.45"
26
27
  },
package/src/helper.ts CHANGED
@@ -1,28 +1,101 @@
1
+ import { getMessageFromCode } from 'eth-rpc-errors';
1
2
  import type { SignerError as SignerErrorType } from 'rango-types';
2
- import { SignerError, SignerErrorCode } from 'rango-types';
3
+ import {
4
+ RPCErrorCode as RangoRPCErrorCode,
5
+ SignerError,
6
+ SignerErrorCode,
7
+ } from 'rango-types';
8
+ import { MetamaskErrorCodes, RPCErrorCode, RPCErrorMessage } from './types';
3
9
 
4
10
  export const cleanEvmError = (error: any): SignerErrorType => {
5
- let message = undefined;
6
- if (
7
- error &&
8
- Object.prototype.hasOwnProperty.call(error, 'message') &&
9
- Object.prototype.hasOwnProperty.call(error, 'code') &&
10
- Object.prototype.hasOwnProperty.call(error, 'reason')
11
- ) {
12
- message = `Error sending the tx (code: ${(error as any).code})`;
13
- } else if (
14
- error &&
15
- Object.prototype.hasOwnProperty.call(error, 'code') &&
16
- Object.prototype.hasOwnProperty.call(error, 'message') &&
17
- (error as any)?.code === -32603
18
- ) {
19
- return new SignerError(
20
- SignerErrorCode.SEND_TX_ERROR,
21
- undefined,
22
- (error as any).message
23
- );
11
+ if (!error) return new SignerError(SignerErrorCode.SEND_TX_ERROR);
12
+ if (SignerError.isSignerError(error)) return error;
13
+ const hasMessage = Object.prototype.hasOwnProperty.call(error, 'message');
14
+ const hasCode = Object.prototype.hasOwnProperty.call(error, 'code');
15
+ if (hasMessage && hasCode) {
16
+ const { message: errorMessage, code: errorCode } = error;
17
+ // rejection error
18
+ if (
19
+ RPCErrorCode.ACTION_REJECTED === errorCode ||
20
+ MetamaskErrorCodes.provider.userRejectedRequest === errorCode
21
+ )
22
+ return new SignerError(
23
+ SignerErrorCode.REJECTED_BY_USER,
24
+ undefined,
25
+ error,
26
+ RangoRPCErrorCode.REJECTION,
27
+ error
28
+ );
29
+ if (typeof errorCode === 'number') {
30
+ // provider errors
31
+ if (Object.values(MetamaskErrorCodes.provider).includes(errorCode)) {
32
+ const msg = getMessageFromCode(errorCode);
33
+ return new SignerError(
34
+ SignerErrorCode.SEND_TX_ERROR,
35
+ undefined,
36
+ msg,
37
+ RangoRPCErrorCode.UNKNOWN_ERROR,
38
+ error
39
+ );
40
+ }
41
+ // rpc errors
42
+ else if (Object.values(MetamaskErrorCodes.rpc).includes(errorCode)) {
43
+ // underpriced errors are sent as internal errors
44
+ if (
45
+ errorCode === MetamaskErrorCodes.rpc.internal &&
46
+ (errorMessage?.includes(RPCErrorMessage.UNDER_PRICED) ||
47
+ errorMessage?.includes(RPCErrorMessage.REPLACEMENT_FEE_TOO_LOW))
48
+ )
49
+ return new SignerError(
50
+ SignerErrorCode.SEND_TX_ERROR,
51
+ undefined,
52
+ 'Transaction is underpriced.',
53
+ RangoRPCErrorCode.UNDER_PRICED,
54
+ error
55
+ );
56
+ // gas limit errors are sent as internal errors
57
+ if (
58
+ errorMessage?.includes(RPCErrorMessage.INTRINSIC_GAS_TOO_LOW) ||
59
+ errorMessage?.includes(RPCErrorMessage.OUT_OF_GAS)
60
+ )
61
+ return new SignerError(
62
+ SignerErrorCode.SEND_TX_ERROR,
63
+ undefined,
64
+ 'Gas limit is low.',
65
+ RangoRPCErrorCode.OUT_OF_GAS,
66
+ error
67
+ );
68
+
69
+ const msg = getMessageFromCode(errorCode);
70
+ return new SignerError(
71
+ SignerErrorCode.SEND_TX_ERROR,
72
+ undefined,
73
+ msg ?? error,
74
+ RangoRPCErrorCode.UNKNOWN_ERROR,
75
+ error
76
+ );
77
+ }
78
+ }
79
+ switch (errorCode) {
80
+ case RPCErrorCode.INVALID_ARGUMENT: {
81
+ const msg = (error.reason || error.message) ?? error;
82
+ return new SignerError(
83
+ SignerErrorCode.SEND_TX_ERROR,
84
+ undefined,
85
+ msg,
86
+ RangoRPCErrorCode.UNKNOWN_ERROR,
87
+ error
88
+ );
89
+ }
90
+ }
24
91
  }
25
- return new SignerError(SignerErrorCode.SEND_TX_ERROR, message, error);
92
+ return new SignerError(
93
+ SignerErrorCode.SEND_TX_ERROR,
94
+ undefined,
95
+ error,
96
+ RangoRPCErrorCode.UNKNOWN_ERROR,
97
+ error
98
+ );
26
99
  };
27
100
 
28
101
  interface TenderlyResponse {
package/src/signer.ts CHANGED
@@ -6,7 +6,12 @@ import type { GenericSigner } from 'rango-types';
6
6
  import { EvmTransaction } from 'rango-types/lib/api/main';
7
7
  import { providers } from 'ethers';
8
8
  import { cleanEvmError, getTenderlyError } from './helper';
9
- import { SignerError, SignerErrorCode } from 'rango-types';
9
+ import {
10
+ RPCErrorCode as RangoRPCErrorCode,
11
+ SignerError,
12
+ SignerErrorCode,
13
+ } from 'rango-types';
14
+ import { RPCErrorCode } from './types';
10
15
 
11
16
  const waitMs = (ms: number) =>
12
17
  new Promise((resolve) => setTimeout(resolve, ms));
@@ -70,6 +75,7 @@ export class DefaultEvmSigner implements GenericSigner<EvmTransaction> {
70
75
  if (!!chainId && !!signerChainId && signerChainId !== parseInt(chainId)) {
71
76
  throw new SignerError(
72
77
  SignerErrorCode.UNEXPECTED_BEHAVIOUR,
78
+ undefined,
73
79
  `Signer chainId: '${signerChainId}' doesn't match with required chainId: '${chainId}' for tx.`
74
80
  );
75
81
  }
@@ -80,6 +86,7 @@ export class DefaultEvmSigner implements GenericSigner<EvmTransaction> {
80
86
  ) {
81
87
  throw new SignerError(
82
88
  SignerErrorCode.UNEXPECTED_BEHAVIOUR,
89
+ undefined,
83
90
  `Signer address: '${signerAddress.toLowerCase()}' doesn't match with required address: '${address.toLowerCase()}' for tx.`
84
91
  );
85
92
  }
@@ -140,17 +147,28 @@ export class DefaultEvmSigner implements GenericSigner<EvmTransaction> {
140
147
  return { hash: txHash };
141
148
  } catch (err) {
142
149
  const error = err as any; // TODO find a proper type
143
- if (error?.code === 'TRANSACTION_REPLACED' && error?.replacement)
150
+ if (
151
+ error?.code === RPCErrorCode.TRANSACTION_REPLACED &&
152
+ error?.replacement
153
+ )
144
154
  return { hash: error?.replacement?.hash, response: error?.replacement };
145
- else if (error?.code === 'CALL_EXCEPTION') {
155
+ else if (error?.code === RPCErrorCode.CALL_EXCEPTION) {
146
156
  const tError = await getTenderlyError(chainId, txHash);
147
- if (!!tError)
148
- // TODO different Signer Error Code
157
+ if (!!tError) {
149
158
  throw new SignerError(
150
- SignerErrorCode.SEND_TX_ERROR,
159
+ SignerErrorCode.TX_FAILED_IN_BLOCKCHAIN,
151
160
  'Trannsaction failed in blockchain',
152
- tError
161
+ tError,
162
+ RangoRPCErrorCode.CALL_EXCEPTION,
163
+ error
153
164
  );
165
+ } else {
166
+ /**
167
+ * In cases where the is no error returen from tenderly, we could ignore
168
+ * the error and proceed with check status flow.
169
+ * */
170
+ return { hash: txHash };
171
+ }
154
172
  }
155
173
  throw cleanEvmError(error);
156
174
  }
package/src/types.ts ADDED
@@ -0,0 +1,38 @@
1
+ export const MetamaskErrorCodes = {
2
+ rpc: {
3
+ invalidInput: -32000,
4
+ resourceNotFound: -32001,
5
+ resourceUnavailable: -32002,
6
+ transactionRejected: -32003,
7
+ methodNotSupported: -32004,
8
+ limitExceeded: -32005,
9
+ parse: -32700,
10
+ invalidRequest: -32600,
11
+ methodNotFound: -32601,
12
+ invalidParams: -32602,
13
+ internal: -32603,
14
+ },
15
+ provider: {
16
+ userRejectedRequest: 4001,
17
+ unauthorized: 4100,
18
+ unsupportedMethod: 4200,
19
+ disconnected: 4900,
20
+ chainDisconnected: 4901,
21
+ },
22
+ };
23
+
24
+ export enum RPCErrorCode {
25
+ ACTION_REJECTED = 'ACTION_REJECTED',
26
+ INVALID_ARGUMENT = 'INVALID_ARGUMENT',
27
+ CALL_EXCEPTION = 'CALL_EXCEPTION',
28
+ INSUFFICIENT_FUNDS = 'INSUFFICIENT_FUNDS',
29
+ TRANSACTION_REPLACED = 'TRANSACTION_REPLACED',
30
+ }
31
+
32
+ export enum RPCErrorMessage {
33
+ UNDER_PRICED = 'underpriced',
34
+ REPLACEMENT_FEE_TOO_LOW = 'replacement fee too low',
35
+ INTRINSIC_GAS_TOO_LOW = 'intrinsic gas too low',
36
+ OUT_OF_GAS = 'out of gas',
37
+ INTERNAL_ERROR = 'Internal JSON-RPC error',
38
+ }