@rango-dev/signer-evm 0.29.0 → 0.29.1-next.1
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 +4 -0
- package/dist/helper.d.ts.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +4 -4
- package/dist/signer-evm.build.json +1 -1
- package/dist/signer.d.ts +3 -7
- package/dist/signer.d.ts.map +1 -1
- package/package.json +2 -4
- package/src/helper.ts +27 -77
- package/src/index.ts +2 -2
- package/src/signer.ts +43 -32
- package/dist/types.d.ts +0 -36
- package/dist/types.d.ts.map +0 -1
- package/src/types.ts +0 -38
package/CHANGELOG.md
CHANGED
package/dist/helper.d.ts.map
CHANGED
|
@@ -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;
|
|
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;AASlE,eAAO,MAAM,aAAa,UAAW,GAAG,KAAG,eAgD1C,CAAC;AAMF,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAkB7B;AAED,eAAO,MAAM,MAAM,OAAc,MAAM,qBACY,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { DefaultEvmSigner } from './signer';
|
|
2
|
-
export { waitMs, cleanEvmError } from './helper';
|
|
1
|
+
export { DefaultEvmSigner } from './signer.js';
|
|
2
|
+
export { waitMs, cleanEvmError } from './helper.js';
|
|
3
3
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var
|
|
1
|
+
var P=Object.defineProperty;var c=(e,r)=>P(e,"name",{value:r,configurable:!0});import{BrowserProvider as S,isError as y}from"ethers";import{RPCErrorCode as _,SignerError as E,SignerErrorCode as u}from"rango-types";import{isError as l}from"ethers";import{RPCErrorCode as f,SignerError as d,SignerErrorCode as g}from"rango-types";var h=c(e=>{if(!e)return new d(g.SEND_TX_ERROR);if(d.isSignerError(e))return e;if(e.code){if(l(e,"UNKNOWN_ERROR")){let t=e.error?.message||e.message;return new d(g.SEND_TX_ERROR,void 0,t,f.UNKNOWN_ERROR,e)}if(l(e,"ACTION_REJECTED")){let t=e.shortMessage.replace("action",`'${e.action}'`);return new d(g.SEND_TX_ERROR,void 0,t,f.REJECTION,e)}let r=e.shortMessage||e.message;return new d(g.SEND_TX_ERROR,void 0,r,f.UNKNOWN_ERROR,e)}return new d(g.SEND_TX_ERROR,void 0,e,f.UNKNOWN_ERROR,e)},"cleanEvmError");async function T(e,r){if(!e||!r)return;let t=parseInt(e);try{let o=`https://api.tenderly.co/api/v1/public-contract/${t}/tx/${r}`,n=await fetch(o,{method:"GET"});return n.ok?(await n.json())?.error_message:void 0}catch{return}}c(T,"getTenderlyError");var m=c(async e=>new Promise(r=>setTimeout(r,e)),"waitMs");var C=c(async(e,r,t,o)=>{let i=!1;return await Promise.race([(async()=>{await r.wait(o),i=!0})(),(async()=>{for(;!i;){if(await m(3e3),i)return null;try{if(!await e.getTransaction(t))return null}catch(s){return console.log({error:s}),null}}return null})()])},"waitWithMempoolCheck"),w=class e{static{c(this,"DefaultEvmSigner")}provider;constructor(r){this.provider=new S(r)}static buildTx(r,t=!1){let n={};return n={data:r.data||"0x"},r.from&&(n={...n,from:r.from}),r.to&&(n={...n,to:r.to}),r.value&&(n={...n,value:r.value}),r.nonce&&(n={...n,nonce:parseInt(r.nonce)}),r.gasLimit&&(n={...n,gasLimit:r.gasLimit}),!t&&r.maxFeePerGas&&r.maxPriorityFeePerGas?n={...n,maxFeePerGas:r.maxFeePerGas,maxPriorityFeePerGas:r.maxPriorityFeePerGas}:r.gasPrice&&(n={...n,gasPrice:"0x"+parseInt(r.gasPrice).toString(16)}),n}async signMessage(r){try{return await(await this.provider.getSigner()).signMessage(r)}catch(t){throw new E(u.SIGN_TX_ERROR,void 0,t)}}async signAndSendTx(r,t,o){try{let n=await this.provider.getSigner(r.from??void 0),i=e.buildTx(r),s=(await this.provider.getNetwork()).chainId,p=await n.getAddress();if(o&&s&&s.toString()!==Number(o).toString())throw new E(u.UNEXPECTED_BEHAVIOUR,void 0,`Signer chainId: '${s}' doesn't match with required chainId: '${o}' for tx.`);if(p&&t&&p.toLowerCase()!==t.toLowerCase())throw new E(u.UNEXPECTED_BEHAVIOUR,void 0,`Signer address: '${p.toLowerCase()}' doesn't match with required address: '${t.toLowerCase()}' for tx.`);try{let a=await n.sendTransaction(i);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 N=e.buildTx(r,!0),R=await n.sendTransaction(N);return{hash:R.hash,response:R}}throw a}}catch(n){throw h(n)}}async wait(r,t,o,n){try{if(o)return await o?.wait(n),{hash:r};if(!this.provider)return{hash:r};if(!t)return{hash:r};let i=(await this.provider.getNetwork()).chainId;if(!i||Number(t).toString()!==i.toString())return{hash:r};let s=await this.provider.getTransaction(r);if(!s)throw Error(`Transaction hash '${r}' not found in blockchain.`);return await C(this.provider,s,r,n),{hash:r}}catch(i){if(y(i,"TRANSACTION_REPLACED")){if(i.reason==="cancelled")throw new E(u.SEND_TX_ERROR,void 0,"Transaction replaced and canceled by user",void 0,i);return{hash:i.replacement.hash,response:i.replacement}}else if(y(i,"CALL_EXCEPTION")){let s=await T(t,r);if(s)throw new E(u.TX_FAILED_IN_BLOCKCHAIN,"Trannsaction failed in blockchain",s,_.CALL_EXCEPTION,i);return{hash:r}}return{hash:r}}}};export{w as DefaultEvmSigner,h as cleanEvmError,m as waitMs};
|
|
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 type {\n TransactionRequest,\n TransactionResponse,\n} from '@ethersproject/abstract-provider';\nimport type { GenericSigner } from 'rango-types';\nimport type { EvmTransaction } from 'rango-types/lib/api/main';\n\nimport { providers } from 'ethers';\nimport {\n RPCErrorCode as RangoRPCErrorCode,\n SignerError,\n SignerErrorCode,\n} from 'rango-types';\n\nimport { cleanEvmError, getTenderlyError, waitMs } from './helper';\nimport { RPCErrorCode } from './types';\n\ntype ProviderType = ConstructorParameters<typeof providers.Web3Provider>[0];\n\nconst waitWithMempoolCheck = async (\n provider: providers.Web3Provider,\n tx: TransactionResponse,\n txHash: string,\n confirmations?: number\n) => {\n const TIMEOUT = 3_000;\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(TIMEOUT);\n if (finished) {\n return null;\n }\n try {\n const mempoolTx = await provider.getTransaction(txHash);\n if (!mempoolTx) {\n return null;\n }\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: ProviderType) {\n this.provider = new providers.Web3Provider(provider);\n this.signer = this.provider.getSigner();\n }\n\n static buildTx(evmTx: EvmTransaction, disableV2 = false): TransactionRequest {\n const TO_STRING_BASE = 16;\n let tx: TransactionRequest = {};\n /*\n * it's better to pass 0x instead of undefined, otherwise some wallets could face issue\n * https://github.com/WalletConnect/web3modal/issues/1082#issuecomment-1637793242\n */\n tx = {\n data: evmTx.data || '0x',\n };\n if (evmTx.from) {\n tx = { ...tx, from: evmTx.from };\n }\n if (evmTx.to) {\n tx = { ...tx, to: evmTx.to };\n }\n if (evmTx.value) {\n tx = { ...tx, value: evmTx.value };\n }\n if (evmTx.nonce) {\n tx = { ...tx, nonce: evmTx.nonce };\n }\n if (evmTx.gasLimit) {\n tx = { ...tx, gasLimit: evmTx.gasLimit };\n }\n if (!disableV2 && evmTx.maxFeePerGas && evmTx.maxPriorityFeePerGas) {\n tx = {\n ...tx,\n maxFeePerGas: evmTx.maxFeePerGas,\n maxPriorityFeePerGas: evmTx.maxPriorityFeePerGas,\n };\n } else if (evmTx.gasPrice) {\n tx = {\n ...tx,\n gasPrice: '0x' + parseInt(evmTx.gasPrice).toString(TO_STRING_BASE),\n };\n }\n return tx;\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\n const transaction = DefaultEvmSigner.buildTx(tx);\n\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 }\n throw error;\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 /*\n * if we have transaction response, use that to wait\n * otherwise, try to get tx response from the wallet provider\n */\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) {\n return { hash: txHash };\n }\n this.signer = this.provider.getSigner();\n\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 */\n if (!chainId) {\n return { hash: txHash };\n }\n const signerChainId = await this.signer.getChainId();\n if (!signerChainId || parseInt(chainId) != signerChainId) {\n return { hash: txHash };\n }\n\n const tx = await this.provider.getTransaction(txHash);\n if (!tx) {\n throw Error(`Transaction hash '${txHash}' not found in blockchain.`);\n }\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 /**\n * Ignore other errors in confirming transaction and proceed with check status flow,\n * Some times rpc gives internal error or other type of errors even if the transaction succeeded\n */\n return { hash: txHash };\n }\n }\n}\n", "import type { SignerError as SignerErrorType } from 'rango-types';\n\nimport { getMessageFromCode } from 'eth-rpc-errors';\nimport {\n RPCErrorCode as RangoRPCErrorCode,\n SignerError,\n SignerErrorCode,\n} from 'rango-types';\n\nimport { MetamaskErrorCodes, RPCErrorCode, RPCErrorMessage } from './types';\n\nexport const cleanEvmError = (error: any): SignerErrorType => {\n if (!error) {\n return new SignerError(SignerErrorCode.SEND_TX_ERROR);\n }\n if (SignerError.isSignerError(error)) {\n return error;\n }\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 }\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 }\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\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) {\n return;\n }\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) {\n return;\n }\n const data: TenderlyResponse = await response.json();\n return data?.error_message;\n } catch (error) {\n return;\n }\n}\n\nexport const waitMs = async (ms: number) =>\n new Promise((resolve) => setTimeout(resolve, ms));\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": "+
|
|
6
|
-
"names": ["
|
|
3
|
+
"sources": ["../src/signer.ts", "../src/helper.ts"],
|
|
4
|
+
"sourcesContent": ["import type {\n AbstractProvider,\n Eip1193Provider,\n TransactionRequest,\n TransactionResponse,\n} from 'ethers';\nimport type { GenericSigner } from 'rango-types';\nimport type { EvmTransaction } from 'rango-types/mainApi';\n\nimport { BrowserProvider, isError } from 'ethers';\nimport {\n RPCErrorCode as RangoRPCErrorCode,\n SignerError,\n SignerErrorCode,\n} from 'rango-types';\n\nimport { cleanEvmError, getTenderlyError, waitMs } from './helper.js';\n\nconst waitWithMempoolCheck = async (\n provider: AbstractProvider,\n tx: TransactionResponse,\n txHash: string,\n confirmations?: number\n) => {\n const TIMEOUT = 3_000;\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(TIMEOUT);\n if (finished) {\n return null;\n }\n try {\n const mempoolTx = await provider.getTransaction(txHash);\n if (!mempoolTx) {\n return null;\n }\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 provider: BrowserProvider;\n\n constructor(provider: Eip1193Provider) {\n this.provider = new BrowserProvider(provider); // provides read-only access to the provider\n }\n\n static buildTx(evmTx: EvmTransaction, disableV2 = false): TransactionRequest {\n const TO_STRING_BASE = 16;\n let tx: TransactionRequest = {};\n /*\n * it's better to pass 0x instead of undefined, otherwise some wallets could face issue\n * https://github.com/WalletConnect/web3modal/issues/1082#issuecomment-1637793242\n */\n tx = {\n data: evmTx.data || '0x',\n };\n if (evmTx.from) {\n tx = { ...tx, from: evmTx.from };\n }\n if (evmTx.to) {\n tx = { ...tx, to: evmTx.to };\n }\n if (evmTx.value) {\n tx = { ...tx, value: evmTx.value };\n }\n if (evmTx.nonce) {\n tx = { ...tx, nonce: parseInt(evmTx.nonce) };\n }\n if (evmTx.gasLimit) {\n tx = { ...tx, gasLimit: evmTx.gasLimit };\n }\n if (!disableV2 && evmTx.maxFeePerGas && evmTx.maxPriorityFeePerGas) {\n tx = {\n ...tx,\n maxFeePerGas: evmTx.maxFeePerGas,\n maxPriorityFeePerGas: evmTx.maxPriorityFeePerGas,\n };\n } else if (evmTx.gasPrice) {\n tx = {\n ...tx,\n gasPrice: '0x' + parseInt(evmTx.gasPrice).toString(TO_STRING_BASE),\n };\n }\n return tx;\n }\n\n async signMessage(msg: string): Promise<string> {\n try {\n const signer = await this.provider.getSigner(); // provides access to write operations\n return await 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 const signer = await this.provider.getSigner(tx.from ?? undefined);\n\n const transaction = DefaultEvmSigner.buildTx(tx);\n\n const signerChainId = (await this.provider.getNetwork()).chainId;\n const signerAddress = await signer.getAddress();\n\n if (\n !!chainId &&\n !!signerChainId &&\n signerChainId.toString() !== Number(chainId).toString()\n ) {\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 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 signer.sendTransaction(transaction);\n return { hash: response.hash, response };\n }\n throw error;\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 /*\n * if we have transaction response, use that to wait\n * otherwise, try to get tx response from the wallet provider\n */\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) {\n return { hash: txHash };\n }\n\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 */\n if (!chainId) {\n return { hash: txHash };\n }\n const signerChainId = (await this.provider.getNetwork()).chainId;\n if (\n !signerChainId ||\n Number(chainId).toString() !== signerChainId.toString()\n ) {\n return { hash: txHash };\n }\n\n const tx = await this.provider.getTransaction(txHash);\n if (!tx) {\n throw Error(`Transaction hash '${txHash}' not found in blockchain.`);\n }\n\n await waitWithMempoolCheck(this.provider, tx, txHash, confirmations);\n return { hash: txHash };\n } catch (error) {\n if (isError(error, 'TRANSACTION_REPLACED')) {\n const reason = error.reason;\n if (reason === 'cancelled') {\n throw new SignerError(\n SignerErrorCode.SEND_TX_ERROR,\n undefined,\n 'Transaction replaced and canceled by user',\n undefined,\n error\n );\n }\n return { hash: error.replacement.hash, response: error.replacement };\n } else if (isError(error, '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 /**\n * Ignore other errors in confirming transaction and proceed with check status flow,\n * Some times rpc gives internal error or other type of errors even if the transaction succeeded\n */\n return { hash: txHash };\n }\n }\n}\n", "import type { SignerError as SignerErrorType } from 'rango-types';\n\nimport { isError } from 'ethers';\nimport {\n RPCErrorCode as RangoRPCErrorCode,\n SignerError,\n SignerErrorCode,\n} from 'rango-types';\n\nexport const cleanEvmError = (error: any): SignerErrorType => {\n if (!error) {\n return new SignerError(SignerErrorCode.SEND_TX_ERROR);\n }\n\n if (SignerError.isSignerError(error)) {\n return error;\n }\n\n if (error.code) {\n if (isError(error, 'UNKNOWN_ERROR')) {\n const msg = error.error?.message || error.message;\n return new SignerError(\n SignerErrorCode.SEND_TX_ERROR,\n undefined,\n msg,\n RangoRPCErrorCode.UNKNOWN_ERROR,\n error\n );\n }\n\n if (isError(error, 'ACTION_REJECTED')) {\n const msg = error.shortMessage.replace('action', `'${error.action}'`);\n return new SignerError(\n SignerErrorCode.SEND_TX_ERROR,\n undefined,\n msg,\n RangoRPCErrorCode.REJECTION,\n error\n );\n }\n\n const msg = error.shortMessage || error.message;\n return new SignerError(\n SignerErrorCode.SEND_TX_ERROR,\n undefined,\n msg,\n RangoRPCErrorCode.UNKNOWN_ERROR,\n error\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) {\n return;\n }\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) {\n return;\n }\n const data: TenderlyResponse = await response.json();\n return data?.error_message;\n } catch (error) {\n return;\n }\n}\n\nexport const waitMs = async (ms: number) =>\n new Promise((resolve) => setTimeout(resolve, ms));\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["BrowserProvider", "isError", "RangoRPCErrorCode", "SignerError", "SignerErrorCode", "isError", "RangoRPCErrorCode", "SignerError", "SignerErrorCode", "cleanEvmError", "__name", "error", "SignerError", "SignerErrorCode", "isError", "msg", "RangoRPCErrorCode", "getTenderlyError", "chainId", "txHash", "chainIdInt", "url", "response", "waitMs", "ms", "resolve", "waitWithMempoolCheck", "__name", "provider", "tx", "txHash", "confirmations", "finished", "waitMs", "error", "DefaultEvmSigner", "_DefaultEvmSigner", "BrowserProvider", "evmTx", "disableV2", "msg", "SignerError", "SignerErrorCode", "address", "chainId", "signer", "transaction", "signerChainId", "signerAddress", "response", "cleanEvmError", "txResponse", "isError", "tError", "getTenderlyError", "RangoRPCErrorCode"]
|
|
7
7
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"inputs":{"src/
|
|
1
|
+
{"inputs":{"src/helper.ts":{"bytes":2050,"imports":[{"path":"ethers","kind":"import-statement","external":true},{"path":"rango-types","kind":"import-statement","external":true},{"path":"<runtime>","kind":"import-statement","external":true}],"format":"esm"},"src/signer.ts":{"bytes":7501,"imports":[{"path":"ethers","kind":"import-statement","external":true},{"path":"rango-types","kind":"import-statement","external":true},{"path":"src/helper.ts","kind":"import-statement","original":"./helper.js"},{"path":"<runtime>","kind":"import-statement","external":true}],"format":"esm"},"src/index.ts":{"bytes":101,"imports":[{"path":"src/signer.ts","kind":"import-statement","original":"./signer.js"},{"path":"src/helper.ts","kind":"import-statement","original":"./helper.js"}],"format":"esm"}},"outputs":{"dist/index.js.map":{"imports":[],"exports":[],"inputs":{},"bytes":14985},"dist/index.js":{"imports":[{"path":"ethers","kind":"import-statement","external":true},{"path":"rango-types","kind":"import-statement","external":true},{"path":"ethers","kind":"import-statement","external":true},{"path":"rango-types","kind":"import-statement","external":true}],"exports":["DefaultEvmSigner","cleanEvmError","waitMs"],"entryPoint":"src/index.ts","inputs":{"src/signer.ts":{"bytesInOutput":2705},"src/helper.ts":{"bytesInOutput":928},"src/index.ts":{"bytesInOutput":0}},"bytes":3808}}}
|
package/dist/signer.d.ts
CHANGED
|
@@ -1,12 +1,9 @@
|
|
|
1
|
-
import type { TransactionRequest, TransactionResponse } from '
|
|
1
|
+
import type { Eip1193Provider, TransactionRequest, TransactionResponse } from 'ethers';
|
|
2
2
|
import type { GenericSigner } from 'rango-types';
|
|
3
|
-
import type { EvmTransaction } from 'rango-types/
|
|
4
|
-
import { providers } from 'ethers';
|
|
5
|
-
type ProviderType = ConstructorParameters<typeof providers.Web3Provider>[0];
|
|
3
|
+
import type { EvmTransaction } from 'rango-types/mainApi';
|
|
6
4
|
export declare class DefaultEvmSigner implements GenericSigner<EvmTransaction> {
|
|
7
|
-
private signer;
|
|
8
5
|
private provider;
|
|
9
|
-
constructor(provider:
|
|
6
|
+
constructor(provider: Eip1193Provider);
|
|
10
7
|
static buildTx(evmTx: EvmTransaction, disableV2?: boolean): TransactionRequest;
|
|
11
8
|
signMessage(msg: string): Promise<string>;
|
|
12
9
|
signAndSendTx(tx: EvmTransaction, address: string, chainId: string | null): Promise<{
|
|
@@ -18,5 +15,4 @@ export declare class DefaultEvmSigner implements GenericSigner<EvmTransaction> {
|
|
|
18
15
|
response?: TransactionResponse;
|
|
19
16
|
}>;
|
|
20
17
|
}
|
|
21
|
-
export {};
|
|
22
18
|
//# sourceMappingURL=signer.d.ts.map
|
package/dist/signer.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"signer.d.ts","sourceRoot":"","sources":["../src/signer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"signer.d.ts","sourceRoot":"","sources":["../src/signer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,eAAe,EACf,kBAAkB,EAClB,mBAAmB,EACpB,MAAM,QAAQ,CAAC;AAChB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AA6C1D,qBAAa,gBAAiB,YAAW,aAAa,CAAC,cAAc,CAAC;IACpE,OAAO,CAAC,QAAQ,CAAkB;gBAEtB,QAAQ,EAAE,eAAe;IAIrC,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,cAAc,EAAE,SAAS,UAAQ,GAAG,kBAAkB;IAwCtE,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IASzC,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;IAqDrD,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;CA6E7D"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rango-dev/signer-evm",
|
|
3
|
-
"version": "0.29.
|
|
3
|
+
"version": "0.29.1-next.1",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"source": "./src/index.ts",
|
|
@@ -24,9 +24,7 @@
|
|
|
24
24
|
"test:coverage": "vitest run --coverage"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"
|
|
28
|
-
"eth-rpc-errors": "^4.0.3",
|
|
29
|
-
"ethers": "^5.7.2",
|
|
27
|
+
"ethers": "^6.13.2",
|
|
30
28
|
"rango-types": "^0.1.69"
|
|
31
29
|
},
|
|
32
30
|
"publishConfig": {
|
package/src/helper.ts
CHANGED
|
@@ -1,102 +1,52 @@
|
|
|
1
1
|
import type { SignerError as SignerErrorType } from 'rango-types';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { isError } from 'ethers';
|
|
4
4
|
import {
|
|
5
5
|
RPCErrorCode as RangoRPCErrorCode,
|
|
6
6
|
SignerError,
|
|
7
7
|
SignerErrorCode,
|
|
8
8
|
} from 'rango-types';
|
|
9
9
|
|
|
10
|
-
import { MetamaskErrorCodes, RPCErrorCode, RPCErrorMessage } from './types';
|
|
11
|
-
|
|
12
10
|
export const cleanEvmError = (error: any): SignerErrorType => {
|
|
13
11
|
if (!error) {
|
|
14
12
|
return new SignerError(SignerErrorCode.SEND_TX_ERROR);
|
|
15
13
|
}
|
|
14
|
+
|
|
16
15
|
if (SignerError.isSignerError(error)) {
|
|
17
16
|
return error;
|
|
18
17
|
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
// rejection error
|
|
24
|
-
if (
|
|
25
|
-
RPCErrorCode.ACTION_REJECTED === errorCode ||
|
|
26
|
-
MetamaskErrorCodes.provider.userRejectedRequest === errorCode
|
|
27
|
-
) {
|
|
18
|
+
|
|
19
|
+
if (error.code) {
|
|
20
|
+
if (isError(error, 'UNKNOWN_ERROR')) {
|
|
21
|
+
const msg = error.error?.message || error.message;
|
|
28
22
|
return new SignerError(
|
|
29
|
-
SignerErrorCode.
|
|
23
|
+
SignerErrorCode.SEND_TX_ERROR,
|
|
30
24
|
undefined,
|
|
31
|
-
|
|
32
|
-
RangoRPCErrorCode.
|
|
25
|
+
msg,
|
|
26
|
+
RangoRPCErrorCode.UNKNOWN_ERROR,
|
|
33
27
|
error
|
|
34
28
|
);
|
|
35
29
|
}
|
|
36
|
-
if (typeof errorCode === 'number') {
|
|
37
|
-
// provider errors
|
|
38
|
-
if (Object.values(MetamaskErrorCodes.provider).includes(errorCode)) {
|
|
39
|
-
const msg = getMessageFromCode(errorCode);
|
|
40
|
-
return new SignerError(
|
|
41
|
-
SignerErrorCode.SEND_TX_ERROR,
|
|
42
|
-
undefined,
|
|
43
|
-
msg,
|
|
44
|
-
RangoRPCErrorCode.UNKNOWN_ERROR,
|
|
45
|
-
error
|
|
46
|
-
);
|
|
47
|
-
}
|
|
48
|
-
// rpc errors
|
|
49
|
-
else if (Object.values(MetamaskErrorCodes.rpc).includes(errorCode)) {
|
|
50
|
-
// underpriced errors are sent as internal errors
|
|
51
|
-
if (
|
|
52
|
-
errorCode === MetamaskErrorCodes.rpc.internal &&
|
|
53
|
-
(errorMessage?.includes(RPCErrorMessage.UNDER_PRICED) ||
|
|
54
|
-
errorMessage?.includes(RPCErrorMessage.REPLACEMENT_FEE_TOO_LOW))
|
|
55
|
-
) {
|
|
56
|
-
return new SignerError(
|
|
57
|
-
SignerErrorCode.SEND_TX_ERROR,
|
|
58
|
-
undefined,
|
|
59
|
-
'Transaction is underpriced.',
|
|
60
|
-
RangoRPCErrorCode.UNDER_PRICED,
|
|
61
|
-
error
|
|
62
|
-
);
|
|
63
|
-
}
|
|
64
|
-
// gas limit errors are sent as internal errors
|
|
65
|
-
if (
|
|
66
|
-
errorMessage?.includes(RPCErrorMessage.INTRINSIC_GAS_TOO_LOW) ||
|
|
67
|
-
errorMessage?.includes(RPCErrorMessage.OUT_OF_GAS)
|
|
68
|
-
) {
|
|
69
|
-
return new SignerError(
|
|
70
|
-
SignerErrorCode.SEND_TX_ERROR,
|
|
71
|
-
undefined,
|
|
72
|
-
'Gas limit is low.',
|
|
73
|
-
RangoRPCErrorCode.OUT_OF_GAS,
|
|
74
|
-
error
|
|
75
|
-
);
|
|
76
|
-
}
|
|
77
30
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
}
|
|
88
|
-
switch (errorCode) {
|
|
89
|
-
case RPCErrorCode.INVALID_ARGUMENT: {
|
|
90
|
-
const msg = (error.reason || error.message) ?? error;
|
|
91
|
-
return new SignerError(
|
|
92
|
-
SignerErrorCode.SEND_TX_ERROR,
|
|
93
|
-
undefined,
|
|
94
|
-
msg,
|
|
95
|
-
RangoRPCErrorCode.UNKNOWN_ERROR,
|
|
96
|
-
error
|
|
97
|
-
);
|
|
98
|
-
}
|
|
31
|
+
if (isError(error, 'ACTION_REJECTED')) {
|
|
32
|
+
const msg = error.shortMessage.replace('action', `'${error.action}'`);
|
|
33
|
+
return new SignerError(
|
|
34
|
+
SignerErrorCode.SEND_TX_ERROR,
|
|
35
|
+
undefined,
|
|
36
|
+
msg,
|
|
37
|
+
RangoRPCErrorCode.REJECTION,
|
|
38
|
+
error
|
|
39
|
+
);
|
|
99
40
|
}
|
|
41
|
+
|
|
42
|
+
const msg = error.shortMessage || error.message;
|
|
43
|
+
return new SignerError(
|
|
44
|
+
SignerErrorCode.SEND_TX_ERROR,
|
|
45
|
+
undefined,
|
|
46
|
+
msg,
|
|
47
|
+
RangoRPCErrorCode.UNKNOWN_ERROR,
|
|
48
|
+
error
|
|
49
|
+
);
|
|
100
50
|
}
|
|
101
51
|
return new SignerError(
|
|
102
52
|
SignerErrorCode.SEND_TX_ERROR,
|
package/src/index.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { DefaultEvmSigner } from './signer';
|
|
2
|
-
export { waitMs, cleanEvmError } from './helper';
|
|
1
|
+
export { DefaultEvmSigner } from './signer.js';
|
|
2
|
+
export { waitMs, cleanEvmError } from './helper.js';
|
package/src/signer.ts
CHANGED
|
@@ -1,24 +1,23 @@
|
|
|
1
1
|
import type {
|
|
2
|
+
AbstractProvider,
|
|
3
|
+
Eip1193Provider,
|
|
2
4
|
TransactionRequest,
|
|
3
5
|
TransactionResponse,
|
|
4
|
-
} from '
|
|
6
|
+
} from 'ethers';
|
|
5
7
|
import type { GenericSigner } from 'rango-types';
|
|
6
|
-
import type { EvmTransaction } from 'rango-types/
|
|
8
|
+
import type { EvmTransaction } from 'rango-types/mainApi';
|
|
7
9
|
|
|
8
|
-
import {
|
|
10
|
+
import { BrowserProvider, isError } from 'ethers';
|
|
9
11
|
import {
|
|
10
12
|
RPCErrorCode as RangoRPCErrorCode,
|
|
11
13
|
SignerError,
|
|
12
14
|
SignerErrorCode,
|
|
13
15
|
} from 'rango-types';
|
|
14
16
|
|
|
15
|
-
import { cleanEvmError, getTenderlyError, waitMs } from './helper';
|
|
16
|
-
import { RPCErrorCode } from './types';
|
|
17
|
-
|
|
18
|
-
type ProviderType = ConstructorParameters<typeof providers.Web3Provider>[0];
|
|
17
|
+
import { cleanEvmError, getTenderlyError, waitMs } from './helper.js';
|
|
19
18
|
|
|
20
19
|
const waitWithMempoolCheck = async (
|
|
21
|
-
provider:
|
|
20
|
+
provider: AbstractProvider,
|
|
22
21
|
tx: TransactionResponse,
|
|
23
22
|
txHash: string,
|
|
24
23
|
confirmations?: number
|
|
@@ -52,12 +51,10 @@ const waitWithMempoolCheck = async (
|
|
|
52
51
|
};
|
|
53
52
|
|
|
54
53
|
export class DefaultEvmSigner implements GenericSigner<EvmTransaction> {
|
|
55
|
-
private
|
|
56
|
-
private provider: providers.Web3Provider;
|
|
54
|
+
private provider: BrowserProvider;
|
|
57
55
|
|
|
58
|
-
constructor(provider:
|
|
59
|
-
this.provider = new
|
|
60
|
-
this.signer = this.provider.getSigner();
|
|
56
|
+
constructor(provider: Eip1193Provider) {
|
|
57
|
+
this.provider = new BrowserProvider(provider); // provides read-only access to the provider
|
|
61
58
|
}
|
|
62
59
|
|
|
63
60
|
static buildTx(evmTx: EvmTransaction, disableV2 = false): TransactionRequest {
|
|
@@ -80,7 +77,7 @@ export class DefaultEvmSigner implements GenericSigner<EvmTransaction> {
|
|
|
80
77
|
tx = { ...tx, value: evmTx.value };
|
|
81
78
|
}
|
|
82
79
|
if (evmTx.nonce) {
|
|
83
|
-
tx = { ...tx, nonce: evmTx.nonce };
|
|
80
|
+
tx = { ...tx, nonce: parseInt(evmTx.nonce) };
|
|
84
81
|
}
|
|
85
82
|
if (evmTx.gasLimit) {
|
|
86
83
|
tx = { ...tx, gasLimit: evmTx.gasLimit };
|
|
@@ -102,7 +99,8 @@ export class DefaultEvmSigner implements GenericSigner<EvmTransaction> {
|
|
|
102
99
|
|
|
103
100
|
async signMessage(msg: string): Promise<string> {
|
|
104
101
|
try {
|
|
105
|
-
|
|
102
|
+
const signer = await this.provider.getSigner(); // provides access to write operations
|
|
103
|
+
return await signer.signMessage(msg);
|
|
106
104
|
} catch (error) {
|
|
107
105
|
throw new SignerError(SignerErrorCode.SIGN_TX_ERROR, undefined, error);
|
|
108
106
|
}
|
|
@@ -114,13 +112,18 @@ export class DefaultEvmSigner implements GenericSigner<EvmTransaction> {
|
|
|
114
112
|
chainId: string | null
|
|
115
113
|
): Promise<{ hash: string; response: TransactionResponse }> {
|
|
116
114
|
try {
|
|
117
|
-
|
|
115
|
+
const signer = await this.provider.getSigner(tx.from ?? undefined);
|
|
118
116
|
|
|
119
117
|
const transaction = DefaultEvmSigner.buildTx(tx);
|
|
120
118
|
|
|
121
|
-
const signerChainId = await this.
|
|
122
|
-
const signerAddress = await
|
|
123
|
-
|
|
119
|
+
const signerChainId = (await this.provider.getNetwork()).chainId;
|
|
120
|
+
const signerAddress = await signer.getAddress();
|
|
121
|
+
|
|
122
|
+
if (
|
|
123
|
+
!!chainId &&
|
|
124
|
+
!!signerChainId &&
|
|
125
|
+
signerChainId.toString() !== Number(chainId).toString()
|
|
126
|
+
) {
|
|
124
127
|
throw new SignerError(
|
|
125
128
|
SignerErrorCode.UNEXPECTED_BEHAVIOUR,
|
|
126
129
|
undefined,
|
|
@@ -139,7 +142,7 @@ export class DefaultEvmSigner implements GenericSigner<EvmTransaction> {
|
|
|
139
142
|
);
|
|
140
143
|
}
|
|
141
144
|
try {
|
|
142
|
-
const response = await
|
|
145
|
+
const response = await signer.sendTransaction(transaction);
|
|
143
146
|
return { hash: response.hash, response };
|
|
144
147
|
} catch (error: any) {
|
|
145
148
|
// retrying EIP-1559 without v2 related fields
|
|
@@ -150,7 +153,7 @@ export class DefaultEvmSigner implements GenericSigner<EvmTransaction> {
|
|
|
150
153
|
) {
|
|
151
154
|
console.log('retrying EIP-1559 error without v2 fields ...');
|
|
152
155
|
const transaction = DefaultEvmSigner.buildTx(tx, true);
|
|
153
|
-
const response = await
|
|
156
|
+
const response = await signer.sendTransaction(transaction);
|
|
154
157
|
return { hash: response.hash, response };
|
|
155
158
|
}
|
|
156
159
|
throw error;
|
|
@@ -181,7 +184,6 @@ export class DefaultEvmSigner implements GenericSigner<EvmTransaction> {
|
|
|
181
184
|
if (!this.provider) {
|
|
182
185
|
return { hash: txHash };
|
|
183
186
|
}
|
|
184
|
-
this.signer = this.provider.getSigner();
|
|
185
187
|
|
|
186
188
|
/*
|
|
187
189
|
* don't proceed if signer chain changed or chain id is not specified
|
|
@@ -190,8 +192,11 @@ export class DefaultEvmSigner implements GenericSigner<EvmTransaction> {
|
|
|
190
192
|
if (!chainId) {
|
|
191
193
|
return { hash: txHash };
|
|
192
194
|
}
|
|
193
|
-
const signerChainId = await this.
|
|
194
|
-
if (
|
|
195
|
+
const signerChainId = (await this.provider.getNetwork()).chainId;
|
|
196
|
+
if (
|
|
197
|
+
!signerChainId ||
|
|
198
|
+
Number(chainId).toString() !== signerChainId.toString()
|
|
199
|
+
) {
|
|
195
200
|
return { hash: txHash };
|
|
196
201
|
}
|
|
197
202
|
|
|
@@ -202,14 +207,20 @@ export class DefaultEvmSigner implements GenericSigner<EvmTransaction> {
|
|
|
202
207
|
|
|
203
208
|
await waitWithMempoolCheck(this.provider, tx, txHash, confirmations);
|
|
204
209
|
return { hash: txHash };
|
|
205
|
-
} catch (
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
210
|
+
} catch (error) {
|
|
211
|
+
if (isError(error, 'TRANSACTION_REPLACED')) {
|
|
212
|
+
const reason = error.reason;
|
|
213
|
+
if (reason === 'cancelled') {
|
|
214
|
+
throw new SignerError(
|
|
215
|
+
SignerErrorCode.SEND_TX_ERROR,
|
|
216
|
+
undefined,
|
|
217
|
+
'Transaction replaced and canceled by user',
|
|
218
|
+
undefined,
|
|
219
|
+
error
|
|
220
|
+
);
|
|
221
|
+
}
|
|
222
|
+
return { hash: error.replacement.hash, response: error.replacement };
|
|
223
|
+
} else if (isError(error, 'CALL_EXCEPTION')) {
|
|
213
224
|
const tError = await getTenderlyError(chainId, txHash);
|
|
214
225
|
if (!!tError) {
|
|
215
226
|
throw new SignerError(
|
package/dist/types.d.ts
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
export declare const MetamaskErrorCodes: {
|
|
2
|
-
rpc: {
|
|
3
|
-
resourceNotFound: number;
|
|
4
|
-
resourceUnavailable: number;
|
|
5
|
-
transactionRejected: number;
|
|
6
|
-
methodNotSupported: number;
|
|
7
|
-
limitExceeded: number;
|
|
8
|
-
parse: number;
|
|
9
|
-
invalidRequest: number;
|
|
10
|
-
methodNotFound: number;
|
|
11
|
-
invalidParams: number;
|
|
12
|
-
internal: number;
|
|
13
|
-
};
|
|
14
|
-
provider: {
|
|
15
|
-
userRejectedRequest: number;
|
|
16
|
-
unauthorized: number;
|
|
17
|
-
unsupportedMethod: number;
|
|
18
|
-
disconnected: number;
|
|
19
|
-
chainDisconnected: number;
|
|
20
|
-
};
|
|
21
|
-
};
|
|
22
|
-
export declare enum RPCErrorCode {
|
|
23
|
-
ACTION_REJECTED = "ACTION_REJECTED",
|
|
24
|
-
INVALID_ARGUMENT = "INVALID_ARGUMENT",
|
|
25
|
-
CALL_EXCEPTION = "CALL_EXCEPTION",
|
|
26
|
-
INSUFFICIENT_FUNDS = "INSUFFICIENT_FUNDS",
|
|
27
|
-
TRANSACTION_REPLACED = "TRANSACTION_REPLACED"
|
|
28
|
-
}
|
|
29
|
-
export declare enum RPCErrorMessage {
|
|
30
|
-
UNDER_PRICED = "underpriced",
|
|
31
|
-
REPLACEMENT_FEE_TOO_LOW = "replacement fee too low",
|
|
32
|
-
INTRINSIC_GAS_TOO_LOW = "intrinsic gas too low",
|
|
33
|
-
OUT_OF_GAS = "out of gas",
|
|
34
|
-
INTERNAL_ERROR = "Internal JSON-RPC error"
|
|
35
|
-
}
|
|
36
|
-
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
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/src/types.ts
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
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
|
-
}
|