bolt.ts 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685
  1. import * as anchor from "@coral-xyz/anchor";
  2. import { type Program, web3 } from "@coral-xyz/anchor";
  3. import { Keypair, type PublicKey } from "@solana/web3.js";
  4. import { type Position } from "../target/types/position";
  5. import { type Velocity } from "../target/types/velocity";
  6. import { type BoltComponent } from "../target/types/bolt_component";
  7. import { type SystemSimpleMovement } from "../target/types/system_simple_movement";
  8. import { type World } from "../target/types/world";
  9. import { type SystemFly } from "../target/types/system_fly";
  10. import { type SystemApplyVelocity } from "../target/types/system_apply_velocity";
  11. import { expect } from "chai";
  12. import type BN from "bn.js";
  13. import {
  14. AddEntity,
  15. createInitializeRegistryInstruction,
  16. DELEGATION_PROGRAM_ID,
  17. FindRegistryPda,
  18. InitializeComponent,
  19. InitializeNewWorld,
  20. ApplySystem,
  21. DelegateComponent,
  22. AddAuthority,
  23. RemoveAuthority,
  24. ApproveSystem,
  25. RemoveSystem,
  26. } from "../clients/bolt-sdk";
  27. enum Direction {
  28. Left = "Left",
  29. Right = "Right",
  30. Up = "Up",
  31. Down = "Down",
  32. }
  33. function padCenter(value: string, width: number) {
  34. const length = value.length;
  35. if (width <= length) {
  36. return value;
  37. }
  38. const padding = (width - length) / 2;
  39. const align = width - padding;
  40. return value.padStart(align, " ").padEnd(width, " ");
  41. }
  42. function logPosition(title: string, { x, y, z }: { x: BN; y: BN; z: BN }) {
  43. console.log(" +----------------------------------+");
  44. console.log(` | ${padCenter(title, 32)} |`);
  45. console.log(" +-----------------+----------------+");
  46. console.log(` | X Position | ${String(x).padEnd(14, " ")} |`);
  47. console.log(` | Y Position | ${String(y).padEnd(14, " ")} |`);
  48. console.log(` | Z Position | ${String(z).padEnd(14, " ")} |`);
  49. console.log(" +-----------------+----------------+");
  50. }
  51. function logVelocity(
  52. title: string,
  53. { x, y, z, lastApplied }: { x: BN; y: BN; z: BN; lastApplied: BN }
  54. ) {
  55. console.log(" +----------------------------------+");
  56. console.log(` | ${padCenter(title, 32)} |`);
  57. console.log(" +-----------------+----------------+");
  58. console.log(` | X Velocity | ${String(x).padEnd(14, " ")} |`);
  59. console.log(` | Y Velocity | ${String(y).padEnd(14, " ")} |`);
  60. console.log(` | Z Velocity | ${String(z).padEnd(14, " ")} |`);
  61. console.log(` | Last Applied | ${String(lastApplied).padEnd(14, " ")} |`);
  62. console.log(" +-----------------+----------------+");
  63. }
  64. describe("bolt", () => {
  65. const provider = anchor.AnchorProvider.env();
  66. anchor.setProvider(provider);
  67. const worldProgram = anchor.workspace.World as Program<World>;
  68. const boltComponentProgram = anchor.workspace
  69. .BoltComponent as Program<BoltComponent>;
  70. const exampleComponentPosition = anchor.workspace
  71. .Position as Program<Position>;
  72. const exampleComponentVelocity = anchor.workspace
  73. .Velocity as Program<Velocity>;
  74. const exampleSystemSimpleMovement = (
  75. anchor.workspace.SystemSimpleMovement as Program<SystemSimpleMovement>
  76. ).programId;
  77. const exampleSystemFly = (anchor.workspace.SystemFly as Program<SystemFly>)
  78. .programId;
  79. const exampleSystemApplyVelocity = (
  80. anchor.workspace.SystemApplyVelocity as Program<SystemApplyVelocity>
  81. ).programId;
  82. let worldPda: PublicKey;
  83. let entity1Pda: PublicKey;
  84. let entity2Pda: PublicKey;
  85. let entity4Pda: PublicKey;
  86. let entity5Pda: PublicKey;
  87. let componentPositionEntity1Pda: PublicKey;
  88. let componentVelocityEntity1Pda: PublicKey;
  89. let componentPositionEntity4Pda: PublicKey;
  90. let componentPositionEntity5Pda: PublicKey;
  91. const secondAuthority = Keypair.generate().publicKey;
  92. it.only("InitializeRegistry", async () => {
  93. const registryPda = FindRegistryPda({});
  94. const initializeRegistryIx = createInitializeRegistryInstruction({
  95. registry: registryPda,
  96. payer: provider.wallet.publicKey,
  97. });
  98. const tx = new anchor.web3.Transaction().add(initializeRegistryIx);
  99. await provider.sendAndConfirm(tx);
  100. });
  101. it.only("InitializeNewWorld", async () => {
  102. const initializeNewWorld = await InitializeNewWorld({
  103. payer: provider.wallet.publicKey,
  104. connection: provider.connection,
  105. });
  106. const signature = await provider.sendAndConfirm(initializeNewWorld.transaction);
  107. console.log("InitializeNewWorld signature: ", signature);
  108. worldPda = initializeNewWorld.worldPda; // Saved for later
  109. });
  110. it("Add authority", async () => {
  111. const addAuthority = await AddAuthority({
  112. authority: provider.wallet.publicKey,
  113. newAuthority: provider.wallet.publicKey,
  114. world: worldPda,
  115. connection: provider.connection,
  116. });
  117. await provider.sendAndConfirm(addAuthority.transaction, [], {
  118. skipPreflight: true,
  119. });
  120. const worldAccount = await worldProgram.account.world.fetch(worldPda);
  121. expect(
  122. worldAccount.authorities.some((auth) =>
  123. auth.equals(provider.wallet.publicKey)
  124. )
  125. );
  126. });
  127. it("Add a second authority", async () => {
  128. const addAuthority = await AddAuthority({
  129. authority: provider.wallet.publicKey,
  130. newAuthority: secondAuthority,
  131. world: worldPda,
  132. connection: provider.connection,
  133. });
  134. const signature = await provider.sendAndConfirm(addAuthority.transaction);
  135. console.log(`Add Authority signature: ${signature}`);
  136. const worldAccount = await worldProgram.account.world.fetch(worldPda);
  137. expect(
  138. worldAccount.authorities.some((auth) => auth.equals(secondAuthority))
  139. );
  140. });
  141. it("Remove an authority", async () => {
  142. const addAuthority = await RemoveAuthority({
  143. authority: provider.wallet.publicKey,
  144. authorityToDelete: secondAuthority,
  145. world: worldPda,
  146. connection: provider.connection,
  147. });
  148. const signature = await provider.sendAndConfirm(addAuthority.transaction);
  149. console.log(`Add Authority signature: ${signature}`);
  150. const worldAccount = await worldProgram.account.world.fetch(worldPda);
  151. expect(
  152. !worldAccount.authorities.some((auth) => auth.equals(secondAuthority))
  153. );
  154. });
  155. it("InitializeNewWorld 2", async () => {
  156. const initializeNewWorld = await InitializeNewWorld({
  157. payer: provider.wallet.publicKey,
  158. connection: provider.connection,
  159. });
  160. await provider.sendAndConfirm(initializeNewWorld.transaction);
  161. });
  162. it("Add entity 1", async () => {
  163. const addEntity = await AddEntity({
  164. payer: provider.wallet.publicKey,
  165. world: worldPda,
  166. connection: provider.connection,
  167. });
  168. await provider.sendAndConfirm(addEntity.transaction);
  169. entity1Pda = addEntity.entityPda; // Saved for later
  170. });
  171. it("Add entity 2", async () => {
  172. const addEntity = await AddEntity({
  173. payer: provider.wallet.publicKey,
  174. world: worldPda,
  175. connection: provider.connection,
  176. });
  177. await provider.sendAndConfirm(addEntity.transaction);
  178. entity2Pda = addEntity.entityPda; // Saved for later
  179. });
  180. it("Add entity 3", async () => {
  181. const addEntity = await AddEntity({
  182. payer: provider.wallet.publicKey,
  183. world: worldPda,
  184. connection: provider.connection,
  185. });
  186. await provider.sendAndConfirm(addEntity.transaction);
  187. });
  188. it("Add entity 4 (with seed)", async () => {
  189. const addEntity = await AddEntity({
  190. payer: provider.wallet.publicKey,
  191. world: worldPda,
  192. seed: "extra-seed",
  193. connection: provider.connection,
  194. });
  195. await provider.sendAndConfirm(addEntity.transaction);
  196. entity4Pda = addEntity.entityPda;
  197. });
  198. it("Add entity 5", async () => {
  199. const addEntity = await AddEntity({
  200. payer: provider.wallet.publicKey,
  201. world: worldPda,
  202. connection: provider.connection,
  203. });
  204. await provider.sendAndConfirm(addEntity.transaction);
  205. entity5Pda = addEntity.entityPda; // Saved for later
  206. });
  207. it("Initialize Original Component on Entity 1, trough the world instance", async () => {
  208. const initializeComponent = await InitializeComponent({
  209. payer: provider.wallet.publicKey,
  210. entity: entity1Pda,
  211. seed: "origin-component",
  212. componentId: boltComponentProgram.programId,
  213. });
  214. await provider.sendAndConfirm(initializeComponent.transaction);
  215. });
  216. it("Initialize Original Component on Entity 2, trough the world instance", async () => {
  217. const initializeComponent = await InitializeComponent({
  218. payer: provider.wallet.publicKey,
  219. entity: entity2Pda,
  220. seed: "origin-component",
  221. componentId: boltComponentProgram.programId,
  222. });
  223. await provider.sendAndConfirm(initializeComponent.transaction);
  224. });
  225. it("Initialize Position Component on Entity 1", async () => {
  226. const initializeComponent = await InitializeComponent({
  227. payer: provider.wallet.publicKey,
  228. entity: entity1Pda,
  229. componentId: exampleComponentPosition.programId,
  230. });
  231. await provider.sendAndConfirm(initializeComponent.transaction);
  232. componentPositionEntity1Pda = initializeComponent.componentPda; // Saved for later
  233. });
  234. it("Initialize Velocity Component on Entity 1 (with seed)", async () => {
  235. const initializeComponent = await InitializeComponent({
  236. payer: provider.wallet.publicKey,
  237. entity: entity1Pda,
  238. componentId: exampleComponentVelocity.programId,
  239. seed: "component-velocity",
  240. });
  241. await provider.sendAndConfirm(initializeComponent.transaction);
  242. componentVelocityEntity1Pda = initializeComponent.componentPda; // Saved for later
  243. });
  244. it("Initialize Position Component on Entity 2", async () => {
  245. const initializeComponent = await InitializeComponent({
  246. payer: provider.wallet.publicKey,
  247. entity: entity2Pda,
  248. componentId: exampleComponentPosition.programId,
  249. });
  250. await provider.sendAndConfirm(initializeComponent.transaction);
  251. });
  252. it("Initialize Position Component on Entity 4", async () => {
  253. const initializeComponent = await InitializeComponent({
  254. payer: provider.wallet.publicKey,
  255. entity: entity4Pda,
  256. componentId: exampleComponentPosition.programId,
  257. });
  258. await provider.sendAndConfirm(initializeComponent.transaction);
  259. componentPositionEntity4Pda = initializeComponent.componentPda; // Saved for later
  260. });
  261. it("Initialize Position Component on Entity 5 (with authority)", async () => {
  262. const initializeComponent = await InitializeComponent({
  263. payer: provider.wallet.publicKey,
  264. entity: entity5Pda,
  265. componentId: exampleComponentPosition.programId,
  266. authority: provider.wallet.publicKey,
  267. });
  268. await provider.sendAndConfirm(initializeComponent.transaction);
  269. componentPositionEntity5Pda = initializeComponent.componentPda; // Saved for later
  270. });
  271. it("Check Position on Entity 1 is default", async () => {
  272. const position = await exampleComponentPosition.account.position.fetch(
  273. componentPositionEntity1Pda
  274. );
  275. logPosition("Default State: Entity 1", position);
  276. expect(position.x.toNumber()).to.equal(0);
  277. expect(position.y.toNumber()).to.equal(0);
  278. expect(position.z.toNumber()).to.equal(0);
  279. });
  280. it("Apply Simple Movement System (Up) on Entity 1", async () => {
  281. const applySystem = await ApplySystem({
  282. authority: provider.wallet.publicKey,
  283. systemId: exampleSystemSimpleMovement,
  284. world: worldPda,
  285. entities: [
  286. {
  287. entity: entity1Pda,
  288. components: [{ componentId: exampleComponentPosition.programId }],
  289. },
  290. ],
  291. args: {
  292. direction: Direction.Up,
  293. },
  294. });
  295. const signature = await provider.sendAndConfirm(
  296. applySystem.transaction,
  297. [],
  298. { skipPreflight: true }
  299. );
  300. console.log(`Signature: ${signature}`);
  301. const position = await exampleComponentPosition.account.position.fetch(
  302. componentPositionEntity1Pda
  303. );
  304. logPosition("Movement System: Entity 1", position);
  305. expect(position.x.toNumber()).to.equal(0);
  306. expect(position.y.toNumber()).to.equal(1);
  307. expect(position.z.toNumber()).to.equal(0);
  308. });
  309. it("Apply Simple Movement System (Right) on Entity 1", async () => {
  310. const applySystem = await ApplySystem({
  311. authority: provider.wallet.publicKey,
  312. systemId: exampleSystemSimpleMovement,
  313. world: worldPda,
  314. entities: [
  315. {
  316. entity: entity1Pda,
  317. components: [{ componentId: exampleComponentPosition.programId }],
  318. },
  319. ],
  320. args: {
  321. direction: Direction.Right,
  322. },
  323. });
  324. await provider.sendAndConfirm(applySystem.transaction);
  325. const position = await exampleComponentPosition.account.position.fetch(
  326. componentPositionEntity1Pda
  327. );
  328. logPosition("Movement System: Entity 1", position);
  329. expect(position.x.toNumber()).to.equal(1);
  330. expect(position.y.toNumber()).to.equal(1);
  331. expect(position.z.toNumber()).to.equal(0);
  332. });
  333. it("Apply Fly System on Entity 1", async () => {
  334. const applySystem = await ApplySystem({
  335. authority: provider.wallet.publicKey,
  336. systemId: exampleSystemFly,
  337. world: worldPda,
  338. entities: [
  339. {
  340. entity: entity1Pda,
  341. components: [{ componentId: exampleComponentPosition.programId }],
  342. },
  343. ],
  344. });
  345. await provider.sendAndConfirm(applySystem.transaction);
  346. const position = await exampleComponentPosition.account.position.fetch(
  347. componentPositionEntity1Pda
  348. );
  349. logPosition("Fly System: Entity 1", position);
  350. expect(position.x.toNumber()).to.equal(1);
  351. expect(position.y.toNumber()).to.equal(1);
  352. expect(position.z.toNumber()).to.equal(1);
  353. });
  354. it("Apply System Velocity on Entity 1", async () => {
  355. const applySystem = await ApplySystem({
  356. authority: provider.wallet.publicKey,
  357. systemId: exampleSystemApplyVelocity,
  358. world: worldPda,
  359. entities: [
  360. {
  361. entity: entity1Pda,
  362. components: [
  363. {
  364. componentId: exampleComponentVelocity.programId,
  365. seed: "component-velocity",
  366. },
  367. { componentId: exampleComponentPosition.programId },
  368. ],
  369. },
  370. ],
  371. });
  372. await provider.sendAndConfirm(applySystem.transaction);
  373. const velocity = await exampleComponentVelocity.account.velocity.fetch(
  374. componentVelocityEntity1Pda
  375. );
  376. logVelocity("Apply System Velocity: Entity 1", velocity);
  377. expect(velocity.x.toNumber()).to.equal(10);
  378. expect(velocity.y.toNumber()).to.equal(0);
  379. expect(velocity.z.toNumber()).to.equal(0);
  380. expect(velocity.lastApplied.toNumber()).to.not.equal(0);
  381. const position = await exampleComponentPosition.account.position.fetch(
  382. componentPositionEntity1Pda
  383. );
  384. logPosition("Apply System Velocity: Entity 1", position);
  385. expect(position.x.toNumber()).to.greaterThan(1);
  386. expect(position.y.toNumber()).to.equal(1);
  387. expect(position.z.toNumber()).to.equal(1);
  388. });
  389. it("Apply System Velocity on Entity 1, with Clock external account", async () => {
  390. const applySystem = await ApplySystem({
  391. authority: provider.wallet.publicKey,
  392. systemId: exampleSystemApplyVelocity,
  393. world: worldPda,
  394. entities: [
  395. {
  396. entity: entity1Pda,
  397. components: [
  398. {
  399. componentId: exampleComponentVelocity.programId,
  400. seed: "component-velocity",
  401. },
  402. { componentId: exampleComponentPosition.programId },
  403. ],
  404. },
  405. ],
  406. extraAccounts: [
  407. {
  408. pubkey: new web3.PublicKey(
  409. "SysvarC1ock11111111111111111111111111111111"
  410. ),
  411. isWritable: false,
  412. isSigner: false,
  413. },
  414. ],
  415. });
  416. await provider.sendAndConfirm(applySystem.transaction);
  417. const position = await exampleComponentPosition.account.position.fetch(
  418. componentPositionEntity1Pda
  419. );
  420. logPosition("Apply System Velocity: Entity 1", position);
  421. expect(position.x.toNumber()).to.greaterThan(1);
  422. expect(position.y.toNumber()).to.equal(1);
  423. expect(position.z.toNumber()).to.equal(300);
  424. });
  425. it("Apply Fly System on Entity 4", async () => {
  426. const applySystem = await ApplySystem({
  427. authority: provider.wallet.publicKey,
  428. systemId: exampleSystemFly,
  429. world: worldPda,
  430. entities: [
  431. {
  432. entity: entity4Pda,
  433. components: [{ componentId: exampleComponentPosition.programId }],
  434. },
  435. ],
  436. });
  437. await provider.sendAndConfirm(applySystem.transaction);
  438. const position = await exampleComponentPosition.account.position.fetch(
  439. componentPositionEntity4Pda
  440. );
  441. logPosition("Fly System: Entity 4", position);
  442. expect(position.x.toNumber()).to.equal(0);
  443. expect(position.y.toNumber()).to.equal(0);
  444. expect(position.z.toNumber()).to.equal(1);
  445. });
  446. it("Apply Fly System on Entity 5 (should fail with wrong authority)", async () => {
  447. const positionBefore =
  448. await exampleComponentPosition.account.position.fetch(
  449. componentPositionEntity5Pda
  450. );
  451. const applySystem = await ApplySystem({
  452. authority: provider.wallet.publicKey,
  453. systemId: exampleSystemFly,
  454. world: worldPda,
  455. entities: [
  456. {
  457. entity: entity5Pda,
  458. components: [{ componentId: exampleComponentPosition.programId }],
  459. },
  460. ],
  461. });
  462. let failed = false;
  463. try {
  464. await provider.sendAndConfirm(applySystem.transaction);
  465. } catch (error) {
  466. failed = true;
  467. // console.log("error", error);
  468. expect(error.logs.join("\n")).to.contain("Error Code: InvalidAuthority");
  469. }
  470. expect(failed).to.equal(true);
  471. const positionAfter = await exampleComponentPosition.account.position.fetch(
  472. componentPositionEntity5Pda
  473. );
  474. expect(positionBefore.x.toNumber()).to.equal(positionAfter.x.toNumber());
  475. expect(positionBefore.y.toNumber()).to.equal(positionAfter.y.toNumber());
  476. expect(positionBefore.z.toNumber()).to.equal(positionAfter.z.toNumber());
  477. });
  478. it("Whitelist System", async () => {
  479. const approveSystem = await ApproveSystem({
  480. authority: provider.wallet.publicKey,
  481. systemToApprove: exampleSystemFly,
  482. world: worldPda,
  483. });
  484. const signature = await provider.sendAndConfirm(
  485. approveSystem.transaction,
  486. [],
  487. { skipPreflight: true }
  488. );
  489. console.log(`Whitelist 2 system approval signature: ${signature}`);
  490. // Get World and check permissionless and systems
  491. const worldAccount = await worldProgram.account.world.fetch(worldPda);
  492. expect(worldAccount.permissionless).to.equal(false);
  493. expect(worldAccount.systems.length).to.be.greaterThan(0);
  494. });
  495. it("Whitelist System 2", async () => {
  496. const approveSystem = await ApproveSystem({
  497. authority: provider.wallet.publicKey,
  498. systemToApprove: exampleSystemApplyVelocity,
  499. world: worldPda,
  500. });
  501. const signature = await provider.sendAndConfirm(
  502. approveSystem.transaction,
  503. [],
  504. { skipPreflight: true }
  505. );
  506. console.log(`Whitelist 2 system approval signature: ${signature}`);
  507. // Get World and check permissionless and systems
  508. const worldAccount = await worldProgram.account.world.fetch(worldPda);
  509. expect(worldAccount.permissionless).to.equal(false);
  510. expect(worldAccount.systems.length).to.be.greaterThan(0);
  511. });
  512. it("Apply Fly System on Entity 1", async () => {
  513. const applySystem = await ApplySystem({
  514. authority: provider.wallet.publicKey,
  515. systemId: exampleSystemFly,
  516. world: worldPda,
  517. entities: [
  518. {
  519. entity: entity1Pda,
  520. components: [{ componentId: exampleComponentPosition.programId }],
  521. },
  522. ],
  523. });
  524. await provider.sendAndConfirm(applySystem.transaction);
  525. });
  526. it("Remove System 1", async () => {
  527. const approveSystem = await RemoveSystem({
  528. authority: provider.wallet.publicKey,
  529. systemToRemove: exampleSystemFly,
  530. world: worldPda,
  531. });
  532. const signature = await provider.sendAndConfirm(
  533. approveSystem.transaction,
  534. [],
  535. { skipPreflight: true }
  536. );
  537. console.log(`Whitelist 2 system approval signature: ${signature}`);
  538. // Get World and check permissionless and systems
  539. const worldAccount = await worldProgram.account.world.fetch(worldPda);
  540. expect(worldAccount.permissionless).to.equal(false);
  541. expect(worldAccount.systems.length).to.be.greaterThan(0);
  542. });
  543. it("Apply Invalid Fly System on Entity 1", async () => {
  544. const applySystem = await ApplySystem({
  545. authority: provider.wallet.publicKey,
  546. systemId: exampleSystemFly,
  547. world: worldPda,
  548. entities: [
  549. {
  550. entity: entity1Pda,
  551. components: [{ componentId: exampleComponentPosition.programId }],
  552. },
  553. ],
  554. });
  555. let invalid = false;
  556. try {
  557. await provider.sendAndConfirm(applySystem.transaction);
  558. } catch (error) {
  559. expect(error.logs.join(" ")).to.contain("Error Code: SystemNotApproved");
  560. invalid = true;
  561. }
  562. expect(invalid).to.equal(true);
  563. });
  564. it("Check invalid component init without CPI", async () => {
  565. let invalid = false;
  566. try {
  567. await exampleComponentPosition.methods
  568. .initialize()
  569. .accounts({
  570. payer: provider.wallet.publicKey,
  571. data: componentPositionEntity5Pda,
  572. entity: entity5Pda,
  573. authority: provider.wallet.publicKey,
  574. })
  575. .rpc();
  576. } catch (error) {
  577. // console.log("error", error);
  578. expect(error.message).to.contain("Error Code: InvalidCaller");
  579. invalid = true;
  580. }
  581. expect(invalid).to.equal(true);
  582. });
  583. it("Check invalid component update without CPI", async () => {
  584. let invalid = false;
  585. try {
  586. await boltComponentProgram.methods
  587. .update(Buffer.from(""))
  588. .accounts({
  589. boltComponent: componentPositionEntity4Pda,
  590. authority: provider.wallet.publicKey,
  591. })
  592. .rpc();
  593. } catch (error) {
  594. // console.log("error", error);
  595. expect(error.message).to.contain(
  596. "bolt_component. Error Code: AccountOwnedByWrongProgram"
  597. );
  598. invalid = true;
  599. }
  600. expect(invalid).to.equal(true);
  601. });
  602. it("Check component delegation", async () => {
  603. const delegateComponent = await DelegateComponent({
  604. payer: provider.wallet.publicKey,
  605. entity: entity1Pda,
  606. componentId: exampleComponentPosition.programId,
  607. });
  608. const txSign = await provider.sendAndConfirm(
  609. delegateComponent.transaction,
  610. [],
  611. { skipPreflight: true, commitment: "confirmed" }
  612. );
  613. console.log(`Delegation signature: ${txSign}`);
  614. const acc = await provider.connection.getAccountInfo(
  615. delegateComponent.componentPda
  616. );
  617. expect(acc.owner.toString()).to.equal(DELEGATION_PROGRAM_ID);
  618. });
  619. });