Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 3 additions & 1 deletion Anchor.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ world = "WorLD15A7CrDwLcLy4fRqtaTb9fbd8o8iqiEMUDse2n"
component-small = "9yBADAhoTWCkNRB6hbfpwUgPpxyJiF9uEiWVPR6k7A4y"
escrow-funding = "4Um2d8SvyfWyLLtfu2iJMFhM77DdjjyQusEy7K3VhPkd"
example-bundle = "CgfPBUeDUL3GT6b5AUDFE56KKgU4ycWA9ERjEWsfMZCj"
large = "DEABKyknxGaCbkthh1mPSSMQnJrSLRJyZShdKpsyrjdL"
position = "Fn1JzzEdyb55fsyduWS94mYHizGhJZuhvjX6DVvrmGbQ"
system-apply-velocity = "6LHhFVwif6N9Po3jHtSmMVtPjF6zRfL3xMosSzcrQAS8"
system-fly = "HT2YawJjkNmqWcLNfPAMvNsLdWwPvvvbKA5bpMw4eUpq"
system-simple-movement = "FSa6qoJXFBR3a7ThQkTAMrC15p6NkchPEjBdd4n6dXxA"
with-large-component = "4X7t7eCjd2pvNThY9DQ3rKQKNLeeHhgEv74JGwh7jJEz"
velocity = "CbHEFbSQdRN4Wnoby9r16umnJ1zWbULBHg4yqzGQonU1"
with-1-component = "BsVKJF2H9GN1P9WrexdgEY4ztiweKvfQo6ydLWUEw6n7"
with-10-components = "C69UYWaXBQXUbhHQGtG8pB7DHSgh2z5Sm9ifyAnM1kkt"
Expand All @@ -35,7 +37,7 @@ cluster = "localnet"
wallet = "./tests/fixtures/provider.json"

[workspace]
members = ["crates/programs/world", "examples/component-position", "examples/component-velocity", "examples/system-apply-velocity", "examples/system-fly", "examples/system-simple-movement", "examples/component-small", "examples/system-with-1-component", "examples/system-with-2-components", "examples/system-with-3-components", "examples/system-with-4-components", "examples/system-with-5-components", "examples/system-with-6-components", "examples/system-with-7-components", "examples/system-with-8-components", "examples/system-with-9-components", "examples/system-with-10-components", "examples/escrow-funding", "examples/bundle"]
members = ["crates/programs/world", "examples/component-position", "examples/component-velocity", "examples/system-apply-velocity", "examples/system-fly", "examples/system-simple-movement", "examples/component-small", "examples/component-large", "examples/with-large-component", "examples/system-with-1-component", "examples/system-with-2-components", "examples/system-with-3-components", "examples/system-with-4-components", "examples/system-with-5-components", "examples/system-with-6-components", "examples/system-with-7-components", "examples/system-with-8-components", "examples/system-with-9-components", "examples/system-with-10-components", "examples/escrow-funding", "examples/bundle"]

[scripts]
test = "tests/script.sh"
Expand Down
16 changes: 16 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ bolt-attribute-bolt-component-id = { path = "crates/bolt-lang/attribute/componen
bolt-utils = { path = "crates/bolt-lang/utils", version = "=0.2.6" }
world = { path = "crates/programs/world", features = ["cpi"], version = "=0.2.6"}
small = { path = "examples/component-small", features = ["cpi"], version = "=0.2.6"}
component-large = { path = "examples/component-large", features = ["cpi"], version = "=0.2.6"}
large = { path = "examples/component-large", features = ["cpi"], version = "=0.2.6"}

## External crates
session-keys = { version = "^2", features = ["no-entrypoint"] }
Expand Down
6 changes: 6 additions & 0 deletions clients/typescript/test/framework.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ import { With8Components } from "../../../target/types/with_8_components";
import { With9Components } from "../../../target/types/with_9_components";
import { With10Components } from "../../../target/types/with_10_components";
import { ExampleBundle } from "../../../target/types/example_bundle";
import { WithLargeComponent } from "../../../target/types/with_large_component";
import { Large } from "../../../target/types/large";

export class Framework {
provider: anchor.AnchorProvider;
Expand All @@ -48,7 +50,9 @@ export class Framework {
systemWith8Components: anchor.Program<With8Components>;
systemWith9Components: anchor.Program<With9Components>;
systemWith10Components: anchor.Program<With10Components>;
systemWithLargeComponent: anchor.Program<WithLargeComponent>;
componentSmall: anchor.Program<Small>;
componentLarge: anchor.Program<Large>;
worldPda: PublicKey;
worldId: BN;

Expand Down Expand Up @@ -76,6 +80,8 @@ export class Framework {
this.systemFly = anchor.workspace.SystemFly;
this.systemApplyVelocity = anchor.workspace.SystemApplyVelocity;
this.componentSmall = anchor.workspace.Small;
this.componentLarge = anchor.workspace.Large;
this.systemWithLargeComponent = anchor.workspace.WithLargeComponent;
this.systemWith1Component = anchor.workspace.With1Component;
this.systemWith2Components = anchor.workspace.With2Components;
this.systemWith3Components = anchor.workspace.With3Components;
Expand Down
34 changes: 21 additions & 13 deletions clients/typescript/test/intermediate-level/ecs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -427,19 +427,27 @@ export function ecs(framework: Framework) {
})),
});

