Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(experimental): errors: addresses package #2187

Merged

Conversation

buffalojoec
Copy link
Collaborator

Adds custom SolanaError throws to the @solana/addresses package.

packages/errors/src/context.ts Outdated Show resolved Hide resolved
packages/errors/src/context.ts Outdated Show resolved Hide resolved
packages/errors/src/context.ts Outdated Show resolved Hide resolved
Copy link
Collaborator

@steveluscher steveluscher left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rather have these all as separate error codes. You can always catch the SolanaError without caring what type it is.

try {
    const pda = await createProgramDerivedAddress(/* ... */);
} catch(e) {
    if (isSolanaError(e)) {
        // bad thing
    } else {
        throw e;
    }
}

packages/addresses/src/address.ts Outdated Show resolved Hide resolved
packages/addresses/src/program-derived-address.ts Outdated Show resolved Hide resolved
packages/errors/src/context.ts Outdated Show resolved Hide resolved
packages/errors/src/context.ts Outdated Show resolved Hide resolved
@steveluscher
Copy link
Collaborator

I see that this sub-error thing happens in later PRs too. Listen, one thing we could do is to to make use of Error#cause. We'd have to extend SolanaError somehow, maybe by adding cause to the context.

throw new SolanaError(SOLANA_ERROR__PDA_SUCKS, {
    cause: new SolanaError(
        SOLANA_ERROR__PDA_SPECIFICALLY_SUCKS_BECAUSE_OF_THIS,
        { /* context for cause */ },
    ),
    /* other context */
});

Then people can be like:

try {
    const pda = await createProgramDerivedAddress(/* ... */);
} catch (e) {
    if (isSolanaError(e, SOLANA_ERROR__PDA_SUCKS)) {
        const why = e.cause;
        // Do something with `cause`, or not.
    } else {
        throw e;
    }
}

I don't love it though. If we can get away without doing that, we probably should. If there are good use cases for sub-errors, then we should lean on cause.

Notes:

  • You'll have to enable ES2022.Error in tsconfig.json to be able to use cause
  • super(message, { cause });
  • TypeScript typing will probably be super tough; you'll have to delete the cause property from context and write some type tests.

@steveluscher steveluscher linked an issue Feb 26, 2024 that may be closed by this pull request
@buffalojoec buffalojoec force-pushed the 02-24-refactor_experimental_errors_accounts_package branch from 399694b to f32df50 Compare February 27, 2024 07:32
@buffalojoec buffalojoec force-pushed the 02-24-refactor_experimental_errors_addresses_package branch from 91b4a68 to 2bf93b9 Compare February 27, 2024 07:32
@buffalojoec
Copy link
Collaborator Author

Alright I think I got the message, guys.

Copy link
Collaborator

@steveluscher steveluscher left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added via Giphy

Comment on lines +64 to +66
throw new SolanaError(SOLANA_ERROR__INCORRECT_BASE58_ADDRESS_LENGTH, {
actualLength: putativeAddress.length,
});
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When I wrote this error it was intended to be a fast-path check on the number of bytes, without actually counting the number of bytes. Like, looking at the string length of the base 58 string is enough to tell you that it's definitely not 32 bytes, without knowing exactly how many bytes you're dealing with.

This, all to say that I think this error and the one below it are meant to be the same one, and that it's not actually interesting to know how long the base 58 string is.

Maybe make them the same error, and make actualLength: number | 'UNKNOWN'?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is a bad check, and the code is (somewhat) informative, but I can see how the two errors could be merged. I'm not really a huge fan of actualLength: 'UNKNOWN', and I certainly don't think we should decode the string just to return the real actual byte length, which could invoke another unrelated error.

