onflow / fcl-js

FCL (Flow Client Library) - The best tool for building JavaScript (browser & NodeJS) applications on Flow 🌊
https://onflow.org
Apache License 2.0
323 stars 118 forks source link

[FEATURE] Improved Cadence Error Reporting #1891

Open JeffreyDoyle opened 1 month ago

JeffreyDoyle commented 1 month ago

Issue to be solved

When a transaction is reverted, due to a Cadence error emitted during its execution, the result of the error is not currently passed to the consumer of FCL in a consumable way. Developers today only get the error text output from the transaction, and are left to their own to extract the error type in some meaningful way.

Suggest A Solution

When a transaction is reverted, and there is an error emitted as part of the execution of the Cadence transaction, FCL should pass that error to the consumer in some consumable way.

There are several existing error codes standardized by the Flow protocol: https://github.com/onflow/flow-go/blob/1ac121d17c75c2c949fa34d6e956b89fa0499d7b/fvm/errors/codes.go

If the error emitted as part of a Cadence transaction reflects one of these standardized error codes, FCL should make that error code available to the consumer.

For other non-standard error types, FCL should make those available to the consumer as well.

What are you currently working on that this is blocking?

No response

jribbink commented 1 month ago

My thought here is to create a FlowError type, roughly like:

// todo: maybe better/more specific messaging?
class FlowError extends Error {
    code: number
    message: string
    constructor(code: number, message: string) {
        this.code = code
        this.message = message
    }
}

class CadenceRunTimeError extends FlowError {
    constructor(message: string) {
        super(1101, message)
    }
}

...etc...

Then any eligible transaction result errors will get mapped -> FlowError type if possible. And a developer can now do the following:

mutate(...).then(txId => fcl.tx(txId).onceSealed()).catch(e => {
    if (e instanceof CadenceRunTimeError) {
        // this is a Cadence runtime error, I can do something special with it...
    }

    // Or, maybe they just want to check if it is any type of FlowError
    if (e instanceof FlowError) {
        // do something
    }

    // right now, this error is just a raw string which is not very usable/identifiable without the developer understanding every error code & how to parse from access node error string, this makes it much easier.
})

thoughts?