Repository navigation
[nodes] has_one account resolution #605
Description
Let's say you have an endpoint like this:
#[derive(Accounts)]
pub struct DequeuetaskV0<'info> {
pub queue_authority: Signer<'info>,
/// CHECK: Via has one
#[account(mut)]
pub rent_refund: AccountInfo<'info>,
#[account(
seeds = [b"task_queue_authority", task_queue.key().as_ref(), queue_authority.key().as_ref()],
bump = task_queue_authority.bump_seed,
)]
pub task_queue_authority: Box<Account<'info, TaskQueueAuthorityV0>>,
#[account(mut)]
pub task_queue: Box<Account<'info, TaskQueueV0>>,
#[account(
mut,
close = rent_refund,
has_one = rent_refund,
has_one = task_queue,
)]
pub task: Box<Account<'info, TaskV0>>,
}In Anchor, the code to use this endpoint is:
await program.methods
.dequeueTaskV0()
.accounts({
task,
})
.rpc();In Codama, the code is:
const task = ... // fetch task account
await dequeueTaskV0(umi, {
task,
queueAuthority,
rentRefund: task.rentRefund,
taskQueue: task.taskQueue
}).sendAndConfirm(umi, options);For more complex endpoints with 10+ accounts, and lots of has_ones, you end up with heaps of boilerplate just to get what needs to be passed to the function.
It would be nice if Codama could use anchor's has_one information from the IDL to make accounts optional in typescript. If you pass them, you avoid an extra fetch. If you don't, it fetches them for you.
So, for example, the code becomes:
await dequeueTaskV0(umi, { task }).sendAndConfirm(umi, options);Another optimization on top of this would be to implement a global cache of accounts, similar to Helium's Account Fetch Cache that makes it so you can omit passing optional accounts for more legible code, without the worry about a performance hit.
This feature also becomes useful if you need to add accounts to an endpoint without breaking old clients. If the clients are smart enough to resolve has_one's, a new account pulled in through has_one is a non-breaking change.
Activity
[-]Feature Request: has_one account resolution[/-][+]has_one account resolution[/+][-]has_one account resolution[/-][+][nodes] has_one account resolution[/+]lorisleiva commentedon Sep 12, 2025
Thank you for writing up this issue btw.
As you know I'm not a fan of forcing users to magically fetch various accounts just to create a single instruction when the accounts are likely already loaded on the app. That being said, I do want that information to exist on the IDL because it is a valuable piece of information that can be used by any visitor. Perhaps an opt-in option on a renderer somewhere could even materialise this auto-fetching of account strategy.
I've just remember that I wrote an issue a while ago about adding the concept of "Constraints" to certain nodes like
AccountNodesorInstructionAccountNodes. As you can see, I even mention thehas_oneconstraint on the issue. Perhaps this would be a good way to include this information on the standard and it would be up to the renderer to decide whether to use this constraint as a default value if none exist.