let signature = await framework.provider.sendAndConfirm(
applySystem.transaction,
);

let transactionResponse: any;
do {
transactionResponse =
await framework.provider.connection.getTransaction(signature, {
commitment: "confirmed",
});
} while (transactionResponse?.meta?.logMessages === undefined);
let report = framework.report(transactionResponse?.meta?.logMessages);
reports.push(report);
try {
let signature = await framework.provider.sendAndConfirm(
applySystem.transaction,
);

let transactionResponse: any;
do {
transactionResponse =
await framework.provider.connection.getTransaction(signature, {
commitment: "confirmed",
});
} while (transactionResponse?.meta?.logMessages === undefined);
let report = framework.report(transactionResponse?.meta?.logMessages);
reports.push(report);
} catch (error) {
reports.push({
cpiCount: 0,
totalCu: 0,
totalCpiCU: 0,
});
}
}

framework.saveReport(reports);
Expand Down
45 changes: 45 additions & 0 deletions clients/typescript/test/low-level/ecs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,51 @@ export function ecs(framework) {
await framework.provider.sendAndConfirm(transaction);
});

it("Initialize Large Component on Entity 4", async () => {
const componentId = framework.componentLarge.programId;
framework.componentLargeEntity4Pda = FindComponentPda({
componentId,
entity: framework.entity4Pda,
});
const instruction = await framework.worldProgram.methods
.initializeComponent()
.accounts({
payer: framework.provider.wallet.publicKey,
entity: framework.entity4Pda,
data: framework.componentLargeEntity4Pda,
componentProgram: componentId,
authority: framework.worldProgram.programId,
})
.instruction();
const transaction = new anchor.web3.Transaction().add(instruction);
await framework.provider.sendAndConfirm(transaction);
});

it("Apply system with large component on Entity 4", async () => {
const instruction = await framework.worldProgram.methods
.apply(SerializeArgs())
.accounts({
authority: framework.provider.wallet.publicKey,
boltSystem: framework.systemWithLargeComponent.programId,
world: framework.worldPda,
})
.remainingAccounts([
{
pubkey: framework.componentLarge.programId,
isSigner: false,
isWritable: false,
},
{
pubkey: framework.componentLargeEntity4Pda,
isSigner: false,
isWritable: true,
},
])
.instruction();
const transaction = new anchor.web3.Transaction().add(instruction);
await framework.provider.sendAndConfirm(transaction);
});

