|
1 | 1 | import { Buffer } from "node:buffer"; |
2 | | -import { |
3 | | - Connection, |
4 | | - Keypair, |
5 | | - SystemProgram, |
6 | | - sendAndConfirmTransaction, |
7 | | - Transaction, |
8 | | - TransactionInstruction, |
9 | | -} from "@solana/web3.js"; |
| 2 | +import * as fs from "node:fs"; |
| 3 | +import * as path from "node:path"; |
| 4 | +import { before, describe, it } from "node:test"; |
| 5 | +import { Keypair, SystemProgram, Transaction, TransactionInstruction } from "@solana/web3.js"; |
10 | 6 | import * as borsh from "borsh"; |
| 7 | +import { LiteSVM, TransactionMetadata } from "litesvm"; |
11 | 8 |
|
12 | | -function createKeypairFromFile(path: string): Keypair { |
13 | | - return Keypair.fromSecretKey(Uint8Array.from(JSON.parse(require("node:fs").readFileSync(path, "utf-8")))); |
| 9 | +const PowerStatusSchema = { struct: { is_on: "u8" } }; |
| 10 | +const SetPowerStatusSchema = { struct: { name: "string" } }; |
| 11 | + |
| 12 | +function borshSerialize(schema: borsh.Schema, data: object): Buffer { |
| 13 | + return Buffer.from(borsh.serialize(schema, data)); |
14 | 14 | } |
15 | 15 |
|
16 | | -describe("CPI Example", () => { |
17 | | - const connection = new Connection("http://localhost:8899", "confirmed"); |
18 | | - const payer = createKeypairFromFile(`${require("node:os").homedir()}/.config/solana/id.json`); |
19 | | - const hand = createKeypairFromFile("./target/so/hand-keypair.json"); |
20 | | - const lever = createKeypairFromFile("./target/so/lever-keypair.json"); |
| 16 | +describe("Native CPI Example", () => { |
| 17 | + let svm: LiteSVM; |
| 18 | + let payer: Keypair; |
| 19 | + let handProgramId: Keypair; |
| 20 | + let leverProgramId: Keypair; |
| 21 | + let powerAccount: Keypair; |
| 22 | + |
| 23 | + before(() => { |
| 24 | + svm = new LiteSVM(); |
| 25 | + payer = Keypair.generate(); |
| 26 | + |
| 27 | + handProgramId = Keypair.fromSecretKey( |
| 28 | + Uint8Array.from( |
| 29 | + JSON.parse(fs.readFileSync("./tests/fixtures/cross_program_invocatio_native_hand-keypair.json", "utf-8")), |
| 30 | + ), |
| 31 | + ); |
| 32 | + leverProgramId = Keypair.fromSecretKey( |
| 33 | + Uint8Array.from( |
| 34 | + JSON.parse(fs.readFileSync("./tests/fixtures/cross_program_invocatio_native_lever-keypair.json", "utf-8")), |
| 35 | + ), |
| 36 | + ); |
| 37 | + |
| 38 | + svm.airdrop(payer.publicKey, BigInt(10 * 1_000_000_000)); |
21 | 39 |
|
22 | | - const PowerStatusSchema = { struct: { is_on: "u8" } }; |
23 | | - const SetPowerStatusSchema = { struct: { name: "string" } }; |
| 40 | + const native_hand = path.join("./tests/fixtures", "cross_program_invocatio_native_hand.so"); |
| 41 | + const native_lever = path.join("./tests/fixtures", "cross_program_invocatio_native_lever.so"); |
24 | 42 |
|
25 | | - function borshSerialize(schema: borsh.Schema, data: object): Buffer { |
26 | | - return Buffer.from(borsh.serialize(schema, data)); |
27 | | - } |
| 43 | + svm.addProgramFromFile(handProgramId.publicKey, native_hand); |
| 44 | + svm.addProgramFromFile(leverProgramId.publicKey, native_lever); |
28 | 45 |
|
29 | | - const powerAccount = Keypair.generate(); |
| 46 | + powerAccount = Keypair.generate(); |
| 47 | + }); |
30 | 48 |
|
31 | | - it("Initialize the lever!", async () => { |
| 49 | + it("Initialize the lever!", () => { |
32 | 50 | const ix = new TransactionInstruction({ |
33 | 51 | keys: [ |
34 | 52 | { pubkey: powerAccount.publicKey, isSigner: true, isWritable: true }, |
35 | 53 | { pubkey: payer.publicKey, isSigner: true, isWritable: true }, |
36 | 54 | { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, |
37 | 55 | ], |
38 | | - programId: lever.publicKey, |
39 | | - data: borshSerialize(PowerStatusSchema, { is_on: true }), |
| 56 | + programId: leverProgramId.publicKey, |
| 57 | + data: borshSerialize(PowerStatusSchema, { is_on: 1 }), |
40 | 58 | }); |
41 | 59 |
|
42 | | - await sendAndConfirmTransaction(connection, new Transaction().add(ix), [payer, powerAccount]); |
| 60 | + const tx = new Transaction(); |
| 61 | + tx.recentBlockhash = svm.latestBlockhash(); |
| 62 | + tx.feePayer = payer.publicKey; |
| 63 | + tx.add(ix); |
| 64 | + tx.sign(payer, powerAccount); |
| 65 | + |
| 66 | + const res = svm.sendTransaction(tx); |
| 67 | + if (!(res instanceof TransactionMetadata)) { |
| 68 | + throw new Error(`Transaction failed: ${res.meta().toString()}`); |
| 69 | + } |
43 | 70 | }); |
44 | 71 |
|
45 | | - it("Pull the lever!", async () => { |
| 72 | + it("Pull the lever!", () => { |
46 | 73 | const ix = new TransactionInstruction({ |
47 | 74 | keys: [ |
48 | 75 | { pubkey: powerAccount.publicKey, isSigner: false, isWritable: true }, |
49 | | - { pubkey: lever.publicKey, isSigner: false, isWritable: false }, |
| 76 | + { pubkey: leverProgramId.publicKey, isSigner: false, isWritable: false }, |
50 | 77 | ], |
51 | | - programId: hand.publicKey, |
| 78 | + programId: handProgramId.publicKey, |
52 | 79 | data: borshSerialize(SetPowerStatusSchema, { name: "Chris" }), |
53 | 80 | }); |
54 | 81 |
|
55 | | - await sendAndConfirmTransaction(connection, new Transaction().add(ix), [payer]); |
| 82 | + const tx = new Transaction(); |
| 83 | + tx.recentBlockhash = svm.latestBlockhash(); |
| 84 | + tx.feePayer = payer.publicKey; |
| 85 | + tx.add(ix); |
| 86 | + tx.sign(payer); |
| 87 | + |
| 88 | + const res = svm.sendTransaction(tx); |
| 89 | + if (!(res instanceof TransactionMetadata)) { |
| 90 | + throw new Error(`Transaction failed: ${res.meta().toString()}`); |
| 91 | + } |
56 | 92 | }); |
57 | 93 |
|
58 | | - it("Pull it again!", async () => { |
| 94 | + it("Pull it again!", () => { |
59 | 95 | const ix = new TransactionInstruction({ |
60 | 96 | keys: [ |
61 | 97 | { pubkey: powerAccount.publicKey, isSigner: false, isWritable: true }, |
62 | | - { pubkey: lever.publicKey, isSigner: false, isWritable: false }, |
| 98 | + { pubkey: leverProgramId.publicKey, isSigner: false, isWritable: false }, |
63 | 99 | ], |
64 | | - programId: hand.publicKey, |
| 100 | + programId: handProgramId.publicKey, |
65 | 101 | data: borshSerialize(SetPowerStatusSchema, { name: "Ashley" }), |
66 | 102 | }); |
67 | 103 |
|
68 | | - await sendAndConfirmTransaction(connection, new Transaction().add(ix), [payer]); |
| 104 | + const tx = new Transaction(); |
| 105 | + tx.recentBlockhash = svm.latestBlockhash(); |
| 106 | + tx.feePayer = payer.publicKey; |
| 107 | + tx.add(ix); |
| 108 | + tx.sign(payer); |
| 109 | + |
| 110 | + const res = svm.sendTransaction(tx); |
| 111 | + if (!(res instanceof TransactionMetadata)) { |
| 112 | + throw new Error(`Transaction failed: ${res.meta().toString()}`); |
| 113 | + } |
69 | 114 | }); |
70 | 115 | }); |
0 commit comments