Browse Source

Feature: Add configurable component authority & Simplify the Components/System API (#14)

* :sparkles: Simplify API & Fix IDL generation

* :sparkles: Component Authority owned by the world program

* :sparkles: Simplify Components & Systems API

* :sparkles: Simplify API for v0.1

* :sparkles: Add component_id macro for external account

* :sparkles: Refactor & Component authority

* :green_heart: Add build programs step

* :construction_worker: Directly install Bolt CLI from source

* :recycle: Code Refactor

* :recycle: Refactor & Fix CI

* :construction_worker: Update CI/CD

* :construction_worker: Update CI

* :green_heart: Fix CI

* :sparkles: Update client SDK

* :bug: Fix macros

* :bug: Fix CLI

* :construction_worker: Update tests workflow

* :zap: Improve example and tests

* :bug: Fix tests
Gabriele Picco 1 year ago
parent
commit
4661d151b6
84 changed files with 1745 additions and 841 deletions
  1. 20 3
      .github/workflows/run-tests.yml
  2. 4 4
      Anchor.toml
  3. 86 27
      Cargo.lock
  4. 134 31
      cli/src/lib.rs
  5. 31 29
      cli/src/rust_template.rs
  6. 56 9
      clients/bolt-sdk/idl/world.json
  7. 1 1
      clients/bolt-sdk/lib/accounts/Entity.d.ts
  8. 1 1
      clients/bolt-sdk/lib/accounts/Registry.d.ts
  9. 1 1
      clients/bolt-sdk/lib/accounts/World.d.ts
  10. 2 2
      clients/bolt-sdk/lib/accounts/index.d.ts
  11. 1 1
      clients/bolt-sdk/lib/accounts/index.d.ts.map
  12. 2 2
      clients/bolt-sdk/lib/accounts/index.js
  13. 1 1
      clients/bolt-sdk/lib/accounts/index.js.map
  14. 13 0
      clients/bolt-sdk/lib/errors/index.d.ts
  15. 1 0
      clients/bolt-sdk/lib/errors/index.d.ts.map
  16. 70 0
      clients/bolt-sdk/lib/errors/index.js
  17. 1 0
      clients/bolt-sdk/lib/errors/index.js.map
  18. 1 0
      clients/bolt-sdk/lib/index.d.ts
  19. 1 1
      clients/bolt-sdk/lib/index.d.ts.map
  20. 4 0
      clients/bolt-sdk/lib/index.js
  21. 1 1
      clients/bolt-sdk/lib/index.js.map
  22. 2 0
      clients/bolt-sdk/lib/instructions/apply.d.ts
  23. 1 1
      clients/bolt-sdk/lib/instructions/apply.d.ts.map
  24. 19 3
      clients/bolt-sdk/lib/instructions/apply.js
  25. 1 1
      clients/bolt-sdk/lib/instructions/apply.js.map
  26. 2 0
      clients/bolt-sdk/lib/instructions/apply2.d.ts
  27. 1 1
      clients/bolt-sdk/lib/instructions/apply2.d.ts.map
  28. 19 3
      clients/bolt-sdk/lib/instructions/apply2.js
  29. 1 1
      clients/bolt-sdk/lib/instructions/apply2.js.map
  30. 2 0
      clients/bolt-sdk/lib/instructions/apply3.d.ts
  31. 1 1
      clients/bolt-sdk/lib/instructions/apply3.d.ts.map
  32. 19 3
      clients/bolt-sdk/lib/instructions/apply3.js
  33. 1 1
      clients/bolt-sdk/lib/instructions/apply3.js.map
  34. 2 0
      clients/bolt-sdk/lib/instructions/initializeComponent.d.ts
  35. 1 1
      clients/bolt-sdk/lib/instructions/initializeComponent.d.ts.map
  36. 21 6
      clients/bolt-sdk/lib/instructions/initializeComponent.js
  37. 1 1
      clients/bolt-sdk/lib/instructions/initializeComponent.js.map
  38. 2 2
      clients/bolt-sdk/src/generated/accounts/index.ts
  39. 55 0
      clients/bolt-sdk/src/generated/errors/index.ts
  40. 4 0
      clients/bolt-sdk/src/generated/index.ts
  41. 15 0
      clients/bolt-sdk/src/generated/instructions/apply.ts
  42. 15 0
      clients/bolt-sdk/src/generated/instructions/apply2.ts
  43. 15 0
      clients/bolt-sdk/src/generated/instructions/apply3.ts
  44. 15 0
      clients/bolt-sdk/src/generated/instructions/initializeComponent.ts
  45. 1 1
      crates/bolt-helpers/Cargo.toml
  46. 1 1
      crates/bolt-helpers/attribute/system-template/Cargo.toml
  47. 3 5
      crates/bolt-helpers/attribute/system-template/src/lib.rs
  48. 12 0
      crates/bolt-helpers/attribute/world-apply/Cargo.toml
  49. 150 0
      crates/bolt-helpers/attribute/world-apply/src/lib.rs
  50. 3 1
      crates/bolt-lang/Cargo.toml
  51. 0 75
      crates/bolt-lang/attribute/account/src/lib.rs
  52. 14 0
      crates/bolt-lang/attribute/bolt-program/Cargo.toml
  53. 186 0
      crates/bolt-lang/attribute/bolt-program/src/lib.rs
  54. 1 0
      crates/bolt-lang/attribute/component-deserialize/Cargo.toml
  55. 13 0
      crates/bolt-lang/attribute/component-deserialize/src/lib.rs
  56. 2 2
      crates/bolt-lang/attribute/component-id/Cargo.toml
  57. 15 0
      crates/bolt-lang/attribute/component-id/src/lib.rs
  58. 2 1
      crates/bolt-lang/attribute/component/Cargo.toml
  59. 67 130
      crates/bolt-lang/attribute/component/src/lib.rs
  60. 14 0
      crates/bolt-lang/attribute/system-input/Cargo.toml
  61. 121 0
      crates/bolt-lang/attribute/system-input/src/lib.rs
  62. 82 36
      crates/bolt-lang/attribute/system/src/lib.rs
  63. 11 0
      crates/bolt-lang/src/errors.rs
  64. 13 1
      crates/bolt-lang/src/lib.rs
  65. 13 0
      crates/bolt-lang/utils/Cargo.toml
  66. 22 0
      crates/bolt-lang/utils/src/lib.rs
  67. 5 4
      examples/component-position/Cargo.toml
  68. 1 8
      examples/component-position/src/lib.rs
  69. 5 4
      examples/component-velocity/Cargo.toml
  70. 1 73
      examples/component-velocity/src/lib.rs
  71. 5 4
      examples/system-apply-velocity/Cargo.toml
  72. 9 13
      examples/system-apply-velocity/src/lib.rs
  73. 4 3
      examples/system-fly/Cargo.toml
  74. 9 15
      examples/system-fly/src/lib.rs
  75. 3 2
      examples/system-simple-movement/Cargo.toml
  76. 28 32
      examples/system-simple-movement/src/lib.rs
  77. 1 0
      programs/bolt-component/Cargo.toml
  78. 45 11
      programs/bolt-component/src/lib.rs
  79. 3 1
      programs/bolt-system/Cargo.toml
  80. 3 89
      programs/bolt-system/src/lib.rs
  81. 4 0
      programs/world/Cargo.toml
  82. 8 0
      programs/world/src/error.rs
  83. 56 165
      programs/world/src/lib.rs
  84. 162 25
      tests/bolt.ts

+ 20 - 3
.github/workflows/run-tests.yml

@@ -4,7 +4,7 @@ on:
   pull_request:
 
 env:
-  solana_version: v1.18.0
+  solana_version: v1.18.1
   anchor_version: 0.29.0
 
 jobs:
@@ -30,6 +30,7 @@ jobs:
         run: |
           sudo apt-get update
           sudo apt-get install -y pkg-config build-essential libudev-dev
+          npm install --global yarn
 
       - name: Cache node dependencies
         uses: actions/cache@v3
@@ -146,10 +147,21 @@ jobs:
           echo ${{ secrets.SYSTEM_FLY }} > target/deploy/system_fly-keypair.json
           echo ${{ secrets.SYSTEM_SIMPLE_MOVEMENT }} > target/deploy/system_simple_movement-keypair.json
 
+      - name: run build
+        run: |
+          export PATH="/home/runner/.local/share/solana/install/active_release/bin:$PATH"
+          npm i -g @coral-xyz/anchor-cli@${{ env.anchor_version }} ts-mocha typescript
+          solana-test-validator > /dev/null &
+          sleep 5
+          solana airdrop -u l 100 tEsT3eV6RFCWs1BZ7AXTzasHqTtMnMLCB2tjQ42TDXD
+          anchor build
+          anchor idl build
+          anchor deploy
+          pkill -9 -f solana-test-validator
+
       - name: run tests
         run: |
           export PATH="/home/runner/.local/share/solana/install/active_release/bin:$PATH"
-          ls node_modules/.bin
           npm i -g @coral-xyz/anchor-cli@${{ env.anchor_version }} ts-mocha typescript
           anchor test
 
@@ -158,7 +170,12 @@ jobs:
           export PATH="/home/runner/.local/share/solana/install/active_release/bin:$PATH"
           cargo install --path cli --force --locked
           bolt init test-project --force
-          cd test-project && bolt build
+          cd test-project
+          cargo add --package position --path "../crates/bolt-lang" # Overrides the version with the local version
+          cargo add --package movement --path "../crates/bolt-lang" # -
+          yarn add file:../clients/bolt-sdk/ -D # Overrides the bolt ts SDK with the local version
+          bolt build
+          bolt test
 
       - uses: actions/upload-artifact@v3
         if: always()

+ 4 - 4
Anchor.toml

@@ -1,16 +1,16 @@
 [toolchain]
 
 [features]
-seeds = false
+seeds = true
 skip-lint = false
 
 [programs.localnet]
 bolt-component = "CmP2djJgABZ4cRokm4ndxuq6LerqpNHLBsaUv2XKEJua"
 bolt-system = "7X4EFsDJ5aYTcEjKzJ94rD8FRKgQeXC89fkpeTS4KaqP"
-component-position = "Fn1JzzEdyb55fsyduWS94mYHizGhJZuhvjX6DVvrmGbQ"
-component-velocity = "CbHEFbSQdRN4Wnoby9r16umnJ1zWbULBHg4yqzGQonU1"
+position = "Fn1JzzEdyb55fsyduWS94mYHizGhJZuhvjX6DVvrmGbQ"
+velocity = "CbHEFbSQdRN4Wnoby9r16umnJ1zWbULBHg4yqzGQonU1"
 system-apply-velocity = "6LHhFVwif6N9Po3jHtSmMVtPjF6zRfL3xMosSzcrQAS8"
-system-fly = "BAQXfRwpNE43pdkeajsffA4rEkFQxwmUEDZKJjQHuvAN"
+system-fly = "HT2YawJjkNmqWcLNfPAMvNsLdWwPvvvbKA5bpMw4eUpq"
 system-simple-movement = "FSa6qoJXFBR3a7ThQkTAMrC15p6NkchPEjBdd4n6dXxA"
 world = "WorLD15A7CrDwLcLy4fRqtaTb9fbd8o8iqiEMUDse2n"
 

+ 86 - 27
Cargo.lock

@@ -382,6 +382,7 @@ dependencies = [
  "anchor-derive-accounts 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "anchor-derive-serde 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "anchor-derive-space 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "anchor-syn 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "arrayref",
  "base64 0.13.1",
  "bincode",
@@ -908,25 +909,36 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae"
 
 [[package]]
-name = "bolt-attribute-bolt-account"
+name = "bolt-attribute-bolt-component"
 version = "0.0.1"
 dependencies = [
+ "bolt-utils",
  "proc-macro2",
  "quote",
  "syn 1.0.109",
 ]
 
 [[package]]
-name = "bolt-attribute-bolt-component"
+name = "bolt-attribute-bolt-component-deserialize"
 version = "0.0.1"
 dependencies = [
+ "bolt-utils",
  "proc-macro2",
  "quote",
  "syn 1.0.109",
 ]
 
 [[package]]
-name = "bolt-attribute-bolt-component-deserialize"
+name = "bolt-attribute-bolt-component-id"
+version = "0.0.1"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "bolt-attribute-bolt-program"
 version = "0.0.1"
 dependencies = [
  "proc-macro2",
@@ -943,6 +955,15 @@ dependencies = [
  "syn 1.0.109",
 ]
 
+[[package]]
+name = "bolt-attribute-bolt-system-input"
+version = "0.0.1"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
 [[package]]
 name = "bolt-cli"
 version = "0.0.1"
@@ -965,7 +986,25 @@ dependencies = [
 
 [[package]]
 name = "bolt-helpers"
-version = "0.1.0"
+version = "0.0.1"
+
+[[package]]
+name = "bolt-helpers-system-template"
+version = "0.0.1"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "bolt-helpers-world-apply"
+version = "0.0.1"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
 
 [[package]]
 name = "bolt-lang"
@@ -973,10 +1012,12 @@ version = "0.0.1"
 dependencies = [
  "ahash 0.8.6",
  "anchor-lang 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "bolt-attribute-bolt-account",
  "bolt-attribute-bolt-component",
  "bolt-attribute-bolt-component-deserialize",
+ "bolt-attribute-bolt-component-id",
+ "bolt-attribute-bolt-program",
  "bolt-attribute-bolt-system",
+ "bolt-attribute-bolt-system-input",
  "bolt-system",
  "serde",
  "serde_json",
@@ -988,6 +1029,16 @@ name = "bolt-system"
 version = "0.0.1"
 dependencies = [
  "anchor-lang 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bolt-helpers-system-template",
+]
+
+[[package]]
+name = "bolt-utils"
+version = "0.0.1"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -1323,22 +1374,6 @@ dependencies = [
  "unreachable",
 ]
 
-[[package]]
-name = "component-position"
-version = "0.1.0"
-dependencies = [
- "anchor-lang 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "bolt-lang",
-]
-
-[[package]]
-name = "component-velocity"
-version = "0.1.0"
-dependencies = [
- "anchor-lang 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "bolt-lang",
-]
-
 [[package]]
 name = "concurrent-queue"
 version = "2.4.0"
@@ -3106,6 +3141,14 @@ dependencies = [
  "rand 0.8.5",
 ]
 
+[[package]]
+name = "position"
+version = "0.0.1"
+dependencies = [
+ "anchor-lang 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bolt-lang",
+]
+
 [[package]]
 name = "powerfmt"
 version = "0.2.0"
@@ -4981,12 +5024,12 @@ dependencies = [
 
 [[package]]
 name = "system-apply-velocity"
-version = "0.1.0"
+version = "0.0.1"
 dependencies = [
  "anchor-lang 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bolt-lang",
- "component-position",
- "component-velocity",
+ "position",
+ "velocity",
 ]
 
 [[package]]
@@ -5012,16 +5055,16 @@ dependencies = [
 
 [[package]]
 name = "system-fly"
-version = "0.1.0"
+version = "0.0.1"
 dependencies = [
  "anchor-lang 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bolt-lang",
- "component-position",
+ "position",
 ]
 
 [[package]]
 name = "system-simple-movement"
-version = "0.1.0"
+version = "0.0.1"
 dependencies = [
  "anchor-lang 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bolt-lang",
@@ -5378,6 +5421,12 @@ dependencies = [
  "webpki-roots 0.24.0",
 ]
 
+[[package]]
+name = "tuple-conv"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1fd6314683350324c1bb3d71a65fbeacb4e870cb4faf30b28d8a7787fb8116dd"
+
 [[package]]
 name = "typenum"
 version = "1.17.0"
@@ -5508,6 +5557,14 @@ version = "0.8.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
 
+[[package]]
+name = "velocity"
+version = "0.0.1"
+dependencies = [
+ "anchor-lang 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bolt-lang",
+]
+
 [[package]]
 name = "version_check"
 version = "0.9.4"
@@ -5905,8 +5962,10 @@ version = "0.0.1"
 dependencies = [
  "anchor-lang 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bolt-component",
+ "bolt-helpers-world-apply",
  "bolt-system",
  "solana-security-txt",
+ "tuple-conv",
 ]
 
 [[package]]

+ 134 - 31
cli/src/lib.rs

@@ -2,7 +2,8 @@ mod rust_template;
 
 use crate::rust_template::{create_component, create_system};
 use anchor_cli::config::{
-    Config, ConfigOverride, ProgramDeployment, TestValidator, Validator, WithPath,
+    BootstrapMode, Config, ConfigOverride, GenesisEntry, ProgramArch, ProgramDeployment,
+    TestValidator, Validator, WithPath,
 };
 use anchor_client::Cluster;
 use anyhow::{anyhow, Result};
@@ -16,6 +17,8 @@ use std::process::Stdio;
 pub const VERSION: &str = env!("CARGO_PKG_VERSION");
 pub const ANCHOR_VERSION: &str = anchor_cli::VERSION;
 
+pub const WORLD_PROGRAM: &str = "WorLD15A7CrDwLcLy4fRqtaTb9fbd8o8iqiEMUDse2n";
+
 #[derive(Debug, Subcommand)]
 pub enum BoltCommand {
     #[clap(about = "Create a new component")]
@@ -54,8 +57,8 @@ pub struct Opts {
 
 pub fn entry(opts: Opts) -> Result<()> {
     match opts.command {
-        BoltCommand::Anchor(command) => {
-            if let anchor_cli::Command::Init {
+        BoltCommand::Anchor(command) => match command {
+            anchor_cli::Command::Init {
                 name,
                 javascript,
                 solidity,
@@ -63,27 +66,54 @@ pub fn entry(opts: Opts) -> Result<()> {
                 jest,
                 template,
                 force,
-            } = command
-            {
-                init(
-                    &opts.cfg_override,
-                    name,
-                    javascript,
-                    solidity,
-                    no_git,
-                    jest,
-                    template,
-                    force,
-                )
-            } else {
-                // Delegate to the existing anchor_cli handler
+            } => init(
+                &opts.cfg_override,
+                name,
+                javascript,
+                solidity,
+                no_git,
+                jest,
+                template,
+                force,
+            ),
+            anchor_cli::Command::Build {
+                idl,
+                idl_ts,
+                verifiable,
+                program_name,
+                solana_version,
+                docker_image,
+                bootstrap,
+                cargo_args,
+                env,
+                skip_lint,
+                no_docs,
+                arch,
+            } => build(
+                &opts.cfg_override,
+                idl,
+                idl_ts,
+                verifiable,
+                skip_lint,
+                program_name,
+                solana_version,
+                docker_image,
+                bootstrap,
+                None,
+                None,
+                env,
+                cargo_args,
+                no_docs,
+                arch,
+            ),
+            _ => {
                 let opts = anchor_cli::Opts {
                     cfg_override: opts.cfg_override,
                     command,
                 };
                 anchor_cli::entry(opts)
             }
-        }
+        },
         BoltCommand::Component(command) => new_component(&opts.cfg_override, command.name),
         BoltCommand::System(command) => new_system(&opts.cfg_override, command.name),
     }
@@ -203,18 +233,11 @@ fn init(
         rpc_port: 8899,
         bind_address: "0.0.0.0".to_owned(),
         ledger: ".bolt/test-ledger".to_owned(),
-        clone: Some(vec![
-            // World program
-            anchor_cli::config::CloneEntry {
-                address: "WorLD15A7CrDwLcLy4fRqtaTb9fbd8o8iqiEMUDse2n".to_owned(),
-            },
-            // World executable data
-            anchor_cli::config::CloneEntry {
-                address: "CrsqUXPpJYpVAAx5qMKU6K8RT1TzT81T8BL6JndWSeo3".to_owned(),
-            },
-            // Registry
-            anchor_cli::config::CloneEntry {
+        account: Some(vec![
+            // Registry account
+            anchor_cli::config::AccountEntry {
                 address: "EHLkWwAT9oebVv9ht3mtqrvHhRVMKrt54tF3MfHTey2K".to_owned(),
+                filename: "tests/fixtures/registry.json".to_owned(),
             },
         ]),
         ..Default::default()
@@ -224,6 +247,11 @@ fn init(
         startup_wait: 5000,
         shutdown_wait: 2000,
         validator: Some(validator),
+        genesis: Some(vec![GenesisEntry {
+            address: WORLD_PROGRAM.to_owned(),
+            program: "tests/fixtures/world.so".to_owned(),
+            upgradeable: Some(false),
+        }]),
         ..Default::default()
     };
 
@@ -256,16 +284,54 @@ fn init(
     if solidity {
         anchor_cli::solidity_template::create_program(&project_name)?;
     } else {
-        create_component(component_name)?;
         create_system(system_name)?;
+        create_component(component_name)?;
         anchor_cli::rust_template::create_program(&project_name, template)?;
+
+        // Add the component as a dependency to the system
+        std::process::Command::new("cargo")
+            .arg("add")
+            .arg("--package")
+            .arg(system_name)
+            .arg("--path")
+            .arg(format!("programs-ecs/components/{}", component_name))
+            .arg("--features")
+            .arg("cpi")
+            .stdout(Stdio::inherit())
+            .stderr(Stdio::inherit())
+            .spawn()
+            .map_err(|e| {
+                anyhow::format_err!(
+                    "error adding component as dependency to the system: {}",
+                    e.to_string()
+                )
+            })?;
     }
 
     // Build the test suite.
-    fs::create_dir_all("tests")?;
+    fs::create_dir_all("tests/fixtures")?;
     // Build the migrations directory.
     fs::create_dir_all("migrations")?;
 
+    // Create the registry account
+    fs::write(
+        "tests/fixtures/registry.json",
+        rust_template::registry_account(),
+    )?;
+
+    // Dump the World program into tests/fixtures/world.so
+    std::process::Command::new("solana")
+        .arg("program")
+        .arg("dump")
+        .arg("-u")
+        .arg("d")
+        .arg(WORLD_PROGRAM)
+        .arg("tests/fixtures/world.so")
+        .stdout(Stdio::inherit())
+        .stderr(Stdio::inherit())
+        .spawn()
+        .map_err(|e| anyhow::format_err!("solana program dump failed: {}", e.to_string()))?;
+
     if javascript {
         // Build javascript config
         let mut package_json = File::create("package.json")?;
@@ -332,6 +398,43 @@ fn init(
     Ok(())
 }
 
+#[allow(clippy::too_many_arguments)]
+pub fn build(
+    cfg_override: &ConfigOverride,
+    idl: Option<String>,
+    idl_ts: Option<String>,
+    verifiable: bool,
+    skip_lint: bool,
+    program_name: Option<String>,
+    solana_version: Option<String>,
+    docker_image: Option<String>,
+    bootstrap: BootstrapMode,
+    stdout: Option<File>,
+    stderr: Option<File>,
+    env_vars: Vec<String>,
+    cargo_args: Vec<String>,
+    no_docs: bool,
+    arch: ProgramArch,
+) -> Result<()> {
+    anchor_cli::build(
+        cfg_override,
+        idl,
+        idl_ts,
+        verifiable,
+        skip_lint,
+        program_name,
+        solana_version,
+        docker_image,
+        bootstrap,
+        stdout,
+        stderr,
+        env_vars,
+        cargo_args,
+        no_docs,
+        arch,
+    )
+}
+
 // Install node modules
 fn install_node_modules(cmd: &str) -> Result<std::process::Output> {
     let mut command = std::process::Command::new(if cfg!(target_os = "windows") {

+ 31 - 29
cli/src/rust_template.rs

@@ -46,14 +46,7 @@ fn create_component_template_simple(name: &str, program_path: &Path) -> Files {
 
 declare_id!("{}");
 
-#[component({})]
-#[program]
-pub mod {} {{
-    use super::*;
-}}
-
-#[account]
-#[bolt_account(component_id = "")]
+#[component]
 pub struct {} {{
     pub x: i64,
     pub y: i64,
@@ -64,8 +57,6 @@ pub struct {} {{
 "#,
             anchor_cli::rust_template::get_or_create_program_id(name),
             name.to_upper_camel_case(),
-            name.to_snake_case(),
-            name.to_upper_camel_case(),
         ),
     )]
 }
@@ -76,34 +67,25 @@ fn create_system_template_simple(name: &str, program_path: &Path) -> Files {
         program_path.join("src").join("lib.rs"),
         format!(
             r#"use bolt_lang::*;
+use position::Position;
 
 declare_id!("{}");
 
 #[system]
-#[program]
 pub mod {} {{
-    use super::*;
 
-    pub fn execute(ctx: Context<Component>, args: Vec<u8>) -> Result<Position> {{
-        let mut position = Position::from_account_info(&ctx.accounts.position)?;
+    pub fn execute(ctx: Context<Components>, args_p: Vec<u8>) -> Result<Components> {{
+        let position = &mut ctx.accounts.position;
         position.x += 1;
-        Ok(position)
+        position.y += 1;
+        Ok(ctx.accounts)
     }}
-}}
 
-// Define the Account to parse from the component
-#[derive(Accounts)]
-pub struct Component<'info> {{
-    /// CHECK: check that the component is the expected account
-    pub position: AccountInfo<'info>,
-}}
+    #[system_input]
+    pub struct Components {{
+        pub position: Position,
+    }}
 
-#[component_deserialize]
-pub struct Position {{
-    pub x: i64,
-    pub y: i64,
-    pub z: i64,
-    pub description: String,
 }}
 "#,
             anchor_cli::rust_template::get_or_create_program_id(name),
@@ -422,7 +404,7 @@ fn cargo_toml(name: &str) -> String {
     format!(
         r#"[package]
 name = "{0}"
-version = "0.1.0"
+version = "0.0.1"
 description = "Created with Bolt"
 edition = "2021"
 
@@ -436,6 +418,7 @@ no-idl = []
 no-log-ix-name = []
 cpi = ["no-entrypoint"]
 default = []
+idl-build = ["anchor-lang/idl-build"]
 
 [dependencies]
 bolt-lang = "{2}"
@@ -478,3 +461,22 @@ build
 test-ledger
 "#
 }
+
+pub fn registry_account() -> &'static str {
+    r#"
+{
+  "pubkey": "EHLkWwAT9oebVv9ht3mtqrvHhRVMKrt54tF3MfHTey2K",
+  "account": {
+    "lamports": 1002240,
+    "data": [
+      "L65u9ri2/NoCAAAAAAAAAA==",
+      "base64"
+    ],
+    "owner": "WorLD15A7CrDwLcLy4fRqtaTb9fbd8o8iqiEMUDse2n",
+    "executable": false,
+    "rentEpoch": 18446744073709551615,
+    "space": 16
+  }
+}
+"#
+}

+ 56 - 9
clients/bolt-sdk/idl/world.json

@@ -105,6 +105,16 @@
           "isMut": false,
           "isSigner": false
         },
+        {
+          "name": "authority",
+          "isMut": false,
+          "isSigner": false
+        },
+        {
+          "name": "instructionSysvarAccount",
+          "isMut": false,
+          "isSigner": false
+        },
         {
           "name": "systemProgram",
           "isMut": false,
@@ -130,6 +140,16 @@
           "name": "boltComponent",
           "isMut": true,
           "isSigner": false
+        },
+        {
+          "name": "authority",
+          "isMut": false,
+          "isSigner": false
+        },
+        {
+          "name": "instructionSysvarAccount",
+          "isMut": false,
+          "isSigner": false
         }
       ],
       "args": [
@@ -166,6 +186,16 @@
           "name": "boltComponent2",
           "isMut": true,
           "isSigner": false
+        },
+        {
+          "name": "authority",
+          "isMut": false,
+          "isSigner": false
+        },
+        {
+          "name": "instructionSysvarAccount",
+          "isMut": false,
+          "isSigner": false
         }
       ],
       "args": [
@@ -212,6 +242,16 @@
           "name": "boltComponent3",
           "isMut": true,
           "isSigner": false
+        },
+        {
+          "name": "authority",
+          "isMut": false,
+          "isSigner": false
+        },
+        {
+          "name": "instructionSysvarAccount",
+          "isMut": false,
+          "isSigner": false
         }
       ],
       "args": [
@@ -224,46 +264,53 @@
   ],
   "accounts": [
     {
-      "name": "Registry",
+      "name": "Entity",
       "type": {
         "kind": "struct",
         "fields": [
           {
-            "name": "worlds",
+            "name": "id",
             "type": "u64"
           }
         ]
       }
     },
     {
-      "name": "World",
+      "name": "Registry",
       "type": {
         "kind": "struct",
         "fields": [
           {
-            "name": "id",
-            "type": "u64"
-          },
-          {
-            "name": "entities",
+            "name": "worlds",
             "type": "u64"
           }
         ]
       }
     },
     {
-      "name": "Entity",
+      "name": "World",
       "type": {
         "kind": "struct",
         "fields": [
           {
             "name": "id",
             "type": "u64"
+          },
+          {
+            "name": "entities",
+            "type": "u64"
           }
         ]
       }
     }
   ],
+  "errors": [
+    {
+      "code": 6000,
+      "name": "InvalidAuthority",
+      "msg": "Invalid authority for instruction"
+    }
+  ],
   "metadata": {
     "address": "WorLD15A7CrDwLcLy4fRqtaTb9fbd8o8iqiEMUDse2n",
     "origin": "anchor",

+ 1 - 1
clients/bolt-sdk/lib/accounts/Entity.d.ts

@@ -20,8 +20,8 @@ export declare class Entity implements EntityArgs {
     commitmentOrConfig?: web3.Commitment | web3.GetAccountInfoConfig
   ): Promise<Entity>;
   static gpaBuilder(programId?: web3.PublicKey): beetSolana.GpaBuilder<{
-    accountDiscriminator: any;
     id: any;
+    accountDiscriminator: any;
   }>;
   static deserialize(buf: Buffer, offset?: number): [Entity, number];
   serialize(): [Buffer, number];

+ 1 - 1
clients/bolt-sdk/lib/accounts/Registry.d.ts

@@ -20,8 +20,8 @@ export declare class Registry implements RegistryArgs {
     commitmentOrConfig?: web3.Commitment | web3.GetAccountInfoConfig
   ): Promise<Registry>;
   static gpaBuilder(programId?: web3.PublicKey): beetSolana.GpaBuilder<{
-    worlds: any;
     accountDiscriminator: any;
+    worlds: any;
   }>;
   static deserialize(buf: Buffer, offset?: number): [Registry, number];
   serialize(): [Buffer, number];

+ 1 - 1
clients/bolt-sdk/lib/accounts/World.d.ts

@@ -22,8 +22,8 @@ export declare class World implements WorldArgs {
     commitmentOrConfig?: web3.Commitment | web3.GetAccountInfoConfig
   ): Promise<World>;
   static gpaBuilder(programId?: web3.PublicKey): beetSolana.GpaBuilder<{
-    accountDiscriminator: any;
     id: any;
+    accountDiscriminator: any;
     entities: any;
   }>;
   static deserialize(buf: Buffer, offset?: number): [World, number];

+ 2 - 2
clients/bolt-sdk/lib/accounts/index.d.ts

@@ -1,12 +1,12 @@
+import { Entity } from "./Entity";
 import { Registry } from "./Registry";
 import { World } from "./World";
-import { Entity } from "./Entity";
 export * from "./Entity";
 export * from "./Registry";
 export * from "./World";
 export declare const accountProviders: {
+  Entity: typeof Entity;
   Registry: typeof Registry;
   World: typeof World;
-  Entity: typeof Entity;
 };
 //# sourceMappingURL=index.d.ts.map

+ 1 - 1
clients/bolt-sdk/lib/accounts/index.d.ts.map

@@ -1 +1 @@
-{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/generated/accounts/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAElC,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,SAAS,CAAC;AAExB,eAAO,MAAM,gBAAgB;;;;CAA8B,CAAC"}
+{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/generated/accounts/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAEhC,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,SAAS,CAAC;AAExB,eAAO,MAAM,gBAAgB;;;;CAA8B,CAAC"}

+ 2 - 2
clients/bolt-sdk/lib/accounts/index.js

@@ -31,15 +31,15 @@ var __exportStar =
   };
 Object.defineProperty(exports, "__esModule", { value: true });
 exports.accountProviders = void 0;
+var Entity_1 = require("./Entity");
 var Registry_1 = require("./Registry");
 var World_1 = require("./World");
-var Entity_1 = require("./Entity");
 __exportStar(require("./Entity"), exports);
 __exportStar(require("./Registry"), exports);
 __exportStar(require("./World"), exports);
 exports.accountProviders = {
+  Entity: Entity_1.Entity,
   Registry: Registry_1.Registry,
   World: World_1.World,
-  Entity: Entity_1.Entity,
 };
 //# sourceMappingURL=index.js.map

+ 1 - 1
clients/bolt-sdk/lib/accounts/index.js.map

@@ -1 +1 @@
-{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/generated/accounts/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,uCAAsC;AACtC,iCAAgC;AAChC,mCAAkC;AAElC,2CAAyB;AACzB,6CAA2B;AAC3B,0CAAwB;AAEX,QAAA,gBAAgB,GAAG,EAAE,QAAQ,qBAAA,EAAE,KAAK,eAAA,EAAE,MAAM,iBAAA,EAAE,CAAC"}
+{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/generated/accounts/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,mCAAkC;AAClC,uCAAsC;AACtC,iCAAgC;AAEhC,2CAAyB;AACzB,6CAA2B;AAC3B,0CAAwB;AAEX,QAAA,gBAAgB,GAAG,EAAE,MAAM,iBAAA,EAAE,QAAQ,qBAAA,EAAE,KAAK,eAAA,EAAE,CAAC"}

+ 13 - 0
clients/bolt-sdk/lib/errors/index.d.ts

@@ -0,0 +1,13 @@
+type ErrorWithCode = Error & {
+  code: number;
+};
+type MaybeErrorWithCode = ErrorWithCode | null | undefined;
+export declare class InvalidAuthorityError extends Error {
+  readonly code: number;
+  readonly name: string;
+  constructor();
+}
+export declare function errorFromCode(code: number): MaybeErrorWithCode;
+export declare function errorFromName(name: string): MaybeErrorWithCode;
+export {};
+//# sourceMappingURL=index.d.ts.map

+ 1 - 0
clients/bolt-sdk/lib/errors/index.d.ts.map

@@ -0,0 +1 @@
+{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/generated/errors/index.ts"],"names":[],"mappings":"AAOA,KAAK,aAAa,GAAG,KAAK,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAC9C,KAAK,kBAAkB,GAAG,aAAa,GAAG,IAAI,GAAG,SAAS,CAAC;AAW3D,qBAAa,qBAAsB,SAAQ,KAAK;IAC9C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAU;IAC/B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAsB;;CAO5C;AAaD,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,kBAAkB,CAG9D;AAOD,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,kBAAkB,CAG9D"}

+ 70 - 0
clients/bolt-sdk/lib/errors/index.js

@@ -0,0 +1,70 @@
+"use strict";
+var __extends =
+  (this && this.__extends) ||
+  (function () {
+    var extendStatics = function (d, b) {
+      extendStatics =
+        Object.setPrototypeOf ||
+        ({ __proto__: [] } instanceof Array &&
+          function (d, b) {
+            d.__proto__ = b;
+          }) ||
+        function (d, b) {
+          for (var p in b)
+            if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];
+        };
+      return extendStatics(d, b);
+    };
+    return function (d, b) {
+      if (typeof b !== "function" && b !== null)
+        throw new TypeError(
+          "Class extends value " + String(b) + " is not a constructor or null"
+        );
+      extendStatics(d, b);
+      function __() {
+        this.constructor = d;
+      }
+      d.prototype =
+        b === null
+          ? Object.create(b)
+          : ((__.prototype = b.prototype), new __());
+    };
+  })();
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.errorFromName =
+  exports.errorFromCode =
+  exports.InvalidAuthorityError =
+    void 0;
+var createErrorFromCodeLookup = new Map();
+var createErrorFromNameLookup = new Map();
+var InvalidAuthorityError = (function (_super) {
+  __extends(InvalidAuthorityError, _super);
+  function InvalidAuthorityError() {
+    var _this = _super.call(this, "Invalid authority for instruction") || this;
+    _this.code = 0x1770;
+    _this.name = "InvalidAuthority";
+    if (typeof Error.captureStackTrace === "function") {
+      Error.captureStackTrace(_this, InvalidAuthorityError);
+    }
+    return _this;
+  }
+  return InvalidAuthorityError;
+})(Error);
+exports.InvalidAuthorityError = InvalidAuthorityError;
+createErrorFromCodeLookup.set(0x1770, function () {
+  return new InvalidAuthorityError();
+});
+createErrorFromNameLookup.set("InvalidAuthority", function () {
+  return new InvalidAuthorityError();
+});
+function errorFromCode(code) {
+  var createError = createErrorFromCodeLookup.get(code);
+  return createError != null ? createError() : null;
+}
+exports.errorFromCode = errorFromCode;
+function errorFromName(name) {
+  var createError = createErrorFromNameLookup.get(name);
+  return createError != null ? createError() : null;
+}
+exports.errorFromName = errorFromName;
+//# sourceMappingURL=index.js.map

+ 1 - 0
clients/bolt-sdk/lib/errors/index.js.map

@@ -0,0 +1 @@
+{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/generated/errors/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;AAUA,IAAM,yBAAyB,GAAG,IAAI,GAAG,EAA+B,CAAC;AACzE,IAAM,yBAAyB,GAAG,IAAI,GAAG,EAA+B,CAAC;AAQzE;IAA2C,yCAAK;IAG9C;QAAA,YACE,kBAAM,mCAAmC,CAAC,SAI3C;QAPQ,UAAI,GAAW,MAAM,CAAC;QACtB,UAAI,GAAW,kBAAkB,CAAC;QAGzC,IAAI,OAAO,KAAK,CAAC,iBAAiB,KAAK,UAAU,EAAE;YACjD,KAAK,CAAC,iBAAiB,CAAC,KAAI,EAAE,qBAAqB,CAAC,CAAC;SACtD;;IACH,CAAC;IACH,4BAAC;AAAD,CAAC,AATD,CAA2C,KAAK,GAS/C;AATY,sDAAqB;AAWlC,yBAAyB,CAAC,GAAG,CAAC,MAAM,EAAE,cAAM,OAAA,IAAI,qBAAqB,EAAE,EAA3B,CAA2B,CAAC,CAAC;AACzE,yBAAyB,CAAC,GAAG,CAC3B,kBAAkB,EAClB,cAAM,OAAA,IAAI,qBAAqB,EAAE,EAA3B,CAA2B,CAClC,CAAC;AAOF,SAAgB,aAAa,CAAC,IAAY;IACxC,IAAM,WAAW,GAAG,yBAAyB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACxD,OAAO,WAAW,IAAI,IAAI,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AACpD,CAAC;AAHD,sCAGC;AAOD,SAAgB,aAAa,CAAC,IAAY;IACxC,IAAM,WAAW,GAAG,yBAAyB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACxD,OAAO,WAAW,IAAI,IAAI,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AACpD,CAAC;AAHD,sCAGC"}

+ 1 - 0
clients/bolt-sdk/lib/index.d.ts

@@ -4,6 +4,7 @@ export * from "./accounts";
 export * from "./instructions";
 export declare const PROGRAM_ADDRESS =
   "WorLD15A7CrDwLcLy4fRqtaTb9fbd8o8iqiEMUDse2n";
+export declare const SYSVAR_INSTRUCTIONS_PUBKEY: PublicKey;
 export declare const PROGRAM_ID: PublicKey;
 export declare function FindWorldRegistryPda(programId?: PublicKey): PublicKey;
 export declare function FindWorldPda(id: BN, programId?: PublicKey): PublicKey;

+ 1 - 1
clients/bolt-sdk/lib/index.d.ts.map

@@ -1 +1 @@
-{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/generated/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,KAAK,EAAE,MAAM,OAAO,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC;AAQ/B,eAAO,MAAM,eAAe,gDAAgD,CAAC;AAQ7E,eAAO,MAAM,UAAU,WAAiC,CAAC;AAEzD,wBAAgB,oBAAoB,CAClC,SAAS,GAAE,SAAqC,aAMjD;AAED,wBAAgB,YAAY,CAC1B,EAAE,EAAE,EAAE,EACN,SAAS,GAAE,SAAqC,aAMjD;AAED,wBAAgB,aAAa,CAC3B,OAAO,EAAE,EAAE,EACX,QAAQ,EAAE,EAAE,EACZ,SAAS,CAAC,EAAE,MAAM,EAClB,SAAS,GAAE,SAAqC,aAUjD;AAED,wBAAgB,gBAAgB,CAC5B,kBAAkB,EAAE,SAAS,EAC7B,MAAM,EAAE,SAAS,EACjB,WAAW,GAAE,MAAW,aAM3B"}
+{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/generated/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,KAAK,EAAE,MAAM,OAAO,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC;AAQ/B,eAAO,MAAM,eAAe,gDAAgD,CAAC;AAE7E,eAAO,MAAM,0BAA0B,WAEtC,CAAC;AAQF,eAAO,MAAM,UAAU,WAAiC,CAAC;AAEzD,wBAAgB,oBAAoB,CAClC,SAAS,GAAE,SAAqC,aAMjD;AAED,wBAAgB,YAAY,CAC1B,EAAE,EAAE,EAAE,EACN,SAAS,GAAE,SAAqC,aAMjD;AAED,wBAAgB,aAAa,CAC3B,OAAO,EAAE,EAAE,EACX,QAAQ,EAAE,EAAE,EACZ,SAAS,CAAC,EAAE,MAAM,EAClB,SAAS,GAAE,SAAqC,aAUjD;AAED,wBAAgB,gBAAgB,CAC9B,kBAAkB,EAAE,SAAS,EAC7B,MAAM,EAAE,SAAS,EACjB,WAAW,GAAE,MAAW,aAMzB"}

+ 4 - 0
clients/bolt-sdk/lib/index.js

@@ -35,12 +35,16 @@ exports.FindComponentPda =
   exports.FindWorldPda =
   exports.FindWorldRegistryPda =
   exports.PROGRAM_ID =
+  exports.SYSVAR_INSTRUCTIONS_PUBKEY =
   exports.PROGRAM_ADDRESS =
     void 0;
 var web3_js_1 = require("@solana/web3.js");
 __exportStar(require("./accounts"), exports);
 __exportStar(require("./instructions"), exports);
 exports.PROGRAM_ADDRESS = "WorLD15A7CrDwLcLy4fRqtaTb9fbd8o8iqiEMUDse2n";
+exports.SYSVAR_INSTRUCTIONS_PUBKEY = new web3_js_1.PublicKey(
+  "Sysvar1nstructions1111111111111111111111111"
+);
 exports.PROGRAM_ID = new web3_js_1.PublicKey(exports.PROGRAM_ADDRESS);
 function FindWorldRegistryPda(programId) {
   if (programId === void 0) {

+ 1 - 1
clients/bolt-sdk/lib/index.js.map

@@ -1 +1 @@
-{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/generated/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,2CAA4C;AAE5C,6CAA2B;AAC3B,iDAA+B;AAQlB,QAAA,eAAe,GAAG,6CAA6C,CAAC;AAQhE,QAAA,UAAU,GAAG,IAAI,mBAAS,CAAC,uBAAe,CAAC,CAAC;AAEzD,SAAgB,oBAAoB,CAClC,SAAgD;IAAhD,0BAAA,EAAA,gBAA2B,mBAAS,CAAC,kBAAU,CAAC;IAEhD,OAAO,mBAAS,CAAC,sBAAsB,CACrC,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,EACzB,SAAS,CACV,CAAC,CAAC,CAAC,CAAC;AACP,CAAC;AAPD,oDAOC;AAED,SAAgB,YAAY,CAC1B,EAAM,EACN,SAAgD;IAAhD,0BAAA,EAAA,gBAA2B,mBAAS,CAAC,kBAAU,CAAC;IAEhD,OAAO,mBAAS,CAAC,sBAAsB,CACrC,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAC5C,SAAS,CACV,CAAC,CAAC,CAAC,CAAC;AACP,CAAC;AARD,oCAQC;AAED,SAAgB,aAAa,CAC3B,OAAW,EACX,QAAY,EACZ,SAAkB,EAClB,SAAgD;IAAhD,0BAAA,EAAA,gBAA2B,mBAAS,CAAC,kBAAU,CAAC;IAEhD,IAAM,KAAK,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IACjE,IAAI,SAAS,IAAI,IAAI,EAAE;QACrB,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3C,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;KACpC;SAAM;QACL,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;KACxC;IACD,OAAO,mBAAS,CAAC,sBAAsB,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;AAC/D,CAAC;AAdD,sCAcC;AAED,SAAgB,gBAAgB,CAC5B,kBAA6B,EAC7B,MAAiB,EACjB,WAAwB;IAAxB,4BAAA,EAAA,gBAAwB;IAE1B,OAAO,mBAAS,CAAC,sBAAsB,CACrC,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC,EAC5C,kBAAkB,CACnB,CAAC,CAAC,CAAC,CAAC;AACP,CAAC;AATD,4CASC"}
+{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/generated/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,2CAA4C;AAE5C,6CAA2B;AAC3B,iDAA+B;AAQlB,QAAA,eAAe,GAAG,6CAA6C,CAAC;AAEhE,QAAA,0BAA0B,GAAG,IAAI,mBAAS,CACrD,6CAA6C,CAC9C,CAAC;AAQW,QAAA,UAAU,GAAG,IAAI,mBAAS,CAAC,uBAAe,CAAC,CAAC;AAEzD,SAAgB,oBAAoB,CAClC,SAAgD;IAAhD,0BAAA,EAAA,gBAA2B,mBAAS,CAAC,kBAAU,CAAC;IAEhD,OAAO,mBAAS,CAAC,sBAAsB,CACrC,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,EACzB,SAAS,CACV,CAAC,CAAC,CAAC,CAAC;AACP,CAAC;AAPD,oDAOC;AAED,SAAgB,YAAY,CAC1B,EAAM,EACN,SAAgD;IAAhD,0BAAA,EAAA,gBAA2B,mBAAS,CAAC,kBAAU,CAAC;IAEhD,OAAO,mBAAS,CAAC,sBAAsB,CACrC,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAC5C,SAAS,CACV,CAAC,CAAC,CAAC,CAAC;AACP,CAAC;AARD,oCAQC;AAED,SAAgB,aAAa,CAC3B,OAAW,EACX,QAAY,EACZ,SAAkB,EAClB,SAAgD;IAAhD,0BAAA,EAAA,gBAA2B,mBAAS,CAAC,kBAAU,CAAC;IAEhD,IAAM,KAAK,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IACjE,IAAI,SAAS,IAAI,IAAI,EAAE;QACrB,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3C,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;KACpC;SAAM;QACL,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;KACxC;IACD,OAAO,mBAAS,CAAC,sBAAsB,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;AAC/D,CAAC;AAdD,sCAcC;AAED,SAAgB,gBAAgB,CAC9B,kBAA6B,EAC7B,MAAiB,EACjB,WAAwB;IAAxB,4BAAA,EAAA,gBAAwB;IAExB,OAAO,mBAAS,CAAC,sBAAsB,CACrC,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC,EAC5C,kBAAkB,CACnB,CAAC,CAAC,CAAC,CAAC;AACP,CAAC;AATD,4CASC"}

+ 2 - 0
clients/bolt-sdk/lib/instructions/apply.d.ts

@@ -12,6 +12,8 @@ export interface ApplyInstructionAccounts {
   componentProgram: web3.PublicKey;
   boltSystem: web3.PublicKey;
   boltComponent: web3.PublicKey;
+  authority?: web3.PublicKey;
+  instructionSysvarAccount?: web3.PublicKey;
   anchorRemainingAccounts?: web3.AccountMeta[];
 }
 export declare const applyInstructionDiscriminator: number[];

+ 1 - 1
clients/bolt-sdk/lib/instructions/apply.d.ts.map

@@ -1 +1 @@
-{"version":3,"file":"apply.d.ts","sourceRoot":"","sources":["../../src/generated/instructions/apply.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,IAAI,MAAM,2BAA2B,CAAC;AAClD,OAAO,KAAK,IAAI,MAAM,iBAAiB,CAAC;AAOxC,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,UAAU,CAAC;CAClB;AAMD,eAAO,MAAM,WAAW;8BAEM,MAAM,EAAE;EAQrC,CAAC;AAWF,MAAM,WAAW,wBAAwB;IACvC,gBAAgB,EAAE,IAAI,CAAC,SAAS,CAAC;IACjC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC;IAC3B,aAAa,EAAE,IAAI,CAAC,SAAS,CAAC;IAC9B,uBAAuB,CAAC,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC;CAC9C;AAED,eAAO,MAAM,6BAA6B,UAEzC,CAAC;AAYF,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,wBAAwB,EAClC,IAAI,EAAE,oBAAoB,EAC1B,SAAS,iBAAoE,+BAoC9E"}
+{"version":3,"file":"apply.d.ts","sourceRoot":"","sources":["../../src/generated/instructions/apply.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,IAAI,MAAM,2BAA2B,CAAC;AAClD,OAAO,KAAK,IAAI,MAAM,iBAAiB,CAAC;AAQxC,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,UAAU,CAAC;CAClB;AAMD,eAAO,MAAM,WAAW;8BAEM,MAAM,EAAE;EAQrC,CAAC;AAaF,MAAM,WAAW,wBAAwB;IACvC,gBAAgB,EAAE,IAAI,CAAC,SAAS,CAAC;IACjC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC;IAC3B,aAAa,EAAE,IAAI,CAAC,SAAS,CAAC;IAC9B,SAAS,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC;IAC3B,wBAAwB,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC;IAC1C,uBAAuB,CAAC,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC;CAC9C;AAED,eAAO,MAAM,6BAA6B,UAEzC,CAAC;AAYF,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,wBAAwB,EAClC,IAAI,EAAE,oBAAoB,EAC1B,SAAS,iBAAoE,+BA8C9E"}

+ 19 - 3
clients/bolt-sdk/lib/instructions/apply.js

@@ -65,6 +65,7 @@ exports.createApplyInstruction =
     void 0;
 var beet = __importStar(require("@metaplex-foundation/beet"));
 var web3 = __importStar(require("@solana/web3.js"));
+var index_1 = require("../index");
 exports.applyStruct = new beet.FixableBeetArgsStruct(
   [
     ["instructionDiscriminator", beet.uniformFixedSizeArray(beet.u8, 8)],
@@ -74,6 +75,7 @@ exports.applyStruct = new beet.FixableBeetArgsStruct(
 );
 exports.applyInstructionDiscriminator = [248, 243, 145, 24, 105, 50, 162, 225];
 function createApplyInstruction(accounts, args, programId) {
+  var _a, _b;
   if (programId === void 0) {
     programId = new web3.PublicKey(
       "WorLD15A7CrDwLcLy4fRqtaTb9fbd8o8iqiEMUDse2n"
@@ -101,14 +103,28 @@ function createApplyInstruction(accounts, args, programId) {
       isWritable: true,
       isSigner: false,
     },
+    {
+      pubkey:
+        (_a = accounts.authority) !== null && _a !== void 0 ? _a : programId,
+      isWritable: false,
+      isSigner: false,
+    },
+    {
+      pubkey:
+        (_b = accounts.instructionSysvarAccount) !== null && _b !== void 0
+          ? _b
+          : index_1.SYSVAR_INSTRUCTIONS_PUBKEY,
+      isWritable: false,
+      isSigner: false,
+    },
   ];
   if (accounts.anchorRemainingAccounts != null) {
     for (
-      var _i = 0, _a = accounts.anchorRemainingAccounts;
-      _i < _a.length;
+      var _i = 0, _c = accounts.anchorRemainingAccounts;
+      _i < _c.length;
       _i++
     ) {
-      var acc = _a[_i];
+      var acc = _c[_i];
       keys.push(acc);
     }
   }

+ 1 - 1
clients/bolt-sdk/lib/instructions/apply.js.map

@@ -1 +1 @@
-{"version":3,"file":"apply.js","sourceRoot":"","sources":["../../src/generated/instructions/apply.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAOA,8DAAkD;AAClD,oDAAwC;AAe3B,QAAA,WAAW,GAAG,IAAI,IAAI,CAAC,qBAAqB,CAKvD;IACE,CAAC,0BAA0B,EAAE,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;IACpE,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC;CACrB,EACD,sBAAsB,CACvB,CAAC;AAkBW,QAAA,6BAA6B,GAAG;IAC3C,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG;CACrC,CAAC;AAYF,SAAgB,sBAAsB,CACpC,QAAkC,EAClC,IAA0B,EAC1B,SAA6E;IAA7E,0BAAA,EAAA,gBAAgB,IAAI,CAAC,SAAS,CAAC,6CAA6C,CAAC;IAEtE,IAAA,IAAI,GAAI,mBAAW,CAAC,SAAS,YAClC,wBAAwB,EAAE,qCAA6B,IACpD,IAAI,EACP,GAHS,CAGR;IACH,IAAM,IAAI,GAAuB;QAC/B;YACE,MAAM,EAAE,QAAQ,CAAC,gBAAgB;YACjC,UAAU,EAAE,KAAK;YACjB,QAAQ,EAAE,KAAK;SAChB;QACD;YACE,MAAM,EAAE,QAAQ,CAAC,UAAU;YAC3B,UAAU,EAAE,KAAK;YACjB,QAAQ,EAAE,KAAK;SAChB;QACD;YACE,MAAM,EAAE,QAAQ,CAAC,aAAa;YAC9B,UAAU,EAAE,IAAI;YAChB,QAAQ,EAAE,KAAK;SAChB;KACF,CAAC;IAEF,IAAI,QAAQ,CAAC,uBAAuB,IAAI,IAAI,EAAE;QAC5C,KAAkB,UAAgC,EAAhC,KAAA,QAAQ,CAAC,uBAAuB,EAAhC,cAAgC,EAAhC,IAAgC,EAAE;YAA/C,IAAM,GAAG,SAAA;YACZ,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;SAChB;KACF;IAED,IAAM,EAAE,GAAG,IAAI,IAAI,CAAC,sBAAsB,CAAC;QACzC,SAAS,WAAA;QACT,IAAI,MAAA;QACJ,IAAI,MAAA;KACL,CAAC,CAAC;IACH,OAAO,EAAE,CAAC;AACZ,CAAC;AAvCD,wDAuCC"}
+{"version":3,"file":"apply.js","sourceRoot":"","sources":["../../src/generated/instructions/apply.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAOA,8DAAkD;AAClD,oDAAwC;AACxC,kCAAsD;AAezC,QAAA,WAAW,GAAG,IAAI,IAAI,CAAC,qBAAqB,CAKvD;IACE,CAAC,0BAA0B,EAAE,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;IACpE,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC;CACrB,EACD,sBAAsB,CACvB,CAAC;AAsBW,QAAA,6BAA6B,GAAG;IAC3C,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG;CACrC,CAAC;AAYF,SAAgB,sBAAsB,CACpC,QAAkC,EAClC,IAA0B,EAC1B,SAA6E;;IAA7E,0BAAA,EAAA,gBAAgB,IAAI,CAAC,SAAS,CAAC,6CAA6C,CAAC;IAEtE,IAAA,IAAI,GAAI,mBAAW,CAAC,SAAS,YAClC,wBAAwB,EAAE,qCAA6B,IACpD,IAAI,EACP,GAHS,CAGR;IACH,IAAM,IAAI,GAAuB;QAC/B;YACE,MAAM,EAAE,QAAQ,CAAC,gBAAgB;YACjC,UAAU,EAAE,KAAK;YACjB,QAAQ,EAAE,KAAK;SAChB;QACD;YACE,MAAM,EAAE,QAAQ,CAAC,UAAU;YAC3B,UAAU,EAAE,KAAK;YACjB,QAAQ,EAAE,KAAK;SAChB;QACD;YACE,MAAM,EAAE,QAAQ,CAAC,aAAa;YAC9B,UAAU,EAAE,IAAI;YAChB,QAAQ,EAAE,KAAK;SAChB;QACD;YACE,MAAM,EAAE,MAAA,QAAQ,CAAC,SAAS,mCAAI,SAAS;YACvC,UAAU,EAAE,KAAK;YACjB,QAAQ,EAAE,KAAK;SAChB;QACD;YACE,MAAM,EAAE,MAAA,QAAQ,CAAC,wBAAwB,mCAAI,kCAA0B;YACvE,UAAU,EAAE,KAAK;YACjB,QAAQ,EAAE,KAAK;SAChB;KACF,CAAC;IAEF,IAAI,QAAQ,CAAC,uBAAuB,IAAI,IAAI,EAAE;QAC5C,KAAkB,UAAgC,EAAhC,KAAA,QAAQ,CAAC,uBAAuB,EAAhC,cAAgC,EAAhC,IAAgC,EAAE;YAA/C,IAAM,GAAG,SAAA;YACZ,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;SAChB;KACF;IAED,IAAM,EAAE,GAAG,IAAI,IAAI,CAAC,sBAAsB,CAAC;QACzC,SAAS,WAAA;QACT,IAAI,MAAA;QACJ,IAAI,MAAA;KACL,CAAC,CAAC;IACH,OAAO,EAAE,CAAC;AACZ,CAAC;AAjDD,wDAiDC"}

+ 2 - 0
clients/bolt-sdk/lib/instructions/apply2.d.ts

@@ -14,6 +14,8 @@ export interface Apply2InstructionAccounts {
   boltComponent1: web3.PublicKey;
   componentProgram2: web3.PublicKey;
   boltComponent2: web3.PublicKey;
+  authority?: web3.PublicKey;
+  instructionSysvarAccount?: web3.PublicKey;
   anchorRemainingAccounts?: web3.AccountMeta[];
 }
 export declare const apply2InstructionDiscriminator: number[];

+ 1 - 1
clients/bolt-sdk/lib/instructions/apply2.d.ts.map

@@ -1 +1 @@
-{"version":3,"file":"apply2.d.ts","sourceRoot":"","sources":["../../src/generated/instructions/apply2.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,IAAI,MAAM,2BAA2B,CAAC;AAClD,OAAO,KAAK,IAAI,MAAM,iBAAiB,CAAC;AAOxC,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,UAAU,CAAC;CAClB;AAMD,eAAO,MAAM,YAAY;8BAEK,MAAM,EAAE;EAQrC,CAAC;AAaF,MAAM,WAAW,yBAAyB;IACxC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC;IAC3B,iBAAiB,EAAE,IAAI,CAAC,SAAS,CAAC;IAClC,cAAc,EAAE,IAAI,CAAC,SAAS,CAAC;IAC/B,iBAAiB,EAAE,IAAI,CAAC,SAAS,CAAC;IAClC,cAAc,EAAE,IAAI,CAAC,SAAS,CAAC;IAC/B,uBAAuB,CAAC,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC;CAC9C;AAED,eAAO,MAAM,8BAA8B,UAE1C,CAAC;AAYF,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,yBAAyB,EACnC,IAAI,EAAE,qBAAqB,EAC3B,SAAS,iBAAoE,+BA8C9E"}
+{"version":3,"file":"apply2.d.ts","sourceRoot":"","sources":["../../src/generated/instructions/apply2.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,IAAI,MAAM,2BAA2B,CAAC;AAClD,OAAO,KAAK,IAAI,MAAM,iBAAiB,CAAC;AAQxC,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,UAAU,CAAC;CAClB;AAMD,eAAO,MAAM,YAAY;8BAEK,MAAM,EAAE;EAQrC,CAAC;AAeF,MAAM,WAAW,yBAAyB;IACxC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC;IAC3B,iBAAiB,EAAE,IAAI,CAAC,SAAS,CAAC;IAClC,cAAc,EAAE,IAAI,CAAC,SAAS,CAAC;IAC/B,iBAAiB,EAAE,IAAI,CAAC,SAAS,CAAC;IAClC,cAAc,EAAE,IAAI,CAAC,SAAS,CAAC;IAC/B,SAAS,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC;IAC3B,wBAAwB,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC;IAC1C,uBAAuB,CAAC,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC;CAC9C;AAED,eAAO,MAAM,8BAA8B,UAE1C,CAAC;AAYF,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,yBAAyB,EACnC,IAAI,EAAE,qBAAqB,EAC3B,SAAS,iBAAoE,+BAwD9E"}

+ 19 - 3
clients/bolt-sdk/lib/instructions/apply2.js

@@ -65,6 +65,7 @@ exports.createApply2Instruction =
     void 0;
 var beet = __importStar(require("@metaplex-foundation/beet"));
 var web3 = __importStar(require("@solana/web3.js"));
+var index_1 = require("../index");
 exports.apply2Struct = new beet.FixableBeetArgsStruct(
   [
     ["instructionDiscriminator", beet.uniformFixedSizeArray(beet.u8, 8)],
@@ -74,6 +75,7 @@ exports.apply2Struct = new beet.FixableBeetArgsStruct(
 );
 exports.apply2InstructionDiscriminator = [120, 32, 116, 154, 158, 159, 208, 73];
 function createApply2Instruction(accounts, args, programId) {
+  var _a, _b;
   if (programId === void 0) {
     programId = new web3.PublicKey(
       "WorLD15A7CrDwLcLy4fRqtaTb9fbd8o8iqiEMUDse2n"
@@ -111,14 +113,28 @@ function createApply2Instruction(accounts, args, programId) {
       isWritable: true,
       isSigner: false,
     },
+    {
+      pubkey:
+        (_a = accounts.authority) !== null && _a !== void 0 ? _a : programId,
+      isWritable: false,
+      isSigner: false,
+    },
+    {
+      pubkey:
+        (_b = accounts.instructionSysvarAccount) !== null && _b !== void 0
+          ? _b
+          : index_1.SYSVAR_INSTRUCTIONS_PUBKEY,
+      isWritable: false,
+      isSigner: false,
+    },
   ];
   if (accounts.anchorRemainingAccounts != null) {
     for (
-      var _i = 0, _a = accounts.anchorRemainingAccounts;
-      _i < _a.length;
+      var _i = 0, _c = accounts.anchorRemainingAccounts;
+      _i < _c.length;
       _i++
     ) {
-      var acc = _a[_i];
+      var acc = _c[_i];
       keys.push(acc);
     }
   }

+ 1 - 1
clients/bolt-sdk/lib/instructions/apply2.js.map

@@ -1 +1 @@
-{"version":3,"file":"apply2.js","sourceRoot":"","sources":["../../src/generated/instructions/apply2.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAOA,8DAAkD;AAClD,oDAAwC;AAe3B,QAAA,YAAY,GAAG,IAAI,IAAI,CAAC,qBAAqB,CAKxD;IACE,CAAC,0BAA0B,EAAE,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;IACpE,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC;CACrB,EACD,uBAAuB,CACxB,CAAC;AAsBW,QAAA,8BAA8B,GAAG;IAC5C,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;CACrC,CAAC;AAYF,SAAgB,uBAAuB,CACrC,QAAmC,EACnC,IAA2B,EAC3B,SAA6E;IAA7E,0BAAA,EAAA,gBAAgB,IAAI,CAAC,SAAS,CAAC,6CAA6C,CAAC;IAEtE,IAAA,IAAI,GAAI,oBAAY,CAAC,SAAS,YACnC,wBAAwB,EAAE,sCAA8B,IACrD,IAAI,EACP,GAHS,CAGR;IACH,IAAM,IAAI,GAAuB;QAC/B;YACE,MAAM,EAAE,QAAQ,CAAC,UAAU;YAC3B,UAAU,EAAE,KAAK;YACjB,QAAQ,EAAE,KAAK;SAChB;QACD;YACE,MAAM,EAAE,QAAQ,CAAC,iBAAiB;YAClC,UAAU,EAAE,KAAK;YACjB,QAAQ,EAAE,KAAK;SAChB;QACD;YACE,MAAM,EAAE,QAAQ,CAAC,cAAc;YAC/B,UAAU,EAAE,IAAI;YAChB,QAAQ,EAAE,KAAK;SAChB;QACD;YACE,MAAM,EAAE,QAAQ,CAAC,iBAAiB;YAClC,UAAU,EAAE,KAAK;YACjB,QAAQ,EAAE,KAAK;SAChB;QACD;YACE,MAAM,EAAE,QAAQ,CAAC,cAAc;YAC/B,UAAU,EAAE,IAAI;YAChB,QAAQ,EAAE,KAAK;SAChB;KACF,CAAC;IAEF,IAAI,QAAQ,CAAC,uBAAuB,IAAI,IAAI,EAAE;QAC5C,KAAkB,UAAgC,EAAhC,KAAA,QAAQ,CAAC,uBAAuB,EAAhC,cAAgC,EAAhC,IAAgC,EAAE;YAA/C,IAAM,GAAG,SAAA;YACZ,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;SAChB;KACF;IAED,IAAM,EAAE,GAAG,IAAI,IAAI,CAAC,sBAAsB,CAAC;QACzC,SAAS,WAAA;QACT,IAAI,MAAA;QACJ,IAAI,MAAA;KACL,CAAC,CAAC;IACH,OAAO,EAAE,CAAC;AACZ,CAAC;AAjDD,0DAiDC"}
+{"version":3,"file":"apply2.js","sourceRoot":"","sources":["../../src/generated/instructions/apply2.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAOA,8DAAkD;AAClD,oDAAwC;AACxC,kCAAsD;AAezC,QAAA,YAAY,GAAG,IAAI,IAAI,CAAC,qBAAqB,CAKxD;IACE,CAAC,0BAA0B,EAAE,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;IACpE,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC;CACrB,EACD,uBAAuB,CACxB,CAAC;AA0BW,QAAA,8BAA8B,GAAG;IAC5C,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;CACrC,CAAC;AAYF,SAAgB,uBAAuB,CACrC,QAAmC,EACnC,IAA2B,EAC3B,SAA6E;;IAA7E,0BAAA,EAAA,gBAAgB,IAAI,CAAC,SAAS,CAAC,6CAA6C,CAAC;IAEtE,IAAA,IAAI,GAAI,oBAAY,CAAC,SAAS,YACnC,wBAAwB,EAAE,sCAA8B,IACrD,IAAI,EACP,GAHS,CAGR;IACH,IAAM,IAAI,GAAuB;QAC/B;YACE,MAAM,EAAE,QAAQ,CAAC,UAAU;YAC3B,UAAU,EAAE,KAAK;YACjB,QAAQ,EAAE,KAAK;SAChB;QACD;YACE,MAAM,EAAE,QAAQ,CAAC,iBAAiB;YAClC,UAAU,EAAE,KAAK;YACjB,QAAQ,EAAE,KAAK;SAChB;QACD;YACE,MAAM,EAAE,QAAQ,CAAC,cAAc;YAC/B,UAAU,EAAE,IAAI;YAChB,QAAQ,EAAE,KAAK;SAChB;QACD;YACE,MAAM,EAAE,QAAQ,CAAC,iBAAiB;YAClC,UAAU,EAAE,KAAK;YACjB,QAAQ,EAAE,KAAK;SAChB;QACD;YACE,MAAM,EAAE,QAAQ,CAAC,cAAc;YAC/B,UAAU,EAAE,IAAI;YAChB,QAAQ,EAAE,KAAK;SAChB;QACD;YACE,MAAM,EAAE,MAAA,QAAQ,CAAC,SAAS,mCAAI,SAAS;YACvC,UAAU,EAAE,KAAK;YACjB,QAAQ,EAAE,KAAK;SAChB;QACD;YACE,MAAM,EAAE,MAAA,QAAQ,CAAC,wBAAwB,mCAAI,kCAA0B;YACvE,UAAU,EAAE,KAAK;YACjB,QAAQ,EAAE,KAAK;SAChB;KACF,CAAC;IAEF,IAAI,QAAQ,CAAC,uBAAuB,IAAI,IAAI,EAAE;QAC5C,KAAkB,UAAgC,EAAhC,KAAA,QAAQ,CAAC,uBAAuB,EAAhC,cAAgC,EAAhC,IAAgC,EAAE;YAA/C,IAAM,GAAG,SAAA;YACZ,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;SAChB;KACF;IAED,IAAM,EAAE,GAAG,IAAI,IAAI,CAAC,sBAAsB,CAAC;QACzC,SAAS,WAAA;QACT,IAAI,MAAA;QACJ,IAAI,MAAA;KACL,CAAC,CAAC;IACH,OAAO,EAAE,CAAC;AACZ,CAAC;AA3DD,0DA2DC"}

+ 2 - 0
clients/bolt-sdk/lib/instructions/apply3.d.ts

@@ -16,6 +16,8 @@ export interface Apply3InstructionAccounts {
   boltComponent2: web3.PublicKey;
   componentProgram3: web3.PublicKey;
   boltComponent3: web3.PublicKey;
+  authority?: web3.PublicKey;
+  instructionSysvarAccount?: web3.PublicKey;
   anchorRemainingAccounts?: web3.AccountMeta[];
 }
 export declare const apply3InstructionDiscriminator: number[];

+ 1 - 1
clients/bolt-sdk/lib/instructions/apply3.d.ts.map

@@ -1 +1 @@
-{"version":3,"file":"apply3.d.ts","sourceRoot":"","sources":["../../src/generated/instructions/apply3.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,IAAI,MAAM,2BAA2B,CAAC;AAClD,OAAO,KAAK,IAAI,MAAM,iBAAiB,CAAC;AAOxC,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,UAAU,CAAC;CAClB;AAMD,eAAO,MAAM,YAAY;8BAEK,MAAM,EAAE;EAQrC,CAAC;AAeF,MAAM,WAAW,yBAAyB;IACxC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC;IAC3B,iBAAiB,EAAE,IAAI,CAAC,SAAS,CAAC;IAClC,cAAc,EAAE,IAAI,CAAC,SAAS,CAAC;IAC/B,iBAAiB,EAAE,IAAI,CAAC,SAAS,CAAC;IAClC,cAAc,EAAE,IAAI,CAAC,SAAS,CAAC;IAC/B,iBAAiB,EAAE,IAAI,CAAC,SAAS,CAAC;IAClC,cAAc,EAAE,IAAI,CAAC,SAAS,CAAC;IAC/B,uBAAuB,CAAC,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC;CAC9C;AAED,eAAO,MAAM,8BAA8B,UAE1C,CAAC;AAYF,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,yBAAyB,EACnC,IAAI,EAAE,qBAAqB,EAC3B,SAAS,iBAAoE,+BAwD9E"}
+{"version":3,"file":"apply3.d.ts","sourceRoot":"","sources":["../../src/generated/instructions/apply3.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,IAAI,MAAM,2BAA2B,CAAC;AAClD,OAAO,KAAK,IAAI,MAAM,iBAAiB,CAAC;AAQxC,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,UAAU,CAAC;CAClB;AAMD,eAAO,MAAM,YAAY;8BAEK,MAAM,EAAE;EAQrC,CAAC;AAiBF,MAAM,WAAW,yBAAyB;IACxC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC;IAC3B,iBAAiB,EAAE,IAAI,CAAC,SAAS,CAAC;IAClC,cAAc,EAAE,IAAI,CAAC,SAAS,CAAC;IAC/B,iBAAiB,EAAE,IAAI,CAAC,SAAS,CAAC;IAClC,cAAc,EAAE,IAAI,CAAC,SAAS,CAAC;IAC/B,iBAAiB,EAAE,IAAI,CAAC,SAAS,CAAC;IAClC,cAAc,EAAE,IAAI,CAAC,SAAS,CAAC;IAC/B,SAAS,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC;IAC3B,wBAAwB,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC;IAC1C,uBAAuB,CAAC,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC;CAC9C;AAED,eAAO,MAAM,8BAA8B,UAE1C,CAAC;AAYF,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,yBAAyB,EACnC,IAAI,EAAE,qBAAqB,EAC3B,SAAS,iBAAoE,+BAkE9E"}

+ 19 - 3
clients/bolt-sdk/lib/instructions/apply3.js

@@ -65,6 +65,7 @@ exports.createApply3Instruction =
     void 0;
 var beet = __importStar(require("@metaplex-foundation/beet"));
 var web3 = __importStar(require("@solana/web3.js"));
+var index_1 = require("../index");
 exports.apply3Struct = new beet.FixableBeetArgsStruct(
   [
     ["instructionDiscriminator", beet.uniformFixedSizeArray(beet.u8, 8)],
@@ -74,6 +75,7 @@ exports.apply3Struct = new beet.FixableBeetArgsStruct(
 );
 exports.apply3InstructionDiscriminator = [254, 146, 49, 7, 236, 131, 105, 221];
 function createApply3Instruction(accounts, args, programId) {
+  var _a, _b;
   if (programId === void 0) {
     programId = new web3.PublicKey(
       "WorLD15A7CrDwLcLy4fRqtaTb9fbd8o8iqiEMUDse2n"
@@ -121,14 +123,28 @@ function createApply3Instruction(accounts, args, programId) {
       isWritable: true,
       isSigner: false,
     },
+    {
+      pubkey:
+        (_a = accounts.authority) !== null && _a !== void 0 ? _a : programId,
+      isWritable: false,
+      isSigner: false,
+    },
+    {
+      pubkey:
+        (_b = accounts.instructionSysvarAccount) !== null && _b !== void 0
+          ? _b
+          : index_1.SYSVAR_INSTRUCTIONS_PUBKEY,
+      isWritable: false,
+      isSigner: false,
+    },
   ];
   if (accounts.anchorRemainingAccounts != null) {
     for (
-      var _i = 0, _a = accounts.anchorRemainingAccounts;
-      _i < _a.length;
+      var _i = 0, _c = accounts.anchorRemainingAccounts;
+      _i < _c.length;
       _i++
     ) {
-      var acc = _a[_i];
+      var acc = _c[_i];
       keys.push(acc);
     }
   }

+ 1 - 1
clients/bolt-sdk/lib/instructions/apply3.js.map

@@ -1 +1 @@
-{"version":3,"file":"apply3.js","sourceRoot":"","sources":["../../src/generated/instructions/apply3.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAOA,8DAAkD;AAClD,oDAAwC;AAe3B,QAAA,YAAY,GAAG,IAAI,IAAI,CAAC,qBAAqB,CAKxD;IACE,CAAC,0BAA0B,EAAE,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;IACpE,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC;CACrB,EACD,uBAAuB,CACxB,CAAC;AA0BW,QAAA,8BAA8B,GAAG;IAC5C,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG;CACpC,CAAC;AAYF,SAAgB,uBAAuB,CACrC,QAAmC,EACnC,IAA2B,EAC3B,SAA6E;IAA7E,0BAAA,EAAA,gBAAgB,IAAI,CAAC,SAAS,CAAC,6CAA6C,CAAC;IAEtE,IAAA,IAAI,GAAI,oBAAY,CAAC,SAAS,YACnC,wBAAwB,EAAE,sCAA8B,IACrD,IAAI,EACP,GAHS,CAGR;IACH,IAAM,IAAI,GAAuB;QAC/B;YACE,MAAM,EAAE,QAAQ,CAAC,UAAU;YAC3B,UAAU,EAAE,KAAK;YACjB,QAAQ,EAAE,KAAK;SAChB;QACD;YACE,MAAM,EAAE,QAAQ,CAAC,iBAAiB;YAClC,UAAU,EAAE,KAAK;YACjB,QAAQ,EAAE,KAAK;SAChB;QACD;YACE,MAAM,EAAE,QAAQ,CAAC,cAAc;YAC/B,UAAU,EAAE,IAAI;YAChB,QAAQ,EAAE,KAAK;SAChB;QACD;YACE,MAAM,EAAE,QAAQ,CAAC,iBAAiB;YAClC,UAAU,EAAE,KAAK;YACjB,QAAQ,EAAE,KAAK;SAChB;QACD;YACE,MAAM,EAAE,QAAQ,CAAC,cAAc;YAC/B,UAAU,EAAE,IAAI;YAChB,QAAQ,EAAE,KAAK;SAChB;QACD;YACE,MAAM,EAAE,QAAQ,CAAC,iBAAiB;YAClC,UAAU,EAAE,KAAK;YACjB,QAAQ,EAAE,KAAK;SAChB;QACD;YACE,MAAM,EAAE,QAAQ,CAAC,cAAc;YAC/B,UAAU,EAAE,IAAI;YAChB,QAAQ,EAAE,KAAK;SAChB;KACF,CAAC;IAEF,IAAI,QAAQ,CAAC,uBAAuB,IAAI,IAAI,EAAE;QAC5C,KAAkB,UAAgC,EAAhC,KAAA,QAAQ,CAAC,uBAAuB,EAAhC,cAAgC,EAAhC,IAAgC,EAAE;YAA/C,IAAM,GAAG,SAAA;YACZ,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;SAChB;KACF;IAED,IAAM,EAAE,GAAG,IAAI,IAAI,CAAC,sBAAsB,CAAC;QACzC,SAAS,WAAA;QACT,IAAI,MAAA;QACJ,IAAI,MAAA;KACL,CAAC,CAAC;IACH,OAAO,EAAE,CAAC;AACZ,CAAC;AA3DD,0DA2DC"}
+{"version":3,"file":"apply3.js","sourceRoot":"","sources":["../../src/generated/instructions/apply3.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAOA,8DAAkD;AAClD,oDAAwC;AACxC,kCAAsD;AAezC,QAAA,YAAY,GAAG,IAAI,IAAI,CAAC,qBAAqB,CAKxD;IACE,CAAC,0BAA0B,EAAE,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;IACpE,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC;CACrB,EACD,uBAAuB,CACxB,CAAC;AA8BW,QAAA,8BAA8B,GAAG;IAC5C,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG;CACpC,CAAC;AAYF,SAAgB,uBAAuB,CACrC,QAAmC,EACnC,IAA2B,EAC3B,SAA6E;;IAA7E,0BAAA,EAAA,gBAAgB,IAAI,CAAC,SAAS,CAAC,6CAA6C,CAAC;IAEtE,IAAA,IAAI,GAAI,oBAAY,CAAC,SAAS,YACnC,wBAAwB,EAAE,sCAA8B,IACrD,IAAI,EACP,GAHS,CAGR;IACH,IAAM,IAAI,GAAuB;QAC/B;YACE,MAAM,EAAE,QAAQ,CAAC,UAAU;YAC3B,UAAU,EAAE,KAAK;YACjB,QAAQ,EAAE,KAAK;SAChB;QACD;YACE,MAAM,EAAE,QAAQ,CAAC,iBAAiB;YAClC,UAAU,EAAE,KAAK;YACjB,QAAQ,EAAE,KAAK;SAChB;QACD;YACE,MAAM,EAAE,QAAQ,CAAC,cAAc;YAC/B,UAAU,EAAE,IAAI;YAChB,QAAQ,EAAE,KAAK;SAChB;QACD;YACE,MAAM,EAAE,QAAQ,CAAC,iBAAiB;YAClC,UAAU,EAAE,KAAK;YACjB,QAAQ,EAAE,KAAK;SAChB;QACD;YACE,MAAM,EAAE,QAAQ,CAAC,cAAc;YAC/B,UAAU,EAAE,IAAI;YAChB,QAAQ,EAAE,KAAK;SAChB;QACD;YACE,MAAM,EAAE,QAAQ,CAAC,iBAAiB;YAClC,UAAU,EAAE,KAAK;YACjB,QAAQ,EAAE,KAAK;SAChB;QACD;YACE,MAAM,EAAE,QAAQ,CAAC,cAAc;YAC/B,UAAU,EAAE,IAAI;YAChB,QAAQ,EAAE,KAAK;SAChB;QACD;YACE,MAAM,EAAE,MAAA,QAAQ,CAAC,SAAS,mCAAI,SAAS;YACvC,UAAU,EAAE,KAAK;YACjB,QAAQ,EAAE,KAAK;SAChB;QACD;YACE,MAAM,EAAE,MAAA,QAAQ,CAAC,wBAAwB,mCAAI,kCAA0B;YACvE,UAAU,EAAE,KAAK;YACjB,QAAQ,EAAE,KAAK;SAChB;KACF,CAAC;IAEF,IAAI,QAAQ,CAAC,uBAAuB,IAAI,IAAI,EAAE;QAC5C,KAAkB,UAAgC,EAAhC,KAAA,QAAQ,CAAC,uBAAuB,EAAhC,cAAgC,EAAhC,IAAgC,EAAE;YAA/C,IAAM,GAAG,SAAA;YACZ,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;SAChB;KACF;IAED,IAAM,EAAE,GAAG,IAAI,IAAI,CAAC,sBAAsB,CAAC;QACzC,SAAS,WAAA;QACT,IAAI,MAAA;QACJ,IAAI,MAAA;KACL,CAAC,CAAC;IACH,OAAO,EAAE,CAAC;AACZ,CAAC;AArED,0DAqEC"}

+ 2 - 0
clients/bolt-sdk/lib/instructions/initializeComponent.d.ts

@@ -8,6 +8,8 @@ export interface InitializeComponentInstructionAccounts {
   data: web3.PublicKey;
   entity: web3.PublicKey;
   componentProgram: web3.PublicKey;
+  authority?: web3.PublicKey;
+  instructionSysvarAccount?: web3.PublicKey;
   systemProgram?: web3.PublicKey;
   anchorRemainingAccounts?: web3.AccountMeta[];
 }

+ 1 - 1
clients/bolt-sdk/lib/instructions/initializeComponent.d.ts.map

@@ -1 +1 @@
-{"version":3,"file":"initializeComponent.d.ts","sourceRoot":"","sources":["../../src/generated/instructions/initializeComponent.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,IAAI,MAAM,2BAA2B,CAAC;AAClD,OAAO,KAAK,IAAI,MAAM,iBAAiB,CAAC;AAOxC,eAAO,MAAM,yBAAyB;8BACV,MAAM,EAAE;EAInC,CAAC;AAYF,MAAM,WAAW,sCAAsC;IACrD,KAAK,EAAE,IAAI,CAAC,SAAS,CAAC;IACtB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;IACrB,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC;IACvB,gBAAgB,EAAE,IAAI,CAAC,SAAS,CAAC;IACjC,aAAa,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC;IAC/B,uBAAuB,CAAC,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC;CAC9C;AAED,eAAO,MAAM,2CAA2C,UAEvD,CAAC;AAUF,wBAAgB,oCAAoC,CAClD,QAAQ,EAAE,sCAAsC,EAChD,SAAS,iBAAoE,+BA6C9E"}
+{"version":3,"file":"initializeComponent.d.ts","sourceRoot":"","sources":["../../src/generated/instructions/initializeComponent.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,IAAI,MAAM,2BAA2B,CAAC;AAClD,OAAO,KAAK,IAAI,MAAM,iBAAiB,CAAC;AAQxC,eAAO,MAAM,yBAAyB;8BACV,MAAM,EAAE;EAInC,CAAC;AAcF,MAAM,WAAW,sCAAsC;IACrD,KAAK,EAAE,IAAI,CAAC,SAAS,CAAC;IACtB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;IACrB,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC;IACvB,gBAAgB,EAAE,IAAI,CAAC,SAAS,CAAC;IACjC,SAAS,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC;IAC3B,wBAAwB,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC;IAC1C,aAAa,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC;IAC/B,uBAAuB,CAAC,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC;CAC9C;AAED,eAAO,MAAM,2CAA2C,UAEvD,CAAC;AAUF,wBAAgB,oCAAoC,CAClD,QAAQ,EAAE,sCAAsC,EAChD,SAAS,iBAAoE,+BAuD9E"}

+ 21 - 6
clients/bolt-sdk/lib/instructions/initializeComponent.js

@@ -50,6 +50,7 @@ exports.createInitializeComponentInstruction =
     void 0;
 var beet = __importStar(require("@metaplex-foundation/beet"));
 var web3 = __importStar(require("@solana/web3.js"));
+var index_1 = require("../index");
 exports.initializeComponentStruct = new beet.BeetArgsStruct(
   [["instructionDiscriminator", beet.uniformFixedSizeArray(beet.u8, 8)]],
   "InitializeComponentInstructionArgs"
@@ -58,7 +59,7 @@ exports.initializeComponentInstructionDiscriminator = [
   36, 143, 233, 113, 12, 234, 61, 30,
 ];
 function createInitializeComponentInstruction(accounts, programId) {
-  var _a;
+  var _a, _b, _c;
   if (programId === void 0) {
     programId = new web3.PublicKey(
       "WorLD15A7CrDwLcLy4fRqtaTb9fbd8o8iqiEMUDse2n"
@@ -91,8 +92,22 @@ function createInitializeComponentInstruction(accounts, programId) {
     },
     {
       pubkey:
-        (_a = accounts.systemProgram) !== null && _a !== void 0
-          ? _a
+        (_a = accounts.authority) !== null && _a !== void 0 ? _a : programId,
+      isWritable: false,
+      isSigner: false,
+    },
+    {
+      pubkey:
+        (_b = accounts.instructionSysvarAccount) !== null && _b !== void 0
+          ? _b
+          : index_1.SYSVAR_INSTRUCTIONS_PUBKEY,
+      isWritable: false,
+      isSigner: false,
+    },
+    {
+      pubkey:
+        (_c = accounts.systemProgram) !== null && _c !== void 0
+          ? _c
           : web3.SystemProgram.programId,
       isWritable: false,
       isSigner: false,
@@ -100,11 +115,11 @@ function createInitializeComponentInstruction(accounts, programId) {
   ];
   if (accounts.anchorRemainingAccounts != null) {
     for (
-      var _i = 0, _b = accounts.anchorRemainingAccounts;
-      _i < _b.length;
+      var _i = 0, _d = accounts.anchorRemainingAccounts;
+      _i < _d.length;
       _i++
     ) {
-      var acc = _b[_i];
+      var acc = _d[_i];
       keys.push(acc);
     }
   }

+ 1 - 1
clients/bolt-sdk/lib/instructions/initializeComponent.js.map

@@ -1 +1 @@
-{"version":3,"file":"initializeComponent.js","sourceRoot":"","sources":["../../src/generated/instructions/initializeComponent.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAOA,8DAAkD;AAClD,oDAAwC;AAO3B,QAAA,yBAAyB,GAAG,IAAI,IAAI,CAAC,cAAc,CAG9D,CAAC,CAAC,0BAA0B,EAAE,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EACtE,oCAAoC,CACrC,CAAC;AAqBW,QAAA,2CAA2C,GAAG;IACzD,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE;CACnC,CAAC;AAUF,SAAgB,oCAAoC,CAClD,QAAgD,EAChD,SAA6E;;IAA7E,0BAAA,EAAA,gBAAgB,IAAI,CAAC,SAAS,CAAC,6CAA6C,CAAC;IAEtE,IAAA,IAAI,GAAI,iCAAyB,CAAC,SAAS,CAAC;QACjD,wBAAwB,EAAE,mDAA2C;KACtE,CAAC,GAFS,CAER;IACH,IAAM,IAAI,GAAuB;QAC/B;YACE,MAAM,EAAE,QAAQ,CAAC,KAAK;YACtB,UAAU,EAAE,IAAI;YAChB,QAAQ,EAAE,IAAI;SACf;QACD;YACE,MAAM,EAAE,QAAQ,CAAC,IAAI;YACrB,UAAU,EAAE,IAAI;YAChB,QAAQ,EAAE,KAAK;SAChB;QACD;YACE,MAAM,EAAE,QAAQ,CAAC,MAAM;YACvB,UAAU,EAAE,KAAK;YACjB,QAAQ,EAAE,KAAK;SAChB;QACD;YACE,MAAM,EAAE,QAAQ,CAAC,gBAAgB;YACjC,UAAU,EAAE,KAAK;YACjB,QAAQ,EAAE,KAAK;SAChB;QACD;YACE,MAAM,EAAE,MAAA,QAAQ,CAAC,aAAa,mCAAI,IAAI,CAAC,aAAa,CAAC,SAAS;YAC9D,UAAU,EAAE,KAAK;YACjB,QAAQ,EAAE,KAAK;SAChB;KACF,CAAC;IAEF,IAAI,QAAQ,CAAC,uBAAuB,IAAI,IAAI,EAAE;QAC5C,KAAkB,UAAgC,EAAhC,KAAA,QAAQ,CAAC,uBAAuB,EAAhC,cAAgC,EAAhC,IAAgC,EAAE;YAA/C,IAAM,GAAG,SAAA;YACZ,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;SAChB;KACF;IAED,IAAM,EAAE,GAAG,IAAI,IAAI,CAAC,sBAAsB,CAAC;QACzC,SAAS,WAAA;QACT,IAAI,MAAA;QACJ,IAAI,MAAA;KACL,CAAC,CAAC;IACH,OAAO,EAAE,CAAC;AACZ,CAAC;AA/CD,oFA+CC"}
+{"version":3,"file":"initializeComponent.js","sourceRoot":"","sources":["../../src/generated/instructions/initializeComponent.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAOA,8DAAkD;AAClD,oDAAwC;AACxC,kCAAsD;AAOzC,QAAA,yBAAyB,GAAG,IAAI,IAAI,CAAC,cAAc,CAG9D,CAAC,CAAC,0BAA0B,EAAE,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EACtE,oCAAoC,CACrC,CAAC;AAyBW,QAAA,2CAA2C,GAAG;IACzD,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE;CACnC,CAAC;AAUF,SAAgB,oCAAoC,CAClD,QAAgD,EAChD,SAA6E;;IAA7E,0BAAA,EAAA,gBAAgB,IAAI,CAAC,SAAS,CAAC,6CAA6C,CAAC;IAEtE,IAAA,IAAI,GAAI,iCAAyB,CAAC,SAAS,CAAC;QACjD,wBAAwB,EAAE,mDAA2C;KACtE,CAAC,GAFS,CAER;IACH,IAAM,IAAI,GAAuB;QAC/B;YACE,MAAM,EAAE,QAAQ,CAAC,KAAK;YACtB,UAAU,EAAE,IAAI;YAChB,QAAQ,EAAE,IAAI;SACf;QACD;YACE,MAAM,EAAE,QAAQ,CAAC,IAAI;YACrB,UAAU,EAAE,IAAI;YAChB,QAAQ,EAAE,KAAK;SAChB;QACD;YACE,MAAM,EAAE,QAAQ,CAAC,MAAM;YACvB,UAAU,EAAE,KAAK;YACjB,QAAQ,EAAE,KAAK;SAChB;QACD;YACE,MAAM,EAAE,QAAQ,CAAC,gBAAgB;YACjC,UAAU,EAAE,KAAK;YACjB,QAAQ,EAAE,KAAK;SAChB;QACD;YACE,MAAM,EAAE,MAAA,QAAQ,CAAC,SAAS,mCAAI,SAAS;YACvC,UAAU,EAAE,KAAK;YACjB,QAAQ,EAAE,KAAK;SAChB;QACD;YACE,MAAM,EAAE,MAAA,QAAQ,CAAC,wBAAwB,mCAAI,kCAA0B;YACvE,UAAU,EAAE,KAAK;YACjB,QAAQ,EAAE,KAAK;SAChB;QACD;YACE,MAAM,EAAE,MAAA,QAAQ,CAAC,aAAa,mCAAI,IAAI,CAAC,aAAa,CAAC,SAAS;YAC9D,UAAU,EAAE,KAAK;YACjB,QAAQ,EAAE,KAAK;SAChB;KACF,CAAC;IAEF,IAAI,QAAQ,CAAC,uBAAuB,IAAI,IAAI,EAAE;QAC5C,KAAkB,UAAgC,EAAhC,KAAA,QAAQ,CAAC,uBAAuB,EAAhC,cAAgC,EAAhC,IAAgC,EAAE;YAA/C,IAAM,GAAG,SAAA;YACZ,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;SAChB;KACF;IAED,IAAM,EAAE,GAAG,IAAI,IAAI,CAAC,sBAAsB,CAAC;QACzC,SAAS,WAAA;QACT,IAAI,MAAA;QACJ,IAAI,MAAA;KACL,CAAC,CAAC;IACH,OAAO,EAAE,CAAC;AACZ,CAAC;AAzDD,oFAyDC"}

+ 2 - 2
clients/bolt-sdk/src/generated/accounts/index.ts

@@ -1,9 +1,9 @@
+import { Entity } from "./Entity";
 import { Registry } from "./Registry";
 import { World } from "./World";
-import { Entity } from "./Entity";
 
 export * from "./Entity";
 export * from "./Registry";
 export * from "./World";
 
-export const accountProviders = { Registry, World, Entity };
+export const accountProviders = { Entity, Registry, World };

+ 55 - 0
clients/bolt-sdk/src/generated/errors/index.ts

@@ -0,0 +1,55 @@
+/**
+ * This code was GENERATED using the solita package.
+ * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality.
+ *
+ * See: https://github.com/metaplex-foundation/solita
+ */
+
+type ErrorWithCode = Error & { code: number };
+type MaybeErrorWithCode = ErrorWithCode | null | undefined;
+
+const createErrorFromCodeLookup = new Map<number, () => ErrorWithCode>();
+const createErrorFromNameLookup = new Map<string, () => ErrorWithCode>();
+
+/**
+ * InvalidAuthority: 'Invalid authority for instruction'
+ *
+ * @category Errors
+ * @category generated
+ */
+export class InvalidAuthorityError extends Error {
+  readonly code: number = 0x1770;
+  readonly name: string = "InvalidAuthority";
+  constructor() {
+    super("Invalid authority for instruction");
+    if (typeof Error.captureStackTrace === "function") {
+      Error.captureStackTrace(this, InvalidAuthorityError);
+    }
+  }
+}
+
+createErrorFromCodeLookup.set(0x1770, () => new InvalidAuthorityError());
+createErrorFromNameLookup.set(
+  "InvalidAuthority",
+  () => new InvalidAuthorityError()
+);
+
+/**
+ * Attempts to resolve a custom program error from the provided error code.
+ * @category Errors
+ * @category generated
+ */
+export function errorFromCode(code: number): MaybeErrorWithCode {
+  const createError = createErrorFromCodeLookup.get(code);
+  return createError != null ? createError() : null;
+}
+
+/**
+ * Attempts to resolve a custom program error from the provided error name, i.e. 'Unauthorized'.
+ * @category Errors
+ * @category generated
+ */
+export function errorFromName(name: string): MaybeErrorWithCode {
+  const createError = createErrorFromNameLookup.get(name);
+  return createError != null ? createError() : null;
+}

+ 4 - 0
clients/bolt-sdk/src/generated/index.ts

@@ -11,6 +11,10 @@ export * from "./instructions";
  */
 export const PROGRAM_ADDRESS = "WorLD15A7CrDwLcLy4fRqtaTb9fbd8o8iqiEMUDse2n";
 
+export const SYSVAR_INSTRUCTIONS_PUBKEY = new PublicKey(
+  "Sysvar1nstructions1111111111111111111111111"
+);
+
 /**
  * Program public key
  *

+ 15 - 0
clients/bolt-sdk/src/generated/instructions/apply.ts

@@ -7,6 +7,7 @@
 
 import * as beet from "@metaplex-foundation/beet";
 import * as web3 from "@solana/web3.js";
+import { SYSVAR_INSTRUCTIONS_PUBKEY } from "../index";
 
 /**
  * @category Instructions
@@ -38,6 +39,8 @@ export const applyStruct = new beet.FixableBeetArgsStruct<
  * @property [] componentProgram
  * @property [] boltSystem
  * @property [_writable_] boltComponent
+ * @property [] authority
+ * @property [] instructionSysvarAccount
  * @category Instructions
  * @category Apply
  * @category generated
@@ -46,6 +49,8 @@ export interface ApplyInstructionAccounts {
   componentProgram: web3.PublicKey;
   boltSystem: web3.PublicKey;
   boltComponent: web3.PublicKey;
+  authority?: web3.PublicKey;
+  instructionSysvarAccount?: web3.PublicKey;
   anchorRemainingAccounts?: web3.AccountMeta[];
 }
 
@@ -88,6 +93,16 @@ export function createApplyInstruction(
       isWritable: true,
       isSigner: false,
     },
+    {
+      pubkey: accounts.authority ?? programId,
+      isWritable: false,
+      isSigner: false,
+    },
+    {
+      pubkey: accounts.instructionSysvarAccount ?? SYSVAR_INSTRUCTIONS_PUBKEY,
+      isWritable: false,
+      isSigner: false,
+    },
   ];
 
   if (accounts.anchorRemainingAccounts != null) {

+ 15 - 0
clients/bolt-sdk/src/generated/instructions/apply2.ts

@@ -7,6 +7,7 @@
 
 import * as beet from "@metaplex-foundation/beet";
 import * as web3 from "@solana/web3.js";
+import { SYSVAR_INSTRUCTIONS_PUBKEY } from "../index";
 
 /**
  * @category Instructions
@@ -40,6 +41,8 @@ export const apply2Struct = new beet.FixableBeetArgsStruct<
  * @property [_writable_] boltComponent1
  * @property [] componentProgram2
  * @property [_writable_] boltComponent2
+ * @property [] authority
+ * @property [] instructionSysvarAccount
  * @category Instructions
  * @category Apply2
  * @category generated
@@ -50,6 +53,8 @@ export interface Apply2InstructionAccounts {
   boltComponent1: web3.PublicKey;
   componentProgram2: web3.PublicKey;
   boltComponent2: web3.PublicKey;
+  authority?: web3.PublicKey;
+  instructionSysvarAccount?: web3.PublicKey;
   anchorRemainingAccounts?: web3.AccountMeta[];
 }
 
@@ -102,6 +107,16 @@ export function createApply2Instruction(
       isWritable: true,
       isSigner: false,
     },
+    {
+      pubkey: accounts.authority ?? programId,
+      isWritable: false,
+      isSigner: false,
+    },
+    {
+      pubkey: accounts.instructionSysvarAccount ?? SYSVAR_INSTRUCTIONS_PUBKEY,
+      isWritable: false,
+      isSigner: false,
+    },
   ];
 
   if (accounts.anchorRemainingAccounts != null) {

+ 15 - 0
clients/bolt-sdk/src/generated/instructions/apply3.ts

@@ -7,6 +7,7 @@
 
 import * as beet from "@metaplex-foundation/beet";
 import * as web3 from "@solana/web3.js";
+import { SYSVAR_INSTRUCTIONS_PUBKEY } from "../index";
 
 /**
  * @category Instructions
@@ -42,6 +43,8 @@ export const apply3Struct = new beet.FixableBeetArgsStruct<
  * @property [_writable_] boltComponent2
  * @property [] componentProgram3
  * @property [_writable_] boltComponent3
+ * @property [] authority
+ * @property [] instructionSysvarAccount
  * @category Instructions
  * @category Apply3
  * @category generated
@@ -54,6 +57,8 @@ export interface Apply3InstructionAccounts {
   boltComponent2: web3.PublicKey;
   componentProgram3: web3.PublicKey;
   boltComponent3: web3.PublicKey;
+  authority?: web3.PublicKey;
+  instructionSysvarAccount?: web3.PublicKey;
   anchorRemainingAccounts?: web3.AccountMeta[];
 }
 
@@ -116,6 +121,16 @@ export function createApply3Instruction(
       isWritable: true,
       isSigner: false,
     },
+    {
+      pubkey: accounts.authority ?? programId,
+      isWritable: false,
+      isSigner: false,
+    },
+    {
+      pubkey: accounts.instructionSysvarAccount ?? SYSVAR_INSTRUCTIONS_PUBKEY,
+      isWritable: false,
+      isSigner: false,
+    },
   ];
 
   if (accounts.anchorRemainingAccounts != null) {

+ 15 - 0
clients/bolt-sdk/src/generated/instructions/initializeComponent.ts

@@ -7,6 +7,7 @@
 
 import * as beet from "@metaplex-foundation/beet";
 import * as web3 from "@solana/web3.js";
+import { SYSVAR_INSTRUCTIONS_PUBKEY } from "../index";
 
 /**
  * @category Instructions
@@ -26,6 +27,8 @@ export const initializeComponentStruct = new beet.BeetArgsStruct<{
  * @property [_writable_] data
  * @property [] entity
  * @property [] componentProgram
+ * @property [] authority
+ * @property [] instructionSysvarAccount
  * @category Instructions
  * @category InitializeComponent
  * @category generated
@@ -35,6 +38,8 @@ export interface InitializeComponentInstructionAccounts {
   data: web3.PublicKey;
   entity: web3.PublicKey;
   componentProgram: web3.PublicKey;
+  authority?: web3.PublicKey;
+  instructionSysvarAccount?: web3.PublicKey;
   systemProgram?: web3.PublicKey;
   anchorRemainingAccounts?: web3.AccountMeta[];
 }
@@ -79,6 +84,16 @@ export function createInitializeComponentInstruction(
       isWritable: false,
       isSigner: false,
     },
+    {
+      pubkey: accounts.authority ?? programId,
+      isWritable: false,
+      isSigner: false,
+    },
+    {
+      pubkey: accounts.instructionSysvarAccount ?? SYSVAR_INSTRUCTIONS_PUBKEY,
+      isWritable: false,
+      isSigner: false,
+    },
     {
       pubkey: accounts.systemProgram ?? web3.SystemProgram.programId,
       isWritable: false,

+ 1 - 1
crates/bolt-helpers/Cargo.toml

@@ -1,6 +1,6 @@
 [package]
 name = "bolt-helpers"
-version = "0.1.0"
+version = "0.0.1"
 edition = "2021"
 
 [dependencies]

+ 1 - 1
crates/bolt-helpers/attribute/system-template/Cargo.toml

@@ -1,6 +1,6 @@
 [package]
 name = "bolt-helpers-system-template"
-version = "0.1.0"
+version = "0.0.1"
 edition = "2021"
 
 [lib]

+ 3 - 5
crates/bolt-helpers/attribute/system-template/src/lib.rs

@@ -6,8 +6,6 @@ use syn::parse::{Parse, ParseStream, Result};
 use syn::{parse_macro_input, Ident, LitInt, Token};
 
 /// This macro attribute is a helper used for defining BOLT systems execute proxy instructions.
-///
-/// ```
 #[proc_macro_attribute]
 pub fn system_template(attr: TokenStream, item: TokenStream) -> TokenStream {
     let attr_p = parse_macro_input!(attr as SystemTemplateInput);
@@ -20,7 +18,7 @@ pub fn system_template(attr: TokenStream, item: TokenStream) -> TokenStream {
     // Generate a function for execute instruction
     let funcs = (2..=max_components).map(|i| {
         let func_name = syn::Ident::new(&format!("execute_{}", i), proc_macro2::Span::call_site());
-        let data_struct = syn::Ident::new("SetData", proc_macro2::Span::call_site());
+        let data_struct = syn::Ident::new(&format!("SetData{}", i), proc_macro2::Span::call_site());
         let return_values = vec![quote!(Vec::<u8>::new()); i];
         let return_types = vec![quote!(Vec<u8>); i];
         quote! {
@@ -49,11 +47,11 @@ pub fn system_template(attr: TokenStream, item: TokenStream) -> TokenStream {
             quote! {
                 #[account()]
                 /// CHECK: unchecked account
-                pub #field_name: anchor_lang::prelude::UncheckedAccount<'info>,
+                pub #field_name: UncheckedAccount<'info>,
             }
         });
         let struct_def = quote! {
-        #[derive(Accounts, BorshDeserialize, BorshSerialize, Clone)]
+            #[derive(Accounts)]
             pub struct #data_struct<'info> {
                 #(#fields)*
             }

+ 12 - 0
crates/bolt-helpers/attribute/world-apply/Cargo.toml

@@ -0,0 +1,12 @@
+[package]
+name = "bolt-helpers-world-apply"
+version = "0.0.1"
+edition = "2021"
+
+[lib]
+proc-macro = true
+
+[dependencies]
+proc-macro2 = "1.0"
+quote = "1.0"
+syn = "1.0"

+ 150 - 0
crates/bolt-helpers/attribute/world-apply/src/lib.rs

@@ -0,0 +1,150 @@
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+use quote::quote;
+use syn::parse::{Parse, ParseStream, Result};
+use syn::{parse_macro_input, Ident, LitInt, Token};
+
+/// This macro attribute is a helper used for defining BOLT apply proxy instructions.
+#[proc_macro_attribute]
+pub fn apply_system(attr: TokenStream, item: TokenStream) -> TokenStream {
+    let attr_p = parse_macro_input!(attr as SystemTemplateInput);
+
+    let max_components = attr_p.max_components;
+
+    // Parse the original module content
+    let mut input: syn::ItemMod = syn::parse(item).expect("Failed to parse input module");
+
+    // Generate a function for execute instruction
+    let funcs = (2..=max_components).map(|i| {
+        let apply_func_name = syn::Ident::new(&format!("apply{}", i), proc_macro2::Span::call_site());
+        let execute_func_name = syn::Ident::new(&format!("execute_{}", i), proc_macro2::Span::call_site());
+        let data_struct = syn::Ident::new(&format!("ApplySystem{}", i), proc_macro2::Span::call_site());
+
+        let updates = (1..=i).enumerate().map(|(index, n)| {
+            let component_program_name = syn::Ident::new(&format!("component_program_{}", n), proc_macro2::Span::call_site());
+            let bolt_component_name = syn::Ident::new(&format!("bolt_component_{}", n), proc_macro2::Span::call_site());
+
+            quote! {
+            let update_result = bolt_component::cpi::update(
+                build_update_context(
+                    ctx.accounts.#component_program_name.clone(),
+                    ctx.accounts.#bolt_component_name.clone(),
+                    ctx.accounts.authority.clone(),
+                    ctx.accounts.instruction_sysvar_account.clone(),
+                ),
+                res[#index].to_owned()
+            )?;
+        }
+        });
+
+        quote! {
+        pub fn #apply_func_name(ctx: Context<#data_struct>, args: Vec<u8>) -> Result<()> {
+            if !ctx.accounts.authority.is_signer && ctx.accounts.authority.key != &ID {
+                return Err(WorldError::InvalidAuthority.into());
+            }
+            let res = bolt_system::cpi::#execute_func_name(ctx.accounts.build(), args)?.get().to_vec();
+            #(#updates)*
+            Ok(())
+        }
+    }
+    });
+
+    // Append each generated function to the module's items
+    if let Some((brace, mut content)) = input.content.take() {
+        for func in funcs {
+            let parsed_func: syn::Item =
+                syn::parse2(func).expect("Failed to parse generated function");
+            content.push(parsed_func);
+        }
+
+        input.content = Some((brace, content));
+    }
+
+    let data_def = (2..=max_components).map(|i| {
+        let data_struct =
+            syn::Ident::new(&format!("ApplySystem{}", i), proc_macro2::Span::call_site());
+        let fields = (1..=i).map(|n| {
+            let component_program_name = syn::Ident::new(
+                &format!("component_program_{}", n),
+                proc_macro2::Span::call_site(),
+            );
+            let component_name = syn::Ident::new(
+                &format!("bolt_component_{}", n),
+                proc_macro2::Span::call_site(),
+            );
+            quote! {
+                /// CHECK: bolt component program check
+                pub #component_program_name: UncheckedAccount<'info>,
+                #[account(mut)]
+                /// CHECK: component account
+                pub #component_name: UncheckedAccount<'info>,
+            }
+        });
+        let struct_def = quote! {
+            #[derive(Accounts)]
+            pub struct #data_struct<'info> {
+                /// CHECK: bolt system program check
+                pub bolt_system: UncheckedAccount<'info>,
+                #(#fields)*
+                 /// CHECK: authority check
+                pub authority: UncheckedAccount<'info>,
+                #[account(address = anchor_lang::solana_program::sysvar::instructions::id())]
+                /// CHECK: instruction sysvar check
+                pub instruction_sysvar_account: UncheckedAccount<'info>,
+            }
+        };
+        quote! {
+            #struct_def
+        }
+    });
+
+    let impl_build_def = (2..=max_components).map(|i| {
+        let data_struct = syn::Ident::new(&format!("ApplySystem{}", i), proc_macro2::Span::call_site());
+        let set_data_struct = syn::Ident::new(&format!("SetData{}", i), proc_macro2::Span::call_site());
+        let fields: Vec<_> = (1..=i).map(|n| {
+            let component_key = syn::Ident::new(&format!("component{}", n), proc_macro2::Span::call_site());
+            let component_name = syn::Ident::new(&format!("bolt_component_{}", n), proc_macro2::Span::call_site());
+            quote! {
+                #component_key: self.#component_name.to_account_info(),
+            }
+        }).collect();
+        quote! {
+            impl<'info> #data_struct<'info> {
+                pub fn build(&self) -> CpiContext<'_, '_, '_, 'info, bolt_system::cpi::accounts::#set_data_struct<'info>> {
+                    let cpi_program = self.bolt_system.to_account_info();
+                    let cpi_accounts = bolt_system::cpi::accounts::#set_data_struct {
+                        #(#fields)*
+                    };
+                    CpiContext::new(cpi_program, cpi_accounts)
+                }
+            }
+        }
+    });
+
+    // Return the modified module
+    let output = quote! {
+        #input
+        #(#data_def)*
+        #(#impl_build_def)*
+    };
+    output.into()
+}
+
+// Define a struct to parse macro input
+struct SystemTemplateInput {
+    max_components: usize,
+}
+
+// Implement parsing for the macro input
+impl Parse for SystemTemplateInput {
+    fn parse(input: ParseStream) -> Result<Self> {
+        let _ = input.parse::<Ident>()?; // Parse the key (e.g., "max_components")
+        let _ = input.parse::<Token![=]>()?; // Parse the '='
+        let max_components: LitInt = input.parse()?; // Parse the value
+        let max_value = max_components.base10_parse()?;
+        Ok(SystemTemplateInput {
+            max_components: max_value,
+        })
+    }
+}

+ 3 - 1
crates/bolt-lang/Cargo.toml

@@ -9,10 +9,12 @@ license = "MIT"
 anchor-lang = { version = "0.29.0"}
 
 # Bolt Attributes
+bolt-attribute-bolt-program = { path = "./attribute/bolt-program", version = "0.0.1" }
 bolt-attribute-bolt-component = { path = "./attribute/component", version = "0.0.1" }
-bolt-attribute-bolt-account = { path = "./attribute/account", version = "0.0.1" }
 bolt-attribute-bolt-system = { path = "./attribute/system", version = "0.0.1" }
+bolt-attribute-bolt-system-input = { path = "./attribute/system-input", version = "0.0.1" }
 bolt-attribute-bolt-component-deserialize = { path = "./attribute/component-deserialize", version = "0.0.1" }
+bolt-attribute-bolt-component-id = { path = "./attribute/component-id", version = "0.0.1" }
 
 # Bolt Programs
 world = { path = "../../programs/world", features = ["cpi"], version = "0.0.1"}

+ 0 - 75
crates/bolt-lang/attribute/account/src/lib.rs

@@ -1,75 +0,0 @@
-use proc_macro::TokenStream;
-use quote::quote;
-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
-///
-/// The component_id define the seed used to generate the PDA which stores the component data.
-/// The macro also adds the InitSpace and Default derives to the struct.
-///
-/// #[account]
-/// #[bolt_account]
-/// pub struct Position {
-///     pub x: i64,
-///     pub y: i64,
-///     pub z: i64,
-/// }
-/// ```
-#[proc_macro_attribute]
-pub fn bolt_account(attr: TokenStream, item: TokenStream) -> TokenStream {
-    let mut input = parse_macro_input!(item as DeriveInput);
-    let mut component_id_value = 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())
-                        } else {
-                            None
-                        }
-                    } else {
-                        None
-                    }
-                } else {
-                    None
-                }
-            }),
-            _ => None,
-        };
-    }
-
-    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);
-
-    let name = &input.ident;
-    let expanded = quote! {
-        #input
-
-        #[automatically_derived]
-        impl ComponentTraits for #name {
-            fn seed() -> &'static [u8] {
-                #component_id_value.as_bytes()
-            }
-
-            fn size() -> usize {
-                8 + <#name>::INIT_SPACE
-            }
-        }
-    };
-    expanded.into()
-}

+ 14 - 0
crates/bolt-lang/attribute/bolt-program/Cargo.toml

@@ -0,0 +1,14 @@
+[package]
+name = "bolt-attribute-bolt-program"
+version = "0.0.1"
+edition = "2021"
+description = "Bolt attribute-bolt-program"
+license = "MIT"
+
+[lib]
+proc-macro = true
+
+[dependencies]
+syn = { version = "1.0", features = ["full"] }
+quote = "1.0"
+proc-macro2 = "1.0"

+ 186 - 0
crates/bolt-lang/attribute/bolt-program/src/lib.rs

@@ -0,0 +1,186 @@
+use proc_macro::TokenStream;
+use proc_macro2::TokenStream as TokenStream2;
+use quote::{quote, ToTokens};
+use syn::{
+    parse_macro_input, parse_quote, Attribute, AttributeArgs, Field, Fields, ItemMod, ItemStruct,
+    NestedMeta, Type,
+};
+
+/// This macro attribute is used to define a BOLT component.
+///
+/// Bolt components are themselves programs that can be called by other programs.
+///
+/// # Example
+/// ```ignore
+/// #[bolt_program(Position)]
+/// #[program]
+/// pub mod component_position {
+///     use super::*;
+/// }
+///
+/// #[account]
+/// #[component]
+/// pub struct Position {
+///     pub x: i64,
+///     pub y: i64,
+///     pub z: i64,
+/// }
+/// ```
+#[proc_macro_attribute]
+pub fn bolt_program(args: TokenStream, input: TokenStream) -> TokenStream {
+    let ast = parse_macro_input!(input as syn::ItemMod);
+    let args = parse_macro_input!(args as syn::AttributeArgs);
+    let component_type =
+        extract_type_name(&args).expect("Expected a component type in macro arguments");
+    let modified = modify_component_module(ast, &component_type);
+    let additional_macro: Attribute = parse_quote! { #[program] };
+    TokenStream::from(quote! {
+        #additional_macro
+        #modified
+    })
+}
+
+/// Modifies the component module and adds the necessary functions and structs.
+fn modify_component_module(mut module: ItemMod, component_type: &Type) -> ItemMod {
+    let (initialize_fn, initialize_struct) = generate_initialize(component_type);
+    //let (apply_fn, apply_struct, apply_impl, update_fn, update_struct) = generate_instructions(component_type);
+    let (update_fn, update_struct) = generate_update(component_type);
+
+    module.content = module.content.map(|(brace, mut items)| {
+        items.extend(
+            vec![initialize_fn, initialize_struct, update_fn, update_struct]
+                .into_iter()
+                .map(|item| syn::parse2(item).unwrap())
+                .collect::<Vec<_>>(),
+        );
+
+        let modified_items = items
+            .into_iter()
+            .map(|item| match item {
+                syn::Item::Struct(mut struct_item) if struct_item.ident == "Apply" => {
+                    modify_apply_struct(&mut struct_item);
+                    syn::Item::Struct(struct_item)
+                }
+                _ => item,
+            })
+            .collect();
+        (brace, modified_items)
+    });
+
+    module
+}
+
+/// Extracts the type name from attribute arguments.
+fn extract_type_name(args: &AttributeArgs) -> Option<Type> {
+    args.iter().find_map(|arg| {
+        if let NestedMeta::Meta(syn::Meta::Path(path)) = arg {
+            Some(Type::Path(syn::TypePath {
+                qself: None,
+                path: path.clone(),
+            }))
+        } else {
+            None
+        }
+    })
+}
+
+/// Modifies the Apply struct, change the bolt system to accept any compatible system.
+fn modify_apply_struct(struct_item: &mut ItemStruct) {
+    if let Fields::Named(fields_named) = &mut struct_item.fields {
+        fields_named
+            .named
+            .iter_mut()
+            .filter(|field| is_expecting_program(field))
+            .for_each(|field| {
+                field.ty = syn::parse_str("UncheckedAccount<'info>").expect("Failed to parse type");
+                field.attrs.push(create_check_attribute());
+            });
+    }
+}
+
+/// Creates the check attribute.
+fn create_check_attribute() -> Attribute {
+    parse_quote! {
+        #[doc = "CHECK: This program can modify the data of the component"]
+    }
+}
+
+/// Generates the initialize function and struct.
+fn generate_initialize(component_type: &Type) -> (TokenStream2, TokenStream2) {
+    (
+        quote! {
+            #[automatically_derived]
+            pub fn initialize(ctx: Context<Initialize>) -> Result<()> {
+                let instruction = anchor_lang::solana_program::sysvar::instructions::get_instruction_relative(
+                    0, &ctx.accounts.instruction_sysvar_account.to_account_info()
+                ).unwrap();
+                if instruction.program_id != World::id() {
+                    return Err(BoltError::InvalidCaller.into());
+                }
+                ctx.accounts.data.set_inner(<#component_type>::default());
+                ctx.accounts.data.bolt_metadata.authority = *ctx.accounts.authority.key;
+                Ok(())
+            }
+        },
+        quote! {
+            #[automatically_derived]
+            #[derive(Accounts)]
+            pub struct Initialize<'info>  {
+                #[account(mut)]
+                pub payer: Signer<'info>,
+                #[account(init_if_needed, payer = payer, space = <#component_type>::size(), seeds = [<#component_type>::seed(), entity.key().as_ref()], bump)]
+                pub data: Account<'info, #component_type>,
+                #[account()]
+                pub entity: Account<'info, Entity>,
+                #[account()]
+                pub authority: AccountInfo<'info>,
+                #[account(address = anchor_lang::solana_program::sysvar::instructions::id())]
+                pub instruction_sysvar_account: UncheckedAccount<'info>,
+                pub system_program: Program<'info, System>,
+            }
+        },
+    )
+}
+
+/// Generates the instructions and related structs to inject in the component.
+fn generate_update(component_type: &Type) -> (TokenStream2, TokenStream2) {
+    (
+        quote! {
+            #[automatically_derived]
+            pub fn update(ctx: Context<Update>, data: Vec<u8>) -> Result<()> {
+                // Check if the instruction is called from the world program
+                let instruction = anchor_lang::solana_program::sysvar::instructions::get_instruction_relative(
+                    0, &ctx.accounts.instruction_sysvar_account.to_account_info()
+                ).unwrap();
+                if instruction.program_id != World::id() {
+                    return Err(BoltError::InvalidCaller.into());
+                }
+                // Check if the authority is authorized to modify the data
+                if ctx.accounts.bolt_component.bolt_metadata.authority != World::id() && ctx.accounts.bolt_component.bolt_metadata.authority != *ctx.accounts.authority.key {
+                    return Err(BoltError::InvalidAuthority.into());
+                }
+
+                ctx.accounts.bolt_component.set_inner(<#component_type>::try_from_slice(&data)?);
+                Ok(())
+            }
+        },
+        quote! {
+            #[automatically_derived]
+            #[derive(Accounts)]
+            pub struct Update<'info> {
+                #[account(mut)]
+                pub bolt_component: Account<'info, #component_type>,
+                #[account()]
+                /// CHECK: The authority of the component
+                pub authority: AccountInfo<'info>,
+                #[account(address = anchor_lang::solana_program::sysvar::instructions::id())]
+                pub instruction_sysvar_account: UncheckedAccount<'info>,
+            }
+        },
+    )
+}
+
+/// Checks if the field is expecting a program.
+fn is_expecting_program(field: &Field) -> bool {
+    field.ty.to_token_stream().to_string().contains("Program")
+}

+ 1 - 0
crates/bolt-lang/attribute/component-deserialize/Cargo.toml

@@ -10,5 +10,6 @@ proc-macro = true
 
 [dependencies]
 syn = { version = "1.0", features = ["full"] }
+bolt-utils = { path = "../../utils", version = "0.0.1" }
 quote = "1.0"
 proc-macro2 = "1.0"

+ 13 - 0
crates/bolt-lang/attribute/component-deserialize/src/lib.rs

@@ -1,7 +1,18 @@
+use bolt_utils::add_bolt_metadata;
 use proc_macro::TokenStream;
 use quote::quote;
 use syn::{parse_macro_input, Attribute, DeriveInput};
 
+/// This macro is used to defined a struct as a BOLT component and automatically implements the
+/// `ComponentDeserialize` and `AccountDeserialize` traits for the struct.
+///
+/// #[component]
+/// pub struct Position {
+///     pub x: i64,
+///     pub y: i64,
+///     pub z: i64,
+/// }
+/// ```
 #[proc_macro_attribute]
 pub fn component_deserialize(_attr: TokenStream, item: TokenStream) -> TokenStream {
     let mut input = parse_macro_input!(item as DeriveInput);
@@ -10,6 +21,8 @@ pub fn component_deserialize(_attr: TokenStream, item: TokenStream) -> TokenStre
     let additional_derives: Attribute = syn::parse_quote! { #[derive(anchor_lang::AnchorDeserialize, anchor_lang::AnchorSerialize)] };
     input.attrs.push(additional_derives);
 
+    add_bolt_metadata(&mut input);
+
     let name = &input.ident;
     let expanded = quote! {
         #input

+ 2 - 2
crates/bolt-lang/attribute/account/Cargo.toml → crates/bolt-lang/attribute/component-id/Cargo.toml

@@ -1,8 +1,8 @@
 [package]
-name = "bolt-attribute-bolt-account"
+name = "bolt-attribute-bolt-component-id"
 version = "0.0.1"
 edition = "2021"
-description = "Bolt attribute-bolt-account"
+description = "Bolt attribute-bolt-component-id"
 license = "MIT"
 
 [lib]

+ 15 - 0
crates/bolt-lang/attribute/component-id/src/lib.rs

@@ -0,0 +1,15 @@
+use proc_macro::TokenStream;
+use quote::quote;
+use syn::{parse_macro_input, DeriveInput};
+
+/// Macro to specify the on-chain ID of a component.
+///
+/// ```
+#[proc_macro_attribute]
+pub fn component_id(_attr: TokenStream, item: TokenStream) -> TokenStream {
+    let input = parse_macro_input!(item as DeriveInput);
+    let expanded = quote! {
+        #input
+    };
+    TokenStream::from(expanded)
+}

+ 2 - 1
crates/bolt-lang/attribute/component/Cargo.toml

@@ -10,5 +10,6 @@ proc-macro = true
 
 [dependencies]
 syn = { version = "1.0", features = ["full"] }
+bolt-utils = { path = "../../utils", version = "0.0.1" }
 quote = "1.0"
-proc-macro2 = "1.0"
+proc-macro2 = "1.0"

+ 67 - 130
crates/bolt-lang/attribute/component/src/lib.rs

@@ -1,25 +1,15 @@
+use bolt_utils::add_bolt_metadata;
 use proc_macro::TokenStream;
-use proc_macro2::TokenStream as TokenStream2;
-use quote::{quote, ToTokens};
-use syn::{
-    parse_macro_input, parse_quote, Attribute, AttributeArgs, Field, Fields, ItemMod, ItemStruct,
-    NestedMeta, Type,
-};
+use quote::quote;
+use syn::{parse_macro_input, parse_quote, Attribute, DeriveInput, Lit, Meta, NestedMeta};
 
-/// This macro attribute is used to define a BOLT component.
+/// This Component attribute is used to automatically generate the seed and size functions
 ///
-/// Bolt components are themselves programs that can be called by other programs.
+/// The component_id can be used to define the seed used to generate the PDA which stores the component data.
+/// The macro also adds the InitSpace and Default derives to the struct.
 ///
-/// # Example
-/// ```ignore
-/// #[component(Position)]
-/// #[program]
-/// pub mod component_position {
-///     use super::*;
-/// }
-///
-/// #[account]
-/// #[bolt_account]
+/// #[component_deserialize]
+/// #[derive(Clone)]
 /// pub struct Position {
 ///     pub x: i64,
 ///     pub y: i64,
@@ -27,128 +17,75 @@ use syn::{
 /// }
 /// ```
 #[proc_macro_attribute]
-pub fn component(args: TokenStream, input: TokenStream) -> TokenStream {
-    let ast = parse_macro_input!(input as syn::ItemMod);
-    let args = parse_macro_input!(args as syn::AttributeArgs);
-    let component_type =
-        extract_type_name(&args).expect("Expected a component type in macro arguments");
-    let modified = modify_component_module(ast, &component_type);
-    TokenStream::from(quote! { #modified })
-}
+pub fn component(attr: TokenStream, item: TokenStream) -> TokenStream {
+    let mut input = parse_macro_input!(item as DeriveInput);
+    let mut component_id_value = None;
 
-/// Modifies the component module and adds the necessary functions and structs.
-fn modify_component_module(mut module: ItemMod, component_type: &Type) -> ItemMod {
-    let (initialize_fn, initialize_struct) = generate_initialize(component_type);
-    //let (apply_fn, apply_struct, apply_impl, update_fn, update_struct) = generate_instructions(component_type);
-    let (update_fn, update_struct) = generate_update(component_type);
+    if !attr.is_empty() {
+        let attr_meta = parse_macro_input!(attr as Meta);
 
-    module.content = module.content.map(|(brace, mut items)| {
-        items.extend(
-            vec![initialize_fn, initialize_struct, update_fn, update_struct]
-                .into_iter()
-                .map(|item| syn::parse2(item).unwrap())
-                .collect::<Vec<_>>(),
-        );
-
-        let modified_items = items
-            .into_iter()
-            .map(|item| match item {
-                syn::Item::Struct(mut struct_item) if struct_item.ident == "Apply" => {
-                    modify_apply_struct(&mut struct_item);
-                    syn::Item::Struct(struct_item)
+        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())
+                        } else {
+                            None
+                        }
+                    } else {
+                        None
+                    }
+                } else {
+                    None
                 }
-                _ => item,
-            })
-            .collect();
-        (brace, modified_items)
-    });
+            }),
+            _ => None,
+        };
+    }
 
-    module
-}
+    let component_id_value = component_id_value.unwrap_or_else(|| "".to_string());
+
+    let additional_macro: Attribute = parse_quote! { #[account] };
+    let additional_derives: Attribute = parse_quote! { #[derive(InitSpace, Default)] };
+    input.attrs.push(additional_derives);
+
+    add_bolt_metadata(&mut input);
+
+    let name = &input.ident;
+    let component_name = syn::Ident::new(&name.to_string().to_lowercase(), input.ident.span());
 
-/// Extracts the type name from attribute arguments.
-fn extract_type_name(args: &AttributeArgs) -> Option<Type> {
-    args.iter().find_map(|arg| {
-        if let NestedMeta::Meta(syn::Meta::Path(path)) = arg {
-            Some(Type::Path(syn::TypePath {
-                qself: None,
-                path: path.clone(),
-            }))
-        } else {
-            None
+    let anchor_program = quote! {
+        #[bolt_program(#name)]
+        pub mod #component_name {
+            use super::*;
         }
-    })
-}
+    };
 
-/// Modifies the Apply struct, change the bolt system to accept any compatible system.
-fn modify_apply_struct(struct_item: &mut ItemStruct) {
-    if let Fields::Named(fields_named) = &mut struct_item.fields {
-        fields_named
-            .named
-            .iter_mut()
-            .filter(|field| is_expecting_program(field))
-            .for_each(|field| {
-                field.ty = syn::parse_str("UncheckedAccount<'info>").expect("Failed to parse type");
-                field.attrs.push(create_check_attribute());
-            });
-    }
-}
+    let expanded = quote! {
+        #anchor_program
 
-/// Creates the check attribute.
-fn create_check_attribute() -> Attribute {
-    parse_quote! {
-        #[doc = "CHECK: This program can modify the data of the component"]
-    }
-}
+        #additional_macro
+        #input
 
-/// Generates the initialize function and struct.
-fn generate_initialize(component_type: &Type) -> (TokenStream2, TokenStream2) {
-    (
-        quote! {
-            #[automatically_derived]
-            pub fn initialize(ctx: Context<Initialize>) -> Result<()> {
-                ctx.accounts.data.set_inner(<#component_type>::default());
-                Ok(())
-            }
-        },
-        quote! {
-            #[automatically_derived]
-            #[derive(Accounts)]
-            pub struct Initialize<'info>  {
-                #[account(mut)]
-                pub payer: Signer<'info>,
-                #[account(init_if_needed, payer = payer, space = <#component_type>::size(), seeds = [<#component_type>::seed(), entity.key().as_ref()], bump)]
-                pub data: Account<'info, #component_type>,
-                #[account()]
-                pub entity: Account<'info, Entity>,
-                pub system_program: Program<'info, System>,
+        #[automatically_derived]
+        impl ComponentTraits for #name {
+            fn seed() -> &'static [u8] {
+                #component_id_value.as_bytes()
             }
-        },
-    )
-}
 
-/// Generates the instructions and related structs to inject in the component.
-fn generate_update(component_type: &Type) -> (TokenStream2, TokenStream2) {
-    (
-        quote! {
-            #[automatically_derived]
-            pub fn update(ctx: Context<Update>, data: Vec<u8>) -> Result<()> {
-                ctx.accounts.bolt_component.set_inner(<#component_type>::try_from_slice(&data)?);
-                Ok(())
-            }
-        },
-        quote! {
-            #[automatically_derived]
-            #[derive(Accounts)]
-            pub struct Update<'info> {
-                #[account(mut)]
-                pub bolt_component: Account<'info, #component_type>,
+            fn size() -> usize {
+                8 + <#name>::INIT_SPACE
             }
-        },
-    )
-}
-
-/// Checks if the field is expecting a program.
-fn is_expecting_program(field: &Field) -> bool {
-    field.ty.to_token_stream().to_string().contains("Program")
+        }
+    };
+    expanded.into()
 }

+ 14 - 0
crates/bolt-lang/attribute/system-input/Cargo.toml

@@ -0,0 +1,14 @@
+[package]
+name = "bolt-attribute-bolt-system-input"
+version = "0.0.1"
+edition = "2021"
+description = "Bolt attribute-bolt-system-input"
+license = "MIT"
+
+[lib]
+proc-macro = true
+
+[dependencies]
+syn = { version = "1.0", features = ["full", "visit-mut"] }
+quote = "1.0"
+proc-macro2 = "1.0"

+ 121 - 0
crates/bolt-lang/attribute/system-input/src/lib.rs

@@ -0,0 +1,121 @@
+use proc_macro::TokenStream;
+use quote::quote;
+use syn::{parse_macro_input, Fields, ItemStruct, Lit, Meta, MetaNameValue};
+
+/// This macro attribute is used to define a BOLT system input.
+///
+/// The input can be defined as a struct and will be transformed into an Anchor context.
+///
+///
+/// # Example
+/// ```ignore
+///#[system_input]
+///pub struct Components {
+///    pub position: Position,
+///}
+///
+/// ```
+#[proc_macro_attribute]
+pub fn system_input(_attr: TokenStream, item: TokenStream) -> TokenStream {
+    // Parse the input TokenStream (the struct) into a Rust data structure
+    let input = parse_macro_input!(item as ItemStruct);
+
+    // Ensure the struct has named fields
+    let fields = if let Fields::Named(fields) = &input.fields {
+        &fields.named
+    } else {
+        panic!("system_input macro only supports structs with named fields");
+    };
+    let name = &input.ident;
+
+    // Impls Owner for each account and
+    let owners_impls = fields.iter().filter_map(|field| {
+        field.attrs.iter().find_map(|attr| {
+            if let Ok(Meta::List(meta_list)) = attr.parse_meta() {
+                if meta_list.path.is_ident("component_id") {
+                    for nested_meta in meta_list.nested.iter() {
+                        if let syn::NestedMeta::Meta(Meta::NameValue(MetaNameValue {
+                            path,
+                            lit: Lit::Str(lit_str),
+                            ..
+                        })) = nested_meta
+                        {
+                            if path.is_ident("address") {
+                                let address = lit_str.value();
+                                let field_type = &field.ty;
+                                return Some(quote! {
+                                    use std::str::FromStr;
+                                    impl Owner for #field_type {
+
+                                        fn owner() -> Pubkey {
+                                            Pubkey::from_str(#address).unwrap()
+                                        }
+                                    }
+                                    impl AccountSerialize for #field_type {
+                                        fn try_serialize<W>(&self, _writer: &mut W) -> Result<()> {
+                                            Ok(())
+                                        }
+                                    }
+                                });
+                            }
+                        }
+                    }
+                }
+            }
+            None
+        })
+    });
+
+    // Transform fields for the struct definition
+    let transformed_fields = fields.iter().map(|f| {
+        let field_name = &f.ident;
+        let field_type = &f.ty;
+        quote! {
+            #[account()]
+            pub #field_name: Account<'info, #field_type>,
+        }
+    });
+
+    // Generate the new struct with the Accounts derive and transformed fields
+    let output_struct = quote! {
+        #[derive(Accounts)]
+        pub struct #name<'info> {
+            #(#transformed_fields)*
+        }
+    };
+
+    // Generate the try_to_vec method
+    let try_to_vec_fields = fields.iter().map(|f| {
+        let field_name = &f.ident;
+        quote! {
+            self.#field_name.try_to_vec()?
+        }
+    });
+
+    let tuple_elements = (0..try_to_vec_fields.len())
+        .map(|_| quote! {Vec<u8>})
+        .collect::<Vec<_>>();
+    let generated_tuple_type = match tuple_elements.len() {
+        0 => panic!("system_input macro only supports structs with named fields"),
+        1 => quote! { (Vec<u8>,) },
+        _ => quote! { (#(#tuple_elements),*) },
+    };
+
+    // Generate the implementation of try_to_vec for the struct
+    let output_impl = quote! {
+        impl<'info> #name<'info> {
+            pub fn try_to_vec(&self) -> Result<#generated_tuple_type> {
+                Ok((#(#try_to_vec_fields,)*))
+            }
+        }
+    };
+
+    // Combine the struct definition and its implementation into the final TokenStream
+    let output = quote! {
+        #output_struct
+        #output_impl
+        #(#owners_impls)*
+    };
+
+    TokenStream::from(output)
+}

+ 82 - 36
crates/bolt-lang/attribute/system/src/lib.rs

@@ -2,11 +2,20 @@ use proc_macro::TokenStream;
 use proc_macro2::Ident;
 use quote::quote;
 use syn::{
-    parse_macro_input, parse_quote, visit_mut::VisitMut, Expr, GenericArgument, ItemFn, ItemMod,
-    PathArguments, ReturnType, Stmt, Type, TypePath,
+    parse_macro_input, parse_quote, visit_mut::VisitMut, Expr, FnArg, GenericArgument, ItemFn,
+    ItemMod, ItemStruct, PathArguments, ReturnType, Stmt, Type, TypePath,
 };
 
-struct SystemTransform;
+#[derive(Default)]
+struct SystemTransform {
+    return_values: usize,
+}
+
+#[derive(Default)]
+struct Extractor {
+    context_struct_name: Option<String>,
+    field_count: Option<usize>,
+}
 
 /// This macro attribute is used to define a BOLT system.
 ///
@@ -15,10 +24,7 @@ struct SystemTransform;
 /// # Example
 /// ```ignore
 /// #[system]
-/// #[program]
 /// pub mod system_fly {
-///     use super::*;
-///
 ///     pub fn execute(ctx: Context<Component>, _args: Vec<u8>) -> Result<Position> {
 ///         let pos = Position {
 ///             x: ctx.accounts.position.x,
@@ -31,11 +37,37 @@ struct SystemTransform;
 /// ```
 #[proc_macro_attribute]
 pub fn system(attr: TokenStream, item: TokenStream) -> TokenStream {
-    let mut input = parse_macro_input!(item as ItemMod);
+    let mut ast = parse_macro_input!(item as ItemMod);
     let _attr = parse_macro_input!(attr as syn::AttributeArgs);
-    let mut transform = SystemTransform;
-    transform.visit_item_mod_mut(&mut input);
-    TokenStream::from(quote! { #input })
+
+    // Extract the number of components from the module
+    let mut extractor = Extractor::default();
+    extractor.visit_item_mod_mut(&mut ast);
+
+    if let Some(components_len) = extractor.field_count {
+        let use_super = syn::parse_quote! { use super::*; };
+        if let Some(ref mut content) = ast.content {
+            content.1.insert(0, syn::Item::Use(use_super));
+        }
+
+        let mut transform = SystemTransform {
+            return_values: components_len,
+        };
+        transform.visit_item_mod_mut(&mut ast);
+
+        // Add `#[program]` macro and try_to_vec implementation
+        let expanded = quote! {
+            #[program]
+            #ast
+        };
+
+        TokenStream::from(expanded)
+    } else {
+        panic!(
+            "Could not find the component bundle: {} in the module",
+            extractor.context_struct_name.unwrap()
+        );
+    }
 }
 
 /// Visits the AST and modifies the system function
@@ -51,28 +83,29 @@ impl VisitMut for SystemTransform {
                     parse_quote! { Ok((#(#tuple_elements),*)) }
                 }
                 _ => {
-                    parse_quote! { Ok((#inner_variable).try_to_vec()?) }
+                    parse_quote! {
+                        #inner_variable.try_to_vec()
+                    }
                 }
             };
             *expr = new_return_expr;
         }
     }
 
-    // Modify the return type of the system function to Result<Vec<u8>>
+    // Modify the return type of the system function to Result<Vec<u8>,*>
     fn visit_item_fn_mut(&mut self, item_fn: &mut ItemFn) {
         if item_fn.sig.ident == "execute" {
             // Modify the return type to Result<Vec<u8>> if necessary
             if let ReturnType::Type(_, type_box) = &item_fn.sig.output {
                 if let Type::Path(type_path) = &**type_box {
-                    let ret_values = Self::extract_return_value(type_path);
-                    if ret_values > 1 {
+                    if self.return_values > 1 {
                         item_fn.sig.ident = Ident::new(
-                            format!("execute_{}", ret_values).as_str(),
+                            format!("execute_{}", self.return_values).as_str(),
                             item_fn.sig.ident.span(),
                         );
                     }
                     if !Self::check_is_vec_u8(type_path) {
-                        Self::modify_fn_return_type(item_fn, ret_values);
+                        Self::modify_fn_return_type(item_fn, self.return_values);
                         // Modify the return statement inside the function body
                         let block = &mut item_fn.block;
                         for stmt in &mut block.stmts {
@@ -136,28 +169,10 @@ impl SystemTransform {
         false
     }
 
-    // Helper function to extract the number of return values from a type
-    fn extract_return_value(ty: &TypePath) -> usize {
-        if let Some(segment) = ty.path.segments.last() {
-            if segment.ident == "Result" {
-                if let PathArguments::AngleBracketed(args) = &segment.arguments {
-                    return if let Some(GenericArgument::Type(Type::Tuple(tuple))) =
-                        args.args.first()
-                    {
-                        tuple.elems.len()
-                    } else {
-                        1
-                    };
-                }
-            }
-        }
-        0
-    }
-
     // Helper function to modify the return type of a function to be Result<Vec<u8>> or Result<(Vec<u8>, Vec<u8>, ...)>
-    fn modify_fn_return_type(item_fn: &mut syn::ItemFn, ret_values: usize) {
+    fn modify_fn_return_type(item_fn: &mut ItemFn, ret_values: usize) {
         item_fn.sig.output = if ret_values == 1 {
-            parse_quote! { -> Result<Vec<u8>> }
+            parse_quote! { -> Result<(Vec<u8>,)> }
         } else {
             let types = std::iter::repeat(quote! { Vec<u8> })
                 .take(ret_values)
@@ -201,3 +216,34 @@ impl SystemTransform {
         None
     }
 }
+
+/// Visits the AST to extract the number of input components
+impl VisitMut for Extractor {
+    fn visit_item_fn_mut(&mut self, i: &mut ItemFn) {
+        for input in &i.sig.inputs {
+            if let FnArg::Typed(pat_type) = input {
+                if let Type::Path(type_path) = &*pat_type.ty {
+                    let last_segment = type_path.path.segments.last().unwrap();
+                    if last_segment.ident == "Context" {
+                        if let PathArguments::AngleBracketed(args) = &last_segment.arguments {
+                            if let Some(syn::GenericArgument::Type(syn::Type::Path(type_path))) =
+                                args.args.first()
+                            {
+                                let ident = &type_path.path.segments.first().unwrap().ident;
+                                self.context_struct_name = Some(ident.to_string());
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    fn visit_item_struct_mut(&mut self, i: &mut ItemStruct) {
+        if let Some(name) = &self.context_struct_name {
+            if i.ident == name {
+                self.field_count = Some(i.fields.len());
+            }
+        }
+    }
+}

+ 11 - 0
crates/bolt-lang/src/errors.rs

@@ -0,0 +1,11 @@
+use anchor_lang::prelude::*;
+
+#[error_code]
+pub enum BoltError {
+    /// Returned if the wrong authority attempts to sign for an instruction
+    #[msg("Invalid authority for instruction")]
+    InvalidAuthority,
+    /// Returned if the wrong authority attempts to sign for an instruction
+    #[msg("Invalid caller: must be called from a CPI instruction")]
+    InvalidCaller,
+}

+ 13 - 1
crates/bolt-lang/src/lib.rs

@@ -1,12 +1,15 @@
 pub use anchor_lang::prelude::*;
 
-pub use bolt_attribute_bolt_account::bolt_account;
 pub use bolt_attribute_bolt_component::component;
 pub use bolt_attribute_bolt_component_deserialize::component_deserialize;
+pub use bolt_attribute_bolt_component_id::component_id;
+pub use bolt_attribute_bolt_program::bolt_program;
 pub use bolt_attribute_bolt_system::system;
+pub use bolt_attribute_bolt_system_input::system_input;
 
 pub use bolt_system;
 pub use world;
+pub use world::program::World;
 pub use world::Entity;
 
 pub use serde;
@@ -14,6 +17,9 @@ pub use serde::{Deserialize as BoltDeserialize, Serialize as BoltSerialize};
 
 use std::str;
 
+mod errors;
+pub use crate::errors::BoltError;
+
 /// Parses the arguments from a byte array.
 pub fn parse_args<T: serde::de::DeserializeOwned>(args_p: &[u8]) -> T {
     let args_string = str::from_utf8(args_p).expect("Failed to convert to string");
@@ -36,3 +42,9 @@ pub trait ComponentDeserialize: Sized {
     /// `Account`.
     fn from_account_info(account: &anchor_lang::prelude::AccountInfo) -> Result<Self>;
 }
+
+/// Metadata for the component.
+#[derive(InitSpace, AnchorSerialize, AnchorDeserialize, Default, Copy, Clone)]
+pub struct BoltMetadata {
+    pub authority: Pubkey,
+}

+ 13 - 0
crates/bolt-lang/utils/Cargo.toml

@@ -0,0 +1,13 @@
+[package]
+name = "bolt-utils"
+version = "0.0.1"
+edition = "2021"
+description = "Bolt utils"
+license = "MIT"
+
+[lib]
+
+[dependencies]
+syn = { version = "1.0", features = ["full"] }
+quote = "1.0"
+proc-macro2 = "1.0"

+ 22 - 0
crates/bolt-lang/utils/src/lib.rs

@@ -0,0 +1,22 @@
+use proc_macro2::Ident;
+use syn::{DeriveInput, Field, Type, Visibility};
+
+pub fn add_bolt_metadata(input: &mut DeriveInput) {
+    let authority_field: Field = Field {
+        attrs: vec![],
+        vis: Visibility::Public(syn::VisPublic {
+            pub_token: Default::default(),
+        }),
+        ident: Some(Ident::new("bolt_metadata", proc_macro2::Span::call_site())),
+        colon_token: Some(Default::default()),
+        ty: Type::Path(syn::TypePath {
+            qself: None,
+            path: syn::Path::from(Ident::new("BoltMetadata", proc_macro2::Span::call_site())),
+        }),
+    };
+    if let syn::Data::Struct(ref mut data) = input.data {
+        if let syn::Fields::Named(ref mut fields) = data.fields {
+            fields.named.push(authority_field);
+        }
+    }
+}

+ 5 - 4
examples/component-position/Cargo.toml

@@ -1,12 +1,12 @@
 [package]
-name = "component-position"
-version = "0.1.0"
-description = "Created with Anchor"
+name = "position"
+version = "0.0.1"
+description = "Created with Bolt"
 edition = "2021"
 
 [lib]
 crate-type = ["cdylib", "lib"]
-name = "component_position"
+name = "position"
 
 [features]
 no-entrypoint = []
@@ -14,6 +14,7 @@ no-idl = []
 no-log-ix-name = []
 cpi = ["no-entrypoint"]
 default = []
+idl-build = ["anchor-lang/idl-build"]
 
 [dependencies]
 anchor-lang = { version = "0.29.0" }

+ 1 - 8
examples/component-position/src/lib.rs

@@ -2,14 +2,7 @@ use bolt_lang::*;
 
 declare_id!("Fn1JzzEdyb55fsyduWS94mYHizGhJZuhvjX6DVvrmGbQ");
 
-#[component(Position)]
-#[program]
-pub mod component_position {
-    use super::*;
-}
-
-#[account]
-#[bolt_account]
+#[component]
 #[derive(Copy)]
 pub struct Position {
     pub x: i64,

+ 5 - 4
examples/component-velocity/Cargo.toml

@@ -1,12 +1,12 @@
 [package]
-name = "component-velocity"
-version = "0.1.0"
-description = "Created with Anchor"
+name = "velocity"
+version = "0.0.1"
+description = "Created with Bolt"
 edition = "2021"
 
 [lib]
 crate-type = ["cdylib", "lib"]
-name = "component_velocity"
+name = "velocity"
 
 [features]
 no-entrypoint = []
@@ -14,6 +14,7 @@ no-idl = []
 no-log-ix-name = []
 cpi = ["no-entrypoint"]
 default = []
+idl-build = ["anchor-lang/idl-build"]
 
 [dependencies]
 anchor-lang = "0.29.0"

+ 1 - 73
examples/component-velocity/src/lib.rs

@@ -2,70 +2,7 @@ use bolt_lang::*;
 
 declare_id!("CbHEFbSQdRN4Wnoby9r16umnJ1zWbULBHg4yqzGQonU1");
 
-#[program]
-pub mod component_velocity {
-    use super::*;
-
-    pub fn initialize(_ctx: Context<Initialize>) -> Result<()> {
-        Ok(())
-    }
-
-    pub fn apply(ctx: Context<Apply>, args: Vec<u8>) -> Result<()> {
-        let result = bolt_system::cpi::execute(ctx.accounts.set_data_ctx(), args)?;
-        let res = Velocity::try_from_slice(&result.get())?;
-        ctx.accounts.bolt_component.set_inner(res);
-        Ok(())
-    }
-
-    #[derive(Accounts)]
-    pub struct Apply<'info> {
-        #[account(mut)]
-        pub bolt_component: Account<'info, Velocity>,
-        /// CHECK: The system can modify the data of the component
-        pub bolt_system: UncheckedAccount<'info>,
-    }
-
-    impl<'info> Apply<'info> {
-        pub fn set_data_ctx(
-            &self,
-        ) -> CpiContext<'_, '_, '_, 'info, bolt_system::cpi::accounts::SetData<'info>> {
-            let cpi_program = self.bolt_system.to_account_info();
-            let cpi_accounts = bolt_system::cpi::accounts::SetData {
-                component: self.bolt_component.to_account_info().clone(),
-            };
-            CpiContext::new(cpi_program, cpi_accounts)
-        }
-    }
-
-    pub fn update(ctx: Context<Update>, data: Vec<u8>) -> Result<()> {
-        ctx.accounts
-            .bolt_component
-            .set_inner(Velocity::try_from_slice(&data)?);
-        Ok(())
-    }
-
-    #[derive(Accounts)]
-    pub struct Update<'info> {
-        #[account(mut)]
-        pub bolt_component: Account<'info, Velocity>,
-    }
-}
-
-#[derive(Accounts)]
-pub struct Initialize<'info> {
-    #[account(mut)]
-    pub payer: Signer<'info>,
-    #[account(init_if_needed, payer = payer, space = Velocity::size(), seeds = [Velocity::seed(), entity.key().as_ref()], bump)]
-    pub data: Account<'info, Velocity>,
-    #[account()]
-    /// CHECK: A generic entity account
-    pub entity: UncheckedAccount<'info>,
-    pub system_program: Program<'info, System>,
-}
-
-// Component data
-#[account]
-#[derive(InitSpace, Default)]
+#[component(component_id = "component-velocity")]
 pub struct Velocity {
     pub x: i64,
     pub y: i64,
@@ -74,12 +11,3 @@ pub struct Velocity {
     #[max_len(20)]
     pub description: String,
 }
-
-impl Velocity {
-    pub fn size() -> usize {
-        8 + Velocity::INIT_SPACE
-    }
-    pub fn seed() -> &'static [u8] {
-        b"component-velocity"
-    }
-}

+ 5 - 4
examples/system-apply-velocity/Cargo.toml

@@ -1,7 +1,7 @@
 [package]
 name = "system-apply-velocity"
-version = "0.1.0"
-description = "Created with Anchor"
+version = "0.0.1"
+description = "Created with Bolt"
 edition = "2021"
 
 [lib]
@@ -14,9 +14,10 @@ no-idl = []
 no-log-ix-name = []
 cpi = ["no-entrypoint"]
 default = []
+idl-build = ["anchor-lang/idl-build"]
 
 [dependencies]
 anchor-lang = "0.29.0"
 bolt-lang = { path = "../../crates/bolt-lang" }
-component-velocity = { path = "../component-velocity", features = ["cpi"]}
-component-position = { path = "../component-position", features = ["cpi"]}
+velocity = { path = "../component-velocity", features = ["cpi"]}
+position = { path = "../component-position", features = ["cpi"]}

+ 9 - 13
examples/system-apply-velocity/src/lib.rs

@@ -1,15 +1,13 @@
 use bolt_lang::*;
-use component_position::Position;
-use component_velocity::Velocity;
+use position::Position;
+use velocity::Velocity;
 
 declare_id!("6LHhFVwif6N9Po3jHtSmMVtPjF6zRfL3xMosSzcrQAS8");
 
 #[system]
-#[program]
 pub mod system_apply_velocity {
-    use super::*;
 
-    pub fn execute(ctx: Context<Component>, _args: Vec<u8>) -> Result<(Velocity, Position)> {
+    pub fn execute(ctx: Context<Components>, _args: Vec<u8>) -> Result<Components> {
         ctx.accounts.velocity.x = 10;
         let clock = Clock::get()?;
         ctx.accounts.velocity.last_applied = clock.unix_timestamp;
@@ -17,14 +15,12 @@ pub mod system_apply_velocity {
         msg!("last applied: {}", ctx.accounts.velocity.last_applied);
         msg!("Position: {}", ctx.accounts.position.x);
         msg!("Remaining accounts: {}", ctx.remaining_accounts.len());
-        Ok((*ctx.accounts.velocity, *ctx.accounts.position))
+        Ok(ctx.accounts)
     }
-}
 
-#[derive(Accounts)]
-pub struct Component<'info> {
-    #[account()]
-    pub velocity: Account<'info, Velocity>,
-    #[account()]
-    pub position: Account<'info, Position>,
+    #[system_input]
+    pub struct Components {
+        pub velocity: Velocity,
+        pub position: Position,
+    }
 }

+ 4 - 3
examples/system-fly/Cargo.toml

@@ -1,7 +1,7 @@
 [package]
 name = "system-fly"
-version = "0.1.0"
-description = "Created with Anchor"
+version = "0.0.1"
+description = "Created with Bolt"
 edition = "2021"
 
 [lib]
@@ -14,10 +14,11 @@ no-idl = []
 no-log-ix-name = []
 cpi = ["no-entrypoint"]
 default = []
+idl-build = ["anchor-lang/idl-build"]
 
 [dependencies]
 anchor-lang = { version = "0.29.0" }
 bolt-lang = { path = "../../crates/bolt-lang" }
-component-position = { path = "../component-position", features = ["cpi"]}
+position = { path = "../component-position", features = ["cpi"]}
 
 

+ 9 - 15
examples/system-fly/src/lib.rs

@@ -1,25 +1,19 @@
 use bolt_lang::*;
-use component_position::Position;
+use position::Position;
 
 declare_id!("HT2YawJjkNmqWcLNfPAMvNsLdWwPvvvbKA5bpMw4eUpq");
 
 #[system]
-#[program]
 pub mod system_fly {
-    use super::*;
 
-    pub fn execute(ctx: Context<Component>, _args: Vec<u8>) -> Result<Position> {
-        let pos = Position {
-            x: ctx.accounts.position.x,
-            y: ctx.accounts.position.y,
-            z: ctx.accounts.position.z + 1,
-        };
-        Ok(pos)
+    pub fn execute(ctx: Context<Components>, _args: Vec<u8>) -> Result<Components> {
+        let pos = &mut ctx.accounts.position;
+        pos.z += 1;
+        Ok(ctx.accounts)
     }
-}
 
-#[derive(Accounts)]
-pub struct Component<'info> {
-    #[account()]
-    pub position: Account<'info, Position>,
+    #[system_input]
+    pub struct Components {
+        pub position: Position,
+    }
 }

+ 3 - 2
examples/system-simple-movement/Cargo.toml

@@ -1,7 +1,7 @@
 [package]
 name = "system-simple-movement"
-version = "0.1.0"
-description = "Created with Anchor"
+version = "0.0.1"
+description = "Created with Bolt"
 edition = "2021"
 
 [lib]
@@ -14,6 +14,7 @@ no-idl = []
 no-log-ix-name = []
 cpi = ["no-entrypoint"]
 default = []
+idl-build = ["anchor-lang/idl-build"]
 
 [dependencies]
 anchor-lang = "0.29.0"

+ 28 - 32
examples/system-simple-movement/src/lib.rs

@@ -3,15 +3,11 @@ use bolt_lang::*;
 declare_id!("FSa6qoJXFBR3a7ThQkTAMrC15p6NkchPEjBdd4n6dXxA");
 
 #[system]
-#[program]
 pub mod system_simple_movement {
-    use super::*;
 
-    pub fn execute(ctx: Context<Component>, args_p: Vec<u8>) -> Result<Position> {
+    pub fn execute(ctx: Context<Components>, args_p: Vec<u8>) -> Result<Components> {
         let args = parse_args::<Args>(&args_p);
 
-        let mut position = Position::from_account_info(&ctx.accounts.position)?;
-
         // Compute the new position based on the direction
         let (dx, dy) = match args.direction {
             Direction::Left => (-1, 0),
@@ -19,37 +15,37 @@ pub mod system_simple_movement {
             Direction::Up => (0, 1),
             Direction::Down => (0, -1),
         };
-        position.x += dx;
-        position.y += dy;
+        ctx.accounts.position.x += dx;
+        ctx.accounts.position.y += dy;
 
-        Ok(position)
+        Ok(ctx.accounts)
     }
-}
 
-// Define the Account to parse from the component
-#[derive(Accounts)]
-pub struct Component<'info> {
-    /// CHECK: check that the component is the expected account
-    pub position: AccountInfo<'info>,
-}
+    #[system_input]
+    pub struct Components {
+        #[component_id(address = "Fn1JzzEdyb55fsyduWS94mYHizGhJZuhvjX6DVvrmGbQ")]
+        pub position: Position,
+    }
 
-#[component_deserialize]
-pub struct Position {
-    pub x: i64,
-    pub y: i64,
-    pub z: i64,
-}
+    #[component_deserialize]
+    #[derive(Clone)]
+    pub struct Position {
+        pub x: i64,
+        pub y: i64,
+        pub z: i64,
+    }
 
-// Define the structs to deserialize the arguments
-#[derive(BoltSerialize, BoltDeserialize)]
-struct Args {
-    direction: Direction,
-}
+    // Define the structs to deserialize the arguments
+    #[derive(BoltSerialize, BoltDeserialize)]
+    struct Args {
+        direction: Direction,
+    }
 
-#[derive(BoltSerialize, BoltDeserialize)]
-pub enum Direction {
-    Left,
-    Right,
-    Up,
-    Down,
+    #[derive(BoltSerialize, BoltDeserialize)]
+    pub enum Direction {
+        Left,
+        Right,
+        Up,
+        Down,
+    }
 }

+ 1 - 0
programs/bolt-component/Cargo.toml

@@ -15,6 +15,7 @@ no-idl = []
 no-log-ix-name = []
 cpi = ["no-entrypoint"]
 default = []
+idl-build = ["anchor-lang/idl-build"]
 
 [dependencies]
 anchor-lang = { version = "0.29.0", features = ["init-if-needed"] }

+ 45 - 11
programs/bolt-component/src/lib.rs

@@ -6,7 +6,17 @@ declare_id!("CmP2djJgABZ4cRokm4ndxuq6LerqpNHLBsaUv2XKEJua");
 pub mod bolt_component {
     use super::*;
 
-    pub fn initialize(_ctx: Context<Initialize>) -> Result<()> {
+    pub fn initialize(ctx: Context<Initialize>) -> Result<()> {
+        let instruction =
+            anchor_lang::solana_program::sysvar::instructions::get_instruction_relative(
+                0,
+                &ctx.accounts.instruction_sysvar_account.to_account_info(),
+            )
+            .unwrap();
+        if instruction.program_id == id() {
+            panic!("The instruction must be called from a CPI");
+        }
+        ctx.accounts.data.bolt_metadata.authority = *ctx.accounts.authority.key;
         Ok(())
     }
 
@@ -17,7 +27,7 @@ pub mod bolt_component {
     #[derive(Accounts)]
     pub struct Apply<'info> {
         #[account(mut)]
-        pub bolt_component: Account<'info, ComponentData>,
+        pub bolt_component: Account<'info, Component>,
         /// CHECK: The system can modify the data of the component
         pub bolt_system: UncheckedAccount<'info>,
     }
@@ -34,14 +44,28 @@ pub mod bolt_component {
         }
     }
 
-    pub fn update(_ctx: Context<Update>, _data: Vec<u8>) -> Result<()> {
+    pub fn update(ctx: Context<Update>, _data: Vec<u8>) -> Result<()> {
+        let instruction =
+            anchor_lang::solana_program::sysvar::instructions::get_instruction_relative(
+                0,
+                &ctx.accounts.instruction_sysvar_account.to_account_info(),
+            )
+            .unwrap();
+        if instruction.program_id == id() {
+            panic!("The instruction must be called from a CPI");
+        }
         Ok(())
     }
 
     #[derive(Accounts)]
     pub struct Update<'info> {
         #[account(mut)]
-        pub bolt_component: Account<'info, ComponentData>,
+        pub bolt_component: Account<'info, Component>,
+        #[account()]
+        /// CHECK: The authority of the component
+        pub authority: AccountInfo<'info>,
+        #[account(address = anchor_lang::solana_program::sysvar::instructions::id())]
+        pub instruction_sysvar_account: UncheckedAccount<'info>,
     }
 }
 
@@ -49,25 +73,30 @@ pub mod bolt_component {
 pub struct Initialize<'info> {
     #[account(mut)]
     pub payer: Signer<'info>,
-    #[account(init_if_needed, payer = payer, space = ComponentData::size(), seeds = [ComponentData::seed(), entity.key().as_ref()], bump)]
-    pub data: Account<'info, ComponentData>,
+    #[account(init_if_needed, payer = payer, space = Component::size(), seeds = [Component::seed(), entity.key().as_ref()], bump)]
+    pub data: Account<'info, Component>,
     #[account()]
     /// CHECK: A generic entity account
-    pub entity: UncheckedAccount<'info>,
+    pub entity: AccountInfo<'info>,
+    #[account()]
+    /// CHECK: The authority of the component
+    pub authority: AccountInfo<'info>,
+    #[account(address = anchor_lang::solana_program::sysvar::instructions::id())]
+    pub instruction_sysvar_account: UncheckedAccount<'info>,
     pub system_program: Program<'info, System>,
 }
 
 // Component data
 #[account]
 #[derive(InitSpace, Default, Copy)]
-pub struct ComponentData {
-    pub id: u64,
+pub struct Component {
     pub position: Position,
+    pub bolt_metadata: BoltMetadata,
 }
 
-impl ComponentData {
+impl Component {
     pub fn size() -> usize {
-        8 + ComponentData::INIT_SPACE
+        8 + Component::INIT_SPACE
     }
     pub fn seed() -> &'static [u8] {
         b"origin-component"
@@ -80,3 +109,8 @@ pub struct Position {
     pub y: i64,
     pub z: i64,
 }
+
+#[derive(InitSpace, AnchorSerialize, AnchorDeserialize, Default, Copy, Clone)]
+pub struct BoltMetadata {
+    pub authority: Pubkey,
+}

+ 3 - 1
programs/bolt-system/Cargo.toml

@@ -15,6 +15,8 @@ no-idl = []
 no-log-ix-name = []
 cpi = ["no-entrypoint"]
 default = []
+idl-build = ["anchor-lang/idl-build"]
 
 [dependencies]
-anchor-lang = "0.29.0"
+anchor-lang = "0.29.0"
+bolt-helpers-system-template = { path = "../../crates/bolt-helpers/attribute/system-template", version = "0.0.1" }

+ 3 - 89
programs/bolt-system/src/lib.rs

@@ -1,107 +1,21 @@
 use anchor_lang::prelude::borsh::{BorshDeserialize, BorshSerialize};
 use anchor_lang::prelude::*;
-//use bolt_helpers_system_template::*;
+use bolt_helpers_system_template::system_template;
 
 declare_id!("7X4EFsDJ5aYTcEjKzJ94rD8FRKgQeXC89fkpeTS4KaqP");
 
-//#[system_template(max_components = 2)]
+#[system_template(max_components = 3)]
 #[program]
 pub mod bolt_system {
     use super::*;
-
     pub fn execute(_ctx: Context<SetData>, _args: Vec<u8>) -> Result<Vec<u8>> {
         Ok(Vec::new())
     }
-
-    pub fn execute_2(_ctx: Context<SetData2>, _args: Vec<u8>) -> Result<(Vec<u8>, Vec<u8>)> {
-        Ok((Vec::new(), Vec::new()))
-    }
-
-    pub fn execute_3(
-        _ctx: Context<SetData3>,
-        _args: Vec<u8>,
-    ) -> Result<(Vec<u8>, Vec<u8>, Vec<u8>)> {
-        Ok((Vec::new(), Vec::new(), Vec::new()))
-    }
-
-    #[allow(clippy::type_complexity)]
-    pub fn execute_4(
-        _ctx: Context<SetData4>,
-        _args: Vec<u8>,
-    ) -> Result<(Vec<u8>, Vec<u8>, Vec<u8>, Vec<u8>)> {
-        Ok((Vec::new(), Vec::new(), Vec::new(), Vec::new()))
-    }
-
-    #[allow(clippy::type_complexity)]
-    pub fn execute_5(
-        _ctx: Context<SetData5>,
-        _args: Vec<u8>,
-    ) -> Result<(Vec<u8>, Vec<u8>, Vec<u8>, Vec<u8>, Vec<u8>)> {
-        Ok((Vec::new(), Vec::new(), Vec::new(), Vec::new(), Vec::new()))
-    }
 }
 
-#[derive(Accounts, BorshDeserialize, BorshSerialize, Clone)]
+#[derive(Accounts, Clone)]
 pub struct SetData<'info> {
     #[account()]
     /// CHECK: unchecked account
     pub component: UncheckedAccount<'info>,
 }
-
-#[derive(Accounts, BorshDeserialize, BorshSerialize, Clone)]
-pub struct SetData2<'info> {
-    #[account()]
-    /// CHECK: unchecked account
-    pub component1: UncheckedAccount<'info>,
-    #[account()]
-    /// CHECK: unchecked account
-    pub component2: UncheckedAccount<'info>,
-}
-
-#[derive(Accounts, BorshDeserialize, BorshSerialize, Clone)]
-pub struct SetData3<'info> {
-    #[account()]
-    /// CHECK: unchecked account
-    pub component1: UncheckedAccount<'info>,
-    #[account()]
-    /// CHECK: unchecked account
-    pub component2: UncheckedAccount<'info>,
-    #[account()]
-    /// CHECK: unchecked account
-    pub component3: UncheckedAccount<'info>,
-}
-
-#[derive(Accounts, BorshDeserialize, BorshSerialize, Clone)]
-pub struct SetData4<'info> {
-    #[account()]
-    /// CHECK: unchecked account
-    pub component1: UncheckedAccount<'info>,
-    #[account()]
-    /// CHECK: unchecked account
-    pub component2: UncheckedAccount<'info>,
-    #[account()]
-    /// CHECK: unchecked account
-    pub component3: UncheckedAccount<'info>,
-    #[account()]
-    /// CHECK: unchecked account
-    pub component4: UncheckedAccount<'info>,
-}
-
-#[derive(Accounts, BorshDeserialize, BorshSerialize, Clone)]
-pub struct SetData5<'info> {
-    #[account()]
-    /// CHECK: unchecked account
-    pub component1: UncheckedAccount<'info>,
-    #[account()]
-    /// CHECK: unchecked account
-    pub component2: UncheckedAccount<'info>,
-    #[account()]
-    /// CHECK: unchecked account
-    pub component3: UncheckedAccount<'info>,
-    #[account()]
-    /// CHECK: unchecked account
-    pub component4: UncheckedAccount<'info>,
-    #[account()]
-    /// CHECK: unchecked account
-    pub component5: UncheckedAccount<'info>,
-}

+ 4 - 0
programs/world/Cargo.toml

@@ -15,9 +15,13 @@ no-idl = []
 no-log-ix-name = []
 cpi = ["no-entrypoint"]
 default = []
+idl-build = ["anchor-lang/idl-build"]
 
 [dependencies]
 anchor-lang = { version = "0.29.0", features = ["init-if-needed"] }
 bolt-component = { path = "../../programs/bolt-component", features = ["cpi"], version = "0.0.1"}
+bolt-helpers-world-apply = { path = "../../crates/bolt-helpers/attribute/world-apply", version = "0.0.1" }
 bolt-system = { path = "../../programs/bolt-system", features = ["cpi"], version = "0.0.1"}
 solana-security-txt = "1.1.1"
+tuple-conv = "1.0.1"
+

+ 8 - 0
programs/world/src/error.rs

@@ -0,0 +1,8 @@
+use anchor_lang::prelude::*;
+
+#[error_code]
+pub enum WorldError {
+    /// Returned if the wrong authority attempts to sign for an instruction
+    #[msg("Invalid authority for instruction")]
+    InvalidAuthority,
+}

+ 56 - 165
programs/world/src/lib.rs

@@ -1,4 +1,6 @@
 use anchor_lang::prelude::*;
+use bolt_helpers_world_apply::apply_system;
+use tuple_conv::RepeatedTuple;
 
 #[cfg(not(feature = "no-entrypoint"))]
 use solana_security_txt::security_txt;
@@ -15,9 +17,13 @@ security_txt! {
     source_code: "https://github.com/magicblock-labs/bolt"
 }
 
+mod error;
+
+#[apply_system(max_components = 3)]
 #[program]
 pub mod world {
     use super::*;
+    use crate::error::WorldError;
 
     pub fn initialize_registry(_ctx: Context<InitializeRegistry>) -> Result<()> {
         Ok(())
@@ -31,163 +37,59 @@ pub mod world {
 
     #[allow(unused_variables)]
     pub fn add_entity(ctx: Context<AddEntity>, extra_seed: Option<String>) -> Result<()> {
-        msg!(
-            "extra seeds: {:?}",
-            match extra_seed {
-                Some(ref seed) => seed.as_bytes(),
-                None => &[],
-            }
-        );
         ctx.accounts.entity.id = ctx.accounts.world.entities;
         ctx.accounts.world.entities += 1;
-        msg!("entity id: {}", ctx.accounts.entity.id);
-        msg!("world entities: {}", ctx.accounts.world.entities);
         Ok(())
     }
 
     pub fn initialize_component(ctx: Context<InitializeComponent>) -> Result<()> {
+        if !ctx.accounts.authority.is_signer && ctx.accounts.authority.key != &ID {
+            return Err(WorldError::InvalidAuthority.into());
+        }
         bolt_component::cpi::initialize(ctx.accounts.build())?;
         Ok(())
     }
 
     pub fn apply(ctx: Context<ApplySystem>, args: Vec<u8>) -> Result<()> {
+        if !ctx.accounts.authority.is_signer && ctx.accounts.authority.key != &ID {
+            return Err(WorldError::InvalidAuthority.into());
+        }
         let res = bolt_system::cpi::execute(ctx.accounts.build(), args)?;
-        bolt_component::cpi::update(ctx.accounts.build_update(), res.get())?;
-        Ok(())
-    }
-
-    // Apply to 2 components
-    pub fn apply2(ctx: Context<ApplySystem2>, args: Vec<u8>) -> Result<()> {
-        let res = bolt_system::cpi::execute_2(ctx.accounts.build(), args)?;
-        let (result1, result2) = res.get();
         bolt_component::cpi::update(
-            ctx.accounts.build_update(
-                ctx.accounts.component_program_1.clone(),
-                ctx.accounts.bolt_component_1.clone(),
+            build_update_context(
+                ctx.accounts.component_program.clone(),
+                ctx.accounts.bolt_component.clone(),
+                ctx.accounts.authority.clone(),
+                ctx.accounts.instruction_sysvar_account.clone(),
             ),
-            result1,
-        )?;
-        bolt_component::cpi::update(
-            ctx.accounts.build_update(
-                ctx.accounts.component_program_2.clone(),
-                ctx.accounts.bolt_component_2.clone(),
-            ),
-            result2,
+            res.get(),
         )?;
         Ok(())
     }
 
     #[derive(Accounts)]
-    pub struct ApplySystem2<'info> {
-        /// CHECK: bolt system program check
-        pub bolt_system: UncheckedAccount<'info>,
+    pub struct ApplySystem<'info> {
         /// CHECK: bolt component program check
-        pub component_program_1: UncheckedAccount<'info>,
-        #[account(mut)]
-        /// CHECK: component account
-        pub bolt_component_1: UncheckedAccount<'info>,
-        /// CHECK: bolt component program check
-        pub component_program_2: UncheckedAccount<'info>,
-        #[account(mut)]
-        /// CHECK: component account
-        pub bolt_component_2: UncheckedAccount<'info>,
-    }
-
-    impl<'info> ApplySystem2<'info> {
-        pub fn build(
-            &self,
-        ) -> CpiContext<'_, '_, '_, 'info, bolt_system::cpi::accounts::SetData2<'info>> {
-            let cpi_program = self.bolt_system.to_account_info();
-            let cpi_accounts = bolt_system::cpi::accounts::SetData2 {
-                component1: self.bolt_component_1.to_account_info(),
-                component2: self.bolt_component_2.to_account_info(),
-            };
-            CpiContext::new(cpi_program, cpi_accounts)
-        }
-
-        pub fn build_update(
-            &self,
-            component_program: UncheckedAccount<'info>,
-            component: UncheckedAccount<'info>,
-        ) -> CpiContext<'_, '_, '_, 'info, bolt_component::cpi::accounts::Update<'info>> {
-            let cpi_program = component_program.to_account_info();
-            let cpi_accounts = bolt_component::cpi::accounts::Update {
-                bolt_component: component.to_account_info(),
-            };
-            CpiContext::new(cpi_program, cpi_accounts)
-        }
-    }
-
-    // Apply to 3 components
-    pub fn apply3(ctx: Context<ApplySystem3>, args: Vec<u8>) -> Result<()> {
-        let res = bolt_system::cpi::execute_3(ctx.accounts.build(), args)?;
-        let (result1, result2, result3) = res.get();
-        bolt_component::cpi::update(
-            ctx.accounts.build_update(
-                ctx.accounts.component_program_1.clone(),
-                ctx.accounts.bolt_component_1.clone(),
-            ),
-            result1,
-        )?;
-        bolt_component::cpi::update(
-            ctx.accounts.build_update(
-                ctx.accounts.component_program_2.clone(),
-                ctx.accounts.bolt_component_2.clone(),
-            ),
-            result2,
-        )?;
-        bolt_component::cpi::update(
-            ctx.accounts.build_update(
-                ctx.accounts.component_program_3.clone(),
-                ctx.accounts.bolt_component_3.clone(),
-            ),
-            result3,
-        )?;
-        Ok(())
-    }
-
-    #[derive(Accounts)]
-    pub struct ApplySystem3<'info> {
+        pub component_program: UncheckedAccount<'info>,
         /// CHECK: bolt system program check
         pub bolt_system: UncheckedAccount<'info>,
-        /// CHECK: bolt component program check
-        pub component_program_1: UncheckedAccount<'info>,
         #[account(mut)]
         /// CHECK: component account
-        pub bolt_component_1: UncheckedAccount<'info>,
-        /// CHECK: bolt component program check
-        pub component_program_2: UncheckedAccount<'info>,
-        #[account(mut)]
-        /// CHECK: component account
-        pub bolt_component_2: UncheckedAccount<'info>,
-        /// CHECK: bolt component program check
-        pub component_program_3: UncheckedAccount<'info>,
-        #[account(mut)]
-        /// CHECK: component account
-        pub bolt_component_3: UncheckedAccount<'info>,
+        pub bolt_component: UncheckedAccount<'info>,
+        /// CHECK: authority check
+        pub authority: UncheckedAccount<'info>,
+        #[account(address = anchor_lang::solana_program::sysvar::instructions::id())]
+        /// CHECK: instruction sysvar check
+        pub instruction_sysvar_account: UncheckedAccount<'info>,
     }
 
-    impl<'info> ApplySystem3<'info> {
+    impl<'info> ApplySystem<'info> {
         pub fn build(
             &self,
-        ) -> CpiContext<'_, '_, '_, 'info, bolt_system::cpi::accounts::SetData3<'info>> {
+        ) -> CpiContext<'_, '_, '_, 'info, bolt_system::cpi::accounts::SetData<'info>> {
             let cpi_program = self.bolt_system.to_account_info();
-            let cpi_accounts = bolt_system::cpi::accounts::SetData3 {
-                component1: self.bolt_component_1.to_account_info(),
-                component2: self.bolt_component_2.to_account_info(),
-                component3: self.bolt_component_3.to_account_info(),
-            };
-            CpiContext::new(cpi_program, cpi_accounts)
-        }
-
-        pub fn build_update(
-            &self,
-            component_program: UncheckedAccount<'info>,
-            component: UncheckedAccount<'info>,
-        ) -> CpiContext<'_, '_, '_, 'info, bolt_component::cpi::accounts::Update<'info>> {
-            let cpi_program = component_program.to_account_info();
-            let cpi_accounts = bolt_component::cpi::accounts::Update {
-                bolt_component: component.to_account_info(),
+            let cpi_accounts = bolt_system::cpi::accounts::SetData {
+                component: self.bolt_component.to_account_info(),
             };
             CpiContext::new(cpi_program, cpi_accounts)
         }
@@ -240,11 +142,16 @@ pub struct InitializeComponent<'info> {
     pub payer: Signer<'info>,
     #[account(mut)]
     /// CHECK: component data check
-    pub data: UncheckedAccount<'info>,
+    pub data: AccountInfo<'info>,
     #[account()]
     pub entity: Account<'info, Entity>,
     /// CHECK: component program check
-    pub component_program: UncheckedAccount<'info>,
+    pub component_program: AccountInfo<'info>,
+    /// CHECK: authority check
+    pub authority: AccountInfo<'info>,
+    #[account(address = anchor_lang::solana_program::sysvar::instructions::id())]
+    /// CHECK: instruction sysvar check
+    pub instruction_sysvar_account: UncheckedAccount<'info>,
     pub system_program: Program<'info, System>,
 }
 
@@ -253,51 +160,19 @@ impl<'info> InitializeComponent<'info> {
         &self,
     ) -> CpiContext<'_, '_, '_, 'info, bolt_component::cpi::accounts::Initialize<'info>> {
         let cpi_program = self.component_program.to_account_info();
+
         let cpi_accounts = bolt_component::cpi::accounts::Initialize {
             payer: self.payer.to_account_info(),
             data: self.data.to_account_info(),
             entity: self.entity.to_account_info(),
+            authority: self.authority.to_account_info(),
+            instruction_sysvar_account: self.instruction_sysvar_account.to_account_info(),
             system_program: self.system_program.to_account_info(),
         };
         CpiContext::new(cpi_program, cpi_accounts)
     }
 }
 
-#[derive(Accounts)]
-pub struct ApplySystem<'info> {
-    /// CHECK: bolt component program check
-    pub component_program: UncheckedAccount<'info>,
-    /// CHECK: bolt system program check
-    pub bolt_system: UncheckedAccount<'info>,
-    #[account(mut)]
-    /// CHECK: component account
-    pub bolt_component: UncheckedAccount<'info>,
-}
-
-impl<'info> ApplySystem<'info> {
-    pub fn build(
-        &self,
-    ) -> CpiContext<'_, '_, '_, 'info, bolt_system::cpi::accounts::SetData<'info>> {
-        let cpi_program = self.bolt_system.to_account_info();
-        let cpi_accounts = bolt_system::cpi::accounts::SetData {
-            component: self.bolt_component.to_account_info(),
-        };
-        CpiContext::new(cpi_program, cpi_accounts)
-    }
-
-    pub fn build_update(
-        &self,
-    ) -> CpiContext<'_, '_, '_, 'info, bolt_component::cpi::accounts::Update<'info>> {
-        let cpi_program = self.component_program.to_account_info();
-        let cpi_accounts = bolt_component::cpi::accounts::Update {
-            bolt_component: self.bolt_component.to_account_info(),
-        };
-        CpiContext::new(cpi_program, cpi_accounts)
-    }
-}
-
-// Accounts
-
 #[account]
 #[derive(InitSpace, Default, Copy)]
 pub struct Registry {
@@ -350,3 +225,19 @@ impl Entity {
         b"entity"
     }
 }
+
+/// Builds the context for updating a component.
+pub fn build_update_context<'info>(
+    component_program: UncheckedAccount<'info>,
+    component: UncheckedAccount<'info>,
+    authority: UncheckedAccount<'info>,
+    instruction_sysvar_account: UncheckedAccount<'info>,
+) -> CpiContext<'info, 'info, 'info, 'info, bolt_component::cpi::accounts::Update<'info>> {
+    let cpi_program = component_program.to_account_info();
+    let cpi_accounts = bolt_component::cpi::accounts::Update {
+        bolt_component: component.to_account_info(),
+        authority: authority.to_account_info(),
+        instruction_sysvar_account: instruction_sysvar_account.to_account_info(),
+    };
+    CpiContext::new(cpi_program, cpi_accounts)
+}

+ 162 - 25
tests/bolt.ts

@@ -1,20 +1,22 @@
 import * as anchor from "@coral-xyz/anchor";
-import { Program } from "@coral-xyz/anchor";
-import { PublicKey } from "@solana/web3.js";
-import { ComponentPosition } from "../target/types/component_position";
-import { ComponentVelocity } from "../target/types/component_velocity";
-import { BoltComponent } from "../target/types/bolt_component";
-import { SystemSimpleMovement } from "../target/types/system_simple_movement";
-import { SystemFly } from "../target/types/system_fly";
-import { SystemApplyVelocity } from "../target/types/system_apply_velocity";
-import { World } from "../target/types/world";
+import { type Program } from "@coral-xyz/anchor";
+import { type PublicKey } from "@solana/web3.js";
+import { type Position } from "../target/types/position";
+import { type Velocity } from "../target/types/velocity";
+import { type BoltComponent } from "../target/types/bolt_component";
+import { type SystemSimpleMovement } from "../target/types/system_simple_movement";
+import { type SystemFly } from "../target/types/system_fly";
+import { type SystemApplyVelocity } from "../target/types/system_apply_velocity";
+import { type World } from "../target/types/world";
 import { expect } from "chai";
 import BN from "bn.js";
 import {
+  createInitializeRegistryInstruction,
   FindComponentPda,
   FindEntityPda,
   FindWorldPda,
   FindWorldRegistryPda,
+  SYSVAR_INSTRUCTIONS_PUBKEY,
 } from "../clients/bolt-sdk";
 
 enum Direction {
@@ -41,9 +43,9 @@ describe("bolt", () => {
 
   const worldProgram = anchor.workspace.World as Program<World>;
   const boltComponentPositionProgram = anchor.workspace
-    .ComponentPosition as Program<ComponentPosition>;
+    .Position as Program<Position>;
   const boltComponentVelocityProgram = anchor.workspace
-    .ComponentVelocity as Program<ComponentVelocity>;
+    .Velocity as Program<Velocity>;
   const boltComponentProgramOrigin = anchor.workspace
     .BoltComponent as Program<BoltComponent>;
 
@@ -58,19 +60,21 @@ describe("bolt", () => {
 
   let entity1: PublicKey;
   let entity2: PublicKey;
+  let entity5: PublicKey;
   let componentPositionEntity1: PublicKey;
   let componentPositionEntity2: PublicKey;
+  let componentPositionEntity5: PublicKey;
   let componentVelocityEntity1: PublicKey;
 
   it("InitializeWorldsRegistry", async () => {
     const registryPda = FindWorldRegistryPda(worldProgram.programId);
-    await worldProgram.methods
-      .initializeRegistry()
-      .accounts({
-        registry: registryPda,
-        payer: provider.wallet.publicKey,
-      })
-      .rpc();
+    const initializeRegistryIx = createInitializeRegistryInstruction({
+      registry: registryPda,
+      payer: provider.wallet.publicKey,
+    });
+
+    const tx = new anchor.web3.Transaction().add(initializeRegistryIx);
+    await provider.sendAndConfirm(tx);
   });
 
   it("InitializeNewWorld", async () => {
@@ -150,7 +154,7 @@ describe("bolt", () => {
   it("Add entity 4 with extra seeds", async () => {
     const worldPda = FindWorldPda(new BN(0), worldProgram.programId);
     const seed = "extra-seed";
-    let entity3 = FindEntityPda(
+    const entity4 = FindEntityPda(
       new BN(0),
       new BN(3),
       seed,
@@ -161,14 +165,28 @@ describe("bolt", () => {
       .addEntity(seed)
       .accounts({
         world: worldPda,
-        entity: entity3,
+        entity: entity4,
+        payer: provider.wallet.publicKey,
+      })
+      .rpc();
+  });
+
+  it("Add entity 5", async () => {
+    const worldPda = FindWorldPda(new BN(0), worldProgram.programId);
+    entity5 = FindEntityPda(new BN(0), new BN(4), null, worldProgram.programId);
+
+    await worldProgram.methods
+      .addEntity(null)
+      .accounts({
+        world: worldPda,
+        entity: entity5,
         payer: provider.wallet.publicKey,
       })
       .rpc();
   });
 
   it("Initialize Original Component on Entity 1, trough the world instance", async () => {
-    let componentEntity1 = FindComponentPda(
+    const componentEntity1 = FindComponentPda(
       boltComponentProgramOrigin.programId,
       entity1,
       "origin-component"
@@ -180,12 +198,14 @@ describe("bolt", () => {
         data: componentEntity1,
         componentProgram: boltComponentProgramOrigin.programId,
         entity: entity1,
+        instructionSysvarAccount: SYSVAR_INSTRUCTIONS_PUBKEY,
+        authority: provider.wallet.publicKey,
       })
       .rpc();
   });
 
   it("Initialize Original Component on Entity 2, trough the world instance", async () => {
-    let componentEntity2 = FindComponentPda(
+    const componentEntity2 = FindComponentPda(
       boltComponentProgramOrigin.programId,
       entity2,
       "origin-component"
@@ -197,6 +217,8 @@ describe("bolt", () => {
         data: componentEntity2,
         componentProgram: boltComponentProgramOrigin.programId,
         entity: entity2,
+        instructionSysvarAccount: SYSVAR_INSTRUCTIONS_PUBKEY,
+        authority: provider.wallet.publicKey,
       })
       .rpc();
   });
@@ -216,6 +238,8 @@ describe("bolt", () => {
         data: componentPositionEntity1,
         componentProgram: boltComponentPositionProgram.programId,
         entity: entity1,
+        instructionSysvarAccount: SYSVAR_INSTRUCTIONS_PUBKEY,
+        authority: worldProgram.programId,
       })
       .rpc();
   });
@@ -234,6 +258,8 @@ describe("bolt", () => {
         data: componentVelocityEntity1,
         componentProgram: boltComponentVelocityProgram.programId,
         entity: entity1,
+        instructionSysvarAccount: SYSVAR_INSTRUCTIONS_PUBKEY,
+        authority: worldProgram.programId,
       })
       .rpc();
   });
@@ -251,6 +277,27 @@ describe("bolt", () => {
         data: componentPositionEntity2,
         componentProgram: boltComponentPositionProgram.programId,
         entity: entity2,
+        instructionSysvarAccount: SYSVAR_INSTRUCTIONS_PUBKEY,
+        authority: worldProgram.programId,
+      })
+      .rpc();
+  });
+
+  it("Initialize Position Component on Entity 5", async () => {
+    componentPositionEntity5 = FindComponentPda(
+      boltComponentPositionProgram.programId,
+      entity5
+    );
+
+    await worldProgram.methods
+      .initializeComponent()
+      .accounts({
+        payer: provider.wallet.publicKey,
+        data: componentPositionEntity5,
+        componentProgram: boltComponentPositionProgram.programId,
+        entity: entity5,
+        instructionSysvarAccount: SYSVAR_INSTRUCTIONS_PUBKEY,
+        authority: provider.wallet.publicKey,
       })
       .rpc();
   });
@@ -289,6 +336,8 @@ describe("bolt", () => {
         componentProgram: boltComponentPositionProgram.programId,
         boltSystem: systemSimpleMovement,
         boltComponent: componentPositionEntity1,
+        instructionSysvarAccount: SYSVAR_INSTRUCTIONS_PUBKEY,
+        authority: worldProgram.programId,
       })
       .rpc({ skipPreflight: true });
 
@@ -320,6 +369,7 @@ describe("bolt", () => {
     console.log("+----------------+------------+");
     console.log("|                             |");
     console.log("+-----------------------------+");
+    console.log("Component Position: ", componentPositionEntity1.toString());
   });
 
   it("Simple Movement System and Right direction on Entity 1", async () => {
@@ -332,8 +382,10 @@ describe("bolt", () => {
         componentProgram: boltComponentPositionProgram.programId,
         boltSystem: systemSimpleMovement,
         boltComponent: componentPositionEntity1,
+        instructionSysvarAccount: SYSVAR_INSTRUCTIONS_PUBKEY,
+        authority: worldProgram.programId,
       })
-      .rpc({ skipPreflight: true });
+      .rpc();
 
     expect(
       (
@@ -379,6 +431,8 @@ describe("bolt", () => {
         componentProgram: boltComponentPositionProgram.programId,
         boltSystem: systemFly,
         boltComponent: componentPositionEntity1,
+        instructionSysvarAccount: SYSVAR_INSTRUCTIONS_PUBKEY,
+        authority: worldProgram.programId,
       })
       .rpc();
 
@@ -421,6 +475,8 @@ describe("bolt", () => {
         boltSystem: applyVelocity,
         boltComponent1: componentVelocityEntity1,
         boltComponent2: componentPositionEntity1,
+        instructionSysvarAccount: SYSVAR_INSTRUCTIONS_PUBKEY,
+        authority: worldProgram.programId,
       })
       .remainingAccounts([
         {
@@ -433,7 +489,7 @@ describe("bolt", () => {
 
     console.log("Component Velocity: ", componentVelocityEntity1.toBase58());
 
-    let componentData =
+    const componentData =
       await boltComponentVelocityProgram.account.velocity.fetch(
         componentVelocityEntity1
       );
@@ -457,7 +513,7 @@ describe("bolt", () => {
     console.log("|                             |");
     console.log("+-----------------------------+");
 
-    let positionData =
+    const positionData =
       await boltComponentPositionProgram.account.position.fetch(
         componentPositionEntity1
       );
@@ -478,4 +534,85 @@ describe("bolt", () => {
     console.log("|                             |");
     console.log("+-----------------------------+");
   });
+
+  // Check illegal authority usage
+  it("Check invalid component update", async () => {
+    const componentDataPrev =
+      await boltComponentPositionProgram.account.position.fetch(
+        componentPositionEntity5
+      );
+
+    try {
+      await worldProgram.methods
+        .apply(Buffer.alloc(0)) // Move Up
+        .accounts({
+          componentProgram: boltComponentPositionProgram.programId,
+          boltSystem: systemFly,
+          boltComponent: componentPositionEntity5,
+          instructionSysvarAccount: SYSVAR_INSTRUCTIONS_PUBKEY,
+          authority: worldProgram.programId,
+        })
+        .rpc();
+    } catch (e) {
+      expect(e.message).to.contain("Invalid authority");
+    }
+
+    const componentData =
+      await boltComponentPositionProgram.account.position.fetch(
+        componentPositionEntity5
+      );
+
+    expect(
+      componentDataPrev.x.toNumber() === componentData.x.toNumber() &&
+        componentDataPrev.y.toNumber() === componentData.y.toNumber() &&
+        componentDataPrev.z.toNumber() === componentData.z.toNumber()
+    ).to.equal(true);
+  });
+
+  // Check illegal call, without CPI
+  it("Check invalid init without CPI", async () => {
+    let invalid = false;
+    const componentVelocityEntity5 = FindComponentPda(
+      boltComponentVelocityProgram.programId,
+      entity5
+    );
+    try {
+      await boltComponentProgramOrigin.methods
+        .initialize()
+        .accounts({
+          payer: provider.wallet.publicKey,
+          data: componentVelocityEntity5,
+          entity: entity5,
+          instructionSysvarAccount: SYSVAR_INSTRUCTIONS_PUBKEY,
+          systemProgram: anchor.web3.SystemProgram.programId,
+          authority: provider.wallet.publicKey,
+        })
+        .rpc();
+    } catch (e) {
+      invalid = true;
+    }
+    expect(invalid).to.equal(true);
+  });
+
+  // Check illegal call, without CPI
+  it("Check invalid update without CPI", async () => {
+    let invalid = false;
+    const componentVelocityEntity5 = FindComponentPda(
+      boltComponentVelocityProgram.programId,
+      entity5
+    );
+    try {
+      await boltComponentProgramOrigin.methods
+        .update(null)
+        .accounts({
+          boltComponent: componentVelocityEntity5,
+          instructionSysvarAccount: SYSVAR_INSTRUCTIONS_PUBKEY,
+          authority: provider.wallet.publicKey,
+        })
+        .rpc();
+    } catch (e) {
+      invalid = true;
+    }
+    expect(invalid).to.equal(true);
+  });
 });