it("Initialize Velocity Component on Entity 1 (with seed)", async () => {
const componentId = framework.exampleComponentVelocity.programId;
framework.componentVelocityEntity1Pda = FindComponentPda({
Expand Down
2 changes: 2 additions & 0 deletions crates/bolt-lang/attribute/src/bundle/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ pub fn process(_attr: TokenStream, item: TokenStream) -> TokenStream {
let bundle_mod = parse_macro_input!(item as ItemMod);
let mut program = generate_program(&bundle_mod.ident.to_string());
component::generate_update(&mut program);
component::generate_set_owner(&mut program);
component::generate_recover_metadata(&mut program);
let mut delegate_components = Vec::new();
if let Some((_, items)) = bundle_mod.content {
for item in items {
Expand Down
2 changes: 1 addition & 1 deletion crates/bolt-lang/attribute/src/common/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ pub fn inject_program(module: &mut syn::ItemMod) {
items.insert(
1,
syn::Item::Struct(syn::parse_quote! {
#[derive(Accounts)]
#[derive(Accounts, Clone)]
pub struct VariadicBoltComponents<'info> {
pub authority: Signer<'info>,
}
Expand Down
48 changes: 48 additions & 0 deletions crates/bolt-lang/attribute/src/component/generate/program.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,54 @@ fn generate_initialize(
)
}

/// Generates the set_owner function and struct.
pub fn generate_set_owner(module: &mut ItemMod) {
let set_owner_fn = quote! {
#[automatically_derived]
pub fn set_owner(ctx: Context<SetOwner>, owner: Pubkey) -> Result<()> {
bolt_lang::instructions::set_owner(&ctx.accounts.instruction_sysvar_account.to_account_info(), &ctx.accounts.component.to_account_info(), owner)
}
};
let set_owner_struct = quote! {
#[automatically_derived]
#[derive(Accounts)]
pub struct SetOwner<'info> {
/// CHECK: This is a component account
#[account(mut)]
pub component: AccountInfo<'info>,
#[account(address = anchor_lang::solana_program::sysvar::instructions::id())]
pub instruction_sysvar_account: AccountInfo<'info>,
}
};
module.content.as_mut().map(|(brace, items)| {
items.extend(vec![set_owner_fn, set_owner_struct].into_iter().map(|item| syn::parse2(item).expect("Failed to parse generate set_owner item")).collect::<Vec<_>>());
(brace, items.clone())
});
}

pub fn generate_recover_metadata(module: &mut ItemMod) {
let recover_metadata_fn = parse_quote! {
#[automatically_derived]
pub fn recover_metadata(ctx: Context<RecoverMetadata>, original_size: u32, discriminator: Vec<u8>, bolt_metadata: bolt_lang::BoltMetadata) -> Result<()> {
bolt_lang::instructions::recover_metadata(&ctx.accounts.instruction_sysvar_account.to_account_info(), &ctx.accounts.bolt_component, original_size, discriminator, bolt_metadata)?;
Ok(())
}
};
let recover_metadata_struct = parse_quote! {
#[automatically_derived]
#[derive(Accounts)]
pub struct RecoverMetadata<'info> {
#[account(mut)]
pub bolt_component: AccountInfo<'info>,
#[account(address = anchor_lang::solana_program::sysvar::instructions::id())]
pub instruction_sysvar_account: AccountInfo<'info>,
}
};
module.content.as_mut().map(|(brace, items)| {
items.extend(vec![recover_metadata_fn, recover_metadata_struct]);
(brace, items.clone())
});
}
/// Generates the instructions and related structs to inject in the component.
pub fn generate_update(module: &mut ItemMod) {
let update_fn = quote! {
Expand Down
2 changes: 2 additions & 0 deletions crates/bolt-lang/attribute/src/component/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ pub fn process(attr: TokenStream, item: TokenStream) -> TokenStream {
inject_delegate_items(&mut program, vec![(type_.ident.clone(), "".to_string())]);
}
generate_update(&mut program);
generate_set_owner(&mut program);
generate_recover_metadata(&mut program);
enrich_type(&mut type_);

let expanded = quote! {
Expand Down
44 changes: 40 additions & 4 deletions crates/bolt-lang/attribute/src/system/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,23 @@ fn generate_bolt_execute_wrapper(
bumps_ident: Ident,
) -> Item {
parse_quote! {
pub fn #fn_ident<'a, 'b, 'info>(ctx: Context<'a, 'b, 'info, 'info, VariadicBoltComponents<'info>>, args: Vec<u8>) -> Result<Vec<Vec<u8>>> {
let mut components = #components_ident::try_from(&ctx)?;
pub fn #fn_ident<'a, 'b, 'info>(ctx: Context<'a, 'b, 'info, 'info, VariadicBoltComponents<'info>>, input: bolt_lang::context::BoltExecuteInput) -> Result<()> {
let mut input = input;
let input: &'info mut bolt_lang::context::BoltExecuteInput = unsafe { std::mem::transmute(&mut input) };
let (rebuilt_context_data, args, buffer) = bolt_lang::context::ContextData::rebuild_from(&ctx, input);
let mut variadic = VariadicBoltComponents {
authority: ctx.accounts.authority.clone(),
};
let variadic_bumps = VariadicBoltComponentsBumps {};
let var_ctx = Context::new(ctx.program_id, &mut variadic, rebuilt_context_data.remaining_accounts, variadic_bumps);
let mut components = #components_ident::try_from(&var_ctx).expect("Failed to convert context to components");
let bumps = #bumps_ident {};
let context = Context::new(ctx.program_id, &mut components, ctx.remaining_accounts, bumps);
#callee_ident(context, args)
let result = #callee_ident(context, args)?;
let result = result.try_to_vec()?;
buffer.realloc(result.len(), false)?;
buffer.data.borrow_mut().copy_from_slice(&result);
Ok(())
}
}
}
Expand All @@ -50,13 +62,37 @@ pub fn process(_attr: TokenStream, item: TokenStream) -> TokenStream {
);
if !has_variadic {
let variadic_struct: Item = parse_quote! {
#[derive(Accounts)]
#[derive(Accounts, Clone)]
pub struct VariadicBoltComponents<'info> {
pub authority: Signer<'info>,
}
};
items.insert(1, variadic_struct);
}
let has_set_owner = items.iter().any(
|it| matches!(it, syn::Item::Fn(f) if f.sig.ident == "set_owner"),
);
if !has_set_owner {
let set_owner_fn: Item = parse_quote! {
#[automatically_derived]
pub fn set_owner(ctx: Context<SetOwner>, new_owner: Pubkey) -> Result<()> {
bolt_lang::instructions::set_owner(&ctx.accounts.instruction_sysvar_account.to_account_info(), &ctx.accounts.component.to_account_info(), new_owner)
}
};
items.push(set_owner_fn);
let set_owner_struct = parse_quote! {
#[automatically_derived]
#[derive(Accounts)]
pub struct SetOwner<'info> {
/// CHECK: This is a component account
#[account(mut)]
pub component: AccountInfo<'info>,
#[account(address = anchor_lang::solana_program::sysvar::instructions::id())]
pub instruction_sysvar_account: AccountInfo<'info>,
}
};
items.push(set_owner_struct);
}
let wrapper = generate_bolt_execute_wrapper(
Ident::new("bolt_execute", Span::call_site()),
Ident::new("execute", Span::call_site()),
Expand Down
Loading