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

Feat: Optional Positional Accounts #2101

Merged
merged 144 commits into from
Dec 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
144 commits
Select commit Hold shift + click to select a range
d2b5510
optional accounts initial implementation
stegaBOB Jul 31, 2022
724cf9e
cargo fmt
stegaBOB Aug 1, 2022
f46cb22
panic if Account related traits are run on none
stegaBOB Aug 1, 2022
7c6c2fb
Allow empty accounts to deserialize to None for optional accounts
stegaBOB Aug 2, 2022
34e34b0
implement constraints for optional accounts
stegaBOB Aug 2, 2022
e2210e0
optional accounts to idl gen
stegaBOB Aug 2, 2022
25e6b5e
accountstruct helper method
stegaBOB Aug 2, 2022
eca2c76
implemented to_account_metas and infos
stegaBOB Aug 2, 2022
6e71942
add test program
stegaBOB Aug 2, 2022
5cc6a5f
Rename optional to is_optional
febo Aug 2, 2022
3357199
added more traits
stegaBOB Aug 2, 2022
55d83e6
Merge branch 'stegaBOB/feat/optional-accounts' of https://github.com/…
febo Aug 2, 2022
e945e50
added TryKey error
stegaBOB Aug 2, 2022
e77b827
fix has_one
stegaBOB Aug 2, 2022
74a472a
update prelude
stegaBOB Aug 2, 2022
584335c
Merge branch 'stegaBOB/feat/optional-accounts' of github.com:stegaBOB…
stegaBOB Aug 2, 2022
8cfb071
is_optional
stegaBOB Aug 2, 2022
5c564e7
add is_optional helper method
stegaBOB Aug 2, 2022
d7c10ab
Add TryAccountInfos trait
febo Aug 3, 2022
4398f36
improve constraint parser
stegaBOB Aug 3, 2022
c50d9fc
initial work on TryToAccountInfo
stegaBOB Aug 3, 2022
cd785d8
Merge pull request #1 from stegaBOB/stegaBOB/feat/optional-accounts
stegaBOB Aug 3, 2022
1bc160b
Merge branch 'master' into febo/try-account-infos
febo Aug 3, 2022
ee1bf5d
Rename to TryToAccountInfo
febo Aug 3, 2022
e21e0ba
finished implementing tryToAccountInfo
stegaBOB Aug 4, 2022
46da864
Using program method
febo Aug 4, 2022
9a29dca
Formatting
febo Aug 4, 2022
3c69fc7
Merge pull request #3 from stegaBOB/feat/try-to-account-info
stegaBOB Aug 4, 2022
13ff1b7
Fix program function call
febo Aug 4, 2022
d0a2d73
Merge branch 'master' into febo/try-account-infos
febo Aug 4, 2022
a9a8d1d
Remove function return borrow
febo Aug 4, 2022
e19f475
Fix access to program field
febo Aug 4, 2022
f780f15
Merge pull request #2 from stegaBOB/febo/try-account-infos
stegaBOB Aug 4, 2022
11d58fb
finished implementing tryToAccountInfo
stegaBOB Aug 4, 2022
4713c33
Merge pull request #4 from stegaBOB/fix/cross-checks
stegaBOB Aug 4, 2022
d9bd0f3
add exit try_to_account_infos
stegaBOB Aug 4, 2022
33ac27b
descriptive ID path
stegaBOB Aug 4, 2022
8ecb81f
try_to_account_info
stegaBOB Aug 4, 2022
c9c504a
fix close constraint
stegaBOB Aug 5, 2022
b6840e8
update test files
stegaBOB Aug 5, 2022
a55701f
completed typescript optional accounts implementation
stegaBOB Aug 5, 2022
f5fed0a
fix try accounts for init
stegaBOB Aug 5, 2022
71d848e
update tests
stegaBOB Aug 5, 2022
d0952a7
Merge branch 'coral-xyz:master' into master
stegaBOB Aug 5, 2022
1d9a3ed
Merge pull request #5 from stegaBOB/feat/ts-client
stegaBOB Aug 5, 2022
185948a
fix to_account_metas
stegaBOB Aug 5, 2022
cc15495
update tests
stegaBOB Aug 5, 2022
201925c
fix linting
stegaBOB Aug 5, 2022
c5f1a52
Merge pull request #6 from stegaBOB/feat/ts-client
stegaBOB Aug 5, 2022
af16400
remove types/node
stegaBOB Aug 5, 2022
b241083
update yarn.lock maybe?
stegaBOB Aug 5, 2022
e0568a0
update optional test
stegaBOB Aug 5, 2022
4cf4768
update optional test
stegaBOB Aug 5, 2022
8979511
update optional rust cli test
stegaBOB Aug 5, 2022
fe8ca60
fix linting and tests
stegaBOB Aug 5, 2022
668dfc9
fix tests
stegaBOB Aug 7, 2022
f4b5dea
Merge branch 'coral-xyz:master' into master
stegaBOB Aug 11, 2022
558f37e
Merge branch 'coral-xyz:master' into master
stegaBOB Aug 14, 2022
cf162e3
Merge branch 'coral-xyz:master' into master
stegaBOB Aug 17, 2022
624212e
update try_accounts to pass in accs during constraint gen
stegaBOB Aug 22, 2022
39db4e9
Add default impl for TryToAccountInfos
febo Aug 22, 2022
39f3e45
Removed TryToAccountInfos trait
febo Aug 22, 2022
a2b127e
Formatting
febo Aug 23, 2022
36c200d
Merge pull request #7 from stegaBOB/febo/default-impl
stegaBOB Aug 23, 2022
e93e383
Merge remote-tracking branch 'origin/master' into master-optional
stegaBOB Aug 23, 2022
2c01f38
remove unneccesary traits and improve constraint gen drastically
stegaBOB Aug 23, 2022
66d6b4c
fix exit generation
stegaBOB Aug 23, 2022
4981049
clippy
stegaBOB Aug 23, 2022
bfa49c5
Merge branch 'master' into master-optional
stegaBOB Aug 23, 2022
a4b365e
improve cross check error message
stegaBOB Aug 23, 2022
3a9ba50
Merge branch 'coral-xyz:master' into master
stegaBOB Aug 23, 2022
04299b3
Merge branch 'coral-xyz:master' into master
stegaBOB Aug 25, 2022
e025f09
improve comments
stegaBOB Aug 29, 2022
fe083c5
more comments
stegaBOB Aug 29, 2022
3852145
update constraints hopefully good now?
stegaBOB Aug 29, 2022
58b1af2
add new errors to ts client
stegaBOB Aug 29, 2022
a419b67
add new errors to ts client
stegaBOB Aug 29, 2022
b2aecdb
update optional test
stegaBOB Aug 29, 2022
90f2322
update anchor ts client
stegaBOB Aug 29, 2022
f32955d
update misc crate
stegaBOB Aug 29, 2022
de8d7c1
linting
stegaBOB Aug 29, 2022
5183b52
temporarily comment out optional rs tests
stegaBOB Aug 29, 2022
4d4f8d0
Merge branch 'coral-xyz:master' into master
stegaBOB Sep 7, 2022
c09f0a5
Merge branch 'master' into master-optional
stegaBOB Sep 24, 2022
4e4debd
update ts
stegaBOB Sep 24, 2022
d7a127a
remove local test files
stegaBOB Sep 24, 2022
6a6822c
linting
stegaBOB Sep 24, 2022
f6e67eb
optional client tests
stegaBOB Sep 24, 2022
2dcf43d
Merge branch 'master' into master-optional
stegaBOB Sep 29, 2022
d6e43c1
fix other lints to make the test pass
stegaBOB Sep 29, 2022
cb9c798
remove comments
stegaBOB Sep 29, 2022
f7fcbf3
remove misc-optional for now
stegaBOB Oct 4, 2022
49bb58f
update optional program
stegaBOB Oct 4, 2022
34bcba1
update optional program and client tests again
stegaBOB Oct 4, 2022
0a7e988
update optional program and client tests again again
stegaBOB Oct 5, 2022
b2d118c
added initialize tests that should pass
stegaBOB Oct 5, 2022
5323658
undo unrelated anchor.toml change
stegaBOB Oct 5, 2022
47237ba
update close on optional program and improve tests
stegaBOB Oct 6, 2022
21efb86
Merge branch 'coral-xyz:master' into master
stegaBOB Oct 12, 2022
e8b18df
update optional program again.
stegaBOB Oct 12, 2022
ec50c2a
update optional program and optional tests
stegaBOB Oct 13, 2022
72162e6
fix has one error message
stegaBOB Oct 13, 2022
81743ac
fix client example tests
stegaBOB Oct 13, 2022
a2865c9
update lockfile
stegaBOB Oct 13, 2022
915b4da
Merge branch 'master' into master-optional
stegaBOB Oct 13, 2022
f931d8e
update lockfile
stegaBOB Oct 13, 2022
8d0f919
regenerate lockfile
stegaBOB Oct 13, 2022
f57ef24
reset lockfile
stegaBOB Oct 13, 2022
3bcd4aa
reset ts yarn lockfile
stegaBOB Oct 13, 2022
f9b447e
update no caching tests
stegaBOB Oct 13, 2022
3cde731
Merge branch 'master' into master-optional
stegaBOB Oct 14, 2022
acfd755
update exit codegen to use generate_optional_check
stegaBOB Oct 18, 2022
0109696
remove `try_to_account_infos`
stegaBOB Oct 18, 2022
e538760
Merge branch 'coral-xyz:master' into master
stegaBOB Oct 18, 2022
5ef63bf
Merge branch 'coral-xyz:master' into master
stegaBOB Oct 18, 2022
e48a278
Merge branch 'coral-xyz:master' into master
stegaBOB Oct 18, 2022
32875eb
update parser to ignore method calls in constraints
stegaBOB Oct 21, 2022
3dc7566
refactor and improve optional checks in constraints
stegaBOB Oct 21, 2022
bedfabc
add misc-optional program and tests
stegaBOB Oct 21, 2022
c864cd5
enable cpi for optional tests
stegaBOB Oct 21, 2022
18d3b81
Revert "enable cpi for optional tests"
stegaBOB Oct 21, 2022
e31b437
Merge branch 'master' into master-optional
stegaBOB Oct 23, 2022
bccae2f
simplify misc tests
stegaBOB Oct 23, 2022
d084ecf
Merge branch 'master' into master-optional
stegaBOB Nov 1, 2022
9daa85c
update version
stegaBOB Nov 1, 2022
0806d9f
Merge branch 'master' into master-optional
stegaBOB Nov 28, 2022
b8f975c
fix rust version and resolve merge conflicts
stegaBOB Nov 28, 2022
481fada
Merge branch 'master' into master-optional
stegaBOB Nov 29, 2022
0baf2c6
prevent Option on composite accounts
stegaBOB Nov 29, 2022
f513b33
Merge branch 'coral-xyz:master' into master
stegaBOB Dec 5, 2022
f19fb5b
hopefully fixed ts stuff?
stegaBOB Dec 6, 2022
3fd1dcd
hopefully fixed ts stuff?
stegaBOB Dec 6, 2022
9b198d2
testing
stegaBOB Dec 6, 2022
e957e5b
hopefully done?
stegaBOB Dec 6, 2022
08e3390
Merge branch 'master' into master-optional
stegaBOB Dec 7, 2022
b76d4ad
update misc test
stegaBOB Dec 8, 2022
4e8454f
fix optional tests
stegaBOB Dec 8, 2022
a622ea5
Merge branch 'master' into master
Dec 8, 2022
d4f41d7
fix ts
stegaBOB Dec 9, 2022
7c24da7
fix ts again!
stegaBOB Dec 9, 2022
f9c0f85
linting urg
stegaBOB Dec 9, 2022
cdc5829
allow-missing-optionals feature
stegaBOB Dec 11, 2022
37204df
fix client tests
stegaBOB Dec 11, 2022
7a6f594
add bnjs types to tests
stegaBOB Dec 11, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .github/workflows/no-cashing-tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ jobs:
fail-fast: false
matrix:
node:
- path: tests/optional/
name: optional.so
- path: tests/events/
name: events.so
- path: examples/tutorial/basic-4/
Expand Down Expand Up @@ -124,6 +126,10 @@ jobs:
- run: chmod +x ~/.cargo/bin/anchor

