test.ts 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. import {
  2. Keypair,
  3. PublicKey,
  4. SystemProgram,
  5. Transaction,
  6. TransactionInstruction,
  7. } from '@solana/web3.js';
  8. import * as borsh from "borsh";
  9. import { Buffer } from "buffer";
  10. import { describe, test } from 'node:test';
  11. import { start } from 'solana-bankrun';
  12. describe("PDAs", async () => {
  13. const PROGRAM_ID = PublicKey.unique();
  14. const context = await start([{ name: 'program_derived_addresses_program', programId: PROGRAM_ID }],[]);
  15. const client = context.banksClient;
  16. const payer = context.payer;
  17. const rent = await client.getRent();
  18. class Assignable {
  19. constructor(properties) {
  20. Object.keys(properties).map((key) => {
  21. return (this[key] = properties[key]);
  22. });
  23. };
  24. };
  25. class PageVisits extends Assignable {
  26. toBuffer() { return Buffer.from(borsh.serialize(PageVisitsSchema, this)) }
  27. static fromBuffer(buffer: Buffer) {
  28. return borsh.deserialize(PageVisitsSchema, PageVisits, buffer);
  29. };
  30. };
  31. const PageVisitsSchema = new Map([
  32. [ PageVisits, {
  33. kind: 'struct',
  34. fields: [ ['page_visits', 'u32'], ['bump', 'u8'] ],
  35. }]
  36. ]);
  37. class IncrementPageVisits extends Assignable {
  38. toBuffer() { return Buffer.from(borsh.serialize(IncrementPageVisitsSchema, this)) }
  39. };
  40. const IncrementPageVisitsSchema = new Map([
  41. [ IncrementPageVisits, {
  42. kind: 'struct',
  43. fields: [],
  44. }]
  45. ]);
  46. const testUser = Keypair.generate();
  47. test("Create a test user", async () => {
  48. let ix = SystemProgram.createAccount({
  49. fromPubkey: payer.publicKey,
  50. lamports: Number(rent.minimumBalance(BigInt(0))),
  51. newAccountPubkey: testUser.publicKey,
  52. programId: SystemProgram.programId,
  53. space: 0,
  54. });
  55. const tx = new Transaction();
  56. const blockhash = context.lastBlockhash;
  57. tx.recentBlockhash = blockhash;
  58. tx.add(ix).sign(payer, testUser); // Add instruction and Sign the transaction
  59. await client.processTransaction(tx);
  60. console.log(`Local Wallet: ${payer.publicKey}`);
  61. console.log(`Created User: ${testUser.publicKey}`);
  62. });
  63. function derivePageVisitsPda(userPubkey: PublicKey) {
  64. return PublicKey.findProgramAddressSync(
  65. [Buffer.from("page_visits"), userPubkey.toBuffer()],
  66. PROGRAM_ID,
  67. )
  68. }
  69. test("Create the page visits tracking PDA", async () => {
  70. const [pageVisitsPda, pageVisitsBump] = derivePageVisitsPda(testUser.publicKey);
  71. let ix = new TransactionInstruction({
  72. keys: [
  73. {pubkey: pageVisitsPda, isSigner: false, isWritable: true},
  74. {pubkey: testUser.publicKey, isSigner: false, isWritable: false},
  75. {pubkey: payer.publicKey, isSigner: true, isWritable: true},
  76. {pubkey: SystemProgram.programId, isSigner: false, isWritable: false}
  77. ],
  78. programId: PROGRAM_ID,
  79. data: (new PageVisits({page_visits: 0, bump: pageVisitsBump})).toBuffer(),
  80. });
  81. const tx = new Transaction();
  82. const blockhash = context.lastBlockhash;
  83. tx.recentBlockhash = blockhash;
  84. tx.add(ix).sign(payer);
  85. await client.processTransaction(tx);
  86. });
  87. test("Visit the page!", async () => {
  88. const [pageVisitsPda, _] = derivePageVisitsPda(testUser.publicKey);
  89. let ix = new TransactionInstruction({
  90. keys: [
  91. {pubkey: pageVisitsPda, isSigner: false, isWritable: true},
  92. {pubkey: payer.publicKey, isSigner: true, isWritable: true},
  93. ],
  94. programId: PROGRAM_ID,
  95. data: new IncrementPageVisits({}).toBuffer(),
  96. });
  97. const tx = new Transaction();
  98. const blockhash = context.lastBlockhash;
  99. tx.recentBlockhash = blockhash;
  100. tx.add(ix).sign(payer);
  101. await client.processTransaction(tx);
  102. });
  103. // commented because couldn't get different blockhash
  104. test("Visit the page!", async () => {
  105. const [pageVisitsPda, _] = derivePageVisitsPda(testUser.publicKey);
  106. let ix = new TransactionInstruction({
  107. keys: [
  108. {pubkey: pageVisitsPda, isSigner: false, isWritable: true},
  109. {pubkey: payer.publicKey, isSigner: true, isWritable: true},
  110. ],
  111. programId: PROGRAM_ID,
  112. data: new IncrementPageVisits({}).toBuffer(),
  113. });
  114. const tx = new Transaction();
  115. const [blockhash, _block_height] = await client.getLatestBlockhash();
  116. tx.recentBlockhash = blockhash;
  117. tx.add(ix).sign(payer);
  118. await client.processTransaction(tx);
  119. });
  120. test("Read page visits", async () => {
  121. const [pageVisitsPda, _] = derivePageVisitsPda(testUser.publicKey);
  122. const accountInfo = await client.getAccount(pageVisitsPda);
  123. const readPageVisits = PageVisits.fromBuffer(Buffer.from(accountInfo.data));
  124. console.log(`Number of page visits: ${readPageVisits.page_visits}`);
  125. });
  126. });