Skip to content

Commit

Permalink
Feat/default component (#13)
Browse files Browse the repository at this point in the history
* ✨ Modify macro to allow [bolt_account] macro without component_id

* ✨ Update client SDK to use default component id

* 🐛 Fix dependencies

* 🐛 Fix dependencies

* 🐛 Update yarn.lock

* ✅ Simplify test
  • Loading branch information
GabrielePicco authored Jan 29, 2024
1 parent 4be0728 commit a9372a9
Show file tree
Hide file tree
Showing 13 changed files with 208 additions and 106 deletions.
2 changes: 1 addition & 1 deletion clients/bolt-sdk/lib/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@ export declare function FindEntityPda(
export declare function FindComponentPda(
componentProgramId: PublicKey,
entity: PublicKey,
componentId: string
componentId?: string
): PublicKey;
//# sourceMappingURL=index.d.ts.map
2 changes: 1 addition & 1 deletion clients/bolt-sdk/lib/index.d.ts.map

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

3 changes: 3 additions & 0 deletions clients/bolt-sdk/lib/index.js

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

2 changes: 1 addition & 1 deletion clients/bolt-sdk/lib/index.js.map

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

6 changes: 5 additions & 1 deletion clients/bolt-sdk/package.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
{
"name": "bolt-sdk",
"version": "0.0.9",
"version": "0.0.10",
"description": "Bolt typescript SDK",
"author": "[email protected]",
"license": "MIT",
"private": false,
"dependencies": {
"@metaplex-foundation/beet": "^0.7.1",
"@metaplex-foundation/beet-solana": "^0.4.0"
},
"devDependencies": {
"@metaplex-foundation/solita": "^0.20.1",
"@typescript-eslint/eslint-plugin": "^6.14.0",
Expand Down
2 changes: 1 addition & 1 deletion clients/bolt-sdk/src/generated/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export function FindEntityPda(
export function FindComponentPda(
componentProgramId: PublicKey,
entity: PublicKey,
componentId: string
componentId: string = ""
) {
return PublicKey.findProgramAddressSync(
[Buffer.from(componentId), entity.toBytes()],
Expand Down
11 changes: 11 additions & 0 deletions clients/bolt-sdk/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,16 @@
bs58 "^5.0.0"
debug "^4.3.4"

"@metaplex-foundation/beet-solana@^0.4.0":
version "0.4.1"
resolved "https://registry.yarnpkg.com/@metaplex-foundation/beet-solana/-/beet-solana-0.4.1.tgz#255747aa7feee1c20202146a752c057feca1948f"
integrity sha512-/6o32FNUtwK8tjhotrvU/vorP7umBuRFvBZrC6XCk51aKidBHe5LPVPA5AjGPbV3oftMfRuXPNd9yAGeEqeCDQ==
dependencies:
"@metaplex-foundation/beet" ">=0.1.0"
"@solana/web3.js" "^1.56.2"
bs58 "^5.0.0"
debug "^4.3.4"

"@metaplex-foundation/beet@>=0.1.0", "@metaplex-foundation/beet@^0.7.1":
version "0.7.1"
resolved "https://registry.npmjs.org/@metaplex-foundation/beet/-/beet-0.7.1.tgz"
Expand Down Expand Up @@ -2169,6 +2179,7 @@ spok@^1.4.3:
find-process "^1.4.7"

"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0:
name string-width-cjs
version "4.2.3"
resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
Expand Down
57 changes: 26 additions & 31 deletions crates/bolt-lang/attribute/account/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use proc_macro::TokenStream;
use quote::quote;
use syn::spanned::Spanned;
use syn::{parse_macro_input, parse_quote, Attribute, DeriveInput, Lit, Meta, NestedMeta};

/// This BoltAccount attribute is used to automatically generate the seed and size functions
Expand All @@ -9,7 +8,7 @@ use syn::{parse_macro_input, parse_quote, Attribute, DeriveInput, Lit, Meta, Nes
/// The macro also adds the InitSpace and Default derives to the struct.
///
/// #[account]
/// #[bolt_account(component_id = "bolt-position")]
/// #[bolt_account]
/// pub struct Position {
/// pub x: i64,
/// pub y: i64,
Expand All @@ -18,45 +17,41 @@ use syn::{parse_macro_input, parse_quote, Attribute, DeriveInput, Lit, Meta, Nes
/// ```
#[proc_macro_attribute]
pub fn bolt_account(attr: TokenStream, item: TokenStream) -> TokenStream {
let attr = parse_macro_input!(attr as Meta);
let mut input = parse_macro_input!(item as DeriveInput);
let mut component_id_value = None;

let component_id_value = match attr {
Meta::NameValue(meta_name_value) if meta_name_value.path.is_ident("component_id") => {
if let Lit::Str(lit) = meta_name_value.lit {
Some(lit.value())
} else {
None
if !attr.is_empty() {
let attr_meta = parse_macro_input!(attr as Meta);

component_id_value = match attr_meta {
Meta::Path(_) => None,
Meta::NameValue(meta_name_value) if meta_name_value.path.is_ident("component_id") => {
if let Lit::Str(lit) = meta_name_value.lit {
Some(lit.value())
} else {
None
}
}
}
Meta::List(meta) => meta.nested.into_iter().find_map(|nested_meta| {
if let NestedMeta::Meta(Meta::NameValue(meta_name_value)) = nested_meta {
if meta_name_value.path.is_ident("component_id") {
if let Lit::Str(lit) = meta_name_value.lit {
Some(lit.value())
Meta::List(meta) => meta.nested.into_iter().find_map(|nested_meta| {
if let NestedMeta::Meta(Meta::NameValue(meta_name_value)) = nested_meta {
if meta_name_value.path.is_ident("component_id") {
if let Lit::Str(lit) = meta_name_value.lit {
Some(lit.value())
} else {
None
}
} else {
None
}
} else {
None
}
} else {
None
}
}),
_ => {
let error = syn::Error::new(attr.span(), "Missing required attribute `component_id`");
return error.to_compile_error().into();
}
};
}),
_ => None,
};
}

let component_id_value = match component_id_value {
Some(value) => value,
None => {
let error = syn::Error::new(input.span(), "The `component_id` attribute is required");
return error.to_compile_error().into();
}
};
let component_id_value = component_id_value.unwrap_or_else(|| "".to_string());

let additional_derives: Attribute = parse_quote! { #[derive(InitSpace, Default)] };
input.attrs.push(additional_derives);
Expand Down
2 changes: 1 addition & 1 deletion crates/bolt-lang/attribute/component/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use syn::{
/// }
///
/// #[account]
/// #[bolt_account(component_id = "bolt-position")]
/// #[bolt_account]
/// pub struct Position {
/// pub x: i64,
/// pub y: i64,
Expand Down
2 changes: 1 addition & 1 deletion examples/component-position/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ pub mod component_position {
}

#[account]
#[bolt_account(component_id = "component-position")]
#[bolt_account]
#[derive(Copy)]
pub struct Position {
pub x: i64,
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
"eslint": "^8.33.0",
"eslint-config-prettier": "^8.6.0",
"eslint-config-standard-with-typescript": "^34.0.0",
"@metaplex-foundation/beet": "^0.7.1",
"@metaplex-foundation/beet-solana": "^0.4.0",
"eslint-plugin-import": "^2.25.3",
"eslint-plugin-n": "^15.6.1",
"eslint-plugin-prettier": "^4.2.1",
Expand Down
91 changes: 31 additions & 60 deletions tests/bolt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ import { SystemApplyVelocity } from "../target/types/system_apply_velocity";
import { World } from "../target/types/world";
import { expect } from "chai";
import BN from "bn.js";
import {
FindComponentPda,
FindEntityPda,
FindWorldPda,
FindWorldRegistryPda,
} from "../clients/bolt-sdk";

enum Direction {
Left = "Left",
Expand Down Expand Up @@ -57,7 +63,7 @@ describe("bolt", () => {
let componentVelocityEntity1: PublicKey;

it("InitializeWorldsRegistry", async () => {
const registryPda = FindWorldRegistryPda(worldProgram);
const registryPda = FindWorldRegistryPda(worldProgram.programId);
await worldProgram.methods
.initializeRegistry()
.accounts({
Expand All @@ -68,9 +74,9 @@ describe("bolt", () => {
});

it("InitializeNewWorld", async () => {
const registryPda = FindWorldRegistryPda(worldProgram);
const registryPda = FindWorldRegistryPda(worldProgram.programId);

const worldPda = FindWorldPda(worldProgram, new BN(0));
const worldPda = FindWorldPda(new BN(0), worldProgram.programId);
await worldProgram.methods
.initializeNewWorld()
.accounts({
Expand All @@ -82,9 +88,9 @@ describe("bolt", () => {
});

it("InitializeNewWorld 2", async () => {
const registryPda = FindWorldRegistryPda(worldProgram);
const registryPda = FindWorldRegistryPda(worldProgram.programId);

const worldPda = FindWorldPda(worldProgram, new BN(1));
const worldPda = FindWorldPda(new BN(1), worldProgram.programId);
await worldProgram.methods
.initializeNewWorld()
.accounts({
Expand All @@ -96,8 +102,8 @@ describe("bolt", () => {
});

it("Add entity 1", async () => {
const worldPda = FindWorldPda(worldProgram, new BN(0));
entity1 = FindEntityPda(worldProgram, new BN(0), new BN(0));
const worldPda = FindWorldPda(new BN(0), worldProgram.programId);
entity1 = FindEntityPda(new BN(0), new BN(0), null, worldProgram.programId);
await worldProgram.methods
.addEntity(null)
.accounts({
Expand All @@ -109,9 +115,9 @@ describe("bolt", () => {
});

it("Add entity 2", async () => {
const worldPda = FindWorldPda(worldProgram, new BN(0));
const worldPda = FindWorldPda(new BN(0), worldProgram.programId);

entity2 = FindEntityPda(worldProgram, new BN(0), new BN(1));
entity2 = FindEntityPda(new BN(0), new BN(1), null, worldProgram.programId);
await worldProgram.methods
.addEntity(null)
.accounts({
Expand All @@ -123,9 +129,14 @@ describe("bolt", () => {
});

it("Add entity 3", async () => {
const worldPda = FindWorldPda(worldProgram, new BN(0));
const worldPda = FindWorldPda(new BN(0), worldProgram.programId);

const entityPda = FindEntityPda(worldProgram, new BN(0), new BN(2));
const entityPda = FindEntityPda(
new BN(0),
new BN(2),
null,
worldProgram.programId
);
await worldProgram.methods
.addEntity(null)
.accounts({
Expand All @@ -137,9 +148,14 @@ describe("bolt", () => {
});

it("Add entity 4 with extra seeds", async () => {
const worldPda = FindWorldPda(worldProgram, new BN(0));
const worldPda = FindWorldPda(new BN(0), worldProgram.programId);
const seed = "extra-seed";
let entity3 = FindEntityPda(worldProgram, new BN(0), new BN(3), seed);
let entity3 = FindEntityPda(
new BN(0),
new BN(3),
seed,
worldProgram.programId
);

await worldProgram.methods
.addEntity(seed)
Expand Down Expand Up @@ -188,8 +204,7 @@ describe("bolt", () => {
it("Initialize Position Component on Entity 1", async () => {
componentPositionEntity1 = FindComponentPda(
boltComponentPositionProgram.programId,
entity1,
"component-position"
entity1
);

console.log("Component Position E1: ", componentPositionEntity1.toBase58());
Expand Down Expand Up @@ -226,8 +241,7 @@ describe("bolt", () => {
it("Initialize Position Component on Entity 2", async () => {
componentPositionEntity2 = FindComponentPda(
boltComponentPositionProgram.programId,
entity2,
"component-position"
entity2
);

await worldProgram.methods
Expand Down Expand Up @@ -464,47 +478,4 @@ describe("bolt", () => {
console.log("| |");
console.log("+-----------------------------+");
});

// Utils

function FindWorldRegistryPda(program: Program<World>) {
return PublicKey.findProgramAddressSync(
[Buffer.from("registry")],
program.programId
)[0];
}

function FindWorldPda(program: Program<World>, id: BN) {
return PublicKey.findProgramAddressSync(
[Buffer.from("world"), id.toBuffer("be", 8)],
program.programId
)[0];
}

function FindEntityPda(
program: Program<World>,
worldId: BN,
entityId: BN,
extraSeed?: string
) {
let seeds = [Buffer.from("entity"), worldId.toBuffer("be", 8)];
if (extraSeed) {
seeds.push(Buffer.from(new Uint8Array(8)));
seeds.push(Buffer.from(extraSeed));
} else {
seeds.push(entityId.toBuffer("be", 8));
}
return PublicKey.findProgramAddressSync(seeds, program.programId)[0];
}

function FindComponentPda(
program: PublicKey,
entity: PublicKey,
seed: string = "component"
) {
return PublicKey.findProgramAddressSync(
[Buffer.from(seed), entity.toBytes()],
program
)[0];
}
});
Loading

0 comments on commit a9372a9

Please sign in to comment.