bolt.ts 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496
  1. import * as anchor from "@coral-xyz/anchor";
  2. import { Program } from "@coral-xyz/anchor";
  3. import { PublicKey } from "@solana/web3.js";
  4. import { ComponentPosition } from "../target/types/component_position";
  5. import { ComponentVelocity } from "../target/types/component_velocity";
  6. import { BoltComponent } from "../target/types/bolt_component";
  7. import { SystemSimpleMovement } from "../target/types/system_simple_movement";
  8. import { SystemFly } from "../target/types/system_fly";
  9. import { SystemApplyVelocity } from "../target/types/system_apply_velocity";
  10. import { World } from "../target/types/world";
  11. import { expect } from "chai";
  12. import BN from "bn.js";
  13. enum Direction {
  14. Left = "Left",
  15. Right = "Right",
  16. Up = "Up",
  17. Down = "Down",
  18. }
  19. function serializeArgs(args: any = {}) {
  20. const jsonString = JSON.stringify(args);
  21. const encoder = new TextEncoder();
  22. const binaryData = encoder.encode(jsonString);
  23. return Buffer.from(
  24. binaryData.buffer,
  25. binaryData.byteOffset,
  26. binaryData.byteLength
  27. );
  28. }
  29. describe("bolt", () => {
  30. const provider = anchor.AnchorProvider.env();
  31. anchor.setProvider(provider);
  32. const worldProgram = anchor.workspace.World as Program<World>;
  33. const boltComponentPositionProgram = anchor.workspace
  34. .ComponentPosition as Program<ComponentPosition>;
  35. const boltComponentVelocityProgram = anchor.workspace
  36. .ComponentVelocity as Program<ComponentVelocity>;
  37. const boltComponentProgramOrigin = anchor.workspace
  38. .BoltComponent as Program<BoltComponent>;
  39. const systemSimpleMovement = (
  40. anchor.workspace.SystemSimpleMovement as Program<SystemSimpleMovement>
  41. ).programId;
  42. const systemFly = (anchor.workspace.SystemFly as Program<SystemFly>)
  43. .programId;
  44. const applyVelocity = (
  45. anchor.workspace.SystemApplyVelocity as Program<SystemApplyVelocity>
  46. ).programId;
  47. let entity1: PublicKey;
  48. let entity2: PublicKey;
  49. let componentPositionEntity1: PublicKey;
  50. let componentPositionEntity2: PublicKey;
  51. let componentVelocityEntity1: PublicKey;
  52. it("InitializeWorldsRegistry", async () => {
  53. const registryPda = FindWorldRegistryPda(worldProgram);
  54. await worldProgram.methods
  55. .initializeRegistry()
  56. .accounts({
  57. registry: registryPda,
  58. payer: provider.wallet.publicKey,
  59. })
  60. .rpc();
  61. });
  62. it("InitializeNewWorld", async () => {
  63. const registryPda = FindWorldRegistryPda(worldProgram);
  64. const worldPda = FindWorldPda(worldProgram, new BN(0));
  65. await worldProgram.methods
  66. .initializeNewWorld()
  67. .accounts({
  68. world: worldPda,
  69. registry: registryPda,
  70. payer: provider.wallet.publicKey,
  71. })
  72. .rpc();
  73. });
  74. it("Add entity 1", async () => {
  75. const worldPda = FindWorldPda(worldProgram, new BN(0));
  76. entity1 = FindEntityPda(worldProgram, new BN(0), new BN(0));
  77. await worldProgram.methods
  78. .addEntity(null)
  79. .accounts({
  80. world: worldPda,
  81. entity: entity1,
  82. payer: provider.wallet.publicKey,
  83. })
  84. .rpc();
  85. });
  86. it("Add entity 2", async () => {
  87. const worldPda = FindWorldPda(worldProgram, new BN(0));
  88. entity2 = FindEntityPda(worldProgram, new BN(0), new BN(1));
  89. await worldProgram.methods
  90. .addEntity(null)
  91. .accounts({
  92. world: worldPda,
  93. entity: entity2,
  94. payer: provider.wallet.publicKey,
  95. })
  96. .rpc();
  97. });
  98. it("Add entity 3", async () => {
  99. const worldPda = FindWorldPda(worldProgram, new BN(0));
  100. const entityPda = FindEntityPda(worldProgram, new BN(0), new BN(2));
  101. await worldProgram.methods
  102. .addEntity(null)
  103. .accounts({
  104. world: worldPda,
  105. entity: entityPda,
  106. payer: provider.wallet.publicKey,
  107. })
  108. .rpc();
  109. });
  110. it("Add entity 4 with extra seeds", async () => {
  111. const worldPda = FindWorldPda(worldProgram, new BN(0));
  112. const seed = "extra-seed";
  113. let entity3 = FindEntityPda(worldProgram, new BN(0), new BN(3), seed);
  114. await worldProgram.methods
  115. .addEntity(seed)
  116. .accounts({
  117. world: worldPda,
  118. entity: entity3,
  119. payer: provider.wallet.publicKey,
  120. })
  121. .rpc();
  122. });
  123. it("Initialize Original Component on Entity 1, trough the world instance", async () => {
  124. let componentEntity1 = FindComponentPda(
  125. boltComponentProgramOrigin.programId,
  126. entity1,
  127. "origin-component"
  128. );
  129. await worldProgram.methods
  130. .initializeComponent()
  131. .accounts({
  132. payer: provider.wallet.publicKey,
  133. data: componentEntity1,
  134. componentProgram: boltComponentProgramOrigin.programId,
  135. entity: entity1,
  136. })
  137. .rpc();
  138. });
  139. it("Initialize Original Component on Entity 2, trough the world instance", async () => {
  140. let componentEntity2 = FindComponentPda(
  141. boltComponentProgramOrigin.programId,
  142. entity2,
  143. "origin-component"
  144. );
  145. await worldProgram.methods
  146. .initializeComponent()
  147. .accounts({
  148. payer: provider.wallet.publicKey,
  149. data: componentEntity2,
  150. componentProgram: boltComponentProgramOrigin.programId,
  151. entity: entity2,
  152. })
  153. .rpc();
  154. });
  155. it("Initialize Position Component on Entity 1", async () => {
  156. componentPositionEntity1 = FindComponentPda(
  157. boltComponentPositionProgram.programId,
  158. entity1,
  159. "component-position"
  160. );
  161. console.log("Component Position E1: ", componentPositionEntity1.toBase58());
  162. await worldProgram.methods
  163. .initializeComponent()
  164. .accounts({
  165. payer: provider.wallet.publicKey,
  166. data: componentPositionEntity1,
  167. componentProgram: boltComponentPositionProgram.programId,
  168. entity: entity1,
  169. })
  170. .rpc();
  171. });
  172. it("Initialize Velocity Component on Entity 1", async () => {
  173. componentVelocityEntity1 = FindComponentPda(
  174. boltComponentVelocityProgram.programId,
  175. entity1,
  176. "component-velocity"
  177. );
  178. await worldProgram.methods
  179. .initializeComponent()
  180. .accounts({
  181. payer: provider.wallet.publicKey,
  182. data: componentVelocityEntity1,
  183. componentProgram: boltComponentVelocityProgram.programId,
  184. entity: entity1,
  185. })
  186. .rpc();
  187. });
  188. it("Initialize Position Component on Entity 2", async () => {
  189. componentPositionEntity2 = FindComponentPda(
  190. boltComponentPositionProgram.programId,
  191. entity2,
  192. "component-position"
  193. );
  194. await worldProgram.methods
  195. .initializeComponent()
  196. .accounts({
  197. payer: provider.wallet.publicKey,
  198. data: componentPositionEntity2,
  199. componentProgram: boltComponentPositionProgram.programId,
  200. entity: entity2,
  201. })
  202. .rpc();
  203. });
  204. it("Check Position on Entity 1 is default", async () => {
  205. expect(
  206. (
  207. await boltComponentPositionProgram.account.position.fetch(
  208. componentPositionEntity1
  209. )
  210. ).x.toNumber()
  211. ).to.equal(0);
  212. expect(
  213. (
  214. await boltComponentPositionProgram.account.position.fetch(
  215. componentPositionEntity1
  216. )
  217. ).y.toNumber()
  218. ).to.equal(0);
  219. expect(
  220. (
  221. await boltComponentPositionProgram.account.position.fetch(
  222. componentPositionEntity1
  223. )
  224. ).z.toNumber()
  225. ).to.equal(0);
  226. });
  227. it("Simple Movement System and Up direction on Entity 1", async () => {
  228. const args = {
  229. direction: Direction.Up,
  230. };
  231. await worldProgram.methods
  232. .apply(serializeArgs(args)) // Move Up
  233. .accounts({
  234. componentProgram: boltComponentPositionProgram.programId,
  235. boltSystem: systemSimpleMovement,
  236. boltComponent: componentPositionEntity1,
  237. })
  238. .rpc({ skipPreflight: true });
  239. expect(
  240. (
  241. await boltComponentPositionProgram.account.position.fetch(
  242. componentPositionEntity1
  243. )
  244. ).y.toNumber()
  245. ).to.equal(1);
  246. const componentData =
  247. await boltComponentPositionProgram.account.position.fetch(
  248. componentPositionEntity1
  249. );
  250. const x = componentData.x.toNumber();
  251. const y = componentData.y.toNumber();
  252. const z = componentData.z.toNumber();
  253. console.log("+-----------------------------+");
  254. console.log("| Movement System: Entity 1 |");
  255. console.log("+----------------+------------+");
  256. console.log("| Coordinate | Value |");
  257. console.log("+----------------+------------+");
  258. console.log(`| X Position | ${String(x).padEnd(10, " ")} |`);
  259. console.log("| | |");
  260. console.log(`| Y Position | ${String(y).padEnd(10, " ")} |`);
  261. console.log("| | |");
  262. console.log(`| Z Position | ${String(z).padEnd(10, " ")} |`);
  263. console.log("+----------------+------------+");
  264. console.log("| |");
  265. console.log("+-----------------------------+");
  266. });
  267. it("Simple Movement System and Right direction on Entity 1", async () => {
  268. const args = {
  269. direction: Direction.Right,
  270. };
  271. await worldProgram.methods
  272. .apply(serializeArgs(args)) // Move Right
  273. .accounts({
  274. componentProgram: boltComponentPositionProgram.programId,
  275. boltSystem: systemSimpleMovement,
  276. boltComponent: componentPositionEntity1,
  277. })
  278. .rpc({ skipPreflight: true });
  279. expect(
  280. (
  281. await boltComponentPositionProgram.account.position.fetch(
  282. componentPositionEntity1
  283. )
  284. ).y.toNumber()
  285. ).to.equal(1);
  286. expect(
  287. (
  288. await boltComponentPositionProgram.account.position.fetch(
  289. componentPositionEntity1
  290. )
  291. ).y.toNumber()
  292. ).to.equal(1);
  293. const componentData =
  294. await boltComponentPositionProgram.account.position.fetch(
  295. componentPositionEntity1
  296. );
  297. const x = componentData.x.toNumber();
  298. const y = componentData.y.toNumber();
  299. const z = componentData.z.toNumber();
  300. console.log("+-----------------------------+");
  301. console.log("| Movement System: Entity 1 |");
  302. console.log("+----------------+------------+");
  303. console.log("| Coordinate | Value |");
  304. console.log("+----------------+------------+");
  305. console.log(`| X Position | ${String(x).padEnd(10, " ")} |`);
  306. console.log("| | |");
  307. console.log(`| Y Position | ${String(y).padEnd(10, " ")} |`);
  308. console.log("| | |");
  309. console.log(`| Z Position | ${String(z).padEnd(10, " ")} |`);
  310. console.log("+----------------+------------+");
  311. console.log("| |");
  312. console.log("+-----------------------------+");
  313. });
  314. it("Fly System on Entity 1", async () => {
  315. await worldProgram.methods
  316. .apply(Buffer.alloc(0)) // Move Up
  317. .accounts({
  318. componentProgram: boltComponentPositionProgram.programId,
  319. boltSystem: systemFly,
  320. boltComponent: componentPositionEntity1,
  321. })
  322. .rpc();
  323. expect(
  324. (
  325. await boltComponentPositionProgram.account.position.fetch(
  326. componentPositionEntity1
  327. )
  328. ).z.toNumber()
  329. ).to.equal(1);
  330. const componentData =
  331. await boltComponentPositionProgram.account.position.fetch(
  332. componentPositionEntity1
  333. );
  334. const x = componentData.x.toNumber();
  335. const y = componentData.y.toNumber();
  336. const z = componentData.z.toNumber();
  337. console.log("+-----------------------------+");
  338. console.log("| Fly: Position Entity 1 |");
  339. console.log("+----------------+------------+");
  340. console.log("| Coordinate | Value |");
  341. console.log("+----------------+------------+");
  342. console.log(`| X Position | ${String(x).padEnd(10, " ")} |`);
  343. console.log("| | |");
  344. console.log(`| Y Position | ${String(y).padEnd(10, " ")} |`);
  345. console.log("| | |");
  346. console.log(`| Z Position | ${String(z).padEnd(10, " ")} |`);
  347. console.log("+----------------+------------+");
  348. console.log("| |");
  349. console.log("+-----------------------------+");
  350. });
  351. it("Apply Velocity on Entity 1", async () => {
  352. await worldProgram.methods
  353. .apply2(Buffer.alloc(0))
  354. .accounts({
  355. componentProgram1: boltComponentVelocityProgram.programId,
  356. componentProgram2: boltComponentPositionProgram.programId,
  357. boltSystem: applyVelocity,
  358. boltComponent1: componentVelocityEntity1,
  359. boltComponent2: componentPositionEntity1,
  360. })
  361. .remainingAccounts([
  362. {
  363. pubkey: componentPositionEntity1,
  364. isWritable: false,
  365. isSigner: false,
  366. },
  367. ])
  368. .rpc();
  369. console.log("Component Velocity: ", componentVelocityEntity1.toBase58());
  370. let componentData =
  371. await boltComponentVelocityProgram.account.velocity.fetch(
  372. componentVelocityEntity1
  373. );
  374. let x = componentData.x.toNumber();
  375. let y = componentData.y.toNumber();
  376. let z = componentData.z.toNumber();
  377. const tmp = componentData.lastApplied.toNumber();
  378. console.log("+-----------------------------+");
  379. console.log("| Apply Velocity: Velocity Entity 1 |");
  380. console.log("+----------------+------------+");
  381. console.log("| Coordinate | Value |");
  382. console.log("+----------------+------------+");
  383. console.log(`| X Position | ${String(x).padEnd(10, " ")} |`);
  384. console.log("| | |");
  385. console.log(`| Y Position | ${String(y).padEnd(10, " ")} |`);
  386. console.log("| | |");
  387. console.log(`| Z Position | ${String(z).padEnd(10, " ")} |`);
  388. console.log("| | |");
  389. console.log(`| Timestamp | ${String(tmp).padEnd(10, " ")} |`);
  390. console.log("+----------------+------------+");
  391. console.log("| |");
  392. console.log("+-----------------------------+");
  393. let positionData =
  394. await boltComponentPositionProgram.account.position.fetch(
  395. componentPositionEntity1
  396. );
  397. x = positionData.x.toNumber();
  398. y = positionData.y.toNumber();
  399. z = positionData.z.toNumber();
  400. console.log("+-----------------------------+");
  401. console.log("| Apply Velocity: Position Entity 1 |");
  402. console.log("+----------------+------------+");
  403. console.log("| Coordinate | Value |");
  404. console.log("+----------------+------------+");
  405. console.log(`| X Position | ${String(x).padEnd(10, " ")} |`);
  406. console.log("| | |");
  407. console.log(`| Y Position | ${String(y).padEnd(10, " ")} |`);
  408. console.log("| | |");
  409. console.log(`| Z Position | ${String(z).padEnd(10, " ")} |`);
  410. console.log("+----------------+------------+");
  411. console.log("| |");
  412. console.log("+-----------------------------+");
  413. });
  414. // Utils
  415. function FindWorldRegistryPda(program: Program<World>) {
  416. return PublicKey.findProgramAddressSync(
  417. [Buffer.from("registry")],
  418. program.programId
  419. )[0];
  420. }
  421. function FindWorldPda(program: Program<World>, id: BN) {
  422. return PublicKey.findProgramAddressSync(
  423. [Buffer.from("world"), id.toBuffer("le", 8)],
  424. program.programId
  425. )[0];
  426. }
  427. function FindEntityPda(
  428. program: Program<World>,
  429. worldId: BN,
  430. entityId: BN,
  431. extraSeed?: string
  432. ) {
  433. let seeds = [Buffer.from("entity"), worldId.toBuffer("be", 8)];
  434. if (extraSeed) {
  435. seeds.push(Buffer.from(new Uint8Array(8)));
  436. seeds.push(Buffer.from(extraSeed));
  437. } else {
  438. seeds.push(entityId.toBuffer("be", 8));
  439. }
  440. return PublicKey.findProgramAddressSync(seeds, program.programId)[0];
  441. }
  442. function FindComponentPda(
  443. program: PublicKey,
  444. entity: PublicKey,
  445. seed: string = "component"
  446. ) {
  447. return PublicKey.findProgramAddressSync(
  448. [Buffer.from(seed), entity.toBytes()],
  449. program
  450. )[0];
  451. }
  452. });