I think where I'm hesitant is "what do I do if my string is < 32 or > 44"?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SOLANA_ERROR__WHERE_DID_YOU_EVEN_GET_THIS

}
// Slow-path; actually attempt to decode the input string.
const base58Encoder = getMemoizedBase58Encoder();
const bytes = base58Encoder.encode(putativeAddress);
const numBytes = bytes.byteLength;
if (numBytes !== 32) {
throw new Error(`Expected input string to decode to a byte array of length 32. Actual length: ${numBytes}`);
throw new SolanaError(SOLANA_ERROR__INCORRECT_BASE58_ADDRESS_BYTE_LENGTH, {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure that it's important, at this point, that the address used to be base58 encoded. The error is that the address itself has the wrong byte length.

Suggested change
throw new SolanaError(SOLANA_ERROR__INCORRECT_BASE58_ADDRESS_BYTE_LENGTH, {
throw new SolanaError(SOLANA_ERROR__INCORRECT_ADDRESS_BYTE_LENGTH, {

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It really only makes sense to include the _BASE58 to match the pattern of the error code above it, if it remains in the set.

Comment on lines 60 to 63
index: number;
maxSeedLength: number;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm trying to think of what I would do with this error. It basically tells me that ‘some seed in this call’ was too long, but not how long it was, nor what the seed was. Also, it makes a value the maximum seed length that probably won't change in our lifetimes, at least not without a code change being necessary in web3.js.

On the other hand, inlining the seed into the error is maybe a bad idea (privacy?).

I'm struggling to think of what this error context could contain that would actually help me fix the bug. Maybe the actual length of the violating seed is a start?

In any case, it's an important question to ask for each error: ‘does this context help the developer find the bug.’

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, it makes a value the maximum seed length that probably won't change in our lifetimes, at least not without a code change being necessary in web3.js.

Yeah, but I really didn't want to have to introduce two areas where we'd have to change that value, if we ever needed to update the code.

On the other hand, inlining the seed into the error is maybe a bad idea (privacy?).

Probably safe to avoid this, yeah.

I'm struggling to think of what this error context could contain that would actually help me fix the bug. Maybe the actual length of the violating seed is a start?

Index and actual length should do, no? I doubt we need more than that.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Btw, the MAX_SEEDS error gets thrown by createProgramAddress (also the case in the Rust library as well). This can be confusing to the downstream user, since if they provide 16 seeds (MAX_SEEDS), they'll actually be feeding createProgramAddress with 17 seeds, because the bump is included, and they'll get this error.

With the changes I have locally right now, you'd basically get a message "provided: 17" when you can visibly see you only provided 16. Is a descriptive message good enough to elaborate this fact? Or do we want to work out the "max seeds" concept to actually be 15?

@buffalojoec buffalojoec force-pushed the 02-24-refactor_experimental_errors_accounts_package branch from f32df50 to a3b445e Compare February 28, 2024 16:30
@buffalojoec buffalojoec force-pushed the 02-24-refactor_experimental_errors_addresses_package branch from 2bf93b9 to b10a9e8 Compare February 28, 2024 16:30
@steveluscher
Copy link
Collaborator

steveluscher commented Feb 29, 2024

Merge activity

  • Feb 29, 11:33 AM PST: @steveluscher started a stack merge that includes this pull request via Graphite.
  • Feb 29, 11:37 AM PST: Graphite rebased this pull request as part of a merge.
  • Feb 29, 11:38 AM PST: @steveluscher merged this pull request with Graphite.

@steveluscher steveluscher force-pushed the 02-24-refactor_experimental_errors_accounts_package branch from 1bc1537 to 8608dc7 Compare February 29, 2024 19:35
Base automatically changed from 02-24-refactor_experimental_errors_accounts_package to master February 29, 2024 19:36
@steveluscher steveluscher force-pushed the 02-24-refactor_experimental_errors_addresses_package branch from bb22886 to 16ce665 Compare February 29, 2024 19:36
@steveluscher steveluscher merged commit bea19d2 into master Feb 29, 2024
6 checks passed
@steveluscher steveluscher deleted the 02-24-refactor_experimental_errors_addresses_package branch February 29, 2024 19:38
steveluscher added a commit that referenced this pull request Mar 1, 2024
#2187 buried these address sub errors in such a way that they'd never reach the caller. This PR allows them to bubble up.

Addresses #2118.
Copy link
Contributor

github-actions bot commented Mar 2, 2024

🎉 This PR is included in version 1.90.1 🎉

The release is available on:

Your semantic-release bot 📦🚀

Copy link
Contributor

Because there has been no activity on this PR for 14 days since it was merged, it has been automatically locked. Please open a new issue if it requires a follow up.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Mar 19, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[experimental] Convert all thrown errors to SolanaError
3 participants