Skip to content

Commit 90a8bb7

Browse files
committed
Add fetch function helpers to accounts page
1 parent 8a778fa commit 90a8bb7

File tree

3 files changed

+100
-0
lines changed

3 files changed

+100
-0
lines changed

packages/renderers-rust/public/templates/accountsMod.njk

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,21 @@
22

33
{% block main %}
44

5+
#[cfg(feature = "fetch")]
6+
#[derive(Debug, Clone)]
7+
pub struct DecodedAccount<T> {
8+
pub address: solana_program::pubkey::Pubkey,
9+
pub account: solana_sdk::account::Account,
10+
pub data: T,
11+
}
12+
13+
#[cfg(feature = "fetch")]
14+
#[derive(Debug, Clone)]
15+
pub enum MaybeAccount<T> {
16+
Exists(DecodedAccount<T>),
17+
NotFound(solana_program::pubkey::Pubkey),
18+
}
19+
520
{% for account in accountsToExport | sort(false, false, 'name') %}
621
pub(crate) mod r#{{ account.name | snakeCase }};
722
{% endfor %}

packages/renderers-rust/public/templates/accountsPage.njk

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,59 @@ impl<'a> TryFrom<&solana_program::account_info::AccountInfo<'a>> for {{ account.
128128
}
129129
}
130130

131+
#[cfg(feature = "fetch")]
132+
pub fn fetch_{{ account.name | snakeCase }}(
133+
rpc: &solana_client::rpc_client::RpcClient,
134+
address: &Pubkey,
135+
) -> Result<super::DecodedAccount<{{ account.name | pascalCase }}>, Error> {
136+
let accounts = fetch_all_{{ account.name | snakeCase }}(rpc, vec![address])?;
137+
Ok(accounts[0].clone())
138+
}
139+
140+
#[cfg(feature = "fetch")]
141+
pub fn fetch_all_{{ account.name | snakeCase }}(
142+
rpc: &solana_client::rpc_client::RpcClient,
143+
addresses: Vec<Pubkey>,
144+
) -> Result<Vec<super::DecodedAccount<{{ account.name | pascalCase }}>>, Error> {
145+
let accounts = rpc.get_multiple_accounts(&addresses)?;
146+
let mut decoded_accounts: Vec<super::DecodedAccount<{{ account.name | pascalCase }}>> = Vec::new();
147+
for i in 0..addresses.len() {
148+
let address = addresses[i];
149+
let account = accounts[i].as_ref().ok_or(format!("Account not found: {}", address))?;
150+
let data = {{ account.name | pascalCase }}::from_bytes(&account.data)?;
151+
decoded_accounts.push(super::DecodedAccount { address, account: account.clone(), data });
152+
}
153+
Ok(decoded_accounts)
154+
}
155+
156+
#[cfg(feature = "fetch")]
157+
pub fn fetch_maybe_{{ account.name | snakeCase }}(
158+
rpc: &solana_client::rpc_client::RpcClient,
159+
address: &Pubkey,
160+
) -> Result<super::MaybeAccount<{{ account.name | pascalCase }}>, Error> {
161+
let accounts = fetch_all_maybe_{{ account.name | snakeCase }}(rpc, vec![address])?;
162+
Ok(accounts[0].clone())
163+
}
164+
165+
#[cfg(feature = "fetch")]
166+
pub fn fetch_all_maybe_{{ account.name | snakeCase }}(
167+
rpc: &solana_client::rpc_client::RpcClient,
168+
addresses: Vec<Pubkey>,
169+
) -> Result<Vec<super::MaybeAccount<{{ account.name | pascalCase }}>>, Error> {
170+
let accounts = rpc.get_multiple_accounts(&addresses)?;
171+
let mut decoded_accounts: Vec<super::MaybeAccount<{{ account.name | pascalCase }}>> = Vec::new();
172+
for i in 0..addresses.len() {
173+
let address = addresses[i];
174+
if let Some(account) = accounts[i].as_ref() {
175+
let data = {{ account.name | pascalCase }}::from_bytes(&account.data)?;
176+
decoded_accounts.push(super::MaybeAccount::Exists(super::DecodedAccount { address, account: account.clone(), data }));
177+
} else {
178+
decoded_accounts.push(super::MaybeAccount::NotFound(address));
179+
}
180+
}
181+
Ok(decoded_accounts)
182+
}
183+
131184
#[cfg(feature = "anchor")]
132185
impl anchor_lang::AccountDeserialize for {{ account.name | pascalCase }} {
133186
fn try_deserialize_unchecked(buf: &mut &[u8]) -> anchor_lang::Result<Self> {

packages/renderers-rust/test/accountsPage.test.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,3 +134,35 @@ test('it renders anchor traits impl', () => {
134134
'impl anchor_lang::Owner for TestAccount',
135135
]);
136136
});
137+
138+
test('it renders fetch functions', () => {
139+
// Given the following account.
140+
const node = programNode({
141+
accounts: [
142+
accountNode({
143+
discriminators: [
144+
{
145+
kind: 'fieldDiscriminatorNode',
146+
name: camelCase('discriminator'),
147+
offset: 0,
148+
},
149+
],
150+
name: 'testAccount',
151+
pda: pdaLinkNode('testPda'),
152+
}),
153+
],
154+
name: 'myProgram',
155+
publicKey: '1111',
156+
});
157+
158+
// When we render it.
159+
const renderMap = visit(node, getRenderMapVisitor());
160+
161+
// Then we expect the following fetch functions to be rendered.
162+
codeContains(renderMap.get('accounts/test_account.rs'), [
163+
'pub fn fetch_test_account',
164+
'pub fn fetch_maybe_test_account',
165+
'pub fn fetch_all_test_account',
166+
'pub fn fetch_all_maybe_test_account',
167+
]);
168+
});

0 commit comments

Comments
 (0)