solforge 0.2.12 → 0.2.14

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.
Files changed (175) hide show
  1. package/package.json +1 -5
  2. package/start.cjs +19 -23
  3. package/docs/API.md +0 -379
  4. package/docs/CONFIGURATION.md +0 -407
  5. package/docs/bun-single-file-executable.md +0 -585
  6. package/docs/cli-plan.md +0 -154
  7. package/docs/data-indexing-plan.md +0 -214
  8. package/docs/gui-roadmap.md +0 -202
  9. package/scripts/decode-b58.ts +0 -10
  10. package/scripts/install.sh +0 -112
  11. package/server/index.ts +0 -5
  12. package/server/lib/base58.ts +0 -33
  13. package/server/lib/faucet.ts +0 -110
  14. package/server/lib/instruction-parser.ts +0 -328
  15. package/server/lib/parsers/spl-associated-token-account.ts +0 -50
  16. package/server/lib/parsers/spl-token.ts +0 -340
  17. package/server/lib/spl-token.ts +0 -57
  18. package/server/methods/TEMPLATE.md +0 -117
  19. package/server/methods/account/get-account-info.ts +0 -86
  20. package/server/methods/account/get-balance.ts +0 -23
  21. package/server/methods/account/get-multiple-accounts.ts +0 -84
  22. package/server/methods/account/get-parsed-account-info.ts +0 -17
  23. package/server/methods/account/index.ts +0 -12
  24. package/server/methods/account/parsers/index.ts +0 -52
  25. package/server/methods/account/parsers/loader-upgradeable.ts +0 -79
  26. package/server/methods/account/parsers/spl-token.ts +0 -256
  27. package/server/methods/account/parsers/system.ts +0 -4
  28. package/server/methods/account/request-airdrop.ts +0 -271
  29. package/server/methods/admin/adopt-mint-authority.ts +0 -94
  30. package/server/methods/admin/clone-program-accounts.ts +0 -55
  31. package/server/methods/admin/clone-program.ts +0 -152
  32. package/server/methods/admin/clone-token-accounts.ts +0 -117
  33. package/server/methods/admin/clone-token-mint.ts +0 -82
  34. package/server/methods/admin/create-mint.ts +0 -114
  35. package/server/methods/admin/create-token-account.ts +0 -137
  36. package/server/methods/admin/helpers.ts +0 -70
  37. package/server/methods/admin/index.ts +0 -10
  38. package/server/methods/admin/list-mints.ts +0 -21
  39. package/server/methods/admin/load-program.ts +0 -52
  40. package/server/methods/admin/mint-to.ts +0 -266
  41. package/server/methods/block/get-block-height.ts +0 -5
  42. package/server/methods/block/get-block.ts +0 -31
  43. package/server/methods/block/get-blocks-with-limit.ts +0 -19
  44. package/server/methods/block/get-latest-blockhash.ts +0 -12
  45. package/server/methods/block/get-slot.ts +0 -5
  46. package/server/methods/block/index.ts +0 -6
  47. package/server/methods/block/is-blockhash-valid.ts +0 -19
  48. package/server/methods/epoch/get-cluster-nodes.ts +0 -17
  49. package/server/methods/epoch/get-epoch-info.ts +0 -16
  50. package/server/methods/epoch/get-epoch-schedule.ts +0 -15
  51. package/server/methods/epoch/get-highest-snapshot-slot.ts +0 -9
  52. package/server/methods/epoch/get-leader-schedule.ts +0 -8
  53. package/server/methods/epoch/get-max-retransmit-slot.ts +0 -9
  54. package/server/methods/epoch/get-max-shred-insert-slot.ts +0 -9
  55. package/server/methods/epoch/get-slot-leader.ts +0 -6
  56. package/server/methods/epoch/get-slot-leaders.ts +0 -9
  57. package/server/methods/epoch/get-stake-activation.ts +0 -9
  58. package/server/methods/epoch/get-stake-minimum-delegation.ts +0 -9
  59. package/server/methods/epoch/get-vote-accounts.ts +0 -19
  60. package/server/methods/epoch/index.ts +0 -13
  61. package/server/methods/epoch/minimum-ledger-slot.ts +0 -5
  62. package/server/methods/fee/get-fee-calculator-for-blockhash.ts +0 -12
  63. package/server/methods/fee/get-fee-for-message.ts +0 -8
  64. package/server/methods/fee/get-fee-rate-governor.ts +0 -16
  65. package/server/methods/fee/get-fees.ts +0 -14
  66. package/server/methods/fee/get-recent-prioritization-fees.ts +0 -22
  67. package/server/methods/fee/index.ts +0 -5
  68. package/server/methods/get-address-lookup-table.ts +0 -27
  69. package/server/methods/index.ts +0 -265
  70. package/server/methods/performance/get-recent-performance-samples.ts +0 -25
  71. package/server/methods/performance/get-transaction-count.ts +0 -5
  72. package/server/methods/performance/index.ts +0 -2
  73. package/server/methods/program/get-block-commitment.ts +0 -9
  74. package/server/methods/program/get-block-production.ts +0 -14
  75. package/server/methods/program/get-block-time.ts +0 -21
  76. package/server/methods/program/get-blocks.ts +0 -11
  77. package/server/methods/program/get-first-available-block.ts +0 -9
  78. package/server/methods/program/get-genesis-hash.ts +0 -6
  79. package/server/methods/program/get-identity.ts +0 -6
  80. package/server/methods/program/get-inflation-governor.ts +0 -15
  81. package/server/methods/program/get-inflation-rate.ts +0 -10
  82. package/server/methods/program/get-inflation-reward.ts +0 -12
  83. package/server/methods/program/get-largest-accounts.ts +0 -8
  84. package/server/methods/program/get-parsed-program-accounts.ts +0 -12
  85. package/server/methods/program/get-parsed-token-accounts-by-delegate.ts +0 -12
  86. package/server/methods/program/get-parsed-token-accounts-by-owner.ts +0 -12
  87. package/server/methods/program/get-program-accounts.ts +0 -221
  88. package/server/methods/program/get-supply.ts +0 -13
  89. package/server/methods/program/get-token-account-balance.ts +0 -60
  90. package/server/methods/program/get-token-accounts-by-delegate.ts +0 -82
  91. package/server/methods/program/get-token-accounts-by-owner.ts +0 -416
  92. package/server/methods/program/get-token-largest-accounts.ts +0 -81
  93. package/server/methods/program/get-token-supply.ts +0 -39
  94. package/server/methods/program/index.ts +0 -21
  95. package/server/methods/solforge/index.ts +0 -158
  96. package/server/methods/system/get-health.ts +0 -5
  97. package/server/methods/system/get-minimum-balance-for-rent-exemption.ts +0 -13
  98. package/server/methods/system/get-version.ts +0 -9
  99. package/server/methods/system/index.ts +0 -3
  100. package/server/methods/transaction/get-confirmed-transaction.ts +0 -11
  101. package/server/methods/transaction/get-parsed-transaction.ts +0 -17
  102. package/server/methods/transaction/get-signature-statuses.ts +0 -79
  103. package/server/methods/transaction/get-signatures-for-address.ts +0 -41
  104. package/server/methods/transaction/get-transaction.ts +0 -639
  105. package/server/methods/transaction/index.ts +0 -7
  106. package/server/methods/transaction/inner-instructions.test.ts +0 -104
  107. package/server/methods/transaction/send-transaction.ts +0 -469
  108. package/server/methods/transaction/simulate-transaction.ts +0 -57
  109. package/server/rpc-server.ts +0 -521
  110. package/server/types.ts +0 -109
  111. package/server/ws-server.ts +0 -178
  112. package/src/api-server-entry.ts +0 -109
  113. package/src/cli/bootstrap.ts +0 -67
  114. package/src/cli/commands/airdrop.ts +0 -37
  115. package/src/cli/commands/config.ts +0 -39
  116. package/src/cli/commands/mint.ts +0 -187
  117. package/src/cli/commands/program-clone.ts +0 -122
  118. package/src/cli/commands/program-load.ts +0 -64
  119. package/src/cli/commands/rpc-start.ts +0 -49
  120. package/src/cli/commands/token-adopt-authority.ts +0 -37
  121. package/src/cli/commands/token-clone.ts +0 -112
  122. package/src/cli/commands/token-create.ts +0 -81
  123. package/src/cli/main.ts +0 -158
  124. package/src/cli/run-solforge.ts +0 -112
  125. package/src/cli/setup-utils.ts +0 -54
  126. package/src/cli/setup-wizard.ts +0 -258
  127. package/src/cli/utils/args.ts +0 -15
  128. package/src/commands/add-program.ts +0 -333
  129. package/src/commands/init.ts +0 -122
  130. package/src/commands/list.ts +0 -136
  131. package/src/commands/mint.ts +0 -287
  132. package/src/commands/start.ts +0 -881
  133. package/src/commands/status.ts +0 -99
  134. package/src/commands/stop.ts +0 -405
  135. package/src/config/index.ts +0 -146
  136. package/src/config/manager.ts +0 -157
  137. package/src/db/index.ts +0 -83
  138. package/src/db/schema/accounts.ts +0 -23
  139. package/src/db/schema/address-signatures.ts +0 -31
  140. package/src/db/schema/index.ts +0 -6
  141. package/src/db/schema/meta-kv.ts +0 -9
  142. package/src/db/schema/transactions.ts +0 -36
  143. package/src/db/schema/tx-account-states.ts +0 -23
  144. package/src/db/schema/tx-accounts.ts +0 -33
  145. package/src/db/tx-store.ts +0 -264
  146. package/src/gui/public/app.css +0 -1556
  147. package/src/gui/public/build/main.css +0 -1569
  148. package/src/gui/public/build/main.js +0 -303
  149. package/src/gui/public/build/main.js.txt +0 -231
  150. package/src/gui/public/index.html +0 -19
  151. package/src/gui/server.ts +0 -296
  152. package/src/gui/src/api.ts +0 -127
  153. package/src/gui/src/app.tsx +0 -441
  154. package/src/gui/src/components/airdrop-mint-form.tsx +0 -246
  155. package/src/gui/src/components/clone-program-modal.tsx +0 -202
  156. package/src/gui/src/components/clone-token-modal.tsx +0 -230
  157. package/src/gui/src/components/modal.tsx +0 -134
  158. package/src/gui/src/components/programs-panel.tsx +0 -124
  159. package/src/gui/src/components/status-panel.tsx +0 -136
  160. package/src/gui/src/components/tokens-panel.tsx +0 -122
  161. package/src/gui/src/hooks/use-interval.ts +0 -17
  162. package/src/gui/src/index.css +0 -557
  163. package/src/gui/src/main.tsx +0 -17
  164. package/src/index.ts +0 -216
  165. package/src/migrations-bundled.ts +0 -23
  166. package/src/rpc/start.ts +0 -44
  167. package/src/services/api-server.ts +0 -504
  168. package/src/services/port-manager.ts +0 -174
  169. package/src/services/process-registry.ts +0 -153
  170. package/src/services/program-cloner.ts +0 -317
  171. package/src/services/token-cloner.ts +0 -811
  172. package/src/services/validator.ts +0 -293
  173. package/src/types/config.ts +0 -110
  174. package/src/utils/shell.ts +0 -110
  175. package/src/utils/token-loader.ts +0 -115
