From 495f960e3a3ff3d4061d538e508b4a2fe11971e4 Mon Sep 17 00:00:00 2001 From: Filip-L <67787091+Filip-L@users.noreply.github.com> Date: Fri, 27 Sep 2024 12:20:09 +0200 Subject: [PATCH] Error handling for comunication with the blockchain (#138) --------- Co-authored-by: Filip Lelek --- package-lock.json | 321 +++++++++++++++++++++++++++++ package.json | 1 + src/hooks/useApplicationActions.ts | 12 +- src/hooks/useWallet.ts | 1 - src/lib/glifApi.ts | 63 +++++- src/lib/wallet/BurnerWallet.ts | 2 +- src/lib/wallet/LedgerWallet.ts | 2 +- src/type.ts | 36 ++++ 8 files changed, 433 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index c3d06bb..96572f5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -36,6 +36,7 @@ "encoding": "^0.1.13", "eslint-config-next": "^12.3.4", "filecoin-verifier-tools": "^2.3.0", + "filecoin-verifier-tools-temporary": "^2.3.0", "fuse.js": "^6.6.2", "lucide-react": "^0.260.0", "next": "13.5.6", @@ -8411,6 +8412,176 @@ "varint": "^6.0.0" } }, + "node_modules/filecoin-verifier-tools-temporary": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/filecoin-verifier-tools-temporary/-/filecoin-verifier-tools-temporary-2.3.0.tgz", + "integrity": "sha512-HQ6/qfkkB9MDild41S5/eX5v6LsgSNWtRsbYDwJre9IQmXucPdMJlRAAHCAInzl/LE5W6BMu6lNWPGGHe2DNrg==", + "dependencies": { + "@babel/core": "7.24.4", + "@babel/helper-compilation-targets": "^7.20.7", + "@babel/preset-env": "^7.20.2", + "@filecoin-shipyard/lotus-client-provider-nodejs": "^1.1.1", + "@filecoin-shipyard/lotus-client-rpc": "^1.2.0", + "@filecoin-shipyard/lotus-client-schema": "4.2.0", + "@glif/filecoin-address": "3.0.4", + "@types/jest": "^29.2.5", + "@types/node": "^18.11.18", + "@zondax/filecoin-signing-tools": "2.4.3", + "axios": "^1.2.1", + "base32-decode": "^1.0.0", + "base32-encode": "^2.0.0", + "bip32": "4.0.0", + "bip39": "^3.0.2", + "blakejs": "^1.1.0", + "cbor": "^5.0.2", + "eslint-plugin-n": "^15.6.0", + "express": "^4.17.1", + "googleapis": "^109.0.1", + "jayson": "^4.0.0", + "jest": "29.7.0", + "js-sha256": "0.11.0", + "multiformats": "13.1.0", + "multihashes": "^4.0.3", + "murmurhash3js-revisited": "^3.0.0", + "node-fetch": "^3.3.0", + "pg": "8.11.5", + "pg-hstore": "^2.3.3", + "secp256k1": "5.0.0", + "sequelize": "^6.3.3", + "ts-jest": "29.1.2", + "typescript": "5.4.4", + "varint": "^6.0.0" + } + }, + "node_modules/filecoin-verifier-tools-temporary/node_modules/@types/node": { + "version": "18.19.51", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.51.tgz", + "integrity": "sha512-IIMkWEIVQDlBpi6pPeGqTqOx7KbzGC3EgIyH8NrxplXOwWw0uVl9vthJUMFrxD7kcEfcRp7jIkgpB28M6JnfWA==", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/filecoin-verifier-tools-temporary/node_modules/@zondax/filecoin-signing-tools": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/@zondax/filecoin-signing-tools/-/filecoin-signing-tools-2.4.3.tgz", + "integrity": "sha512-MfVd3t2iP//jcgeF+Mbx8A5UZVaeC5GicE4a9DY/hPQskm78wzCSuNwrJTlvKFgT3aPqWm7vYHGO0bbr21V0iw==", + "dependencies": { + "@ipld/dag-cbor": "^8.0.0", + "axios": "^1.2.1", + "base32-decode": "^1.0.0", + "base32-encode": "^2.0.0", + "bip32": "^3.1.0", + "bip39": "^3.0.4", + "blakejs": "^1.2.1", + "bn.js": "^5.2.1", + "leb128": "^0.0.5", + "secp256k1": "^4.0.3", + "tiny-secp256k1": "^2.2.1" + } + }, + "node_modules/filecoin-verifier-tools-temporary/node_modules/@zondax/filecoin-signing-tools/node_modules/bip32": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bip32/-/bip32-3.1.0.tgz", + "integrity": "sha512-eoeajYEzJ4d6yyVtby8C+XkCeKItiC4Mx56a0M9VaqTMC73SWOm4xVZG7SaR8e/yp4eSyky2XcBpH3DApPdu7Q==", + "dependencies": { + "bs58check": "^2.1.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "ripemd160": "^2.0.2", + "typeforce": "^1.11.5", + "wif": "^2.0.6" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/filecoin-verifier-tools-temporary/node_modules/@zondax/filecoin-signing-tools/node_modules/secp256k1": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.3.tgz", + "integrity": "sha512-NLZVf+ROMxwtEj3Xa562qgv2BK5e2WNmXPiOdVIPLgs6lyTzMvBq0aWTYMI5XCP9jZMVKOcqZLw/Wc4vDkuxhA==", + "hasInstallScript": true, + "dependencies": { + "elliptic": "^6.5.4", + "node-addon-api": "^2.0.0", + "node-gyp-build": "^4.2.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/filecoin-verifier-tools-temporary/node_modules/bip32": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/bip32/-/bip32-4.0.0.tgz", + "integrity": "sha512-aOGy88DDlVUhspIXJN+dVEtclhIsfAUppD43V0j40cPTld3pv/0X/MlrZSZ6jowIaQQzFwP8M6rFU2z2mVYjDQ==", + "dependencies": { + "@noble/hashes": "^1.2.0", + "@scure/base": "^1.1.1", + "typeforce": "^1.11.5", + "wif": "^2.0.6" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/filecoin-verifier-tools-temporary/node_modules/eslint-plugin-n": { + "version": "15.7.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-15.7.0.tgz", + "integrity": "sha512-jDex9s7D/Qial8AGVIHq4W7NswpUD5DPDL2RH8Lzd9EloWUuvUkHfv4FRLMipH5q2UtyurorBkPeNi1wVWNh3Q==", + "dependencies": { + "builtins": "^5.0.1", + "eslint-plugin-es": "^4.1.0", + "eslint-utils": "^3.0.0", + "ignore": "^5.1.1", + "is-core-module": "^2.11.0", + "minimatch": "^3.1.2", + "resolve": "^1.22.1", + "semver": "^7.3.8" + }, + "engines": { + "node": ">=12.22.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/filecoin-verifier-tools-temporary/node_modules/multiformats": { + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-13.1.0.tgz", + "integrity": "sha512-HzdtdBwxsIkzpeXzhQ5mAhhuxcHbjEHH+JQoxt7hG/2HGFjjwyolLo7hbaexcnhoEuV4e0TNJ8kkpMjiEYY4VQ==" + }, + "node_modules/filecoin-verifier-tools-temporary/node_modules/secp256k1": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-5.0.0.tgz", + "integrity": "sha512-TKWX8xvoGHrxVdqbYeZM9w+izTF4b9z3NhSaDkdn81btvuh+ivbIMGT/zQvDtTFWhRlThpoz6LEYTr7n8A5GcA==", + "hasInstallScript": true, + "dependencies": { + "elliptic": "^6.5.4", + "node-addon-api": "^5.0.0", + "node-gyp-build": "^4.2.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/filecoin-verifier-tools-temporary/node_modules/secp256k1/node_modules/node-addon-api": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", + "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==" + }, + "node_modules/filecoin-verifier-tools-temporary/node_modules/tiny-secp256k1": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/tiny-secp256k1/-/tiny-secp256k1-2.2.3.tgz", + "integrity": "sha512-SGcL07SxcPN2nGKHTCvRMkQLYPSoeFcvArUSCYtjVARiFAWU44cCIqYS0mYAU6nY7XfvwURuTIGo2Omt3ZQr0Q==", + "dependencies": { + "uint8array-tools": "0.0.7" + }, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/filecoin-verifier-tools/node_modules/@types/node": { "version": "18.19.45", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.45.tgz", @@ -21234,6 +21405,156 @@ } } }, + "filecoin-verifier-tools-temporary": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/filecoin-verifier-tools-temporary/-/filecoin-verifier-tools-temporary-2.3.0.tgz", + "integrity": "sha512-HQ6/qfkkB9MDild41S5/eX5v6LsgSNWtRsbYDwJre9IQmXucPdMJlRAAHCAInzl/LE5W6BMu6lNWPGGHe2DNrg==", + "requires": { + "@babel/core": "7.24.4", + "@babel/helper-compilation-targets": "^7.20.7", + "@babel/preset-env": "^7.20.2", + "@filecoin-shipyard/lotus-client-provider-nodejs": "^1.1.1", + "@filecoin-shipyard/lotus-client-rpc": "^1.2.0", + "@filecoin-shipyard/lotus-client-schema": "4.2.0", + "@glif/filecoin-address": "3.0.4", + "@types/jest": "^29.2.5", + "@types/node": "^18.11.18", + "@zondax/filecoin-signing-tools": "2.4.3", + "axios": "^1.2.1", + "base32-decode": "^1.0.0", + "base32-encode": "^2.0.0", + "bip32": "4.0.0", + "bip39": "^3.0.2", + "blakejs": "^1.1.0", + "cbor": "^5.0.2", + "eslint-plugin-n": "^15.6.0", + "express": "^4.17.1", + "googleapis": "^109.0.1", + "jayson": "^4.0.0", + "jest": "29.7.0", + "js-sha256": "0.11.0", + "multiformats": "13.1.0", + "multihashes": "^4.0.3", + "murmurhash3js-revisited": "^3.0.0", + "node-fetch": "^3.3.0", + "pg": "8.11.5", + "pg-hstore": "^2.3.3", + "secp256k1": "5.0.0", + "sequelize": "^6.3.3", + "ts-jest": "29.1.2", + "typescript": "5.4.4", + "varint": "^6.0.0" + }, + "dependencies": { + "@types/node": { + "version": "18.19.51", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.51.tgz", + "integrity": "sha512-IIMkWEIVQDlBpi6pPeGqTqOx7KbzGC3EgIyH8NrxplXOwWw0uVl9vthJUMFrxD7kcEfcRp7jIkgpB28M6JnfWA==", + "requires": { + "undici-types": "~5.26.4" + } + }, + "@zondax/filecoin-signing-tools": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/@zondax/filecoin-signing-tools/-/filecoin-signing-tools-2.4.3.tgz", + "integrity": "sha512-MfVd3t2iP//jcgeF+Mbx8A5UZVaeC5GicE4a9DY/hPQskm78wzCSuNwrJTlvKFgT3aPqWm7vYHGO0bbr21V0iw==", + "requires": { + "@ipld/dag-cbor": "^8.0.0", + "axios": "^1.2.1", + "base32-decode": "^1.0.0", + "base32-encode": "^2.0.0", + "bip32": "^3.1.0", + "bip39": "^3.0.4", + "blakejs": "^1.2.1", + "bn.js": "^5.2.1", + "leb128": "^0.0.5", + "secp256k1": "^4.0.3", + "tiny-secp256k1": "^2.2.1" + }, + "dependencies": { + "bip32": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bip32/-/bip32-3.1.0.tgz", + "integrity": "sha512-eoeajYEzJ4d6yyVtby8C+XkCeKItiC4Mx56a0M9VaqTMC73SWOm4xVZG7SaR8e/yp4eSyky2XcBpH3DApPdu7Q==", + "requires": { + "bs58check": "^2.1.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "ripemd160": "^2.0.2", + "typeforce": "^1.11.5", + "wif": "^2.0.6" + } + }, + "secp256k1": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.3.tgz", + "integrity": "sha512-NLZVf+ROMxwtEj3Xa562qgv2BK5e2WNmXPiOdVIPLgs6lyTzMvBq0aWTYMI5XCP9jZMVKOcqZLw/Wc4vDkuxhA==", + "requires": { + "elliptic": "^6.5.4", + "node-addon-api": "^2.0.0", + "node-gyp-build": "^4.2.0" + } + } + } + }, + "bip32": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/bip32/-/bip32-4.0.0.tgz", + "integrity": "sha512-aOGy88DDlVUhspIXJN+dVEtclhIsfAUppD43V0j40cPTld3pv/0X/MlrZSZ6jowIaQQzFwP8M6rFU2z2mVYjDQ==", + "requires": { + "@noble/hashes": "^1.2.0", + "@scure/base": "^1.1.1", + "typeforce": "^1.11.5", + "wif": "^2.0.6" + } + }, + "eslint-plugin-n": { + "version": "15.7.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-15.7.0.tgz", + "integrity": "sha512-jDex9s7D/Qial8AGVIHq4W7NswpUD5DPDL2RH8Lzd9EloWUuvUkHfv4FRLMipH5q2UtyurorBkPeNi1wVWNh3Q==", + "requires": { + "builtins": "^5.0.1", + "eslint-plugin-es": "^4.1.0", + "eslint-utils": "^3.0.0", + "ignore": "^5.1.1", + "is-core-module": "^2.11.0", + "minimatch": "^3.1.2", + "resolve": "^1.22.1", + "semver": "^7.3.8" + } + }, + "multiformats": { + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-13.1.0.tgz", + "integrity": "sha512-HzdtdBwxsIkzpeXzhQ5mAhhuxcHbjEHH+JQoxt7hG/2HGFjjwyolLo7hbaexcnhoEuV4e0TNJ8kkpMjiEYY4VQ==" + }, + "secp256k1": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-5.0.0.tgz", + "integrity": "sha512-TKWX8xvoGHrxVdqbYeZM9w+izTF4b9z3NhSaDkdn81btvuh+ivbIMGT/zQvDtTFWhRlThpoz6LEYTr7n8A5GcA==", + "requires": { + "elliptic": "^6.5.4", + "node-addon-api": "^5.0.0", + "node-gyp-build": "^4.2.0" + }, + "dependencies": { + "node-addon-api": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", + "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==" + } + } + }, + "tiny-secp256k1": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/tiny-secp256k1/-/tiny-secp256k1-2.2.3.tgz", + "integrity": "sha512-SGcL07SxcPN2nGKHTCvRMkQLYPSoeFcvArUSCYtjVARiFAWU44cCIqYS0mYAU6nY7XfvwURuTIGo2Omt3ZQr0Q==", + "requires": { + "uint8array-tools": "0.0.7" + } + } + } + }, "fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", diff --git a/package.json b/package.json index d377bb6..e697a2e 100644 --- a/package.json +++ b/package.json @@ -39,6 +39,7 @@ "encoding": "^0.1.13", "eslint-config-next": "^12.3.4", "filecoin-verifier-tools": "^2.3.0", + "filecoin-verifier-tools-temporary": "^2.3.0", "fuse.js": "^6.6.2", "lucide-react": "^0.260.0", "next": "13.5.6", diff --git a/src/hooks/useApplicationActions.ts b/src/hooks/useApplicationActions.ts index c1cd52d..d0d4e0a 100644 --- a/src/hooks/useApplicationActions.ts +++ b/src/hooks/useApplicationActions.ts @@ -18,6 +18,7 @@ import { useQueryClient, type UseMutationResult, } from 'react-query' +import { getStateWaitMsg } from '@/lib/glifApi' interface ApplicationActions { application: Application @@ -444,7 +445,16 @@ const useApplicationActions = ( 'Error sending proposal. Please try again or contact support.', ) } - + const response = await getStateWaitMsg(messageCID) + if ( + typeof response.data === 'object' && + response.data.ReturnDec.Applied && + response.data.ReturnDec.Code !== 0 + ) { + throw new Error( + `Error sending transaction. Please try again or contact support. Error code: ${response.data.ReturnDec.Code}`, + ) + } return await postApplicationProposal( initialApplication.ID, requestId, diff --git a/src/hooks/useWallet.ts b/src/hooks/useWallet.ts index 404f84d..522c954 100644 --- a/src/hooks/useWallet.ts +++ b/src/hooks/useWallet.ts @@ -268,7 +268,6 @@ const useWallet = (): WalletState => { contractAddress, calldata, activeAccountIndex, - wallet, ) }, [wallet, multisigAddress, activeAccountIndex], diff --git a/src/lib/glifApi.ts b/src/lib/glifApi.ts index e4c0ee1..42ccf96 100644 --- a/src/lib/glifApi.ts +++ b/src/lib/glifApi.ts @@ -1,4 +1,4 @@ -import { type ApiAllowanceResponse } from '@/type' +import type { ApiAllowanceResponse, ApiStateWaitMsgResponse } from '@/type' import { config } from '@/config' /** @@ -94,3 +94,64 @@ export const getAllowanceForClient = async ( } } } + +/** + * Wait for a message to appear on chain and get it. + * + * @param {string} cid - Transaction CID. + * @returns {Promise} ApiStateWaitMsgResponse - The response from the API. + */ +export const getStateWaitMsg = async ( + cid: string, +): Promise => { + try { + const confidence = 1 + const limitChainEpoch = 10 + const allowReplaced = true + const requestBody = { + jsonrpc: '2.0', + method: 'Filecoin.StateWaitMsg', + params: [ + { + '/': cid, + }, + confidence, + limitChainEpoch, + allowReplaced, + ], + id: 1, + } + const response = await fetch(`${config.glifNodeUrl}`, { + method: 'POST', + body: JSON.stringify(requestBody), + }) + + const data = await response.json() + if (data?.error && data.error.data === 'Request timeout') { + return await getStateWaitMsg(cid) + } + + if (data?.error) { + return { + data: '', + error: data.error.message, + success: false, + } + } + + return { + data: data.result, + error: '', + success: true, + } + } catch (error: unknown) { + const errMessage = `Error accessing GLIF API Filecoin.StateWaitMsg: ${ + (error as Error).message + }` + return { + data: '', + error: errMessage, + success: false, + } + } +} diff --git a/src/lib/wallet/BurnerWallet.ts b/src/lib/wallet/BurnerWallet.ts index 274fb4a..5dba12c 100644 --- a/src/lib/wallet/BurnerWallet.ts +++ b/src/lib/wallet/BurnerWallet.ts @@ -1,5 +1,5 @@ import signer from '@zondax/filecoin-signing-tools/js' -import { VerifyAPI } from 'filecoin-verifier-tools' +import { VerifyAPI } from 'filecoin-verifier-tools-temporary' import { config } from '../../config' import { BaseWallet } from './BaseWallet' diff --git a/src/lib/wallet/LedgerWallet.ts b/src/lib/wallet/LedgerWallet.ts index 459f727..b45bf26 100644 --- a/src/lib/wallet/LedgerWallet.ts +++ b/src/lib/wallet/LedgerWallet.ts @@ -1,7 +1,7 @@ import TransportWebUSB from '@ledgerhq/hw-transport-webusb' import signer from '@zondax/filecoin-signing-tools/js' import FilecoinApp from '@zondax/ledger-filecoin' -import { VerifyAPI } from 'filecoin-verifier-tools' +import { VerifyAPI } from 'filecoin-verifier-tools-temporary' import { config } from '../../config' import { BaseWallet } from './BaseWallet' diff --git a/src/type.ts b/src/type.ts index b5b5584..a866fe9 100644 --- a/src/type.ts +++ b/src/type.ts @@ -115,6 +115,42 @@ export interface ApiAllowanceResponse { data: string } +export interface ApiStateWaitMsgResponse { + error: string + success: boolean + data: + | { + Height: number + Message: { + '/': string + } + Receipt: { + EventsRoot: string | null + ExitCode: number + GasUsed: number + Return: string + } + ReturnDec: ApproveReturn | ProposeReturn + TipSet: Array<{ + '/': string + }> + } + | string +} + +interface ApproveReturn { + Applied: boolean + Code: number + Ret: string +} + +interface ProposeReturn { + Applied: boolean + Code: number + Ret: string + TxnID: number +} + export interface LDNActorsResponse { governance_gh_handles: string[] notary_gh_handles: string[]