From 2567952dc5be0f4ae06651198022713e33d12716 Mon Sep 17 00:00:00 2001 From: Jordan Ribbink Date: Mon, 3 Jun 2024 17:37:43 -0700 Subject: [PATCH 01/13] initial commit --- packages/sdk/src/errors/errors.ts | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 packages/sdk/src/errors/errors.ts diff --git a/packages/sdk/src/errors/errors.ts b/packages/sdk/src/errors/errors.ts new file mode 100644 index 000000000..6894228c1 --- /dev/null +++ b/packages/sdk/src/errors/errors.ts @@ -0,0 +1,30 @@ +import { TransactionStatus } from "@onflow/typedefs"; + +export class TransactionError extends Error { + constructor( + public message: string, + public code?: T, + public name: string = "TransactionError" + ) { + super(message); + } + + static fromErrorMessage(message: string) { + return new TransactionError(message); + } + + static fromStatus(status: TransactionStatus): TransactionError | null { + if (!status.errorMessage) return null; + return TransactionError.fromErrorMessage(status.errorMessage); + } +} + +export class TransactionRejectedError extends TransactionError<403> { + constructor(message: string) { + super(message, 403, "TransactionRejectedError"); + } + + static fromErrorMessage(message: string) { + return new TransactionRejectedError(message); + } +} \ No newline at end of file From 404f5b4c68672a85cc7b6e9acde0851a6a4c1707 Mon Sep 17 00:00:00 2001 From: Jordan Ribbink Date: Wed, 5 Jun 2024 23:51:29 -0700 Subject: [PATCH 02/13] PKG -- [fcl] Use TransactionError type for FVM errors encountered when polling TX status --- .changeset/pink-students-divide.md | 5 ++ .changeset/soft-tomatoes-brake.md | 5 ++ .changeset/witty-pants-argue.md | 5 ++ packages/fcl-core/src/transaction/index.js | 17 +++- .../src/transaction/transaction-error.test.ts | 61 +++++++++++++++ .../src/transaction/transaction-error.ts | 21 +++++ packages/typedefs/src/fvm-errors.ts | 77 +++++++++++++++++++ packages/typedefs/src/index.ts | 20 ++++- 8 files changed, 206 insertions(+), 5 deletions(-) create mode 100644 .changeset/pink-students-divide.md create mode 100644 .changeset/soft-tomatoes-brake.md create mode 100644 .changeset/witty-pants-argue.md create mode 100644 packages/fcl-core/src/transaction/transaction-error.test.ts create mode 100644 packages/fcl-core/src/transaction/transaction-error.ts create mode 100644 packages/typedefs/src/fvm-errors.ts diff --git a/.changeset/pink-students-divide.md b/.changeset/pink-students-divide.md new file mode 100644 index 000000000..4f0849df4 --- /dev/null +++ b/.changeset/pink-students-divide.md @@ -0,0 +1,5 @@ +--- +"@onflow/typedefs": minor +--- + +Add missing field to TransactionStatus type diff --git a/.changeset/soft-tomatoes-brake.md b/.changeset/soft-tomatoes-brake.md new file mode 100644 index 000000000..719088952 --- /dev/null +++ b/.changeset/soft-tomatoes-brake.md @@ -0,0 +1,5 @@ +--- +"@onflow/typedefs": minor +--- + +Add FvmErrorCode enum for categorizing transaction/script execution errors diff --git a/.changeset/witty-pants-argue.md b/.changeset/witty-pants-argue.md new file mode 100644 index 000000000..2e52dd184 --- /dev/null +++ b/.changeset/witty-pants-argue.md @@ -0,0 +1,5 @@ +--- +"@onflow/fcl-core": minor +--- + +Add custom error `TransactionError` type for failing transaction results diff --git a/packages/fcl-core/src/transaction/index.js b/packages/fcl-core/src/transaction/index.js index 3f985269a..df78e1292 100644 --- a/packages/fcl-core/src/transaction/index.js +++ b/packages/fcl-core/src/transaction/index.js @@ -12,6 +12,7 @@ import { import {send as fclSend, decode, getTransactionStatus} from "@onflow/sdk" import {HTTPRequestError} from "@onflow/transport-http" import {grpc} from "@improbable-eng/grpc-web" +import {TransactionError} from "./transaction-error" const TXID_REGEXP = /^[0-9a-fA-F]{64}$/ @@ -149,12 +150,20 @@ export function transaction( const suppress = opts.suppress || false return new Promise((resolve, reject) => { const unsub = subscribe((txStatus, error) => { - if ((error || txStatus.statusCode) && !suppress) { - reject(error || txStatus.errorMessage) - unsub() + if (!suppress) { + const transactionError = new TransactionError.from(txStatus) + if (error != null) { + reject(transactionError) + unsub() + } else if (transactionError != null) { + reject(transactionError) + unsub() + } } else if (predicate(txStatus)) { resolve(txStatus) unsub() + } else { + return } }) }) @@ -176,3 +185,5 @@ transaction.isFinalized = isFinalized transaction.isExecuted = isExecuted transaction.isSealed = isSealed transaction.isExpired = isExpired + +export {TransactionError} diff --git a/packages/fcl-core/src/transaction/transaction-error.test.ts b/packages/fcl-core/src/transaction/transaction-error.test.ts new file mode 100644 index 000000000..0f2c7d8a2 --- /dev/null +++ b/packages/fcl-core/src/transaction/transaction-error.test.ts @@ -0,0 +1,61 @@ +import {FvmErrorCode, TransactionStatus} from "@onflow/typedefs" +import {TransactionError} from "./transaction-error" + +describe("TransactionError", () => { + test("parses transaction error from status", () => { + const status: TransactionStatus = { + blockId: "123", + status: 1, + statusString: "PENDING", + statusCode: 1, + errorMessage: "Transaction rejected by the network", + events: [], + } + const error = TransactionError.from(status) + expect(error).toBeInstanceOf(TransactionError) + expect(error!.message).toEqual("Transaction rejected by the network") + expect(error!.code).toBeUndefined() + }) + + test("parses transaction error with code from status", () => { + const status: TransactionStatus = { + blockId: "123", + status: 1, + statusString: "PENDING", + statusCode: 1, + errorMessage: "[Error Code: 1101] Some Cadence Error", + events: [], + } + const error = TransactionError.from(status) + expect(error).toBeInstanceOf(TransactionError) + expect(error!.message).toEqual("[Error Code: 1101] Some Cadence Error") + expect(error!.code).toEqual(FvmErrorCode.CadenceRunTimeError) + }) + + test("returns null for successful transaction", () => { + const status: TransactionStatus = { + blockId: "123", + status: 1, + statusString: "PENDING", + statusCode: 0, + errorMessage: "", + events: [], + } + const error = TransactionError.from(status) + expect(error).toBeNull() + }) + + test("returns unknown error for missing error message", () => { + const status: TransactionStatus = { + blockId: "123", + status: 1, + statusString: "PENDING", + statusCode: 1, + errorMessage: "", + events: [], + } + const error = TransactionError.from(status) + expect(error).toBeInstanceOf(TransactionError) + expect(error!.message).toEqual("Unknown error") + }) +}) diff --git a/packages/fcl-core/src/transaction/transaction-error.ts b/packages/fcl-core/src/transaction/transaction-error.ts new file mode 100644 index 000000000..2ecf8d221 --- /dev/null +++ b/packages/fcl-core/src/transaction/transaction-error.ts @@ -0,0 +1,21 @@ +import {FvmErrorCode, TransactionStatus} from "@onflow/typedefs" + +const ERROR_CODE_REGEX = /\[Error Code: (\d+)\]/ + +export class TransactionError extends Error { + public code?: FvmErrorCode + + private constructor(message: string, code?: FvmErrorCode) { + super(message) + this.code = code + } + + static from(status: TransactionStatus): TransactionError | null { + if (status.statusCode === 0) return null + + const match = status.errorMessage.match(ERROR_CODE_REGEX) + const code = match ? parseInt(match[1]) : undefined + + return new TransactionError(status.errorMessage || "Unknown error", code) + } +} diff --git a/packages/typedefs/src/fvm-errors.ts b/packages/typedefs/src/fvm-errors.ts new file mode 100644 index 000000000..1134d006b --- /dev/null +++ b/packages/typedefs/src/fvm-errors.ts @@ -0,0 +1,77 @@ +export enum FvmErrorCode { + // tx validation errors 1000 - 1049 + // Deprecated: no longer in use + TxValidationError = 1000, + // Deprecated: No longer used. + InvalidTxByteSizeError = 1001, + // Deprecated: No longer used. + InvalidReferenceBlockError = 1002, + // Deprecated: No longer used. + ExpiredTransactionError = 1003, + // Deprecated: No longer used. + InvalidScriptError = 1004, + // Deprecated: No longer used. + InvalidGasLimitError = 1005, + InvalidProposalSignatureError = 1006, + InvalidProposalSeqNumberError = 1007, + InvalidPayloadSignatureError = 1008, + InvalidEnvelopeSignatureError = 1009, + + // base errors 1050 - 1100 + // Deprecated: No longer used. + FVMInternalError = 1050, + ValueError = 1051, + InvalidArgumentError = 1052, + InvalidAddressError = 1053, + InvalidLocationError = 1054, + AccountAuthorizationError = 1055, + OperationAuthorizationError = 1056, + OperationNotSupportedError = 1057, + BlockHeightOutOfRangeError = 1058, + + // execution errors 1100 - 1200 + // Deprecated: No longer used. + ExecutionError = 1100, + CadenceRunTimeError = 1101, + // Deprecated: No longer used. + EncodingUnsupportedValue = 1102, + StorageCapacityExceeded = 1103, + // Deprecated: No longer used. + GasLimitExceededError = 1104, + EventLimitExceededError = 1105, + LedgerInteractionLimitExceededError = 1106, + StateKeySizeLimitError = 1107, + StateValueSizeLimitError = 1108, + TransactionFeeDeductionFailedError = 1109, + ComputationLimitExceededError = 1110, + MemoryLimitExceededError = 1111, + CouldNotDecodeExecutionParameterFromState = 1112, + ScriptExecutionTimedOutError = 1113, + ScriptExecutionCancelledError = 1114, + EventEncodingError = 1115, + InvalidInternalStateAccessError = 1116, + // 1117 was never deployed and is free to use + InsufficientPayerBalance = 1118, + + // accounts errors 1200 - 1250 + // Deprecated: No longer used. + AccountError = 1200, + AccountNotFoundError = 1201, + AccountPublicKeyNotFoundError = 1202, + AccountAlreadyExistsError = 1203, + // Deprecated: No longer used. + FrozenAccountError = 1204, + // Deprecated: No longer used. + AccountStorageNotInitializedError = 1205, + AccountPublicKeyLimitError = 1206, + + // contract errors 1250 - 1300 + // Deprecated: No longer used. + ContractError = 1250, + ContractNotFoundError = 1251, + // Deprecated: No longer used. + ContractNamesNotFoundError = 1252, + + // fvm std lib errors 1300-1400 + EVMExecutionError = 1300, +} diff --git a/packages/typedefs/src/index.ts b/packages/typedefs/src/index.ts index 097c3e477..c6d0250ba 100644 --- a/packages/typedefs/src/index.ts +++ b/packages/typedefs/src/index.ts @@ -330,13 +330,17 @@ export type TransactionStatus = { */ blockId: string /** - * - The status code of the transaction. + * - The execution status of the transaction */ - status: number + status: TransactionExecutionStatus /** * - The status as as descriptive text (e.g. "FINALIZED"). */ statusString: string + /** + * - The result of the transaction, if executed (i.e. 0 for success, 1 for failure) + */ + statusCode: 0 | 1 /** * - The error message of the transaction. */ @@ -346,6 +350,17 @@ export type TransactionStatus = { */ events: Array } +/** + * The execution status of the transaction. + */ +export enum TransactionExecutionStatus { + UNKNOWN = 0, + PENDING = 1, + FINALIZED = 2, + EXECUTED = 3, + SEALED = 4, + EXPIRED = 5, +} export type Provider = { /** * - Provider name. @@ -412,3 +427,4 @@ export type EventStream = StreamConnection<{ }> export * from "./interaction" +export * from "./fvm-errors" From 226cc4e39ccc26b5321aa9ed0fa07633a87cd652 Mon Sep 17 00:00:00 2001 From: Jordan Ribbink Date: Thu, 6 Jun 2024 00:24:09 -0700 Subject: [PATCH 03/13] fix casing --- .../src/transaction/transaction-error.test.ts | 2 +- packages/typedefs/src/fvm-errors.ts | 96 +++++++++---------- 2 files changed, 49 insertions(+), 49 deletions(-) diff --git a/packages/fcl-core/src/transaction/transaction-error.test.ts b/packages/fcl-core/src/transaction/transaction-error.test.ts index 0f2c7d8a2..59a436b5c 100644 --- a/packages/fcl-core/src/transaction/transaction-error.test.ts +++ b/packages/fcl-core/src/transaction/transaction-error.test.ts @@ -29,7 +29,7 @@ describe("TransactionError", () => { const error = TransactionError.from(status) expect(error).toBeInstanceOf(TransactionError) expect(error!.message).toEqual("[Error Code: 1101] Some Cadence Error") - expect(error!.code).toEqual(FvmErrorCode.CadenceRunTimeError) + expect(error!.code).toEqual(FvmErrorCode.CADENCE_RUNTIME_ERROR) }) test("returns null for successful transaction", () => { diff --git a/packages/typedefs/src/fvm-errors.ts b/packages/typedefs/src/fvm-errors.ts index 1134d006b..1b063911c 100644 --- a/packages/typedefs/src/fvm-errors.ts +++ b/packages/typedefs/src/fvm-errors.ts @@ -1,77 +1,77 @@ export enum FvmErrorCode { // tx validation errors 1000 - 1049 // Deprecated: no longer in use - TxValidationError = 1000, + TX_VALIDATION_ERROR = 1000, // Deprecated: No longer used. - InvalidTxByteSizeError = 1001, + INVALID_TX_BYTE_SIZE_ERROR = 1001, // Deprecated: No longer used. - InvalidReferenceBlockError = 1002, + INVALID_REFERENCE_BLOCK_ERROR = 1002, // Deprecated: No longer used. - ExpiredTransactionError = 1003, + EXPIRED_TRANSACTION_ERROR = 1003, // Deprecated: No longer used. - InvalidScriptError = 1004, + INVALID_SCRIPT_ERROR = 1004, // Deprecated: No longer used. - InvalidGasLimitError = 1005, - InvalidProposalSignatureError = 1006, - InvalidProposalSeqNumberError = 1007, - InvalidPayloadSignatureError = 1008, - InvalidEnvelopeSignatureError = 1009, + INVALID_GAS_LIMIT_ERROR = 1005, + INVALID_PROPOSAL_SIGNATURE_ERROR = 1006, + INVALID_PROPOSAL_SEQ_NUMBER_ERROR = 1007, + INVALID_PAYLOAD_SIGNATURE_ERROR = 1008, + INVALID_ENVELOPE_SIGNATURE_ERROR = 1009, // base errors 1050 - 1100 // Deprecated: No longer used. - FVMInternalError = 1050, - ValueError = 1051, - InvalidArgumentError = 1052, - InvalidAddressError = 1053, - InvalidLocationError = 1054, - AccountAuthorizationError = 1055, - OperationAuthorizationError = 1056, - OperationNotSupportedError = 1057, - BlockHeightOutOfRangeError = 1058, + FVM_INTERNAL_ERROR = 1050, + VALUE_ERROR = 1051, + INVALID_ARGUMENT_ERROR = 1052, + INVALID_ADDRESS_ERROR = 1053, + INVALID_LOCATION_ERROR = 1054, + ACCOUNT_AUTHORIZATION_ERROR = 1055, + OPERATION_AUTHORIZATION_ERROR = 1056, + OPERATION_NOT_SUPPORTED_ERROR = 1057, + BLOCK_HEIGHT_OUT_OF_RANGE_ERROR = 1058, // execution errors 1100 - 1200 // Deprecated: No longer used. - ExecutionError = 1100, - CadenceRunTimeError = 1101, + EXECUTION_ERROR = 1100, + CADENCE_RUNTIME_ERROR = 1101, // Deprecated: No longer used. - EncodingUnsupportedValue = 1102, - StorageCapacityExceeded = 1103, + ENCODING_UNSUPPORTED_VALUE = 1102, + STORAGE_CAPACITY_EXCEEDED = 1103, // Deprecated: No longer used. - GasLimitExceededError = 1104, - EventLimitExceededError = 1105, - LedgerInteractionLimitExceededError = 1106, - StateKeySizeLimitError = 1107, - StateValueSizeLimitError = 1108, - TransactionFeeDeductionFailedError = 1109, - ComputationLimitExceededError = 1110, - MemoryLimitExceededError = 1111, - CouldNotDecodeExecutionParameterFromState = 1112, - ScriptExecutionTimedOutError = 1113, - ScriptExecutionCancelledError = 1114, - EventEncodingError = 1115, - InvalidInternalStateAccessError = 1116, + GAS_LIMIT_EXCEEDED_ERROR = 1104, + EVENT_LIMIT_EXCEEDED_ERROR = 1105, + LEDGER_INTERACTION_LIMIT_EXCEEDED_ERROR = 1106, + STATE_KEY_SIZE_LIMIT_ERROR = 1107, + STATE_VALUE_SIZE_LIMIT_ERROR = 1108, + TRANSACTION_FEE_DEDUCTION_FAILED_ERROR = 1109, + COMPUTATION_LIMIT_EXCEEDED_ERROR = 1110, + MEMORY_LIMIT_EXCEEDED_ERROR = 1111, + COULD_NOT_DECODE_EXECUTION_PARAMETER_FROM_STATE = 1112, + SCRIPT_EXECUTION_TIMED_OUT_ERROR = 1113, + SCRIPT_EXECUTION_CANCELLED_ERROR = 1114, + EVENT_ENCODING_ERROR = 1115, + INVALID_INTERNAL_STATE_ACCESS_ERROR = 1116, // 1117 was never deployed and is free to use - InsufficientPayerBalance = 1118, + INSUFFICIENT_PAYER_BALANCE = 1118, // accounts errors 1200 - 1250 // Deprecated: No longer used. - AccountError = 1200, - AccountNotFoundError = 1201, - AccountPublicKeyNotFoundError = 1202, - AccountAlreadyExistsError = 1203, + ACCOUNT_ERROR = 1200, + ACCOUNT_NOT_FOUND_ERROR = 1201, + ACCOUNT_PUBLIC_KEY_NOT_FOUND_ERROR = 1202, + ACCOUNT_ALREADY_EXISTS_ERROR = 1203, // Deprecated: No longer used. - FrozenAccountError = 1204, + FROZEN_ACCOUNT_ERROR = 1204, // Deprecated: No longer used. - AccountStorageNotInitializedError = 1205, - AccountPublicKeyLimitError = 1206, + ACCOUNT_STORAGE_NOT_INITIALIZED_ERROR = 1205, + ACCOUNT_PUBLIC_KEY_LIMIT_ERROR = 1206, // contract errors 1250 - 1300 // Deprecated: No longer used. - ContractError = 1250, - ContractNotFoundError = 1251, + CONTRACT_ERROR = 1250, + CONTRACT_NOT_FOUND_ERROR = 1251, // Deprecated: No longer used. - ContractNamesNotFoundError = 1252, + CONTRACT_NAMES_NOT_FOUND_ERROR = 1252, // fvm std lib errors 1300-1400 - EVMExecutionError = 1300, + EVM_EXECUTION_ERROR = 1300, } From d098479866ae44d519c0c0e37a66ff4e3825c73b Mon Sep 17 00:00:00 2001 From: Jordan Ribbink Date: Thu, 6 Jun 2024 00:33:18 -0700 Subject: [PATCH 04/13] prettier --- packages/sdk/src/errors/errors.ts | 46 ++++++++++++++++--------------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/packages/sdk/src/errors/errors.ts b/packages/sdk/src/errors/errors.ts index 6894228c1..776095ce7 100644 --- a/packages/sdk/src/errors/errors.ts +++ b/packages/sdk/src/errors/errors.ts @@ -1,30 +1,32 @@ -import { TransactionStatus } from "@onflow/typedefs"; +import {TransactionStatus} from "@onflow/typedefs" export class TransactionError extends Error { - constructor( - public message: string, - public code?: T, - public name: string = "TransactionError" - ) { - super(message); - } + constructor( + public message: string, + public code?: T, + public name: string = "TransactionError" + ) { + super(message) + } - static fromErrorMessage(message: string) { - return new TransactionError(message); - } + static fromErrorMessage(message: string) { + return new TransactionError(message) + } - static fromStatus(status: TransactionStatus): TransactionError | null { - if (!status.errorMessage) return null; - return TransactionError.fromErrorMessage(status.errorMessage); - } + static fromStatus( + status: TransactionStatus + ): TransactionError | null { + if (!status.errorMessage) return null + return TransactionError.fromErrorMessage(status.errorMessage) + } } export class TransactionRejectedError extends TransactionError<403> { - constructor(message: string) { - super(message, 403, "TransactionRejectedError"); - } + constructor(message: string) { + super(message, 403, "TransactionRejectedError") + } - static fromErrorMessage(message: string) { - return new TransactionRejectedError(message); - } -} \ No newline at end of file + static fromErrorMessage(message: string) { + return new TransactionRejectedError(message) + } +} From c9e9af514182641c729e8de1b3e0f9e1200ef48b Mon Sep 17 00:00:00 2001 From: Jordan Ribbink Date: Thu, 6 Jun 2024 13:42:56 -0700 Subject: [PATCH 05/13] fix conditional --- packages/fcl-core/src/transaction/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/fcl-core/src/transaction/index.js b/packages/fcl-core/src/transaction/index.js index df78e1292..ee837632c 100644 --- a/packages/fcl-core/src/transaction/index.js +++ b/packages/fcl-core/src/transaction/index.js @@ -155,15 +155,15 @@ export function transaction( if (error != null) { reject(transactionError) unsub() + return } else if (transactionError != null) { reject(transactionError) unsub() + return } } else if (predicate(txStatus)) { resolve(txStatus) unsub() - } else { - return } }) }) From 06ddbbad493790afba8c55c7fb5fc144394b4480 Mon Sep 17 00:00:00 2001 From: Jordan Ribbink Date: Fri, 14 Jun 2024 11:05:24 -0700 Subject: [PATCH 06/13] Update packages/fcl-core/src/transaction/transaction-error.ts Co-authored-by: Alex <12097569+nialexsan@users.noreply.github.com> --- packages/fcl-core/src/transaction/transaction-error.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/fcl-core/src/transaction/transaction-error.ts b/packages/fcl-core/src/transaction/transaction-error.ts index 2ecf8d221..231fb4fe8 100644 --- a/packages/fcl-core/src/transaction/transaction-error.ts +++ b/packages/fcl-core/src/transaction/transaction-error.ts @@ -14,7 +14,7 @@ export class TransactionError extends Error { if (status.statusCode === 0) return null const match = status.errorMessage.match(ERROR_CODE_REGEX) - const code = match ? parseInt(match[1]) : undefined + const code = match ? parseInt(match[1], 10) : undefined return new TransactionError(status.errorMessage || "Unknown error", code) } From a9c4c5cda24bf8bb1df80b0c044b1d0f68ffdb9f Mon Sep 17 00:00:00 2001 From: Jordan Ribbink Date: Wed, 9 Oct 2024 08:50:28 -0700 Subject: [PATCH 07/13] stash --- .../fcl-core/src/transaction/transaction-error.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/packages/fcl-core/src/transaction/transaction-error.ts b/packages/fcl-core/src/transaction/transaction-error.ts index 231fb4fe8..42b6a37d9 100644 --- a/packages/fcl-core/src/transaction/transaction-error.ts +++ b/packages/fcl-core/src/transaction/transaction-error.ts @@ -9,13 +9,15 @@ export class TransactionError extends Error { super(message) this.code = code } +} - static from(status: TransactionStatus): TransactionError | null { - if (status.statusCode === 0) return null +function createTransactionError( + status: TransactionStatus +): TransactionError | null { + if (status.statusCode === 0) return null - const match = status.errorMessage.match(ERROR_CODE_REGEX) - const code = match ? parseInt(match[1], 10) : undefined + const match = status.errorMessage.match(ERROR_CODE_REGEX) + const code = match ? parseInt(match[1], 10) : undefined - return new TransactionError(status.errorMessage || "Unknown error", code) - } + return new TransactionError(status.errorMessage || "Unknown error", code) } From 027c44581e45b1d4dc76ba0cac792376d4121e4a Mon Sep 17 00:00:00 2001 From: Jordan Ribbink Date: Wed, 23 Oct 2024 10:08:53 -0700 Subject: [PATCH 08/13] remove sdk errors --- packages/sdk/src/errors/errors.ts | 32 ------------------------------- 1 file changed, 32 deletions(-) delete mode 100644 packages/sdk/src/errors/errors.ts diff --git a/packages/sdk/src/errors/errors.ts b/packages/sdk/src/errors/errors.ts deleted file mode 100644 index 776095ce7..000000000 --- a/packages/sdk/src/errors/errors.ts +++ /dev/null @@ -1,32 +0,0 @@ -import {TransactionStatus} from "@onflow/typedefs" - -export class TransactionError extends Error { - constructor( - public message: string, - public code?: T, - public name: string = "TransactionError" - ) { - super(message) - } - - static fromErrorMessage(message: string) { - return new TransactionError(message) - } - - static fromStatus( - status: TransactionStatus - ): TransactionError | null { - if (!status.errorMessage) return null - return TransactionError.fromErrorMessage(status.errorMessage) - } -} - -export class TransactionRejectedError extends TransactionError<403> { - constructor(message: string) { - super(message, 403, "TransactionRejectedError") - } - - static fromErrorMessage(message: string) { - return new TransactionRejectedError(message) - } -} From 779244a0f0071b2804775f93755079d8c77c5784 Mon Sep 17 00:00:00 2001 From: Jordan Ribbink Date: Wed, 23 Oct 2024 11:27:16 -0700 Subject: [PATCH 09/13] stash --- packages/fcl-core/src/transaction/transaction-error.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/fcl-core/src/transaction/transaction-error.ts b/packages/fcl-core/src/transaction/transaction-error.ts index 42b6a37d9..9e3a23a62 100644 --- a/packages/fcl-core/src/transaction/transaction-error.ts +++ b/packages/fcl-core/src/transaction/transaction-error.ts @@ -11,13 +11,13 @@ export class TransactionError extends Error { } } -function createTransactionError( +export function parseTransactionErrorCode( status: TransactionStatus -): TransactionError | null { +): FvmErrorCode | undefined { if (status.statusCode === 0) return null const match = status.errorMessage.match(ERROR_CODE_REGEX) const code = match ? parseInt(match[1], 10) : undefined - return new TransactionError(status.errorMessage || "Unknown error", code) + return code || FvmErrorCode.Unknown } From 00b64378ef7df0a770847776c02f0bb2fd186a0c Mon Sep 17 00:00:00 2001 From: Jordan Ribbink Date: Thu, 24 Oct 2024 12:32:19 -0700 Subject: [PATCH 10/13] Update --- packages/fcl-core/src/transaction/index.js | 12 +-- .../src/transaction/transaction-error.test.ts | 75 +++++++------------ .../src/transaction/transaction-error.ts | 16 ++-- 3 files changed, 38 insertions(+), 65 deletions(-) diff --git a/packages/fcl-core/src/transaction/index.js b/packages/fcl-core/src/transaction/index.js index ee837632c..4685d8ce1 100644 --- a/packages/fcl-core/src/transaction/index.js +++ b/packages/fcl-core/src/transaction/index.js @@ -12,7 +12,7 @@ import { import {send as fclSend, decode, getTransactionStatus} from "@onflow/sdk" import {HTTPRequestError} from "@onflow/transport-http" import {grpc} from "@improbable-eng/grpc-web" -import {TransactionError} from "./transaction-error" +import {TransactionError, parseTransactionErrorCode} from "./transaction-error" const TXID_REGEXP = /^[0-9a-fA-F]{64}$/ @@ -151,17 +151,19 @@ export function transaction( return new Promise((resolve, reject) => { const unsub = subscribe((txStatus, error) => { if (!suppress) { - const transactionError = new TransactionError.from(txStatus) if (error != null) { - reject(transactionError) + reject(error) unsub() return - } else if (transactionError != null) { + } else if (txStatus.statusCode === 1) { + const transactionError = parseTransactionErrorCode(txStatus) reject(transactionError) unsub() return } - } else if (predicate(txStatus)) { + } + + if (predicate(txStatus)) { resolve(txStatus) unsub() } diff --git a/packages/fcl-core/src/transaction/transaction-error.test.ts b/packages/fcl-core/src/transaction/transaction-error.test.ts index 59a436b5c..d5d6a4704 100644 --- a/packages/fcl-core/src/transaction/transaction-error.test.ts +++ b/packages/fcl-core/src/transaction/transaction-error.test.ts @@ -1,61 +1,36 @@ -import {FvmErrorCode, TransactionStatus} from "@onflow/typedefs" -import {TransactionError} from "./transaction-error" +import {FvmErrorCode} from "@onflow/typedefs" +import {parseTransactionErrorCode} from "./transaction-error" -describe("TransactionError", () => { - test("parses transaction error from status", () => { - const status: TransactionStatus = { - blockId: "123", - status: 1, - statusString: "PENDING", - statusCode: 1, - errorMessage: "Transaction rejected by the network", - events: [], - } - const error = TransactionError.from(status) - expect(error).toBeInstanceOf(TransactionError) - expect(error!.message).toEqual("Transaction rejected by the network") - expect(error!.code).toBeUndefined() +describe("parseTransactionErrorCode", () => { + test("returns unknown error if no code exists", () => { + const errorMessage = "Transaction rejected by the network" + const errorCode = parseTransactionErrorCode(status) + expect(errorCode).toEqual(FvmErrorCode.UNKNOWN_ERROR) }) test("parses transaction error with code from status", () => { - const status: TransactionStatus = { - blockId: "123", - status: 1, - statusString: "PENDING", - statusCode: 1, - errorMessage: "[Error Code: 1101] Some Cadence Error", - events: [], - } - const error = TransactionError.from(status) - expect(error).toBeInstanceOf(TransactionError) - expect(error!.message).toEqual("[Error Code: 1101] Some Cadence Error") - expect(error!.code).toEqual(FvmErrorCode.CADENCE_RUNTIME_ERROR) + const errorMessage = "[Error Code: 1101] Some Cadence Error" + const errorCode = parseTransactionErrorCode(errorMessage) + expect(errorCode).toEqual(FvmErrorCode.CADENCE_RUNTIME_ERROR) }) - test("returns null for successful transaction", () => { - const status: TransactionStatus = { - blockId: "123", - status: 1, - statusString: "PENDING", - statusCode: 0, - errorMessage: "", - events: [], - } - const error = TransactionError.from(status) - expect(error).toBeNull() + test("uses first instance of error code in message", () => { + const errorMessage = + "[Error Code: 1102] Some Cadence Error [Error Code: 1105] Something else to say" + const errorCode = parseTransactionErrorCode(errorMessage) + expect(errorCode).toEqual(FvmErrorCode.ENCODING_UNSUPPORTED_VALUE) + }) + + test("allows leading text before error code", () => { + const errorMessage = + "This is a message [Error Code: 1102] Some Cadence Error" + const errorCode = parseTransactionErrorCode(errorMessage) + expect(errorCode).toEqual(FvmErrorCode.ENCODING_UNSUPPORTED_VALUE) }) test("returns unknown error for missing error message", () => { - const status: TransactionStatus = { - blockId: "123", - status: 1, - statusString: "PENDING", - statusCode: 1, - errorMessage: "", - events: [], - } - const error = TransactionError.from(status) - expect(error).toBeInstanceOf(TransactionError) - expect(error!.message).toEqual("Unknown error") + const errorMessage = "" + const errorCode = parseTransactionErrorCode(errorMessage) + expect(errorCode).toEqual(FvmErrorCode.UNKNOWN_ERROR) }) }) diff --git a/packages/fcl-core/src/transaction/transaction-error.ts b/packages/fcl-core/src/transaction/transaction-error.ts index 9e3a23a62..6d182c268 100644 --- a/packages/fcl-core/src/transaction/transaction-error.ts +++ b/packages/fcl-core/src/transaction/transaction-error.ts @@ -1,23 +1,19 @@ -import {FvmErrorCode, TransactionStatus} from "@onflow/typedefs" +import {FvmErrorCode} from "@onflow/typedefs" const ERROR_CODE_REGEX = /\[Error Code: (\d+)\]/ export class TransactionError extends Error { - public code?: FvmErrorCode + public code: FvmErrorCode - private constructor(message: string, code?: FvmErrorCode) { + constructor(message: string, code: FvmErrorCode) { super(message) this.code = code } } -export function parseTransactionErrorCode( - status: TransactionStatus -): FvmErrorCode | undefined { - if (status.statusCode === 0) return null - - const match = status.errorMessage.match(ERROR_CODE_REGEX) +export function parseTransactionErrorCode(errorMessage: string): FvmErrorCode { + const match = errorMessage.match(ERROR_CODE_REGEX) const code = match ? parseInt(match[1], 10) : undefined - return code || FvmErrorCode.Unknown + return code || FvmErrorCode.UNKNOWN_ERROR } From 758c982afa7603b290326468b1b6cb1f3030fbc1 Mon Sep 17 00:00:00 2001 From: Jordan Ribbink Date: Thu, 24 Oct 2024 12:49:58 -0700 Subject: [PATCH 11/13] revert TransactionError interface --- packages/fcl-core/src/transaction/index.js | 4 +- .../src/transaction/transaction-error.test.ts | 68 +++++++++++-------- .../src/transaction/transaction-error.ts | 17 +++-- packages/typedefs/src/fvm-errors.ts | 3 + 4 files changed, 57 insertions(+), 35 deletions(-) diff --git a/packages/fcl-core/src/transaction/index.js b/packages/fcl-core/src/transaction/index.js index 4685d8ce1..332161b8b 100644 --- a/packages/fcl-core/src/transaction/index.js +++ b/packages/fcl-core/src/transaction/index.js @@ -156,7 +156,9 @@ export function transaction( unsub() return } else if (txStatus.statusCode === 1) { - const transactionError = parseTransactionErrorCode(txStatus) + const transactionError = TransactionError.fromErrorMessage( + txStatus.errorMessage + ) reject(transactionError) unsub() return diff --git a/packages/fcl-core/src/transaction/transaction-error.test.ts b/packages/fcl-core/src/transaction/transaction-error.test.ts index d5d6a4704..3506787f7 100644 --- a/packages/fcl-core/src/transaction/transaction-error.test.ts +++ b/packages/fcl-core/src/transaction/transaction-error.test.ts @@ -1,36 +1,48 @@ import {FvmErrorCode} from "@onflow/typedefs" -import {parseTransactionErrorCode} from "./transaction-error" +import {TransactionError} from "./transaction-error" -describe("parseTransactionErrorCode", () => { - test("returns unknown error if no code exists", () => { - const errorMessage = "Transaction rejected by the network" - const errorCode = parseTransactionErrorCode(status) - expect(errorCode).toEqual(FvmErrorCode.UNKNOWN_ERROR) - }) +describe("TransactionError", () => { + describe("fromErrorMessage", () => { + test("returns unknown error if no code exists", () => { + const errorMessage = "Transaction rejected by the network" + const error = TransactionError.fromErrorMessage(errorMessage) + expect(error).toBeInstanceOf(TransactionError) + expect(error.code).toEqual(FvmErrorCode.UNKNOWN_ERROR) + expect(error.type).toEqual("UNKNOWN_ERROR") + }) - test("parses transaction error with code from status", () => { - const errorMessage = "[Error Code: 1101] Some Cadence Error" - const errorCode = parseTransactionErrorCode(errorMessage) - expect(errorCode).toEqual(FvmErrorCode.CADENCE_RUNTIME_ERROR) - }) + test("parses transaction error with code from status", () => { + const errorMessage = "[Error Code: 1101] Some Cadence Error" + const error = TransactionError.fromErrorMessage(errorMessage) + expect(error).toBeInstanceOf(TransactionError) + expect(error.code).toEqual(FvmErrorCode.CADENCE_RUNTIME_ERROR) + expect(error.type).toEqual("CADENCE_RUNTIME_ERROR") + }) - test("uses first instance of error code in message", () => { - const errorMessage = - "[Error Code: 1102] Some Cadence Error [Error Code: 1105] Something else to say" - const errorCode = parseTransactionErrorCode(errorMessage) - expect(errorCode).toEqual(FvmErrorCode.ENCODING_UNSUPPORTED_VALUE) - }) + test("uses first instance of error code in message", () => { + const errorMessage = + "[Error Code: 1102] Unsupported value... [Error Code: 1105] Something else to say" + const error = TransactionError.fromErrorMessage(errorMessage) + expect(error).toBeInstanceOf(TransactionError) + expect(error.code).toEqual(FvmErrorCode.ENCODING_UNSUPPORTED_VALUE) + expect(error.type).toEqual("ENCODING_UNSUPPORTED_VALUE") + }) - test("allows leading text before error code", () => { - const errorMessage = - "This is a message [Error Code: 1102] Some Cadence Error" - const errorCode = parseTransactionErrorCode(errorMessage) - expect(errorCode).toEqual(FvmErrorCode.ENCODING_UNSUPPORTED_VALUE) - }) + test("allows leading text before error code", () => { + const errorMessage = + "This is a message [Error Code: 1102] Unsupported value" + const error = TransactionError.fromErrorMessage(errorMessage) + expect(error).toBeInstanceOf(TransactionError) + expect(error.code).toEqual(FvmErrorCode.ENCODING_UNSUPPORTED_VALUE) + expect(error.type).toEqual("ENCODING_UNSUPPORTED_VALUE") + }) - test("returns unknown error for missing error message", () => { - const errorMessage = "" - const errorCode = parseTransactionErrorCode(errorMessage) - expect(errorCode).toEqual(FvmErrorCode.UNKNOWN_ERROR) + test("returns unknown error for missing error message", () => { + const errorMessage = "" + const error = TransactionError.fromErrorMessage(errorMessage) + expect(error).toBeInstanceOf(TransactionError) + expect(error.code).toEqual(FvmErrorCode.UNKNOWN_ERROR) + expect(error.type).toEqual("UNKNOWN_ERROR") + }) }) }) diff --git a/packages/fcl-core/src/transaction/transaction-error.ts b/packages/fcl-core/src/transaction/transaction-error.ts index 6d182c268..4fca209ab 100644 --- a/packages/fcl-core/src/transaction/transaction-error.ts +++ b/packages/fcl-core/src/transaction/transaction-error.ts @@ -4,16 +4,21 @@ const ERROR_CODE_REGEX = /\[Error Code: (\d+)\]/ export class TransactionError extends Error { public code: FvmErrorCode + public type: string - constructor(message: string, code: FvmErrorCode) { + private constructor(message: string, code: FvmErrorCode) { super(message) this.code = code + this.type = FvmErrorCode[code] } -} -export function parseTransactionErrorCode(errorMessage: string): FvmErrorCode { - const match = errorMessage.match(ERROR_CODE_REGEX) - const code = match ? parseInt(match[1], 10) : undefined + static fromErrorMessage(errorMessage: string): TransactionError { + const match = errorMessage.match(ERROR_CODE_REGEX) + const code = match ? parseInt(match[1], 10) : undefined - return code || FvmErrorCode.UNKNOWN_ERROR + return new TransactionError( + errorMessage, + code || FvmErrorCode.UNKNOWN_ERROR + ) + } } diff --git a/packages/typedefs/src/fvm-errors.ts b/packages/typedefs/src/fvm-errors.ts index 1b063911c..9c5d68441 100644 --- a/packages/typedefs/src/fvm-errors.ts +++ b/packages/typedefs/src/fvm-errors.ts @@ -1,4 +1,7 @@ export enum FvmErrorCode { + // We use -1 for unknown error in FCL because FVM defines error codes as uint16 + // This means we have no risk of collision with FVM error codes + UNKNOWN_ERROR = -1, // tx validation errors 1000 - 1049 // Deprecated: no longer in use TX_VALIDATION_ERROR = 1000, From 9487b95447d52ee76db3604e5a46f2f14d825682 Mon Sep 17 00:00:00 2001 From: Jordan Ribbink Date: Thu, 24 Oct 2024 12:58:21 -0700 Subject: [PATCH 12/13] fix else --- packages/fcl-core/src/transaction/index.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/fcl-core/src/transaction/index.js b/packages/fcl-core/src/transaction/index.js index 332161b8b..bf7eab0d7 100644 --- a/packages/fcl-core/src/transaction/index.js +++ b/packages/fcl-core/src/transaction/index.js @@ -163,9 +163,7 @@ export function transaction( unsub() return } - } - - if (predicate(txStatus)) { + } else if (predicate(txStatus)) { resolve(txStatus) unsub() } From b2bbf9b803e4114d27bac3355a18cad615ede019 Mon Sep 17 00:00:00 2001 From: Jordan Ribbink Date: Thu, 24 Oct 2024 13:01:25 -0700 Subject: [PATCH 13/13] prettier --- .changeset/pre.json | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.changeset/pre.json b/.changeset/pre.json index 85f8e9194..1577f7398 100644 --- a/.changeset/pre.json +++ b/.changeset/pre.json @@ -25,8 +25,5 @@ "@onflow/util-template": "1.2.2", "@onflow/util-uid": "1.2.2" }, - "changesets": [ - "slow-lies-fix", - "tasty-ducks-mix" - ] + "changesets": ["slow-lies-fix", "tasty-ducks-mix"] }