Skip to content

Commit

Permalink
ts: Include unresolved accounts in the resolution error message (cora…
Browse files Browse the repository at this point in the history
  • Loading branch information
acheroncrypto committed Aug 28, 2024
1 parent a245dce commit 65c159f
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 1 deletion.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ The minor version will be incremented upon a breaking change and the patch versi
- idl: Add `IdlBuilder` ([#3188](https://github.com/coral-xyz/anchor/pull/3188)).
- cli: Make `clean` command also remove the `.anchor` directory ([#3192](https://github.com/coral-xyz/anchor/pull/3192)).
- lang: Deprecate `#[interface]` attribute ([#3195](https://github.com/coral-xyz/anchor/pull/3195)).
- ts: Include unresolved accounts in the resolution error message ([#3207](https://github.com/coral-xyz/anchor/pull/3207)).

### Fixes

Expand Down
13 changes: 13 additions & 0 deletions tests/pda-derivation/programs/pda-derivation/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ pub mod pda_derivation {
pub fn seed_math_expr(_ctx: Context<SeedMathExpr>) -> Result<()> {
Ok(())
}

pub fn resolution_error(_ctx: Context<ResolutionError>) -> Result<()> {
Ok(())
}
}

#[derive(Accounts)]
Expand Down Expand Up @@ -178,6 +182,15 @@ pub struct SeedMathExpr<'info> {
pub math_expr_account: UncheckedAccount<'info>,
}

#[derive(Accounts)]
pub struct ResolutionError<'info> {
pub unknown: UncheckedAccount<'info>,
#[account(seeds = [unknown.key.as_ref()], bump)]
pub pda: UncheckedAccount<'info>,
#[account(seeds = [pda.key.as_ref()], bump)]
pub another_pda: UncheckedAccount<'info>,
}

#[account]
pub struct MyAccount {
data: u64,
Expand Down
13 changes: 13 additions & 0 deletions tests/pda-derivation/tests/typescript.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,4 +121,17 @@ describe("typescript", () => {
it("Can use unsupported expressions", () => {
// Compilation test to fix issues like https://github.com/coral-xyz/anchor/issues/2933
});

it("Includes the unresolved accounts if resolution fails", async () => {
try {
// `unknown` account is required for account resolution to work, but it's
// intentionally not provided to test the error message
await program.methods.resolutionError().rpc();
throw new Error("Should throw due to account resolution failure!");
} catch (e) {
expect(e.message).to.equal(
"Reached maximum depth for account resolution. Unresolved accounts: `pda`, `anotherPda`"
);
}
});
});
38 changes: 37 additions & 1 deletion ts/packages/anchor/src/program/accounts-resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,43 @@ export class AccountsResolver<IDL extends Idl> {
) {
depth++;
if (depth === 16) {
throw new Error("Reached maximum depth for account resolution");
const isResolvable = (acc: IdlInstructionAccountItem) => {
if (!isCompositeAccounts(acc)) {
return !!(acc.address || acc.pda || acc.relations);
}

return acc.accounts.some(isResolvable);
};

const getPaths = (
accs: IdlInstructionAccountItem[],
path: string[] = [],
paths: string[][] = []
) => {
for (const acc of accs) {
if (isCompositeAccounts(acc)) {
paths.push(...getPaths(acc.accounts, [...path, acc.name]));
} else {
paths.push([...path, acc.name]);
}
}

return paths;
};

const resolvableAccs = this._idlIx.accounts.filter(isResolvable);
const unresolvedAccs = getPaths(resolvableAccs)
.filter((path) => !this.get(path))
.map((path) => path.reduce((acc, p) => acc + "." + p))
.map((acc) => `\`${acc}\``)
.join(", ");

throw new Error(
[
`Reached maximum depth for account resolution.`,
`Unresolved accounts: ${unresolvedAccs}`,
].join(" ")
);
}
}
}
Expand Down

0 comments on commit 65c159f

Please sign in to comment.