@@ -1,416 +0,0 @@
1
- import {
2
- ACCOUNT_SIZE,
3
- getAssociatedTokenAddressSync,
4
- TOKEN_2022_PROGRAM_ID,
5
- TOKEN_PROGRAM_ID,
6
- unpackAccount,
7
- unpackMint,
8
- } from "@solana/spl-token";
9
- import { type AccountInfo, PublicKey } from "@solana/web3.js";
10
- import type { RpcMethodHandler } from "../../types";
11
-
12
- export const getTokenAccountsByOwner: RpcMethodHandler = async (
13
- id,
14
- params,
15
- context,
16
- ) => {
17
- try {
18
- const [ownerStr, filter, config] = params || [];
19
- if (!ownerStr) throw new Error("owner public key required");
20
- const owner = new PublicKey(ownerStr);
21
- const wantMint: string | null = filter?.mint ? String(filter.mint) : null;
22
- const requestedProgramId: string | null = filter?.programId
23
- ? String(filter.programId)
24
- : null;
25
- const encoding: string = config?.encoding || "jsonParsed";
26
- const classicId = TOKEN_PROGRAM_ID.toBase58();
27
- const token2022Id = TOKEN_2022_PROGRAM_ID.toBase58();
28
- const programIds = requestedProgramId
29
- ? [requestedProgramId]
30
- : [classicId, token2022Id];
31
-
32
- // Query DB for accounts owned by both SPL Token programs (classic + 2022)
33
- const rows: Array<{ address: string; lastSlot: number }> = [];
34
- for (const programId of programIds) {
35
- try {
36
- const found =
37
- (await context.store?.getAccountsByOwner(programId, 50_000)) || [];
38
- rows.push(...found);
39
- } catch (dbErr) {
40
- try {
41
- console.warn("[rpc] getTokenAccountsByOwner: db read failed", dbErr);
42
- } catch {}
43
- }
44
- }
45
-
46
- const out: unknown[] = [];
47
- const seen = new Set<string>();
48
- for (const r of rows) {
49
- if (seen.has(r.address)) continue;
50
- try {
51
- const pk = new PublicKey(r.address);
52
- const acc = context.svm.getAccount(pk);
53
- if (!acc) continue;
54
- if ((acc.data?.length ?? 0) < 165) continue;
55
- let ownerPk: PublicKey;
56
- try {
57
- // acc.owner may already be a PublicKey in LiteSVM
58
- const rawOwner = (acc as { owner?: unknown }).owner;
59
- ownerPk =
60
- rawOwner &&
61
- typeof (rawOwner as { toBase58?: unknown }).toBase58 === "function"
62
- ? (rawOwner as PublicKey)
63
- : new PublicKey(String(rawOwner));
64
- } catch {
65
- ownerPk = TOKEN_PROGRAM_ID; // fallback avoids throw; unpackAccount will fail if wrong and be skipped
66
- }
67
- const programPk = ownerPk.equals(TOKEN_2022_PROGRAM_ID)
68
- ? TOKEN_2022_PROGRAM_ID
69
- : TOKEN_PROGRAM_ID;
70
- const dec = unpackAccount(
71
- pk,
72
- { data: Buffer.from(acc.data), owner: ownerPk },
73
- programPk,
74
- );
75
- const decMint = dec.mint.toBase58();
76
- const decOwner = dec.owner.toBase58();
77
- if (decOwner !== owner.toBase58()) continue;
78
- if (wantMint && decMint !== wantMint) continue;
79
- if (encoding === "jsonParsed") {
80
- let decimals = 0;
81
- try {
82
- const mintAcc = context.svm.getAccount(dec.mint);
83
- const mintOwnerPk = mintAcc
84
- ? ((): PublicKey => {
85
- const ro = (mintAcc as { owner?: unknown }).owner;
86
- return ro &&
87
- typeof (ro as { toBase58?: unknown }).toBase58 ===
88
- "function"
89
- ? (ro as PublicKey)
90
- : new PublicKey(String(ro));
91
- })()
92
- : programPk;
93
- const info = mintAcc
94
- ? unpackMint(
95
- dec.mint,
96
- {
97
- data: Buffer.from(mintAcc.data),
98
- owner: mintOwnerPk,
99
- } as AccountInfo<Buffer>,
100
- mintOwnerPk,
101
- )
102
- : null;
103
- decimals = info?.decimals ?? 0;
104
- } catch {}
105
- const amount = BigInt(dec.amount?.toString?.() ?? dec.amount ?? 0);
106
- const ui = decimals >= 0 ? Number(amount) / 10 ** decimals : null;
107
- const state = dec.isFrozen
108
- ? "frozen"
109
- : dec.isInitialized
110
- ? "initialized"
111
- : "uninitialized";
112
- const amountUi = {
113
- amount: amount.toString(),
114
- decimals,
115
- uiAmount: ui,
116
- uiAmountString: (ui ?? 0).toString(),
117
- };
118
- // delegatedAmount as UiTokenAmount per RPC schema
119
- const delegated = BigInt(
120
- dec.delegatedAmount?.toString?.() ?? dec.delegatedAmount ?? 0n,
121
- );
122
- const delegatedUiAmount =
123
- decimals >= 0 ? Number(delegated) / 10 ** decimals : null;
124
- const delegatedAmount = {
125
- amount: delegated.toString(),
126
- decimals,
127
- uiAmount: delegatedUiAmount,
128
- uiAmountString: (delegatedUiAmount ?? 0).toString(),
129
- };
130
- // rentExemptReserve only for native (wrapped SOL) accounts; value in lamports (9 decimals)
131
- let rentExemptReserve: {
132
- amount: string;
133
- decimals: number;
134
- uiAmount: number | null;
135
- uiAmountString: string;
136
- } | null = null;
137
- if (dec.isNative) {
138
- const lamports = BigInt(
139
- dec.rentExemptReserve?.toString?.() ??
140
- dec.rentExemptReserve ??
141
- 0n,
142
- );
143
- const lamportsUi = Number(lamports) / 1_000_000_000;
144
- rentExemptReserve = {
145
- amount: lamports.toString(),
146
- decimals: 9,
147
- uiAmount: lamportsUi,
148
- uiAmountString: lamportsUi.toString(),
149
- };
150
- }
151
- const programLabel = programPk.equals(TOKEN_2022_PROGRAM_ID)
152
- ? "spl-token-2022"
153
- : "spl-token";
154
- out.push({
155
- pubkey: r.address,
156
- account: {
157
- lamports: Number(acc.lamports || 0n),
158
- owner: ownerPk.toBase58(),
159
- executable: !!acc.executable,
160
- rentEpoch: Number(acc.rentEpoch || 0),
161
- data: {
162
- program: programLabel,
163
- parsed: {
164
- type: "account",
165
- info: {
166
- mint: decMint,
167
- owner: decOwner,
168
- tokenAmount: amountUi,
169
- state,
170
- isNative: !!dec.isNative,
171
- delegatedAmount: delegatedAmount,
172
- delegate: dec.delegate ? dec.delegate.toBase58() : null,
173
- rentExemptReserve,
174
- closeAuthority: dec.closeAuthority
175
- ? dec.closeAuthority.toBase58()
176
- : null,
177
- },
178
- },
179
- space: acc.data?.length ?? 0,
180
- },
181
- },
182
- });
183
- seen.add(r.address);
184
- } else {
185
- out.push({
186
- pubkey: r.address,
187
- account: {
188
- lamports: Number(acc.lamports || 0n),
189
- owner: ownerPk.toBase58(),
190
- executable: !!acc.executable,
191
- rentEpoch: Number(acc.rentEpoch || 0),
192
- data: [
193
- Buffer.from(acc.data).toString("base64"),
194
- "base64",
195
- ] as const,
196
- },
197
- });
198
- seen.add(r.address);
199
- }
200
- } catch {}
201
- }
202
- // Fallback: probe known mints' ATAs for this owner
203
- try {
204
- const mints = context.listMints ? context.listMints() : [];
205
- for (const m of mints) {
206
- try {
207
- const mintPk = new PublicKey(m);
208
- const mintAcc = context.svm.getAccount(mintPk);
209
- const mintOwnerPk = mintAcc
210
- ? ((): PublicKey => {
211
- const ro = (mintAcc as { owner?: unknown }).owner;
212
- return ro &&
213
- typeof (ro as { toBase58?: unknown }).toBase58 === "function"
214
- ? (ro as PublicKey)
215
- : new PublicKey(String(ro));
216
- })()
217
- : TOKEN_PROGRAM_ID;
218
- // Determine which token program this mint belongs to
219
- const programForMint = mintOwnerPk.equals(TOKEN_2022_PROGRAM_ID)
220
- ? TOKEN_2022_PROGRAM_ID
221
- : TOKEN_PROGRAM_ID;
222
- // If a specific programId filter was requested, honor it strictly
223
- if (
224
- requestedProgramId &&
225
- programForMint.toBase58() !== requestedProgramId
226
- ) {
227
- continue;
228
- }
229
-
230
- const ata = getAssociatedTokenAddressSync(
231
- mintPk,
232
- owner,
233
- true,
234
- programForMint,
235
- );
236
- const acc = context.svm.getAccount(ata);
237
- if (!acc || (acc.data?.length ?? 0) < ACCOUNT_SIZE) continue;
238
- if (seen.has(ata.toBase58())) continue;
239
- const rawOwner = (acc as { owner?: unknown }).owner;
240
- const ownerPk: PublicKey =
241
- rawOwner &&
242
- typeof (rawOwner as { toBase58?: unknown }).toBase58 === "function"
243
- ? (rawOwner as PublicKey)
244
- : new PublicKey(String(rawOwner));
245
- const programPk = ownerPk.equals(TOKEN_2022_PROGRAM_ID)
246
- ? TOKEN_2022_PROGRAM_ID
247
- : TOKEN_PROGRAM_ID;
248
- // If a programId filter was provided, skip non-matching accounts
249
- if (
250
- requestedProgramId &&
251
- programPk.toBase58() !== requestedProgramId
252
- ) {
253
- continue;
254
- }
255
- const dec = unpackAccount(
256
- ata,
257
- { data: Buffer.from(acc.data), owner: ownerPk },
258
- programPk,
259
- );
260
- const decMint = dec.mint.toBase58();
261
- const decOwner = dec.owner.toBase58();
262
- if (decOwner !== owner.toBase58()) continue;
263
- let decimals = 0;
264
- try {
265
- const mintAcc = context.svm.getAccount(dec.mint);
266
- const mintOwnerPk = mintAcc
267
- ? ((): PublicKey => {
268
- const ro = (mintAcc as { owner?: unknown }).owner;
269
- return ro &&
270
- typeof (ro as { toBase58?: unknown }).toBase58 ===
271
- "function"
272
- ? (ro as PublicKey)
273
- : new PublicKey(String(ro));
274
- })()
275
- : programPk;
276
- const info = mintAcc
277
- ? unpackMint(
278
- dec.mint,
279
- {
280
- data: Buffer.from(mintAcc.data),
281
- owner: mintOwnerPk,
282
- } as AccountInfo<Buffer>,
283
- mintOwnerPk,
284
- )
285
- : null;
286
- decimals = info?.decimals ?? 0;
287
- } catch {}
288
- const amount = BigInt(dec.amount?.toString?.() ?? dec.amount ?? 0);
289
- const ui = decimals >= 0 ? Number(amount) / 10 ** decimals : null;
290
- const state = dec.isFrozen
291
- ? "frozen"
292
- : dec.isInitialized
293
- ? "initialized"
294
- : "uninitialized";
295
- const amountUi = {
296
- amount: amount.toString(),
297
- decimals,
298
- uiAmount: ui,
299
- uiAmountString: (ui ?? 0).toString(),
300
- };
301
- const programLabel = programPk.equals(TOKEN_2022_PROGRAM_ID)
302
- ? "spl-token-2022"
303
- : "spl-token";
304
- out.push({
305
- pubkey: ata.toBase58(),
306
- account: {
307
- lamports: Number(acc.lamports || 0n),
308
- owner: ownerPk.toBase58(),
309
- executable: !!acc.executable,
310
- rentEpoch: Number(acc.rentEpoch || 0),
311
- data: {
312
- program: programLabel,
313
- parsed: {
314
- type: "account",
315
- info: {
316
- mint: decMint,
317
- owner: decOwner,
318
- tokenAmount: amountUi,
319
- state,
320
- isNative: !!dec.isNative,
321
- },
322
- },
323
- space: acc.data?.length ?? 0,
324
- },
325
- },
326
- });
327
- seen.add(ata.toBase58());
328
- } catch {}
329
- }
330
- } catch {}
331
-
332
- // Deduplicate: prefer the canonical ATA for each (owner,mint) under the mint's token program
333
- if (encoding === "jsonParsed") {
334
- try {
335
- const pick = new Map<string, number>();
336
- for (let i = 0; i < out.length; i++) {
337
- const entry = out[i];
338
- const pubkey: string = entry.pubkey;
339
- const info = entry.account?.data?.parsed?.info;
340
- const mintStr: string | undefined = info?.mint;
341
- const ownerStr: string | undefined = info?.owner;
342
- if (!mintStr || !ownerStr) continue;
343
- let canonical = pubkey;
344
- try {
345
- const mintPk = new PublicKey(mintStr);
346
- const ownerPk = new PublicKey(ownerStr);
347
- const mintAcc = context.svm.getAccount(mintPk);
348
- const mintOwnerPk = mintAcc
349
- ? ((): PublicKey => {
350
- const ro = (mintAcc as { owner?: unknown }).owner;
351
- return ro &&
352
- typeof (ro as { toBase58?: unknown }).toBase58 ===
353
- "function"
354
- ? (ro as PublicKey)
355
- : new PublicKey(String(ro));
356
- })()
357
- : TOKEN_PROGRAM_ID;
358
- const programForMint = mintOwnerPk.equals(TOKEN_2022_PROGRAM_ID)
359
- ? TOKEN_2022_PROGRAM_ID
360
- : TOKEN_PROGRAM_ID;
361
- const ata = getAssociatedTokenAddressSync(
362
- mintPk,
363
- ownerPk,
364
- true,
365
- programForMint,
366
- );
367
- canonical = ata.toBase58();
368
- } catch {}
369
- const key = `${ownerStr}:${mintStr}`;
370
- const prev = pick.get(key);
371
- if (prev === undefined) {
372
- // First time; keep if canonical, otherwise tentatively keep
373
- pick.set(key, i);
374
- // Prefer canonical if current isn't canonical but later we may find it
375
- if (pubkey !== canonical) pick.set(`${key}:prefer`, -1);
376
- } else {
377
- // If previous wasn't canonical and this one is, replace
378
- const prefer = pick.get(`${key}:prefer`) === -1;
379
- if (prefer && pubkey === canonical) {
380
- pick.set(key, i);
381
- pick.delete(`${key}:prefer`);
382
- }
383
- }
384
- }
385
-
386
- // Build filtered list keeping only chosen indices
387
- const keep = new Set<number>(
388
- Array.from(pick.values()).filter(
389
- (v) => typeof v === "number" && v >= 0,
390
- ),
391
- );
392
- const filtered: unknown[] = [];
393
- for (let i = 0; i < out.length; i++) {
394
- const e = out[i];
395
- const info = e.account?.data?.parsed?.info;
396
- const key =
397
- info?.owner && info?.mint ? `${info.owner}:${info.mint}` : null;
398
- if (key && keep.has(i)) filtered.push(e);
399
- else if (!key) filtered.push(e); // non-parsed or unexpected shape
400
- }
401
- out.length = 0;
402
- out.push(...filtered);
403
- } catch {}
404
- }
405
- return context.createSuccessResponse(id, {
406
- context: { slot: Number(context.slot) },
407
- value: out,
408
- });
409
- } catch (e: unknown) {
410
- try {
411
- console.error("[rpc] getTokenAccountsByOwner error", e);
412
- } catch {}
413
- const message = e instanceof Error ? e.message : String(e);
414
- return context.createErrorResponse(id, -32603, "Internal error", message);
415
- }
416
- };
@@ -1,81 +0,0 @@
1
- import {
2
- TOKEN_2022_PROGRAM_ID,
3
- TOKEN_PROGRAM_ID,
4
- unpackAccount,
5
- unpackMint,
6
- } from "@solana/spl-token";
7
- import { PublicKey } from "@solana/web3.js";
8
- import type { RpcMethodHandler } from "../../types";
9
-
10
- export const getTokenLargestAccounts: RpcMethodHandler = async (
11
- id,
12
- params,
13
- context,
14
- ) => {
15
- const [mintStr] = params || [];
16
- try {
17
- const mint = new PublicKey(mintStr);
18
- const mintAcc = context.svm.getAccount(mint);
19
- const programPk =
20
- mintAcc && new PublicKey(mintAcc.owner).equals(TOKEN_2022_PROGRAM_ID)
21
- ? TOKEN_2022_PROGRAM_ID
22
- : TOKEN_PROGRAM_ID;
23
- const mintInfo = mintAcc
24
- ? unpackMint(
25
- mint,
26
- {
27
- data: Buffer.from(mintAcc.data),
28
- owner: new PublicKey(mintAcc.owner),
29
- },
30
- programPk,
31
- )
32
- : null;
33
- const decimals = mintInfo?.decimals ?? 0;
34
- // Scan DB list of SPL token accounts and pick those with this mint
35
- const rows =
36
- (await context.store?.getAccountsByOwner(
37
- TOKEN_PROGRAM_ID.toBase58(),
38
- 50_000,
39
- )) || [];
40
- const list: Array<{ address: string; amount: bigint }> = [];
41
- for (const r of rows) {
42
- try {
43
- const acc = context.svm.getAccount(new PublicKey(r.address));
44
- if (!acc) continue;
45
- if ((acc.data?.length ?? 0) < 165) continue;
46
- const accOwnerPk = new PublicKey(acc.owner);
47
- const accProgramPk = accOwnerPk.equals(TOKEN_2022_PROGRAM_ID)
48
- ? TOKEN_2022_PROGRAM_ID
49
- : TOKEN_PROGRAM_ID;
50
- const dec = unpackAccount(
51
- new PublicKey(r.address),
52
- { data: Buffer.from(acc.data), owner: accOwnerPk },
53
- accProgramPk,
54
- );
55
- if (!dec.mint.equals(mint)) continue;
56
- const amount = BigInt(dec.amount?.toString?.() ?? dec.amount ?? 0);
57
- list.push({ address: r.address, amount });
58
- } catch {}
59
- }
60
- list.sort((a, b) =>
61
- a.amount < b.amount ? 1 : a.amount > b.amount ? -1 : 0,
62
- );
63
- const top = list.slice(0, 20).map((e) => {
64
- const ui = Number(e.amount) / 10 ** decimals;
65
- return {
66
- address: e.address,
67
- amount: e.amount.toString(),
68
- decimals,
69
- uiAmount: ui,
70
- uiAmountString: ui.toString(),
71
- };
72
- });
73
- return context.createSuccessResponse(id, {
74
- context: { slot: Number(context.slot) },
75
- value: top,
76
- });
77
- } catch (e: unknown) {
78
- const message = e instanceof Error ? e.message : String(e);
79
- return context.createErrorResponse(id, -32602, "Invalid params", message);
80
- }
81
- };
@@ -1,39 +0,0 @@
1
- import {
2
- TOKEN_2022_PROGRAM_ID,
3
- TOKEN_PROGRAM_ID,
4
- unpackMint,
5
- } from "@solana/spl-token";
6
- import { PublicKey } from "@solana/web3.js";
7
- import type { RpcMethodHandler } from "../../types";
8
-
9
- export const getTokenSupply: RpcMethodHandler = (id, params, context) => {
10
- const [mintStr] = params || [];
11
- try {
12
- const mint = new PublicKey(mintStr);
13
- const acc = context.svm.getAccount(mint);
14
- if (!acc) return context.createErrorResponse(id, -32602, "Mint not found");
15
- const ownerPk = new PublicKey(acc.owner);
16
- const programPk = ownerPk.equals(TOKEN_2022_PROGRAM_ID)
17
- ? TOKEN_2022_PROGRAM_ID
18
- : TOKEN_PROGRAM_ID;
19
- const info = unpackMint(
20
- mint,
21
- { data: Buffer.from(acc.data), owner: ownerPk },
22
- programPk,
23
- );
24
- const supply = BigInt(info.supply?.toString?.() ?? info.supply ?? 0);
25
- const ui = Number(supply) / 10 ** info.decimals;
26
- return context.createSuccessResponse(id, {
27
- context: { slot: Number(context.slot) },
28
- value: {
29
- amount: supply.toString(),
30
- decimals: info.decimals,
31
- uiAmount: ui,
32
- uiAmountString: ui.toString(),
33
- },
34
- });
35
- } catch (e: unknown) {
36
- const message = e instanceof Error ? e.message : String(e);
37
- return context.createErrorResponse(id, -32602, "Invalid params", message);
38
- }
39
- };
@@ -1,21 +0,0 @@
1
- export { getBlockCommitment } from "./get-block-commitment";
2
- export { getBlockProduction } from "./get-block-production";
3
- export { getBlockTime } from "./get-block-time";
4
- export { getBlocks } from "./get-blocks";
5
- export { getFirstAvailableBlock } from "./get-first-available-block";
6
- export { getGenesisHash } from "./get-genesis-hash";
7
- export { getIdentity } from "./get-identity";
8
- export { getInflationGovernor } from "./get-inflation-governor";
9
- export { getInflationRate } from "./get-inflation-rate";
10
- export { getInflationReward } from "./get-inflation-reward";
11
- export { getLargestAccounts } from "./get-largest-accounts";
12
- export { getParsedProgramAccounts } from "./get-parsed-program-accounts";
13
- export { getParsedTokenAccountsByDelegate } from "./get-parsed-token-accounts-by-delegate";
14
- export { getParsedTokenAccountsByOwner } from "./get-parsed-token-accounts-by-owner";
15
- export { getProgramAccounts } from "./get-program-accounts";
16
- export { getSupply } from "./get-supply";
17
- export { getTokenAccountBalance } from "./get-token-account-balance";
18
- export { getTokenAccountsByDelegate } from "./get-token-accounts-by-delegate";
19
- export { getTokenAccountsByOwner } from "./get-token-accounts-by-owner";
20
- export { getTokenLargestAccounts } from "./get-token-largest-accounts";
21
- export { getTokenSupply } from "./get-token-supply";