solforge 0.2.5 → 0.2.7
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/lib/instruction-parser.ts +242 -0
- 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 +122 -86
- package/server/methods/admin/mint-to.ts +11 -38
- 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 +434 -287
- package/server/methods/transaction/inner-instructions.test.ts +63 -0
- package/server/methods/transaction/send-transaction.ts +248 -56
- package/server/methods/transaction/simulate-transaction.ts +3 -2
- package/server/rpc-server.ts +98 -61
- package/server/types.ts +65 -30
- 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/schema/index.ts +1 -0
- package/src/db/schema/transactions.ts +29 -22
- package/src/db/schema/tx-account-states.ts +21 -0
- package/src/db/tx-store.ts +113 -76
- 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/migrations-bundled.ts +8 -2
- 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
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { test, expect } from "bun:test";
|
|
2
|
+
import {
|
|
3
|
+
Keypair,
|
|
4
|
+
LAMPORTS_PER_SOL,
|
|
5
|
+
TransactionMessage,
|
|
6
|
+
VersionedTransaction,
|
|
7
|
+
PublicKey,
|
|
8
|
+
} from "@solana/web3.js";
|
|
9
|
+
import {
|
|
10
|
+
getAssociatedTokenAddress,
|
|
11
|
+
createAssociatedTokenAccountInstruction,
|
|
12
|
+
} from "@solana/spl-token";
|
|
13
|
+
import { LiteSVMRpcServer } from "../../rpc-server";
|
|
14
|
+
|
|
15
|
+
type RpcResp<T = any> = { jsonrpc: "2.0"; id: number; result?: T; error?: { code: number; message: string; data?: unknown } };
|
|
16
|
+
|
|
17
|
+
function jsonReq(method: string, params?: unknown) {
|
|
18
|
+
return { jsonrpc: "2.0", id: Math.floor(Math.random() * 1e9), method, params };
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
test("captures inner instructions for ATA create (CPI)", async () => {
|
|
22
|
+
const server = new LiteSVMRpcServer();
|
|
23
|
+
async function call<T = any>(method: string, params?: unknown): Promise<RpcResp<T>> {
|
|
24
|
+
return (await server.handleRequest(jsonReq(method, params))) as RpcResp<T>;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Payer + airdrop
|
|
28
|
+
const payer = Keypair.generate();
|
|
29
|
+
const recip = Keypair.generate();
|
|
30
|
+
await call("requestAirdrop", [payer.publicKey.toBase58(), 1 * LAMPORTS_PER_SOL]);
|
|
31
|
+
|
|
32
|
+
// Create a test mint via admin helper
|
|
33
|
+
const mintResp = await call<{ mint: string }>("solforgeCreateMint", [null, 6, null]);
|
|
34
|
+
expect(mintResp.error).toBeUndefined();
|
|
35
|
+
const mint = new PublicKey(mintResp.result!.mint);
|
|
36
|
+
|
|
37
|
+
// Build 1 ATA instruction that triggers CPIs into system + token
|
|
38
|
+
const bh = await call<{ value: { blockhash: string } }>("getLatestBlockhash", []);
|
|
39
|
+
const ata = await getAssociatedTokenAddress(mint, recip.publicKey, false);
|
|
40
|
+
const ix = createAssociatedTokenAccountInstruction(payer.publicKey, ata, recip.publicKey, mint);
|
|
41
|
+
const msg = new TransactionMessage({ payerKey: payer.publicKey, recentBlockhash: bh.result!.value.blockhash, instructions: [ix] }).compileToLegacyMessage();
|
|
42
|
+
const tx = new VersionedTransaction(msg);
|
|
43
|
+
tx.sign([payer]);
|
|
44
|
+
|
|
45
|
+
const sigResp = await call<string>("sendTransaction", [Buffer.from(tx.serialize()).toString("base64")]);
|
|
46
|
+
expect(sigResp.error).toBeUndefined();
|
|
47
|
+
const sig = sigResp.result!;
|
|
48
|
+
|
|
49
|
+
const txResp = await call<any>("getTransaction", [sig, { encoding: "json" }]);
|
|
50
|
+
expect(txResp.error).toBeUndefined();
|
|
51
|
+
const tr = txResp.result!;
|
|
52
|
+
|
|
53
|
+
// At least one top-level instruction
|
|
54
|
+
expect(Array.isArray(tr.transaction.message.instructions)).toBe(true);
|
|
55
|
+
expect(tr.transaction.message.instructions.length).toBe(1);
|
|
56
|
+
|
|
57
|
+
// Check inner instructions captured or (worst case) logs exist
|
|
58
|
+
const ii = tr.meta.innerInstructions;
|
|
59
|
+
const logs = tr.meta.logMessages || [];
|
|
60
|
+
expect(Array.isArray(ii)).toBe(true);
|
|
61
|
+
// At minimum, either we have structured inner ixs, or logs were captured
|
|
62
|
+
expect(ii.length > 0 || logs.length > 0).toBe(true);
|
|
63
|
+
});
|
|
@@ -16,32 +16,67 @@ 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
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
28
|
+
const staticKeys = rawKeys
|
|
29
|
+
.map((k) => {
|
|
30
|
+
try {
|
|
31
|
+
return typeof k === "string" ? new PublicKey(k) : (k as PublicKey);
|
|
32
|
+
} catch {
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
})
|
|
36
|
+
.filter(Boolean) as PublicKey[];
|
|
37
|
+
// Pre snapshots and balances
|
|
38
|
+
const preBalances = staticKeys.map((pk) => {
|
|
39
|
+
try {
|
|
40
|
+
return Number(context.svm.getBalance(pk));
|
|
41
|
+
} catch {
|
|
42
|
+
return 0;
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
const preAccountStates = staticKeys.map((pk) => {
|
|
46
|
+
try {
|
|
47
|
+
const addr = pk.toBase58();
|
|
48
|
+
const acc = context.svm.getAccount(pk);
|
|
49
|
+
if (!acc) return { address: addr, pre: null } as const;
|
|
50
|
+
return {
|
|
51
|
+
address: addr,
|
|
52
|
+
pre: {
|
|
53
|
+
lamports: Number(acc.lamports || 0n),
|
|
54
|
+
ownerProgram: new PublicKey(acc.owner).toBase58(),
|
|
55
|
+
executable: !!acc.executable,
|
|
56
|
+
rentEpoch: Number(acc.rentEpoch || 0),
|
|
57
|
+
dataLen: acc.data?.length ?? 0,
|
|
58
|
+
dataBase64: undefined,
|
|
59
|
+
lastSlot: Number(context.slot),
|
|
60
|
+
},
|
|
61
|
+
} as const;
|
|
62
|
+
} catch {
|
|
63
|
+
return { address: pk.toBase58(), pre: null } as const;
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
try {
|
|
67
|
+
if (process.env.DEBUG_TX_CAPTURE === "1") {
|
|
68
|
+
console.debug(
|
|
69
|
+
`[tx-capture] pre snapshots: keys=${staticKeys.length} captured=${preAccountStates.length}`,
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
} catch {}
|
|
41
73
|
|
|
42
74
|
// Collect SPL token accounts from instructions for pre/post token balance snapshots
|
|
43
|
-
const msgAny
|
|
44
|
-
|
|
75
|
+
const msgAny = msg as unknown as {
|
|
76
|
+
compiledInstructions?: unknown[];
|
|
77
|
+
instructions?: unknown[];
|
|
78
|
+
};
|
|
79
|
+
const compiled: unknown[] = Array.isArray(msgAny.compiledInstructions)
|
|
45
80
|
? msgAny.compiledInstructions
|
|
46
81
|
: Array.isArray(msgAny.instructions)
|
|
47
82
|
? msgAny.instructions
|
|
@@ -67,7 +102,7 @@ export const sendTransaction: RpcMethodHandler = (id, params, context) => {
|
|
|
67
102
|
} catch {}
|
|
68
103
|
}
|
|
69
104
|
// Pre token balances
|
|
70
|
-
const preTokenBalances:
|
|
105
|
+
const preTokenBalances: unknown[] = [];
|
|
71
106
|
const ataToInfo = new Map<
|
|
72
107
|
string,
|
|
73
108
|
{
|
|
@@ -124,11 +159,12 @@ export const sendTransaction: RpcMethodHandler = (id, params, context) => {
|
|
|
124
159
|
} catch {}
|
|
125
160
|
}
|
|
126
161
|
|
|
127
|
-
|
|
162
|
+
const result = context.svm.sendTransaction(tx);
|
|
128
163
|
|
|
129
164
|
try {
|
|
130
|
-
|
|
131
|
-
const maybeErr =
|
|
165
|
+
const rawErr = (result as { err?: unknown }).err;
|
|
166
|
+
const maybeErr =
|
|
167
|
+
typeof rawErr === "function" ? (rawErr as () => unknown)() : rawErr;
|
|
132
168
|
if (maybeErr) {
|
|
133
169
|
return context.createErrorResponse(
|
|
134
170
|
id,
|
|
@@ -139,20 +175,48 @@ export const sendTransaction: RpcMethodHandler = (id, params, context) => {
|
|
|
139
175
|
}
|
|
140
176
|
} catch {}
|
|
141
177
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
178
|
+
const signature = tx.signatures[0]
|
|
179
|
+
? context.encodeBase58(tx.signatures[0])
|
|
180
|
+
: context.encodeBase58(new Uint8Array(64).fill(0));
|
|
181
|
+
context.notifySignature(signature);
|
|
182
|
+
// Snapshot post balances and capture logs for rich view
|
|
183
|
+
const postBalances = staticKeys.map((pk) => {
|
|
184
|
+
try {
|
|
185
|
+
return Number(context.svm.getBalance(pk));
|
|
186
|
+
} catch {
|
|
187
|
+
return 0;
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
const postAccountStates = staticKeys.map((pk) => {
|
|
191
|
+
try {
|
|
192
|
+
const addr = pk.toBase58();
|
|
193
|
+
const acc = context.svm.getAccount(pk);
|
|
194
|
+
if (!acc) return { address: addr, post: null } as const;
|
|
195
|
+
return {
|
|
196
|
+
address: addr,
|
|
197
|
+
post: {
|
|
198
|
+
lamports: Number(acc.lamports || 0n),
|
|
199
|
+
ownerProgram: new PublicKey(acc.owner).toBase58(),
|
|
200
|
+
executable: !!acc.executable,
|
|
201
|
+
rentEpoch: Number(acc.rentEpoch || 0),
|
|
202
|
+
dataLen: acc.data?.length ?? 0,
|
|
203
|
+
dataBase64: undefined,
|
|
204
|
+
lastSlot: Number(context.slot),
|
|
205
|
+
},
|
|
206
|
+
} as const;
|
|
207
|
+
} catch {
|
|
208
|
+
return { address: pk.toBase58(), post: null } as const;
|
|
209
|
+
}
|
|
210
|
+
});
|
|
211
|
+
try {
|
|
212
|
+
if (process.env.DEBUG_TX_CAPTURE === "1") {
|
|
213
|
+
console.debug(
|
|
214
|
+
`[tx-capture] post snapshots: keys=${staticKeys.length} captured=${postAccountStates.length}`,
|
|
215
|
+
);
|
|
216
|
+
}
|
|
217
|
+
} catch {}
|
|
154
218
|
// Post token balances
|
|
155
|
-
const postTokenBalances:
|
|
219
|
+
const postTokenBalances: unknown[] = [];
|
|
156
220
|
for (const addr of tokenAccountSet) {
|
|
157
221
|
try {
|
|
158
222
|
const pk = new PublicKey(addr);
|
|
@@ -202,31 +266,159 @@ export const sendTransaction: RpcMethodHandler = (id, params, context) => {
|
|
|
202
266
|
}
|
|
203
267
|
} catch {}
|
|
204
268
|
}
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
269
|
+
let logs: string[] = [];
|
|
270
|
+
let innerInstructions: unknown[] = [];
|
|
271
|
+
let computeUnits: number | null = null;
|
|
272
|
+
let returnData: { programId: string; dataBase64: string } | null = null;
|
|
273
|
+
try {
|
|
274
|
+
const DBG = process.env.DEBUG_TX_CAPTURE === "1";
|
|
275
|
+
const r: any = result as any;
|
|
276
|
+
// Logs can be on TransactionMetadata or in meta() for failures
|
|
277
|
+
try {
|
|
278
|
+
if (typeof r?.logs === "function") logs = r.logs();
|
|
279
|
+
} catch {}
|
|
280
|
+
let metaObj: any | undefined;
|
|
281
|
+
// Success shape: methods on result
|
|
282
|
+
if (
|
|
283
|
+
typeof r?.innerInstructions === "function" ||
|
|
284
|
+
typeof r?.computeUnitsConsumed === "function" ||
|
|
285
|
+
typeof r?.returnData === "function"
|
|
286
|
+
) {
|
|
287
|
+
metaObj = r;
|
|
288
|
+
}
|
|
289
|
+
// Failed shape: meta() returns TransactionMetadata
|
|
290
|
+
if (!metaObj && typeof r?.meta === "function") {
|
|
291
|
+
try {
|
|
292
|
+
metaObj = r.meta();
|
|
293
|
+
if (!logs.length && typeof metaObj?.logs === "function") {
|
|
294
|
+
logs = metaObj.logs();
|
|
295
|
+
}
|
|
296
|
+
} catch (e) {
|
|
297
|
+
if (DBG)
|
|
298
|
+
console.debug("[tx-capture] meta() threw while extracting:", e);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
// Extract richer metadata from whichever object exposes it
|
|
302
|
+
if (metaObj) {
|
|
303
|
+
try {
|
|
304
|
+
const inner = metaObj.innerInstructions?.();
|
|
305
|
+
if (Array.isArray(inner)) {
|
|
306
|
+
innerInstructions = inner.map((group: any, index: number) => {
|
|
307
|
+
const instructions = Array.isArray(group)
|
|
308
|
+
? group
|
|
309
|
+
.map((ii: any) => {
|
|
310
|
+
try {
|
|
311
|
+
const inst = ii.instruction?.();
|
|
312
|
+
const accIdxs: number[] = Array.from(
|
|
313
|
+
inst?.accounts?.() || [],
|
|
314
|
+
);
|
|
315
|
+
const dataBytes: Uint8Array =
|
|
316
|
+
inst?.data?.() || new Uint8Array();
|
|
317
|
+
return {
|
|
318
|
+
programIdIndex: Number(
|
|
319
|
+
inst?.programIdIndex?.() ?? 0,
|
|
320
|
+
),
|
|
321
|
+
accounts: accIdxs,
|
|
322
|
+
data: context.encodeBase58(dataBytes),
|
|
323
|
+
stackHeight: Number(ii.stackHeight?.() ?? 0),
|
|
324
|
+
};
|
|
325
|
+
} catch {
|
|
326
|
+
return null;
|
|
327
|
+
}
|
|
328
|
+
})
|
|
329
|
+
.filter(Boolean)
|
|
330
|
+
: [];
|
|
331
|
+
return { index, instructions };
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
} catch (e) {
|
|
335
|
+
if (DBG)
|
|
336
|
+
console.debug(
|
|
337
|
+
"[tx-capture] innerInstructions extraction failed:",
|
|
338
|
+
e,
|
|
339
|
+
);
|
|
340
|
+
}
|
|
341
|
+
try {
|
|
342
|
+
const cu = metaObj.computeUnitsConsumed?.();
|
|
343
|
+
if (typeof cu === "bigint") computeUnits = Number(cu);
|
|
344
|
+
} catch (e) {
|
|
345
|
+
if (DBG)
|
|
346
|
+
console.debug(
|
|
347
|
+
"[tx-capture] computeUnitsConsumed extraction failed:",
|
|
348
|
+
e,
|
|
349
|
+
);
|
|
350
|
+
}
|
|
351
|
+
try {
|
|
352
|
+
const rd = metaObj.returnData?.();
|
|
353
|
+
if (rd) {
|
|
354
|
+
const pid = new PublicKey(rd.programId()).toBase58();
|
|
355
|
+
const dataB64 = Buffer.from(rd.data()).toString("base64");
|
|
356
|
+
returnData = { programId: pid, dataBase64: dataB64 };
|
|
357
|
+
}
|
|
358
|
+
} catch (e) {
|
|
359
|
+
if (DBG)
|
|
360
|
+
console.debug(
|
|
361
|
+
"[tx-capture] returnData extraction failed:",
|
|
362
|
+
e,
|
|
363
|
+
);
|
|
364
|
+
}
|
|
365
|
+
} else if (DBG) {
|
|
366
|
+
console.debug(
|
|
367
|
+
"[tx-capture] no metadata object found on result shape",
|
|
368
|
+
);
|
|
369
|
+
}
|
|
370
|
+
} catch {}
|
|
371
|
+
try {
|
|
372
|
+
if (process.env.DEBUG_TX_CAPTURE === "1") {
|
|
373
|
+
console.debug(
|
|
374
|
+
`[tx-capture] sendTransaction meta: logs=${logs.length} innerGroups=${Array.isArray(innerInstructions) ? innerInstructions.length : 0} computeUnits=${computeUnits} returnData=${returnData ? "yes" : "no"}`,
|
|
375
|
+
);
|
|
376
|
+
}
|
|
377
|
+
} catch {}
|
|
378
|
+
context.recordTransaction(signature, tx, {
|
|
379
|
+
logs,
|
|
380
|
+
fee: 5000,
|
|
381
|
+
blockTime: Math.floor(Date.now() / 1000),
|
|
382
|
+
preBalances,
|
|
383
|
+
postBalances,
|
|
384
|
+
preTokenBalances,
|
|
385
|
+
postTokenBalances,
|
|
386
|
+
innerInstructions,
|
|
387
|
+
computeUnits,
|
|
388
|
+
returnData,
|
|
389
|
+
accountStates: (() => {
|
|
390
|
+
try {
|
|
391
|
+
const byAddr = new Map<string, { pre?: any; post?: any }>();
|
|
392
|
+
for (const s of preAccountStates)
|
|
393
|
+
byAddr.set(s.address, { pre: s.pre || null });
|
|
394
|
+
for (const s of postAccountStates) {
|
|
395
|
+
const e = byAddr.get(s.address) || {};
|
|
396
|
+
e.post = s.post || null;
|
|
397
|
+
byAddr.set(s.address, e);
|
|
398
|
+
}
|
|
399
|
+
return Array.from(byAddr.entries()).map(([address, v]) => ({
|
|
400
|
+
address,
|
|
401
|
+
pre: v.pre || null,
|
|
402
|
+
post: v.post || null,
|
|
403
|
+
}));
|
|
404
|
+
} catch {
|
|
405
|
+
return [] as Array<{
|
|
406
|
+
address: string;
|
|
407
|
+
pre?: unknown;
|
|
408
|
+
post?: unknown;
|
|
409
|
+
}>;
|
|
410
|
+
}
|
|
411
|
+
})(),
|
|
412
|
+
});
|
|
222
413
|
|
|
223
414
|
return context.createSuccessResponse(id, signature);
|
|
224
|
-
} catch (error:
|
|
415
|
+
} catch (error: unknown) {
|
|
416
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
225
417
|
return context.createErrorResponse(
|
|
226
418
|
id,
|
|
227
419
|
-32003,
|
|
228
420
|
"Transaction failed",
|
|
229
|
-
|
|
421
|
+
message,
|
|
230
422
|
);
|
|
231
423
|
}
|
|
232
424
|
};
|
|
@@ -45,12 +45,13 @@ export const simulateTransaction: RpcMethodHandler = (id, params, context) => {
|
|
|
45
45
|
: null,
|
|
46
46
|
},
|
|
47
47
|
});
|
|
48
|
-
} catch (error:
|
|
48
|
+
} catch (error: unknown) {
|
|
49
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
49
50
|
return context.createErrorResponse(
|
|
50
51
|
id,
|
|
51
52
|
-32003,
|
|
52
53
|
"Simulation failed",
|
|
53
|
-
|
|
54
|
+
message,
|
|
54
55
|
);
|
|
55
56
|
}
|
|
56
57
|
};
|