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