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.
@@ -150,36 +150,34 @@ export class LiteSVMRpcServer {
150
150
  } catch {}
151
151
  },
152
152
  listPrograms: () => Array.from(this.knownPrograms),
153
- recordTransaction: (signature, tx, meta) => {
154
- this.txRecords.set(signature, {
155
- tx,
156
- logs: meta?.logs || [],
157
- err: meta?.err ?? null,
158
- fee: meta?.fee ?? 5000,
159
- slot: Number(this.slot),
160
- blockTime: meta?.blockTime,
161
- preBalances: meta?.preBalances,
162
- postBalances: meta?.postBalances,
163
- preTokenBalances: (
164
- meta as { preTokenBalances?: unknown[] } | undefined
165
- )?.preTokenBalances,
166
- postTokenBalances: (
167
- meta as { postTokenBalances?: unknown[] } | undefined
168
- )?.postTokenBalances,
169
- innerInstructions: meta?.innerInstructions || [],
170
- computeUnits:
171
- meta?.computeUnits == null
172
- ? null
173
- : Number(meta.computeUnits),
174
- returnData: meta?.returnData ?? null,
175
- });
176
- try {
177
- if (process.env.DEBUG_TX_CAPTURE === "1") {
178
- console.debug(
179
- `[tx-capture] recordTransaction: sig=${signature} slot=${this.slot} logs=${meta?.logs?.length || 0} inner=${Array.isArray(meta?.innerInstructions) ? meta?.innerInstructions?.length : 0} cu=${meta?.computeUnits ?? null} returnData=${meta?.returnData ? "yes" : "no"}`,
180
- );
181
- }
182
- } catch {}
153
+ recordTransaction: (signature, tx, meta) => {
154
+ this.txRecords.set(signature, {
155
+ tx,
156
+ logs: meta?.logs || [],
157
+ err: meta?.err ?? null,
158
+ fee: meta?.fee ?? 5000,
159
+ slot: Number(this.slot),
160
+ blockTime: meta?.blockTime,
161
+ preBalances: meta?.preBalances,
162
+ postBalances: meta?.postBalances,
163
+ preTokenBalances: (
164
+ meta as { preTokenBalances?: unknown[] } | undefined
165
+ )?.preTokenBalances,
166
+ postTokenBalances: (
167
+ meta as { postTokenBalances?: unknown[] } | undefined
168
+ )?.postTokenBalances,
169
+ innerInstructions: meta?.innerInstructions || [],
170
+ computeUnits:
171
+ meta?.computeUnits == null ? null : Number(meta.computeUnits),
172
+ returnData: meta?.returnData ?? null,
173
+ });
174
+ try {
175
+ if (process.env.DEBUG_TX_CAPTURE === "1") {
176
+ console.debug(
177
+ `[tx-capture] recordTransaction: sig=${signature} slot=${this.slot} logs=${meta?.logs?.length || 0} inner=${Array.isArray(meta?.innerInstructions) ? meta?.innerInstructions?.length : 0} cu=${meta?.computeUnits ?? null} returnData=${meta?.returnData ? "yes" : "no"}`,
178
+ );
179
+ }
180
+ } catch {}
183
181
 
184
182
  // Persist to SQLite for durability and history queries
185
183
  try {
@@ -240,82 +238,81 @@ export class LiteSVMRpcServer {
240
238
  : "legacy"
241
239
  : 0;
242
240
  const rawBase64 = Buffer.from(tx.serialize()).toString("base64");
243
- this.store
244
- .insertTransactionBundle({
245
- signature,
246
- slot: Number(this.slot),
247
- blockTime: meta?.blockTime,
248
- version,
249
- fee: Number(meta?.fee ?? 5000),
250
- err: meta?.err ?? null,
251
- rawBase64,
252
- preBalances: Array.isArray(meta?.preBalances)
253
- ? (meta?.preBalances as number[])
254
- : [],
255
- postBalances: Array.isArray(meta?.postBalances)
256
- ? (meta?.postBalances as number[])
257
- : [],
258
- logs: Array.isArray(meta?.logs) ? (meta?.logs as string[]) : [],
259
- preTokenBalances: (() => {
260
- const arr = (
261
- meta as { preTokenBalances?: unknown[] } | undefined
262
- )?.preTokenBalances;
263
- return Array.isArray(arr) ? arr : [];
264
- })(),
265
- postTokenBalances: (() => {
266
- const arr = (
267
- meta as { postTokenBalances?: unknown[] } | undefined
268
- )?.postTokenBalances;
269
- return Array.isArray(arr) ? arr : [];
270
- })(),
271
- innerInstructions: Array.isArray(meta?.innerInstructions)
272
- ? meta?.innerInstructions
273
- : [],
274
- computeUnits:
275
- meta?.computeUnits == null
276
- ? null
277
- : Number(meta.computeUnits),
278
- returnData: meta?.returnData ?? null,
279
- accounts,
280
- accountStates: Array.isArray(meta?.accountStates)
281
- ? meta?.accountStates
282
- : [],
283
- })
284
- .catch(() => {});
241
+ this.store
242
+ .insertTransactionBundle({
243
+ signature,
244
+ slot: Number(this.slot),
245
+ blockTime: meta?.blockTime,
246
+ version,
247
+ fee: Number(meta?.fee ?? 5000),
248
+ err: meta?.err ?? null,
249
+ rawBase64,
250
+ preBalances: Array.isArray(meta?.preBalances)
251
+ ? (meta?.preBalances as number[])
252
+ : [],
253
+ postBalances: Array.isArray(meta?.postBalances)
254
+ ? (meta?.postBalances as number[])
255
+ : [],
256
+ logs: Array.isArray(meta?.logs) ? (meta?.logs as string[]) : [],
257
+ preTokenBalances: (() => {
258
+ const arr = (
259
+ meta as { preTokenBalances?: unknown[] } | undefined
260
+ )?.preTokenBalances;
261
+ return Array.isArray(arr) ? arr : [];
262
+ })(),
263
+ postTokenBalances: (() => {
264
+ const arr = (
265
+ meta as { postTokenBalances?: unknown[] } | undefined
266
+ )?.postTokenBalances;
267
+ return Array.isArray(arr) ? arr : [];
268
+ })(),
269
+ innerInstructions: Array.isArray(meta?.innerInstructions)
270
+ ? meta?.innerInstructions
271
+ : [],
272
+ computeUnits:
273
+ meta?.computeUnits == null ? null : Number(meta.computeUnits),
274
+ returnData: meta?.returnData ?? null,
275
+ accounts,
276
+ accountStates: Array.isArray(meta?.accountStates)
277
+ ? meta?.accountStates
278
+ : [],
279
+ })
280
+ .catch(() => {});
285
281
 
286
282
  // Upsert account snapshots for static keys
287
- const snapshots = keys
288
- .map((addr) => {
289
- try {
290
- const acc = this.svm.getAccount(new PublicKey(addr));
291
- if (!acc) return null;
292
- const ownerStr = new PublicKey(acc.owner).toBase58();
293
- let dataBase64: string | undefined;
294
- // Store raw data for SPL Token accounts to reflect balance changes
295
- try {
296
- if (
297
- ownerStr === "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" ||
298
- ownerStr === "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb"
299
- ) {
300
- if (acc.data && acc.data.length > 0) {
301
- dataBase64 = Buffer.from(acc.data).toString("base64");
302
- }
303
- }
304
- } catch {}
305
- return {
306
- address: addr,
307
- lamports: Number(acc.lamports || 0n),
308
- ownerProgram: ownerStr,
309
- executable: !!acc.executable,
310
- rentEpoch: Number(acc.rentEpoch || 0),
311
- dataLen: acc.data?.length ?? 0,
312
- dataBase64,
313
- lastSlot: Number(this.slot),
314
- };
315
- } catch {
316
- return null;
317
- }
318
- })
283
+ const snapshots = keys
284
+ .map((addr) => {
285
+ try {
286
+ const acc = this.svm.getAccount(new PublicKey(addr));
287
+ if (!acc) return null;
288
+ const ownerStr = new PublicKey(acc.owner).toBase58();
289
+ let dataBase64: string | undefined;
290
+ // Store raw data for SPL Token accounts to reflect balance changes
291
+ try {
292
+ if (
293
+ ownerStr ===
294
+ "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" ||
295
+ ownerStr === "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb"
296
+ ) {
297
+ if (acc.data && acc.data.length > 0) {
298
+ dataBase64 = Buffer.from(acc.data).toString("base64");
299
+ }
300
+ }
301
+ } catch {}
302
+ return {
303
+ address: addr,
304
+ lamports: Number(acc.lamports || 0n),
305
+ ownerProgram: ownerStr,
306
+ executable: !!acc.executable,
307
+ rentEpoch: Number(acc.rentEpoch || 0),
308
+ dataLen: acc.data?.length ?? 0,
309
+ dataBase64,
310
+ lastSlot: Number(this.slot),
311
+ };
312
+ } catch {
313
+ return null;
314
+ }
315
+ })
319
316
  .filter(Boolean) as import("../src/db/tx-store").AccountSnapshot[];
320
317
  if (snapshots.length > 0)
321
318
  this.store.upsertAccounts(snapshots).catch(() => {});
package/server/types.ts CHANGED
@@ -44,62 +44,62 @@ export interface RpcMethodContext {
44
44
  listMints?: () => string[];
45
45
  registerProgram?: (program: PublicKey | string) => void;
46
46
  listPrograms?: () => string[];
47
- recordTransaction: (
48
- signature: string,
49
- tx: VersionedTransaction,
50
- meta?: {
51
- logs?: string[];
52
- err?: unknown;
53
- fee?: number;
54
- blockTime?: number;
55
- preBalances?: number[];
56
- postBalances?: number[];
57
- preTokenBalances?: unknown[];
58
- postTokenBalances?: unknown[];
59
- innerInstructions?: unknown[];
60
- computeUnits?: number | bigint | null;
61
- returnData?: { programId: string; dataBase64: string } | null;
62
- // Optional rich per-account snapshots captured around execution
63
- accountStates?: Array<{
64
- address: string;
65
- pre?: {
66
- lamports?: number;
67
- ownerProgram?: string;
68
- executable?: boolean;
69
- rentEpoch?: number;
70
- dataLen?: number;
71
- dataBase64?: string | null;
72
- lastSlot?: number;
73
- } | null;
74
- post?: {
75
- lamports?: number;
76
- ownerProgram?: string;
77
- executable?: boolean;
78
- rentEpoch?: number;
79
- dataLen?: number;
80
- dataBase64?: string | null;
81
- lastSlot?: number;
82
- } | null;
83
- }>;
84
- },
85
- ) => void;
86
- getRecordedTransaction: (signature: string) =>
87
- | {
88
- tx: VersionedTransaction;
89
- logs: string[];
90
- err: unknown;
91
- fee: number;
92
- slot: number;
93
- blockTime?: number;
94
- preBalances?: number[];
95
- postBalances?: number[];
96
- preTokenBalances?: unknown[];
97
- postTokenBalances?: unknown[];
98
- innerInstructions?: unknown[];
99
- computeUnits?: number | null;
100
- returnData?: { programId: string; dataBase64: string } | null;
101
- }
102
- | undefined;
47
+ recordTransaction: (
48
+ signature: string,
49
+ tx: VersionedTransaction,
50
+ meta?: {
51
+ logs?: string[];
52
+ err?: unknown;
53
+ fee?: number;
54
+ blockTime?: number;
55
+ preBalances?: number[];
56
+ postBalances?: number[];
57
+ preTokenBalances?: unknown[];
58
+ postTokenBalances?: unknown[];
59
+ innerInstructions?: unknown[];
60
+ computeUnits?: number | bigint | null;
61
+ returnData?: { programId: string; dataBase64: string } | null;
62
+ // Optional rich per-account snapshots captured around execution
63
+ accountStates?: Array<{
64
+ address: string;
65
+ pre?: {
66
+ lamports?: number;
67
+ ownerProgram?: string;
68
+ executable?: boolean;
69
+ rentEpoch?: number;
70
+ dataLen?: number;
71
+ dataBase64?: string | null;
72
+ lastSlot?: number;
73
+ } | null;
74
+ post?: {
75
+ lamports?: number;
76
+ ownerProgram?: string;
77
+ executable?: boolean;
78
+ rentEpoch?: number;
79
+ dataLen?: number;
80
+ dataBase64?: string | null;
81
+ lastSlot?: number;
82
+ } | null;
83
+ }>;
84
+ },
85
+ ) => void;
86
+ getRecordedTransaction: (signature: string) =>
87
+ | {
88
+ tx: VersionedTransaction;
89
+ logs: string[];
90
+ err: unknown;
91
+ fee: number;
92
+ slot: number;
93
+ blockTime?: number;
94
+ preBalances?: number[];
95
+ postBalances?: number[];
96
+ preTokenBalances?: unknown[];
97
+ postTokenBalances?: unknown[];
98
+ innerInstructions?: unknown[];
99
+ computeUnits?: number | null;
100
+ returnData?: { programId: string; dataBase64: string } | null;
101
+ }
102
+ | undefined;
103
103
  }
104
104
 
105
105
  export type RpcMethodHandler = (
@@ -1,35 +1,35 @@
1
1
  import { index, integer, sqliteTable, text } from "drizzle-orm/sqlite-core";
2
2
 
3
3
  export const transactions = sqliteTable(
4
- "transactions",
5
- {
6
- signature: text("signature").primaryKey(),
7
- slot: integer("slot").notNull(),
8
- blockTime: integer("block_time"),
9
- version: text("version").notNull(), // 0 | "legacy"
10
- errJson: text("err_json"),
11
- fee: integer("fee").notNull(),
12
- rawBase64: text("raw_base64").notNull(),
13
- preBalancesJson: text("pre_balances_json").notNull(),
14
- postBalancesJson: text("post_balances_json").notNull(),
15
- logsJson: text("logs_json").notNull(),
16
- preTokenBalancesJson: text("pre_token_balances_json")
17
- .default("[]")
18
- .notNull(),
19
- postTokenBalancesJson: text("post_token_balances_json")
20
- .default("[]")
21
- .notNull(),
22
- // Additional rich metadata captured after execution
23
- innerInstructionsJson: text("inner_instructions_json")
24
- .default("[]")
25
- .notNull(),
26
- computeUnits: integer("compute_units"),
27
- returnDataProgramId: text("return_data_program_id"),
28
- returnDataBase64: text("return_data_base64"),
29
- },
30
- (t) => ({
31
- slotIdx: index("idx_transactions_slot").on(t.slot),
32
- }),
4
+ "transactions",
5
+ {
6
+ signature: text("signature").primaryKey(),
7
+ slot: integer("slot").notNull(),
8
+ blockTime: integer("block_time"),
9
+ version: text("version").notNull(), // 0 | "legacy"
10
+ errJson: text("err_json"),
11
+ fee: integer("fee").notNull(),
12
+ rawBase64: text("raw_base64").notNull(),
13
+ preBalancesJson: text("pre_balances_json").notNull(),
14
+ postBalancesJson: text("post_balances_json").notNull(),
15
+ logsJson: text("logs_json").notNull(),
16
+ preTokenBalancesJson: text("pre_token_balances_json")
17
+ .default("[]")
18
+ .notNull(),
19
+ postTokenBalancesJson: text("post_token_balances_json")
20
+ .default("[]")
21
+ .notNull(),
22
+ // Additional rich metadata captured after execution
23
+ innerInstructionsJson: text("inner_instructions_json")
24
+ .default("[]")
25
+ .notNull(),
26
+ computeUnits: integer("compute_units"),
27
+ returnDataProgramId: text("return_data_program_id"),
28
+ returnDataBase64: text("return_data_base64"),
29
+ },
30
+ (t) => ({
31
+ slotIdx: index("idx_transactions_slot").on(t.slot),
32
+ }),
33
33
  );
34
34
 
35
35
  export type TransactionRow = typeof transactions.$inferSelect;
@@ -1,21 +1,23 @@
1
1
  import { index, primaryKey, sqliteTable, text } from "drizzle-orm/sqlite-core";
2
2
 
3
3
  export const txAccountStates = sqliteTable(
4
- "tx_account_states",
5
- {
6
- signature: text("signature").notNull(),
7
- address: text("address").notNull(),
8
- // JSON blobs capturing minimal account snapshot
9
- // { lamports, ownerProgram, executable, rentEpoch, dataLen, dataBase64? }
10
- preJson: text("pre_json"),
11
- postJson: text("post_json"),
12
- },
13
- (t) => ({
14
- pk: primaryKey({ columns: [t.signature, t.address], name: "pk_tx_account_states" }),
15
- addrIdx: index("idx_tx_account_states_address").on(t.address),
16
- }),
4
+ "tx_account_states",
5
+ {
6
+ signature: text("signature").notNull(),
7
+ address: text("address").notNull(),
8
+ // JSON blobs capturing minimal account snapshot
9
+ // { lamports, ownerProgram, executable, rentEpoch, dataLen, dataBase64? }
10
+ preJson: text("pre_json"),
11
+ postJson: text("post_json"),
12
+ },
13
+ (t) => ({
14
+ pk: primaryKey({
15
+ columns: [t.signature, t.address],
16
+ name: "pk_tx_account_states",
17
+ }),
18
+ addrIdx: index("idx_tx_account_states_address").on(t.address),
19
+ }),
17
20
  );
18
21
 
19
22
  export type TxAccountStateRow = typeof txAccountStates.$inferSelect;
20
23
  export type NewTxAccountStateRow = typeof txAccountStates.$inferInsert;
21
-