- uses: actions/download-artifact@v3
with:
name: optional.so
path: tests/optional/target/deploy/
- uses: actions/download-artifact@v2
with:
name: events.so
path: tests/events/target/deploy/
Expand Down Expand Up @@ -289,6 +295,8 @@ jobs:
path: tests/cpi-returns
- cmd: cd tests/multiple-suites && anchor test --skip-lint && npx tsc --noEmit
path: tests/multiple-suites
- cmd: cd tests/optional && anchor test --skip-lint && npx tsc --noEmit
path: tests/optional
- cmd: cd tests/multiple-suites-run-single && anchor test --skip-lint --run tests/should-run && npx tsc --noEmit
path: tests/multiple-suites-run-single
- cmd: cd tests/pda-derivation && anchor test --skip-lint && npx tsc --noEmit
Expand Down
8 changes: 8 additions & 0 deletions .github/workflows/tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,8 @@ jobs:
fail-fast: false
matrix:
node:
- path: tests/optional/
name: optional.so
- path: tests/events/
name: events.so
- path: examples/tutorial/basic-4/
Expand Down Expand Up @@ -182,6 +184,10 @@ jobs:
- run: chmod +x ~/.cargo/bin/anchor

- uses: actions/download-artifact@v3
with:
name: optional.so
path: tests/optional/target/deploy/
- uses: actions/download-artifact@v2
with:
name: events.so
path: tests/events/target/deploy/
Expand Down Expand Up @@ -403,6 +409,8 @@ jobs:
path: tests/multiple-suites
- cmd: cd tests/multiple-suites-run-single && anchor test --skip-lint --run tests/should-run && npx tsc --noEmit
path: tests/multiple-suites-run-single
- cmd: cd tests/optional && anchor test --skip-lint && npx tsc --noEmit
path: tests/optional
- cmd: cd tests/pda-derivation && anchor test --skip-lint && npx tsc --noEmit
path: tests/pda-derivation
- cmd: cd tests/relations-derivation && anchor test --skip-lint && npx tsc --noEmit
Expand Down
1 change: 1 addition & 0 deletions client/example/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ anchor-client = { path = "../", features = ["debug"] }
basic-2 = { path = "../../examples/tutorial/basic-2/programs/basic-2", features = ["no-entrypoint"] }
basic-4 = { path = "../../examples/tutorial/basic-4/programs/basic-4", features = ["no-entrypoint"] }
composite = { path = "../../tests/composite/programs/composite", features = ["no-entrypoint"] }
optional = { path = "../../tests/optional/programs/optional", features = ["no-entrypoint"] }
events = { path = "../../tests/events/programs/events", features = ["no-entrypoint"] }
shellexpand = "2.1.0"
anyhow = "1.0.32"
Expand Down
4 changes: 3 additions & 1 deletion client/example/run-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ main() {
local basic_2_pid="Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS"
local basic_4_pid="CwrqeMj2U8tFr1Rhkgwc84tpAsqbt9pTt2a4taoTADPr"
local events_pid="2dhGsWUzy5YKUsjZdLHLmkNpUDAXkNa9MYWsPc4Ziqzy"
local optional_pid="FNqz6pqLAwvMSds2FYjR4nKV3moVpPNtvkfGFrqLKrgG"

#
# Bootup validator.
Expand All @@ -35,13 +36,14 @@ main() {
--bpf-program $basic_2_pid ../../examples/tutorial/basic-2/target/deploy/basic_2.so \
--bpf-program $basic_4_pid ../../examples/tutorial/basic-4/target/deploy/basic_4.so \
--bpf-program $events_pid ../../tests/events/target/deploy/events.so \
--bpf-program $optional_pid ../../tests/optional/target/deploy/optional.so \
> test-validator.log &
sleep 5

#
# Run Test.
#
cargo run -- --composite-pid $composite_pid --basic-2-pid $basic_2_pid --basic-4-pid $basic_4_pid --events-pid $events_pid
cargo run -- --composite-pid $composite_pid --basic-2-pid $basic_2_pid --basic-4-pid $basic_4_pid --events-pid $events_pid --optional-pid $optional_pid
}

cleanup() {
Expand Down
64 changes: 64 additions & 0 deletions client/example/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ use basic_2::instruction as basic_2_instruction;
use basic_2::Counter;
use events::instruction as events_instruction;
use events::MyEvent;
use optional::accounts::Initialize as OptionalInitialize;
use optional::instruction as optional_instruction;
// The `accounts` and `instructions` modules are generated by the framework.
use basic_4::accounts as basic_4_accounts;
use basic_4::basic_4::Counter as CounterState;
Expand All @@ -21,6 +23,7 @@ use clap::Parser;
use composite::accounts::{Bar, CompositeUpdate, Foo, Initialize};
use composite::instruction as composite_instruction;
use composite::{DummyA, DummyB};
use optional::account::{DataAccount, DataPda};
use std::rc::Rc;
use std::time::Duration;

Expand All @@ -34,6 +37,8 @@ pub struct Opts {
basic_4_pid: Pubkey,
#[clap(long)]
events_pid: Pubkey,
#[clap(long)]
optional_pid: Pubkey,
}

// This example assumes a local validator is running with the programs
Expand All @@ -58,6 +63,7 @@ fn main() -> Result<()> {
basic_2(&client, opts.basic_2_pid)?;
basic_4(&client, opts.basic_4_pid)?;
events(&client, opts.events_pid)?;
optional(&client, opts.optional_pid)?;

// Success.
Ok(())
Expand Down Expand Up @@ -226,3 +232,61 @@ pub fn basic_4(client: &Client, pid: Pubkey) -> Result<()> {

Ok(())
}

// Runs a client for tests/optional.
//
// Make sure to run a localnet with the program deploy to run this example.
fn optional(client: &Client, pid: Pubkey) -> Result<()> {
// Program client.
let program = client.program(pid);

// `Initialize` parameters.
let data_account_keypair = Keypair::new();

let data_account_key = data_account_keypair.pubkey();

let data_pda_seeds = &[DataPda::PREFIX.as_ref(), data_account_key.as_ref()];
let data_pda_key = Pubkey::find_program_address(data_pda_seeds, &pid).0;
let required_keypair = Keypair::new();
let value: u64 = 10;

// Build and send a transaction.

program
.request()
.instruction(system_instruction::create_account(
&program.payer(),
&required_keypair.pubkey(),
program
.rpc()
.get_minimum_balance_for_rent_exemption(DataAccount::LEN)?,
DataAccount::LEN as u64,
&program.id(),
))
.signer(&data_account_keypair)
.signer(&required_keypair)
.accounts(OptionalInitialize {
payer: Some(program.payer()),
required: required_keypair.pubkey(),
system_program: Some(system_program::id()),
optional_account: Some(data_account_keypair.pubkey()),
optional_pda: None,
})
.args(optional_instruction::Initialize { value, key: pid })
.send()
.unwrap();

// Assert the transaction worked.
let required: DataAccount = program.account(required_keypair.pubkey())?;
assert_eq!(required.data, 0);

let optional_pda = program.account::<DataPda>(data_pda_key);
assert!(optional_pda.is_err());

let optional_account: DataAccount = program.account(data_account_keypair.pubkey())?;
assert_eq!(optional_account.data, value * 2);

println!("Optional success!");

Ok(())
}
1 change: 1 addition & 0 deletions lang/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ license = "Apache-2.0"
description = "Solana Sealevel eDSL"

[features]
allow-missing-optionals = ["anchor-derive-accounts/allow-missing-optionals"]
init-if-needed = ["anchor-derive-accounts/init-if-needed"]
derive = []
default = []
Expand Down
1 change: 1 addition & 0 deletions lang/derive/accounts/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ edition = "2021"
proc-macro = true

[features]
allow-missing-optionals = ["anchor-syn/allow-missing-optionals"]
init-if-needed = ["anchor-syn/init-if-needed"]
default = []
anchor-debug = ["anchor-syn/anchor-debug"]
Expand Down
1 change: 1 addition & 0 deletions lang/src/accounts/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ pub mod cpi_state;
#[doc(hidden)]
#[allow(deprecated)]
pub mod loader;
pub mod option;
pub mod program;
#[doc(hidden)]
#[allow(deprecated)]
Expand Down
84 changes: 84 additions & 0 deletions lang/src/accounts/option.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
//! Option<T> type for optional accounts.
//!
//! # Example
//! ```ignore
//! #[derive(Accounts)]
//! pub struct Example {
//! pub my_acc: Option<Account<'info, MyData>>
//! }
//! ```

use std::collections::{BTreeMap, BTreeSet};

use solana_program::account_info::AccountInfo;
use solana_program::instruction::AccountMeta;
use solana_program::pubkey::Pubkey;

use crate::{
error::ErrorCode, Accounts, AccountsClose, AccountsExit, Result, ToAccountInfos, ToAccountMetas,
};

impl<'info, T: Accounts<'info>> Accounts<'info> for Option<T> {
Henry-E marked this conversation as resolved.
Show resolved Hide resolved
fn try_accounts(
program_id: &Pubkey,
accounts: &mut &[AccountInfo<'info>],
ix_data: &[u8],
bumps: &mut BTreeMap<String, u8>,
reallocs: &mut BTreeSet<Pubkey>,
) -> Result<Self> {
if accounts.is_empty() {
stegaBOB marked this conversation as resolved.
Show resolved Hide resolved
return if cfg!(feature = "allow-missing-optionals") {
// We don't care if accounts is empty (when this feature is active),
// so if that's the case we return None. This allows adding optional
// accounts at the end of the Accounts struct without causing a breaking
// change. This is safe and will error out if a required account is then
// added after the optional account and the accounts aren't passed in.
Ok(None)
} else {
// If the feature is inactive (it is off by default), then we error out
// like every other Account.
Err(ErrorCode::AccountNotEnoughKeys.into())
};
}

// If there are enough accounts, it will check the program_id and return
// None if it matches, popping the first account off the accounts vec.
if accounts[0].key == program_id {
*accounts = &accounts[1..];
Ok(None)
} else {
// If the program_id doesn't equal the account key, we default to
// the try_accounts implementation for the inner type and then wrap that with
// Some. This should handle all possible valid cases.
T::try_accounts(program_id, accounts, ix_data, bumps, reallocs).map(Some)
}
}
}

impl<'info, T: ToAccountInfos<'info>> ToAccountInfos<'info> for Option<T> {
fn to_account_infos(&self) -> Vec<AccountInfo<'info>> {
self.as_ref()
.map_or_else(Vec::new, |account| account.to_account_infos())
Henry-E marked this conversation as resolved.
Show resolved Hide resolved
}
}

impl<T: ToAccountMetas> ToAccountMetas for Option<T> {
fn to_account_metas(&self, is_signer: Option<bool>) -> Vec<AccountMeta> {
self.as_ref()
.expect("Cannot run `to_account_metas` on None")
Henry-E marked this conversation as resolved.
Show resolved Hide resolved
.to_account_metas(is_signer)
}
}

impl<'info, T: AccountsClose<'info>> AccountsClose<'info> for Option<T> {
fn close(&self, sol_destination: AccountInfo<'info>) -> Result<()> {
self.as_ref()
.map_or(Ok(()), |t| T::close(t, sol_destination))
}
}

