solforge 0.2.8 → 0.2.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/scripts/decode-b58.ts +5 -1
- package/server/lib/instruction-parser.ts +302 -238
- package/server/lib/parsers/spl-associated-token-account.ts +36 -30
- package/server/lib/parsers/spl-token.ts +285 -142
- package/server/methods/account/request-airdrop.ts +121 -105
- package/server/methods/admin/mint-to.ts +29 -14
- package/server/methods/transaction/get-transaction.ts +390 -326
- package/server/methods/transaction/inner-instructions.test.ts +91 -50
- package/server/methods/transaction/send-transaction.ts +269 -236
- package/server/rpc-server.ts +101 -104
- package/server/types.ts +56 -56
- package/src/db/schema/transactions.ts +29 -29
- package/src/db/schema/tx-account-states.ts +16 -14
- package/src/db/tx-store.ts +97 -99
- package/src/migrations-bundled.ts +4 -4
|
@@ -1,63 +1,104 @@
|
|
|
1
1
|
import { test, expect } from "bun:test";
|
|
2
2
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
Keypair,
|
|
4
|
+
LAMPORTS_PER_SOL,
|
|
5
|
+
TransactionMessage,
|
|
6
|
+
VersionedTransaction,
|
|
7
|
+
PublicKey,
|
|
8
8
|
} from "@solana/web3.js";
|
|
9
9
|
import {
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
getAssociatedTokenAddress,
|
|
11
|
+
createAssociatedTokenAccountInstruction,
|
|
12
12
|
} from "@solana/spl-token";
|
|
13
13
|
import { LiteSVMRpcServer } from "../../rpc-server";
|
|
14
14
|
|
|
15
|
-
type RpcResp<T =
|
|
15
|
+
type RpcResp<T = unknown> = {
|
|
16
|
+
jsonrpc: "2.0";
|
|
17
|
+
id: number;
|
|
18
|
+
result?: T;
|
|
19
|
+
error?: { code: number; message: string; data?: unknown };
|
|
20
|
+
};
|
|
16
21
|
|
|
17
22
|
function jsonReq(method: string, params?: unknown) {
|
|
18
|
-
|
|
23
|
+
return {
|
|
24
|
+
jsonrpc: "2.0",
|
|
25
|
+
id: Math.floor(Math.random() * 1e9),
|
|
26
|
+
method,
|
|
27
|
+
params,
|
|
28
|
+
};
|
|
19
29
|
}
|
|
20
30
|
|
|
21
31
|
test("captures inner instructions for ATA create (CPI)", async () => {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
32
|
+
const server = new LiteSVMRpcServer();
|
|
33
|
+
async function call<T = unknown>(
|
|
34
|
+
method: string,
|
|
35
|
+
params?: unknown,
|
|
36
|
+
): Promise<RpcResp<T>> {
|
|
37
|
+
return (await server.handleRequest(jsonReq(method, params))) as RpcResp<T>;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Payer + airdrop
|
|
41
|
+
const payer = Keypair.generate();
|
|
42
|
+
const recip = Keypair.generate();
|
|
43
|
+
await call("requestAirdrop", [
|
|
44
|
+
payer.publicKey.toBase58(),
|
|
45
|
+
1 * LAMPORTS_PER_SOL,
|
|
46
|
+
]);
|
|
47
|
+
|
|
48
|
+
// Create a test mint via admin helper
|
|
49
|
+
const mintResp = await call<{ mint: string }>("solforgeCreateMint", [
|
|
50
|
+
null,
|
|
51
|
+
6,
|
|
52
|
+
null,
|
|
53
|
+
]);
|
|
54
|
+
expect(mintResp.error).toBeUndefined();
|
|
55
|
+
const mint = new PublicKey(mintResp.result?.mint);
|
|
56
|
+
|
|
57
|
+
// Build 1 ATA instruction that triggers CPIs into system + token
|
|
58
|
+
const bh = await call<{ value: { blockhash: string } }>(
|
|
59
|
+
"getLatestBlockhash",
|
|
60
|
+
[],
|
|
61
|
+
);
|
|
62
|
+
const ata = await getAssociatedTokenAddress(mint, recip.publicKey, false);
|
|
63
|
+
const ix = createAssociatedTokenAccountInstruction(
|
|
64
|
+
payer.publicKey,
|
|
65
|
+
ata,
|
|
66
|
+
recip.publicKey,
|
|
67
|
+
mint,
|
|
68
|
+
);
|
|
69
|
+
const msg = new TransactionMessage({
|
|
70
|
+
payerKey: payer.publicKey,
|
|
71
|
+
recentBlockhash: bh.result?.value.blockhash,
|
|
72
|
+
instructions: [ix],
|
|
73
|
+
}).compileToLegacyMessage();
|
|
74
|
+
const tx = new VersionedTransaction(msg);
|
|
75
|
+
tx.sign([payer]);
|
|
76
|
+
|
|
77
|
+
const sigResp = await call<string>("sendTransaction", [
|
|
78
|
+
Buffer.from(tx.serialize()).toString("base64"),
|
|
79
|
+
]);
|
|
80
|
+
expect(sigResp.error).toBeUndefined();
|
|
81
|
+
const sig = sigResp.result;
|
|
82
|
+
|
|
83
|
+
const txResp = await call<unknown>("getTransaction", [
|
|
84
|
+
sig,
|
|
85
|
+
{ encoding: "json" },
|
|
86
|
+
]);
|
|
87
|
+
expect(txResp.error).toBeUndefined();
|
|
88
|
+
type TxResp = {
|
|
89
|
+
transaction: { message: { instructions: unknown[] } };
|
|
90
|
+
meta: { innerInstructions: unknown[]; logMessages?: string[] };
|
|
91
|
+
};
|
|
92
|
+
const tr = txResp.result as TxResp;
|
|
93
|
+
|
|
94
|
+
// At least one top-level instruction
|
|
95
|
+
expect(Array.isArray(tr.transaction.message.instructions)).toBe(true);
|
|
96
|
+
expect(tr.transaction.message.instructions.length).toBe(1);
|
|
97
|
+
|
|
98
|
+
// Check inner instructions captured or (worst case) logs exist
|
|
99
|
+
const ii = tr.meta.innerInstructions;
|
|
100
|
+
const logs = tr.meta.logMessages || [];
|
|
101
|
+
expect(Array.isArray(ii)).toBe(true);
|
|
102
|
+
// At minimum, either we have structured inner ixs, or logs were captured
|
|
103
|
+
expect(ii.length > 0 || logs.length > 0).toBe(true);
|
|
63
104
|
});
|