solforge 0.2.5 → 0.2.6
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/postinstall.cjs +3 -3
- package/server/lib/base58.ts +1 -1
- package/server/methods/account/get-account-info.ts +3 -7
- package/server/methods/account/get-balance.ts +3 -7
- package/server/methods/account/get-multiple-accounts.ts +2 -1
- package/server/methods/account/get-parsed-account-info.ts +3 -7
- package/server/methods/account/parsers/index.ts +2 -2
- package/server/methods/account/parsers/loader-upgradeable.ts +14 -1
- package/server/methods/account/parsers/spl-token.ts +29 -10
- package/server/methods/account/request-airdrop.ts +44 -31
- package/server/methods/block/get-block.ts +3 -7
- package/server/methods/block/get-blocks-with-limit.ts +3 -7
- package/server/methods/block/is-blockhash-valid.ts +3 -7
- package/server/methods/get-address-lookup-table.ts +3 -7
- package/server/methods/program/get-program-accounts.ts +9 -9
- package/server/methods/program/get-token-account-balance.ts +3 -7
- package/server/methods/program/get-token-accounts-by-delegate.ts +4 -3
- package/server/methods/program/get-token-accounts-by-owner.ts +54 -33
- package/server/methods/program/get-token-largest-accounts.ts +3 -2
- package/server/methods/program/get-token-supply.ts +3 -2
- package/server/methods/solforge/index.ts +9 -6
- package/server/methods/transaction/get-parsed-transaction.ts +3 -7
- package/server/methods/transaction/get-signature-statuses.ts +14 -7
- package/server/methods/transaction/get-signatures-for-address.ts +3 -7
- package/server/methods/transaction/get-transaction.ts +167 -81
- package/server/methods/transaction/send-transaction.ts +29 -16
- package/server/methods/transaction/simulate-transaction.ts +3 -2
- package/server/rpc-server.ts +47 -34
- package/server/types.ts +9 -6
- package/server/ws-server.ts +11 -7
- package/src/api-server-entry.ts +5 -5
- package/src/cli/commands/airdrop.ts +2 -2
- package/src/cli/commands/config.ts +2 -2
- package/src/cli/commands/mint.ts +3 -3
- package/src/cli/commands/program-clone.ts +9 -11
- package/src/cli/commands/program-load.ts +3 -3
- package/src/cli/commands/rpc-start.ts +7 -7
- package/src/cli/commands/token-adopt-authority.ts +1 -1
- package/src/cli/commands/token-clone.ts +5 -6
- package/src/cli/commands/token-create.ts +5 -5
- package/src/cli/main.ts +33 -36
- package/src/cli/run-solforge.ts +3 -3
- package/src/cli/setup-wizard.ts +8 -6
- package/src/commands/add-program.ts +1 -1
- package/src/commands/init.ts +2 -2
- package/src/commands/mint.ts +5 -6
- package/src/commands/start.ts +10 -9
- package/src/commands/status.ts +1 -1
- package/src/commands/stop.ts +1 -1
- package/src/config/index.ts +33 -17
- package/src/config/manager.ts +3 -3
- package/src/db/index.ts +2 -2
- package/src/db/tx-store.ts +12 -8
- package/src/gui/public/app.css +13 -13
- package/src/gui/server.ts +1 -1
- package/src/gui/src/api.ts +1 -1
- package/src/gui/src/app.tsx +49 -17
- package/src/gui/src/components/airdrop-mint-form.tsx +32 -8
- package/src/gui/src/components/clone-program-modal.tsx +25 -6
- package/src/gui/src/components/clone-token-modal.tsx +25 -6
- package/src/gui/src/components/modal.tsx +6 -1
- package/src/gui/src/components/status-panel.tsx +1 -1
- package/src/index.ts +19 -6
- package/src/services/api-server.ts +41 -19
- package/src/services/port-manager.ts +7 -10
- package/src/services/process-registry.ts +4 -5
- package/src/services/program-cloner.ts +4 -4
- package/src/services/token-cloner.ts +4 -4
- package/src/services/validator.ts +2 -4
- package/src/types/config.ts +2 -2
- package/src/utils/shell.ts +1 -1
- package/src/utils/token-loader.ts +2 -2
|
@@ -32,7 +32,8 @@ export const getTokenSupply: RpcMethodHandler = (id, params, context) => {
|
|
|
32
32
|
uiAmountString: ui.toString(),
|
|
33
33
|
},
|
|
34
34
|
});
|
|
35
|
-
} catch (e:
|
|
36
|
-
|
|
35
|
+
} catch (e: unknown) {
|
|
36
|
+
const message = e instanceof Error ? e.message : String(e);
|
|
37
|
+
return context.createErrorResponse(id, -32602, "Invalid params", message);
|
|
37
38
|
}
|
|
38
39
|
};
|
|
@@ -46,12 +46,13 @@ export const solforgeGetStatus: RpcMethodHandler = async (
|
|
|
46
46
|
...formatLamports(faucetLamports),
|
|
47
47
|
},
|
|
48
48
|
});
|
|
49
|
-
} catch (error:
|
|
49
|
+
} catch (error: unknown) {
|
|
50
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
50
51
|
return context.createErrorResponse(
|
|
51
52
|
id,
|
|
52
53
|
-32603,
|
|
53
54
|
"Status unavailable",
|
|
54
|
-
|
|
55
|
+
message,
|
|
55
56
|
);
|
|
56
57
|
}
|
|
57
58
|
};
|
|
@@ -90,12 +91,13 @@ export const solforgeListPrograms: RpcMethodHandler = async (
|
|
|
90
91
|
.filter(Boolean);
|
|
91
92
|
|
|
92
93
|
return context.createSuccessResponse(id, detailed);
|
|
93
|
-
} catch (error:
|
|
94
|
+
} catch (error: unknown) {
|
|
95
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
94
96
|
return context.createErrorResponse(
|
|
95
97
|
id,
|
|
96
98
|
-32603,
|
|
97
99
|
"List programs failed",
|
|
98
|
-
|
|
100
|
+
message,
|
|
99
101
|
);
|
|
100
102
|
}
|
|
101
103
|
};
|
|
@@ -144,12 +146,13 @@ export const solforgeListTokensDetailed: RpcMethodHandler = async (
|
|
|
144
146
|
.filter(Boolean);
|
|
145
147
|
|
|
146
148
|
return context.createSuccessResponse(id, detailed);
|
|
147
|
-
} catch (error:
|
|
149
|
+
} catch (error: unknown) {
|
|
150
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
148
151
|
return context.createErrorResponse(
|
|
149
152
|
id,
|
|
150
153
|
-32603,
|
|
151
154
|
"List tokens failed",
|
|
152
|
-
|
|
155
|
+
message,
|
|
153
156
|
);
|
|
154
157
|
}
|
|
155
158
|
};
|
|
@@ -10,12 +10,8 @@ export const getParsedTransaction: RpcMethodHandler = async (
|
|
|
10
10
|
const cfg = { ...(config || {}), encoding: "jsonParsed" };
|
|
11
11
|
try {
|
|
12
12
|
return await getTransaction(id, [signature, cfg], context);
|
|
13
|
-
} catch (error:
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
-32603,
|
|
17
|
-
"Internal error",
|
|
18
|
-
error.message,
|
|
19
|
-
);
|
|
13
|
+
} catch (error: unknown) {
|
|
14
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
15
|
+
return context.createErrorResponse(id, -32603, "Internal error", message);
|
|
20
16
|
}
|
|
21
17
|
};
|
|
@@ -7,7 +7,7 @@ export const getSignatureStatuses: RpcMethodHandler = async (
|
|
|
7
7
|
) => {
|
|
8
8
|
const [signatures] = params;
|
|
9
9
|
|
|
10
|
-
let persisted: Map<string, { slot: number; err:
|
|
10
|
+
let persisted: Map<string, { slot: number; err: unknown | null }> = new Map();
|
|
11
11
|
try {
|
|
12
12
|
persisted = (await context.store?.getStatuses(signatures)) || new Map();
|
|
13
13
|
} catch {}
|
|
@@ -17,7 +17,7 @@ export const getSignatureStatuses: RpcMethodHandler = async (
|
|
|
17
17
|
// Prefer locally recorded transactions for reliability with CLI tooling
|
|
18
18
|
const rec = context.getRecordedTransaction(sig);
|
|
19
19
|
if (rec) {
|
|
20
|
-
const errVal:
|
|
20
|
+
const errVal: unknown = rec.err ?? null;
|
|
21
21
|
const status = errVal ? { Err: errVal } : { Ok: null };
|
|
22
22
|
return {
|
|
23
23
|
slot: rec.slot,
|
|
@@ -29,7 +29,7 @@ export const getSignatureStatuses: RpcMethodHandler = async (
|
|
|
29
29
|
}
|
|
30
30
|
const db = persisted.get(sig);
|
|
31
31
|
if (db) {
|
|
32
|
-
const errVal:
|
|
32
|
+
const errVal: unknown = db.err ?? null;
|
|
33
33
|
const status = errVal ? { Err: errVal } : { Ok: null };
|
|
34
34
|
return {
|
|
35
35
|
slot: db.slot,
|
|
@@ -41,13 +41,20 @@ export const getSignatureStatuses: RpcMethodHandler = async (
|
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
const sigBytes = context.decodeBase58(sig);
|
|
44
|
-
const
|
|
44
|
+
const txGetter = (
|
|
45
|
+
context.svm as unknown as {
|
|
46
|
+
getTransaction?: (sig: Uint8Array) => { err?: unknown } | undefined;
|
|
47
|
+
}
|
|
48
|
+
).getTransaction;
|
|
49
|
+
const tx =
|
|
50
|
+
typeof txGetter === "function" ? txGetter(sigBytes) : undefined;
|
|
45
51
|
if (!tx) return null;
|
|
46
52
|
|
|
47
|
-
let errVal:
|
|
53
|
+
let errVal: unknown = null;
|
|
48
54
|
try {
|
|
49
|
-
|
|
50
|
-
errVal =
|
|
55
|
+
const rawErr = (tx as { err?: unknown }).err;
|
|
56
|
+
errVal =
|
|
57
|
+
typeof rawErr === "function" ? (rawErr as () => unknown)() : rawErr;
|
|
51
58
|
} catch {
|
|
52
59
|
errVal = null;
|
|
53
60
|
}
|
|
@@ -31,15 +31,11 @@ export const getSignaturesForAddress: RpcMethodHandler = async (
|
|
|
31
31
|
// Graceful fallback: return empty list instead of error
|
|
32
32
|
return context.createSuccessResponse(id, []);
|
|
33
33
|
}
|
|
34
|
-
} catch (error:
|
|
34
|
+
} catch (error: unknown) {
|
|
35
35
|
try {
|
|
36
36
|
console.error("[rpc] getSignaturesForAddress error", error);
|
|
37
37
|
} catch {}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
-32603,
|
|
41
|
-
"Internal error",
|
|
42
|
-
error.message,
|
|
43
|
-
);
|
|
38
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
39
|
+
return context.createErrorResponse(id, -32603, "Internal error", message);
|
|
44
40
|
}
|
|
45
41
|
};
|
|
@@ -8,14 +8,14 @@ export const getTransaction: RpcMethodHandler = async (id, params, context) => {
|
|
|
8
8
|
try {
|
|
9
9
|
const rec = context.getRecordedTransaction(signature);
|
|
10
10
|
if (rec) {
|
|
11
|
-
const tx = rec.tx
|
|
11
|
+
const tx = rec.tx;
|
|
12
12
|
if (encoding === "base64") {
|
|
13
13
|
const raw = Buffer.from(tx.serialize()).toString("base64");
|
|
14
14
|
// Top-level version is required by some clients
|
|
15
|
-
const isV0 =
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
const isV0 = (() => {
|
|
16
|
+
const m = tx.message as unknown as { version?: number };
|
|
17
|
+
return typeof m?.version === "number" ? m.version === 0 : true;
|
|
18
|
+
})();
|
|
19
19
|
return context.createSuccessResponse(id, {
|
|
20
20
|
slot: rec.slot,
|
|
21
21
|
transaction: [raw, "base64"],
|
|
@@ -31,55 +31,86 @@ export const getTransaction: RpcMethodHandler = async (id, params, context) => {
|
|
|
31
31
|
: [],
|
|
32
32
|
innerInstructions: [],
|
|
33
33
|
logMessages: rec.logs || [],
|
|
34
|
-
preTokenBalances:
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
34
|
+
preTokenBalances: (() => {
|
|
35
|
+
const arr = (rec as unknown as { preTokenBalances?: unknown[] })
|
|
36
|
+
.preTokenBalances;
|
|
37
|
+
return Array.isArray(arr) ? arr : [];
|
|
38
|
+
})(),
|
|
39
|
+
postTokenBalances: (() => {
|
|
40
|
+
const arr = (rec as unknown as { postTokenBalances?: unknown[] })
|
|
41
|
+
.postTokenBalances;
|
|
42
|
+
return Array.isArray(arr) ? arr : [];
|
|
43
|
+
})(),
|
|
40
44
|
rewards: [],
|
|
41
45
|
},
|
|
42
46
|
blockTime: rec.blockTime,
|
|
43
47
|
});
|
|
44
48
|
}
|
|
45
49
|
|
|
46
|
-
const msg
|
|
47
|
-
|
|
50
|
+
const msg = tx.message as unknown as {
|
|
51
|
+
staticAccountKeys?: unknown[];
|
|
52
|
+
accountKeys?: unknown[];
|
|
53
|
+
compiledInstructions?: unknown[];
|
|
54
|
+
instructions?: unknown[];
|
|
55
|
+
header?: unknown;
|
|
56
|
+
recentBlockhash?: string;
|
|
57
|
+
version?: number;
|
|
58
|
+
addressTableLookups?: unknown[];
|
|
59
|
+
isAccountSigner?: (i: number) => boolean;
|
|
60
|
+
isAccountWritable?: (i: number) => boolean;
|
|
61
|
+
};
|
|
62
|
+
const rawKeys1: unknown[] = Array.isArray(msg.staticAccountKeys)
|
|
48
63
|
? msg.staticAccountKeys
|
|
49
64
|
: Array.isArray(msg.accountKeys)
|
|
50
65
|
? msg.accountKeys
|
|
51
66
|
: [];
|
|
52
|
-
const accountKeys = rawKeys1.map((k
|
|
67
|
+
const accountKeys = rawKeys1.map((k) => {
|
|
53
68
|
try {
|
|
54
|
-
return typeof k === "string"
|
|
69
|
+
return typeof k === "string"
|
|
70
|
+
? k
|
|
71
|
+
: (k as { toBase58: () => string }).toBase58();
|
|
55
72
|
} catch {
|
|
56
73
|
return String(k);
|
|
57
74
|
}
|
|
58
75
|
});
|
|
59
|
-
const compiled = Array.isArray(msg.compiledInstructions)
|
|
76
|
+
const compiled: unknown[] = Array.isArray(msg.compiledInstructions)
|
|
60
77
|
? msg.compiledInstructions
|
|
61
78
|
: Array.isArray(msg.instructions)
|
|
62
79
|
? msg.instructions
|
|
63
80
|
: [];
|
|
64
|
-
const instructions = compiled.map((ci
|
|
81
|
+
const instructions = compiled.map((ci) => {
|
|
82
|
+
const c = ci as {
|
|
83
|
+
programIdIndex: number;
|
|
84
|
+
accountKeyIndexes?: number[];
|
|
85
|
+
accounts?: number[];
|
|
86
|
+
data: Uint8Array | number[];
|
|
87
|
+
};
|
|
65
88
|
const dataBytes: Uint8Array =
|
|
66
|
-
|
|
89
|
+
c.data instanceof Uint8Array ? c.data : Buffer.from(c.data);
|
|
67
90
|
return {
|
|
68
|
-
programIdIndex:
|
|
69
|
-
accounts: Array.from(
|
|
91
|
+
programIdIndex: c.programIdIndex,
|
|
92
|
+
accounts: Array.from(c.accountKeyIndexes || c.accounts || []),
|
|
70
93
|
data: context.encodeBase58(dataBytes),
|
|
71
94
|
};
|
|
72
95
|
});
|
|
73
|
-
const addressTableLookups = (
|
|
74
|
-
(
|
|
96
|
+
const addressTableLookups = (
|
|
97
|
+
Array.isArray(msg.addressTableLookups) ? msg.addressTableLookups : []
|
|
98
|
+
).map((l) => {
|
|
99
|
+
const a = l as {
|
|
100
|
+
accountKey?: { toBase58?: () => string } | string;
|
|
101
|
+
writableIndexes?: number[];
|
|
102
|
+
readonlyIndexes?: number[];
|
|
103
|
+
};
|
|
104
|
+
return {
|
|
75
105
|
accountKey:
|
|
76
|
-
typeof
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
106
|
+
typeof (a.accountKey as { toBase58?: unknown })?.toBase58 ===
|
|
107
|
+
"function"
|
|
108
|
+
? (a.accountKey as { toBase58: () => string }).toBase58()
|
|
109
|
+
: String(a.accountKey),
|
|
110
|
+
writableIndexes: Array.from(a.writableIndexes || []),
|
|
111
|
+
readonlyIndexes: Array.from(a.readonlyIndexes || []),
|
|
112
|
+
};
|
|
113
|
+
});
|
|
83
114
|
const header = msg.header || {
|
|
84
115
|
numRequiredSignatures: tx.signatures.length,
|
|
85
116
|
numReadonlySignedAccounts: 0,
|
|
@@ -88,7 +119,7 @@ export const getTransaction: RpcMethodHandler = async (id, params, context) => {
|
|
|
88
119
|
const recentBlockhash = msg.recentBlockhash || "";
|
|
89
120
|
|
|
90
121
|
const isV0 = typeof msg.version === "number" ? msg.version === 0 : true;
|
|
91
|
-
const result
|
|
122
|
+
const result = {
|
|
92
123
|
slot: rec.slot,
|
|
93
124
|
transaction: {
|
|
94
125
|
signatures: [signature],
|
|
@@ -110,12 +141,16 @@ export const getTransaction: RpcMethodHandler = async (id, params, context) => {
|
|
|
110
141
|
postBalances: Array.isArray(rec.postBalances) ? rec.postBalances : [],
|
|
111
142
|
innerInstructions: [],
|
|
112
143
|
logMessages: rec.logs || [],
|
|
113
|
-
preTokenBalances:
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
144
|
+
preTokenBalances: (() => {
|
|
145
|
+
const arr = (rec as unknown as { preTokenBalances?: unknown[] })
|
|
146
|
+
.preTokenBalances;
|
|
147
|
+
return Array.isArray(arr) ? arr : [];
|
|
148
|
+
})(),
|
|
149
|
+
postTokenBalances: (() => {
|
|
150
|
+
const arr = (rec as unknown as { postTokenBalances?: unknown[] })
|
|
151
|
+
.postTokenBalances;
|
|
152
|
+
return Array.isArray(arr) ? arr : [];
|
|
153
|
+
})(),
|
|
119
154
|
rewards: [],
|
|
120
155
|
},
|
|
121
156
|
blockTime: rec.blockTime,
|
|
@@ -134,12 +169,18 @@ export const getTransaction: RpcMethodHandler = async (id, params, context) => {
|
|
|
134
169
|
? !!msg.isAccountWritable(i)
|
|
135
170
|
: i < (header?.numRequiredSignatures ?? 0),
|
|
136
171
|
}));
|
|
137
|
-
const parsedInstructions = compiled.map((ci
|
|
138
|
-
const
|
|
139
|
-
|
|
172
|
+
const parsedInstructions = compiled.map((ci) => {
|
|
173
|
+
const c = ci as {
|
|
174
|
+
programIdIndex: number;
|
|
175
|
+
accountKeyIndexes?: number[];
|
|
176
|
+
accounts?: number[];
|
|
177
|
+
data: Uint8Array | number[];
|
|
178
|
+
};
|
|
179
|
+
const programId = accountKeys[c.programIdIndex];
|
|
180
|
+
let parsed: unknown;
|
|
140
181
|
try {
|
|
141
182
|
const data: Uint8Array =
|
|
142
|
-
|
|
183
|
+
c.data instanceof Uint8Array ? c.data : Buffer.from(c.data);
|
|
143
184
|
if (programId === SYSTEM_PROGRAM_ID && data.length >= 12) {
|
|
144
185
|
const dv = new DataView(
|
|
145
186
|
data.buffer,
|
|
@@ -152,8 +193,9 @@ export const getTransaction: RpcMethodHandler = async (id, params, context) => {
|
|
|
152
193
|
(ci.accountKeyIndexes?.length ?? 0) >= 2
|
|
153
194
|
) {
|
|
154
195
|
const lamports = Number(dv.getBigUint64(4, true));
|
|
155
|
-
const source = accountKeys[
|
|
156
|
-
const destination =
|
|
196
|
+
const source = accountKeys[c.accountKeyIndexes?.[0] as number];
|
|
197
|
+
const destination =
|
|
198
|
+
accountKeys[c.accountKeyIndexes?.[1] as number];
|
|
157
199
|
parsed = {
|
|
158
200
|
type: "transfer",
|
|
159
201
|
info: { source, destination, lamports },
|
|
@@ -164,16 +206,19 @@ export const getTransaction: RpcMethodHandler = async (id, params, context) => {
|
|
|
164
206
|
if (parsed) return { program: "system", programId, parsed };
|
|
165
207
|
return {
|
|
166
208
|
programId,
|
|
167
|
-
accounts: (
|
|
209
|
+
accounts: (c.accountKeyIndexes || []).map(
|
|
168
210
|
(ix: number) => accountKeys[ix],
|
|
169
211
|
),
|
|
170
212
|
data: context.encodeBase58(
|
|
171
|
-
|
|
213
|
+
c.data instanceof Uint8Array ? c.data : Buffer.from(c.data),
|
|
172
214
|
),
|
|
173
215
|
};
|
|
174
216
|
});
|
|
175
|
-
result.transaction.message.accountKeys =
|
|
176
|
-
|
|
217
|
+
(result.transaction.message as { accountKeys: unknown[] }).accountKeys =
|
|
218
|
+
accountKeysParsed;
|
|
219
|
+
(
|
|
220
|
+
result.transaction.message as { instructions: unknown[] }
|
|
221
|
+
).instructions = parsedInstructions as unknown[];
|
|
177
222
|
}
|
|
178
223
|
|
|
179
224
|
return context.createSuccessResponse(id, result);
|
|
@@ -213,15 +258,27 @@ export const getTransaction: RpcMethodHandler = async (id, params, context) => {
|
|
|
213
258
|
// Build jsonParsed similar to in-memory path
|
|
214
259
|
const raw = Buffer.from(row.rawBase64, "base64");
|
|
215
260
|
const tx = VersionedTransaction.deserialize(raw);
|
|
216
|
-
const msg
|
|
217
|
-
|
|
261
|
+
const msg = tx.message as unknown as {
|
|
262
|
+
staticAccountKeys?: unknown[];
|
|
263
|
+
accountKeys?: unknown[];
|
|
264
|
+
compiledInstructions?: unknown[];
|
|
265
|
+
instructions?: unknown[];
|
|
266
|
+
header?: unknown;
|
|
267
|
+
recentBlockhash?: string;
|
|
268
|
+
addressTableLookups?: unknown[];
|
|
269
|
+
isAccountSigner?: (i: number) => boolean;
|
|
270
|
+
isAccountWritable?: (i: number) => boolean;
|
|
271
|
+
};
|
|
272
|
+
const rawKeys2: unknown[] = Array.isArray(msg.staticAccountKeys)
|
|
218
273
|
? msg.staticAccountKeys
|
|
219
274
|
: Array.isArray(msg.accountKeys)
|
|
220
275
|
? msg.accountKeys
|
|
221
276
|
: [];
|
|
222
|
-
const accountKeys = rawKeys2.map((k
|
|
277
|
+
const accountKeys = rawKeys2.map((k) => {
|
|
223
278
|
try {
|
|
224
|
-
return typeof k === "string"
|
|
279
|
+
return typeof k === "string"
|
|
280
|
+
? k
|
|
281
|
+
: (k as { toBase58: () => string }).toBase58();
|
|
225
282
|
} catch {
|
|
226
283
|
return String(k);
|
|
227
284
|
}
|
|
@@ -231,17 +288,23 @@ export const getTransaction: RpcMethodHandler = async (id, params, context) => {
|
|
|
231
288
|
numReadonlySignedAccounts: 0,
|
|
232
289
|
numReadonlyUnsignedAccounts: 0,
|
|
233
290
|
};
|
|
234
|
-
const compiled = Array.isArray(msg.compiledInstructions)
|
|
291
|
+
const compiled: unknown[] = Array.isArray(msg.compiledInstructions)
|
|
235
292
|
? msg.compiledInstructions
|
|
236
293
|
: Array.isArray(msg.instructions)
|
|
237
294
|
? msg.instructions
|
|
238
295
|
: [];
|
|
239
|
-
const parsedInstructions = compiled.map((ci
|
|
240
|
-
const
|
|
241
|
-
|
|
296
|
+
const parsedInstructions = compiled.map((ci) => {
|
|
297
|
+
const c = ci as {
|
|
298
|
+
programIdIndex: number;
|
|
299
|
+
accountKeyIndexes?: number[];
|
|
300
|
+
accounts?: number[];
|
|
301
|
+
data: Uint8Array | number[];
|
|
302
|
+
};
|
|
303
|
+
const programId = accountKeys[c.programIdIndex];
|
|
304
|
+
let parsed: unknown;
|
|
242
305
|
try {
|
|
243
306
|
const data: Uint8Array =
|
|
244
|
-
|
|
307
|
+
c.data instanceof Uint8Array ? c.data : Buffer.from(c.data);
|
|
245
308
|
// Minimal system transfer parser
|
|
246
309
|
if (
|
|
247
310
|
programId === "11111111111111111111111111111111" &&
|
|
@@ -258,8 +321,8 @@ export const getTransaction: RpcMethodHandler = async (id, params, context) => {
|
|
|
258
321
|
(ci.accountKeyIndexes?.length ?? 0) >= 2
|
|
259
322
|
) {
|
|
260
323
|
const lamports = Number(dv.getBigUint64(4, true));
|
|
261
|
-
const source = accountKeys[
|
|
262
|
-
const destination = accountKeys[
|
|
324
|
+
const source = accountKeys[c.accountKeyIndexes?.[0]];
|
|
325
|
+
const destination = accountKeys[c.accountKeyIndexes?.[1]];
|
|
263
326
|
parsed = {
|
|
264
327
|
type: "transfer",
|
|
265
328
|
info: { source, destination, lamports },
|
|
@@ -270,11 +333,11 @@ export const getTransaction: RpcMethodHandler = async (id, params, context) => {
|
|
|
270
333
|
if (parsed) return { program: "system", programId, parsed };
|
|
271
334
|
return {
|
|
272
335
|
programId,
|
|
273
|
-
accounts: (
|
|
336
|
+
accounts: (c.accountKeyIndexes || []).map(
|
|
274
337
|
(ix: number) => accountKeys[ix],
|
|
275
338
|
),
|
|
276
339
|
data: context.encodeBase58(
|
|
277
|
-
|
|
340
|
+
c.data instanceof Uint8Array ? c.data : Buffer.from(c.data),
|
|
278
341
|
),
|
|
279
342
|
};
|
|
280
343
|
});
|
|
@@ -291,7 +354,7 @@ export const getTransaction: RpcMethodHandler = async (id, params, context) => {
|
|
|
291
354
|
: i < (header?.numRequiredSignatures ?? 0),
|
|
292
355
|
}),
|
|
293
356
|
);
|
|
294
|
-
const result
|
|
357
|
+
const result = {
|
|
295
358
|
slot: Number(row.slot),
|
|
296
359
|
transaction: {
|
|
297
360
|
signatures: [signature],
|
|
@@ -323,15 +386,25 @@ export const getTransaction: RpcMethodHandler = async (id, params, context) => {
|
|
|
323
386
|
} else {
|
|
324
387
|
const raw = Buffer.from(row.rawBase64, "base64");
|
|
325
388
|
const tx = VersionedTransaction.deserialize(raw);
|
|
326
|
-
const msg
|
|
327
|
-
|
|
389
|
+
const msg = tx.message as unknown as {
|
|
390
|
+
staticAccountKeys?: unknown[];
|
|
391
|
+
accountKeys?: unknown[];
|
|
392
|
+
compiledInstructions?: unknown[];
|
|
393
|
+
instructions?: unknown[];
|
|
394
|
+
header?: unknown;
|
|
395
|
+
recentBlockhash?: string;
|
|
396
|
+
addressTableLookups?: unknown[];
|
|
397
|
+
};
|
|
398
|
+
const rawKeys3: unknown[] = Array.isArray(msg.staticAccountKeys)
|
|
328
399
|
? msg.staticAccountKeys
|
|
329
400
|
: Array.isArray(msg.accountKeys)
|
|
330
401
|
? msg.accountKeys
|
|
331
402
|
: [];
|
|
332
|
-
const accountKeys = rawKeys3.map((k
|
|
403
|
+
const accountKeys = rawKeys3.map((k) => {
|
|
333
404
|
try {
|
|
334
|
-
return typeof k === "string"
|
|
405
|
+
return typeof k === "string"
|
|
406
|
+
? k
|
|
407
|
+
: (k as { toBase58: () => string }).toBase58();
|
|
335
408
|
} catch {
|
|
336
409
|
return String(k);
|
|
337
410
|
}
|
|
@@ -341,19 +414,27 @@ export const getTransaction: RpcMethodHandler = async (id, params, context) => {
|
|
|
341
414
|
numReadonlySignedAccounts: 0,
|
|
342
415
|
numReadonlyUnsignedAccounts: 0,
|
|
343
416
|
};
|
|
344
|
-
const compiled = Array.isArray(msg.compiledInstructions)
|
|
417
|
+
const compiled: unknown[] = Array.isArray(msg.compiledInstructions)
|
|
345
418
|
? msg.compiledInstructions
|
|
346
419
|
: Array.isArray(msg.instructions)
|
|
347
420
|
? msg.instructions
|
|
348
421
|
: [];
|
|
349
|
-
const instructions = compiled.map((ci
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
422
|
+
const instructions = compiled.map((ci) => {
|
|
423
|
+
const c = ci as {
|
|
424
|
+
programIdIndex: number;
|
|
425
|
+
accountKeyIndexes?: number[];
|
|
426
|
+
accounts?: number[];
|
|
427
|
+
data: Uint8Array | number[];
|
|
428
|
+
};
|
|
429
|
+
return {
|
|
430
|
+
programIdIndex: c.programIdIndex,
|
|
431
|
+
accounts: Array.from(c.accountKeyIndexes || c.accounts || []),
|
|
432
|
+
data: context.encodeBase58(
|
|
433
|
+
c.data instanceof Uint8Array ? c.data : Buffer.from(c.data),
|
|
434
|
+
),
|
|
435
|
+
};
|
|
436
|
+
});
|
|
437
|
+
const result = {
|
|
357
438
|
slot: Number(row.slot),
|
|
358
439
|
transaction: {
|
|
359
440
|
signatures: [signature],
|
|
@@ -388,7 +469,16 @@ export const getTransaction: RpcMethodHandler = async (id, params, context) => {
|
|
|
388
469
|
|
|
389
470
|
// Fallback to LiteSVM history when no local record exists
|
|
390
471
|
const sigBytes = context.decodeBase58(signature);
|
|
391
|
-
const
|
|
472
|
+
const getTx = (
|
|
473
|
+
context.svm as unknown as {
|
|
474
|
+
getTransaction?: (
|
|
475
|
+
sig: Uint8Array,
|
|
476
|
+
) =>
|
|
477
|
+
| { logs: () => string[]; err: () => unknown }
|
|
478
|
+
| { meta: () => { logs: () => string[] }; err: () => unknown };
|
|
479
|
+
}
|
|
480
|
+
).getTransaction;
|
|
481
|
+
const txh = typeof getTx === "function" ? getTx(sigBytes) : undefined;
|
|
392
482
|
if (!txh) return context.createSuccessResponse(id, null);
|
|
393
483
|
|
|
394
484
|
const isError = "err" in txh;
|
|
@@ -417,12 +507,8 @@ export const getTransaction: RpcMethodHandler = async (id, params, context) => {
|
|
|
417
507
|
},
|
|
418
508
|
blockTime: Math.floor(Date.now() / 1000),
|
|
419
509
|
});
|
|
420
|
-
} catch (error:
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
-32602,
|
|
424
|
-
"Invalid params",
|
|
425
|
-
error.message,
|
|
426
|
-
);
|
|
510
|
+
} catch (error: unknown) {
|
|
511
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
512
|
+
return context.createErrorResponse(id, -32602, "Invalid params", message);
|
|
427
513
|
}
|
|
428
514
|
};
|
|
@@ -16,14 +16,17 @@ export const sendTransaction: RpcMethodHandler = (id, params, context) => {
|
|
|
16
16
|
const tx = VersionedTransaction.deserialize(txData);
|
|
17
17
|
|
|
18
18
|
// Snapshot pre balances
|
|
19
|
-
const msg
|
|
20
|
-
|
|
19
|
+
const msg = tx.message as unknown as {
|
|
20
|
+
staticAccountKeys?: unknown[];
|
|
21
|
+
accountKeys?: unknown[];
|
|
22
|
+
};
|
|
23
|
+
const rawKeys: unknown[] = Array.isArray(msg.staticAccountKeys)
|
|
21
24
|
? msg.staticAccountKeys
|
|
22
25
|
: Array.isArray(msg.accountKeys)
|
|
23
26
|
? msg.accountKeys
|
|
24
27
|
: [];
|
|
25
28
|
const staticKeys = rawKeys
|
|
26
|
-
.map((k
|
|
29
|
+
.map((k) => {
|
|
27
30
|
try {
|
|
28
31
|
return typeof k === "string" ? new PublicKey(k) : (k as PublicKey);
|
|
29
32
|
} catch {
|
|
@@ -40,8 +43,11 @@ export const sendTransaction: RpcMethodHandler = (id, params, context) => {
|
|
|
40
43
|
});
|
|
41
44
|
|
|
42
45
|
// Collect SPL token accounts from instructions for pre/post token balance snapshots
|
|
43
|
-
const msgAny
|
|
44
|
-
|
|
46
|
+
const msgAny = msg as unknown as {
|
|
47
|
+
compiledInstructions?: unknown[];
|
|
48
|
+
instructions?: unknown[];
|
|
49
|
+
};
|
|
50
|
+
const compiled: unknown[] = Array.isArray(msgAny.compiledInstructions)
|
|
45
51
|
? msgAny.compiledInstructions
|
|
46
52
|
: Array.isArray(msgAny.instructions)
|
|
47
53
|
? msgAny.instructions
|
|
@@ -67,7 +73,7 @@ export const sendTransaction: RpcMethodHandler = (id, params, context) => {
|
|
|
67
73
|
} catch {}
|
|
68
74
|
}
|
|
69
75
|
// Pre token balances
|
|
70
|
-
const preTokenBalances:
|
|
76
|
+
const preTokenBalances: unknown[] = [];
|
|
71
77
|
const ataToInfo = new Map<
|
|
72
78
|
string,
|
|
73
79
|
{
|
|
@@ -127,8 +133,9 @@ export const sendTransaction: RpcMethodHandler = (id, params, context) => {
|
|
|
127
133
|
const result = context.svm.sendTransaction(tx);
|
|
128
134
|
|
|
129
135
|
try {
|
|
130
|
-
|
|
131
|
-
const maybeErr =
|
|
136
|
+
const rawErr = (result as { err?: unknown }).err;
|
|
137
|
+
const maybeErr =
|
|
138
|
+
typeof rawErr === "function" ? (rawErr as () => unknown)() : rawErr;
|
|
132
139
|
if (maybeErr) {
|
|
133
140
|
return context.createErrorResponse(
|
|
134
141
|
id,
|
|
@@ -152,7 +159,7 @@ export const sendTransaction: RpcMethodHandler = (id, params, context) => {
|
|
|
152
159
|
}
|
|
153
160
|
});
|
|
154
161
|
// Post token balances
|
|
155
|
-
const postTokenBalances:
|
|
162
|
+
const postTokenBalances: unknown[] = [];
|
|
156
163
|
for (const addr of tokenAccountSet) {
|
|
157
164
|
try {
|
|
158
165
|
const pk = new PublicKey(addr);
|
|
@@ -204,11 +211,16 @@ export const sendTransaction: RpcMethodHandler = (id, params, context) => {
|
|
|
204
211
|
}
|
|
205
212
|
let logs: string[] = [];
|
|
206
213
|
try {
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
214
|
+
const sr = result as {
|
|
215
|
+
logs?: () => string[];
|
|
216
|
+
meta?: () => { logs?: () => string[] } | undefined;
|
|
217
|
+
};
|
|
218
|
+
if (typeof sr?.logs === "function") logs = sr.logs();
|
|
219
|
+
else if (typeof sr?.meta === "function") {
|
|
220
|
+
const m = sr.meta();
|
|
221
|
+
const lg = m?.logs;
|
|
222
|
+
if (typeof lg === "function") logs = lg();
|
|
223
|
+
}
|
|
212
224
|
} catch {}
|
|
213
225
|
context.recordTransaction(signature, tx, {
|
|
214
226
|
logs,
|
|
@@ -221,12 +233,13 @@ export const sendTransaction: RpcMethodHandler = (id, params, context) => {
|
|
|
221
233
|
});
|
|
222
234
|
|
|
223
235
|
return context.createSuccessResponse(id, signature);
|
|
224
|
-
} catch (error:
|
|
236
|
+
} catch (error: unknown) {
|
|
237
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
225
238
|
return context.createErrorResponse(
|
|
226
239
|
id,
|
|
227
240
|
-32003,
|
|
228
241
|
"Transaction failed",
|
|
229
|
-
|
|
242
|
+
message,
|
|
230
243
|
);
|
|
231
244
|
}
|
|
232
245
|
};
|