impl<'info, T: AccountsExit<'info>> AccountsExit<'info> for Option<T> {
fn exit(&self, program_id: &Pubkey) -> Result<()> {
self.as_ref().map_or(Ok(()), |t| t.exit(program_id))
}
}
3 changes: 3 additions & 0 deletions lang/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,9 @@ pub enum ErrorCode {
/// 2019 - A space constraint was violated
#[msg("A space constraint was violated")]
ConstraintSpace,
/// 2020 - A required account for the constraint is None
#[msg("A required account for the constraint is None")]
ConstraintAccountIsNone,

// Require
/// 2500 - A require expression was violated
Expand Down
1 change: 1 addition & 0 deletions lang/syn/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ rust-version = "1.59"
edition = "2021"

[features]
allow-missing-optionals = []
init-if-needed = []
idl = []
hash = []
Expand Down
27 changes: 22 additions & 5 deletions lang/syn/src/codegen/accounts/__client_accounts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,16 @@ pub fn generate(accs: &AccountsStruct) -> proc_macro2::TokenStream {
} else {
quote!()
};
quote! {
#docs
pub #name: anchor_lang::solana_program::pubkey::Pubkey
if f.is_optional {
quote! {
#docs
pub #name: Option<anchor_lang::solana_program::pubkey::Pubkey>
}
} else {
quote! {
#docs
pub #name: anchor_lang::solana_program::pubkey::Pubkey
}
}
}
})
Expand Down Expand Up @@ -93,8 +100,18 @@ pub fn generate(accs: &AccountsStruct) -> proc_macro2::TokenStream {
true => quote! { anchor_lang::solana_program::instruction::AccountMeta::new },
};
let name = &f.ident;
quote! {
account_metas.push(#meta(self.#name, #is_signer));
if f.is_optional {
quote! {
if let Some(#name) = &self.#name {
account_metas.push(#meta(*#name, #is_signer));
} else {
account_metas.push(anchor_lang::solana_program::instruction::AccountMeta::new_readonly(crate::ID, false));
}
}
} else {
quote! {
account_metas.push(#meta(self.#name, #is_signer));
}
}
}
})
Expand Down
Loading