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,112 +0,0 @@
1
- #!/usr/bin/env sh
2
- set -e
3
-
4
- # SolForge installer (downloads GitHub release binary)
5
- # Usage: curl -fsSL https://sh.solforge.sh | sh
6
- # Optional: SOLFORGE_VERSION=v0.2.5 curl -fsSL https://sh.solforge.sh | sh
7
-
8
- REPO="nitishxyz/solforge"
9
- BIN_NAME="solforge"
10
- VERSION="${SOLFORGE_VERSION:-latest}"
11
-
12
- info() { printf "\033[1;34m[i]\033[0m %s\n" "$*"; }
13
- warn() { printf "\033[1;33m[!]\033[0m %s\n" "$*"; }
14
- err() { printf "\033[1;31m[x]\033[0m %s\n" "$*" 1>&2; }
15
-
16
- # Detect downloader
17
- http_get() {
18
- if command -v curl >/dev/null 2>&1; then
19
- curl -fsSL "$1"
20
- elif command -v wget >/dev/null 2>&1; then
21
- wget -qO- "$1"
22
- else
23
- err "Need 'curl' or 'wget' to download binaries"
24
- exit 1
25
- fi
26
- }
27
-
28
- http_down() {
29
- dest="$2"
30
- if command -v curl >/dev/null 2>&1; then
31
- curl -fL --progress-bar -o "$dest" "$1"
32
- else
33
- wget -qO "$dest" "$1"
34
- fi
35
- }
36
-
37
- # OS/arch detection
38
- uname_s=$(uname -s 2>/dev/null || echo unknown)
39
- uname_m=$(uname -m 2>/dev/null || echo unknown)
40
-
41
- case "$uname_s" in
42
- Linux) os="linux" ;;
43
- Darwin) os="darwin" ;;
44
- *) err "Unsupported OS: $uname_s"; exit 1 ;;
45
- esac
46
-
47
- case "$uname_m" in
48
- x86_64|amd64) arch="x64" ;;
49
- arm64|aarch64) arch="arm64" ;;
50
- *) err "Unsupported architecture: $uname_m"; exit 1 ;;
51
- esac
52
-
53
- asset="${BIN_NAME}-${os}-${arch}"
54
- ext=""
55
- filename="$asset$ext"
56
-
57
- # Build URL
58
- if [ "$VERSION" = "latest" ]; then
59
- base="https://github.com/$REPO/releases/latest/download"
60
- else
61
- base="https://github.com/$REPO/releases/download/$VERSION"
62
- fi
63
-
64
- url="$base/$filename"
65
-
66
- info "Installing $BIN_NAME ($os/$arch) from: $url"
67
-
68
- # Download
69
- tmpdir=${TMPDIR:-/tmp}
70
- tmpfile="$tmpdir/$filename"
71
- http_down "$url" "$tmpfile"
72
-
73
- # Make executable
74
- chmod +x "$tmpfile"
75
-
76
- # Choose install dir
77
- install_dir="/usr/local/bin"
78
- if [ ! -w "$install_dir" ]; then
79
- if command -v sudo >/dev/null 2>&1; then
80
- sudo_cmd="sudo"
81
- else
82
- sudo_cmd=""
83
- fi
84
- fi
85
-
86
- if [ -n "$sudo_cmd" ] && [ -d "$install_dir" ] && [ ! -w "$install_dir" ]; then
87
- info "Moving binary to $install_dir (requires sudo)"
88
- $sudo_cmd mv "$tmpfile" "$install_dir/$BIN_NAME"
89
- else
90
- # Fallback to user bin
91
- user_bin="$HOME/.local/bin"
92
- mkdir -p "$user_bin"
93
- info "Moving binary to $user_bin"
94
- mv "$tmpfile" "$user_bin/$BIN_NAME"
95
- install_dir="$user_bin"
96
- fi
97
-
98
- # Verify
99
- if "$install_dir/$BIN_NAME" --version >/dev/null 2>&1; then
100
- ver=$("$install_dir/$BIN_NAME" --version 2>/dev/null || true)
101
- info "$BIN_NAME installed: $ver"
102
- else
103
- warn "Installed, but failed to run --version"
104
- fi
105
-
106
- # PATH hint
107
- case ":$PATH:" in
108
- *":$install_dir:"*) :;;
109
- *) warn "Add $install_dir to your PATH to use '$BIN_NAME'" ;;
110
- esac
111
-
112
- info "Done. Run: $BIN_NAME --help"
package/server/index.ts DELETED
@@ -1,5 +0,0 @@
1
- export * from "./methods";
2
- export { rpcMethods } from "./methods";
3
- export { createLiteSVMRpcServer, LiteSVMRpcServer } from "./rpc-server";
4
- export * from "./types";
5
- export { createLiteSVMWebSocketServer } from "./ws-server";
@@ -1,33 +0,0 @@
1
- const ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
2
- const BASE = BigInt(ALPHABET.length);
3
-
4
- export function encodeBase58(bytes: Uint8Array): string {
5
- let num = 0n;
6
- for (let i = 0; i < bytes.length; i++)
7
- num = num * 256n + BigInt(bytes[i] || 0);
8
- let encoded = "";
9
- while (num > 0n) {
10
- const remainder = num % BASE;
11
- num = num / BASE;
12
- encoded = ALPHABET[Number(remainder)] + encoded;
13
- }
14
- for (let i = 0; i < bytes.length && bytes[i] === 0; i++)
15
- encoded = `1${encoded}`;
16
- return encoded || "1";
17
- }
18
-
19
- export function decodeBase58(str: string): Uint8Array {
20
- let num = 0n;
21
- for (const char of str) {
22
- const index = ALPHABET.indexOf(char);
23
- if (index === -1) throw new Error("Invalid base58 character");
24
- num = num * BASE + BigInt(index);
25
- }
26
- const bytes: number[] = [];
27
- while (num > 0n) {
28
- bytes.unshift(Number(num % 256n));
29
- num = num / 256n;
30
- }
31
- for (let i = 0; i < str.length && str[i] === "1"; i++) bytes.unshift(0);
32
- return new Uint8Array(bytes.length > 0 ? bytes : [0]);
33
- }
@@ -1,110 +0,0 @@
1
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
- import { dirname } from "node:path";
3
- import {
4
- Keypair,
5
- type PublicKey,
6
- SystemProgram,
7
- Transaction,
8
- } from "@solana/web3.js";
9
- import type { LiteSVM } from "litesvm";
10
-
11
- const DEFAULT_PATH =
12
- process.env.SOLFORGE_FAUCET_PATH || ".solforge/faucet.json";
13
- // Default to 1,000,000 SOL so we never run out in local dev.
14
- // Override with SOLFORGE_FAUCET_LAMPORTS if desired.
15
- const DEFAULT_INITIAL_LAMPORTS = BigInt(
16
- process.env.SOLFORGE_FAUCET_LAMPORTS || "1000000000000000",
17
- ); // 1e15 lamports = 1,000,000 SOL
18
-
19
- type FaucetFile = { secretKey: string; publicKey: string; createdAt: string };
20
-
21
- function ensureDir(path: string) {
22
- try {
23
- mkdirSync(dirname(path), { recursive: true });
24
- } catch {}
25
- }
26
-
27
- export function loadOrCreateFaucet(path: string = DEFAULT_PATH): Keypair {
28
- try {
29
- if (existsSync(path)) {
30
- const raw = readFileSync(path, "utf8");
31
- const data = JSON.parse(raw) as FaucetFile;
32
- const secret = Buffer.from(data.secretKey, "base64");
33
- return Keypair.fromSecretKey(new Uint8Array(secret));
34
- }
35
- } catch {}
36
-
37
- const kp = Keypair.generate();
38
- try {
39
- ensureDir(path);
40
- const payload: FaucetFile = {
41
- secretKey: Buffer.from(kp.secretKey).toString("base64"),
42
- publicKey: kp.publicKey.toBase58(),
43
- createdAt: new Date().toISOString(),
44
- };
45
- writeFileSync(path, JSON.stringify(payload, null, 2), "utf8");
46
- } catch {}
47
- return kp;
48
- }
49
-
50
- export function fundFaucetIfNeeded(
51
- svm: LiteSVM,
52
- faucet: Keypair,
53
- targetLamports: bigint = DEFAULT_INITIAL_LAMPORTS,
54
- ): bigint {
55
- let bal = 0n;
56
- try {
57
- bal = svm.getBalance(faucet.publicKey as PublicKey) || 0n;
58
- } catch {
59
- bal = 0n;
60
- }
61
- if (bal >= targetLamports) return bal;
62
-
63
- // Observed per-account airdrop cap ~10k SOL. Work around by creating feeder accounts,
64
- // airdropping to each, then transferring to the faucet until the target is reached.
65
- const LAMPORTS_PER_SOL = 1_000_000_000n;
66
- const PER_ACCOUNT_CAP = 10_000n * LAMPORTS_PER_SOL; // 10k SOL per feeder
67
- const FEE = 5_000n; // rough fee for legacy transfer
68
-
69
- let remaining = targetLamports - bal;
70
- let safety = 0;
71
- while (remaining > 0n && safety < 1000) {
72
- safety++;
73
- const feeder = Keypair.generate();
74
- const mint = remaining > PER_ACCOUNT_CAP ? PER_ACCOUNT_CAP : remaining;
75
- // Airdrop enough to cover transfer + fee
76
- try {
77
- svm.airdrop(feeder.publicKey as PublicKey, mint + FEE);
78
- } catch {
79
- // If airdrop fails, try smaller amount; if still fails, stop
80
- try {
81
- svm.airdrop(feeder.publicKey as PublicKey, 1_000_000_000n);
82
- } catch {
83
- break;
84
- }
85
- }
86
-
87
- // Transfer from feeder -> faucet
88
- try {
89
- const tx = new Transaction();
90
- try {
91
- tx.recentBlockhash = svm.latestBlockhash();
92
- } catch {}
93
- tx.add(
94
- SystemProgram.transfer({
95
- fromPubkey: feeder.publicKey,
96
- toPubkey: faucet.publicKey as PublicKey,
97
- lamports: Number(mint),
98
- }),
99
- );
100
- tx.sign(feeder);
101
- svm.sendTransaction(tx);
102
- remaining -= mint;
103
- } catch {}
104
- }
105
-
106
- try {
107
- bal = svm.getBalance(faucet.publicKey as PublicKey) || 0n;
108
- } catch {}
109
- return bal;
110
- }
@@ -1,328 +0,0 @@
1
- import {
2
- AddressLookupTableInstruction,
3
- ComputeBudgetInstruction,
4
- PublicKey,
5
- StakeInstruction,
6
- SystemInstruction,
7
- SystemProgram,
8
- TransactionInstruction,
9
- VoteInstruction,
10
- } from "@solana/web3.js";
11
- import {
12
- TOKEN_PROGRAM_ID,
13
- ASSOCIATED_TOKEN_PROGRAM_ID,
14
- TOKEN_2022_PROGRAM_ID,
15
- } from "@solana/spl-token";
16
- import { tryParseSplToken } from "./parsers/spl-token";
17
- import { tryParseAta } from "./parsers/spl-associated-token-account";
18
- import { decodeBase58 as _decodeBase58 } from "./base58";
19
-
20
- export type ParsedInstruction =
21
- | {
22
- program: string;
23
- programId: string;
24
- parsed: { type: string; info: unknown };
25
- }
26
- | { programId: string; accounts: string[]; data: string };
27
-
28
- function makeIx(
29
- programId: string,
30
- accountKeys: string[],
31
- accounts: number[],
32
- dataBase58: string,
33
- ): TransactionInstruction {
34
- const keys = accounts.map((i) => ({
35
- pubkey: new PublicKey(accountKeys[i] || SystemProgram.programId),
36
- isSigner: false,
37
- isWritable: false,
38
- }));
39
- const data = Buffer.from(_decodeBase58(dataBase58));
40
- return new TransactionInstruction({
41
- programId: new PublicKey(programId),
42
- keys,
43
- data,
44
- });
45
- }
46
-
47
- function ok(
48
- program: string,
49
- programId: string,
50
- type: string,
51
- info: unknown,
52
- ): ParsedInstruction {
53
- return { program, programId, parsed: { type, info } };
54
- }
55
-
56
- export function parseInstruction(
57
- programId: string,
58
- accounts: number[],
59
- dataBase58: string,
60
- accountKeys: string[],
61
- tokenBalanceHints?: Array<{ mint: string; decimals: number }>,
62
- ): ParsedInstruction {
63
- try {
64
- const pid = new PublicKey(programId);
65
- const ix = makeIx(programId, accountKeys, accounts, dataBase58);
66
-
67
- // SPL Token (legacy) and Token-2022
68
- if (pid.equals(TOKEN_PROGRAM_ID) || pid.equals(TOKEN_2022_PROGRAM_ID)) {
69
- const parsed = tryParseSplToken(
70
- ix,
71
- programId,
72
- accountKeys,
73
- dataBase58,
74
- tokenBalanceHints,
75
- );
76
- if (parsed) return parsed;
77
- }
78
-
79
- // Associated Token Account
80
- if (pid.equals(ASSOCIATED_TOKEN_PROGRAM_ID)) {
81
- const parsed = tryParseAta(ix, programId);
82
- if (parsed) return parsed;
83
- }
84
-
85
- // System Program
86
- if (pid.equals(SystemProgram.programId)) {
87
- try {
88
- const t = SystemInstruction.decodeInstructionType(ix);
89
- switch (t) {
90
- case "Create": {
91
- try {
92
- const p = SystemInstruction.decodeCreateAccount(ix);
93
- const from = p.fromPubkey.toBase58();
94
- const newAcc = p.newAccountPubkey.toBase58();
95
- const owner = p.programId.toBase58();
96
- return ok("system", programId, "createAccount", {
97
- // Explorer-compatible field names
98
- source: from,
99
- newAccount: newAcc,
100
- owner,
101
- lamports: Number(p.lamports),
102
- space: Number(p.space),
103
- // Keep legacy aliases too
104
- fromPubkey: from,
105
- newAccountPubkey: newAcc,
106
- programId: owner,
107
- });
108
- } catch {
109
- return ok("system", programId, "createAccount", {});
110
- }
111
- }
112
- case "Transfer": {
113
- try {
114
- const p = SystemInstruction.decodeTransfer(ix);
115
- return ok("system", programId, "transfer", {
116
- source: p.fromPubkey.toBase58(),
117
- destination: p.toPubkey.toBase58(),
118
- lamports: Number(p.lamports),
119
- });
120
- } catch {
121
- return ok("system", programId, "transfer", {});
122
- }
123
- }
124
- case "TransferWithSeed": {
125
- try {
126
- const p = SystemInstruction.decodeTransferWithSeed(ix);
127
- return ok("system", programId, "transferWithSeed", {
128
- fromPubkey: p.fromPubkey.toBase58(),
129
- basePubkey: p.basePubkey.toBase58(),
130
- toPubkey: p.toPubkey.toBase58(),
131
- lamports: Number(p.lamports),
132
- seed: p.seed,
133
- programId: p.programId.toBase58(),
134
- });
135
- } catch {
136
- return ok("system", programId, "transferWithSeed", {});
137
- }
138
- }
139
- case "Allocate": {
140
- try {
141
- const p = SystemInstruction.decodeAllocate(ix);
142
- return ok("system", programId, "allocate", {
143
- accountPubkey: p.accountPubkey.toBase58(),
144
- space: Number(p.space),
145
- });
146
- } catch {
147
- return ok("system", programId, "allocate", {});
148
- }
149
- }
150
- case "AllocateWithSeed": {
151
- try {
152
- const p = SystemInstruction.decodeAllocateWithSeed(ix);
153
- return ok("system", programId, "allocateWithSeed", {
154
- accountPubkey: p.accountPubkey.toBase58(),
155
- basePubkey: p.basePubkey.toBase58(),
156
- seed: p.seed,
157
- space: Number(p.space),
158
- programId: p.programId.toBase58(),
159
- });
160
- } catch {
161
- return ok("system", programId, "allocateWithSeed", {});
162
- }
163
- }
164
- case "Assign": {
165
- try {
166
- const p = SystemInstruction.decodeAssign(ix);
167
- return ok("system", programId, "assign", {
168
- accountPubkey: p.accountPubkey.toBase58(),
169
- programId: p.programId.toBase58(),
170
- });
171
- } catch {
172
- return ok("system", programId, "assign", {});
173
- }
174
- }
175
- case "AssignWithSeed": {
176
- try {
177
- const p = SystemInstruction.decodeAssignWithSeed(ix);
178
- return ok("system", programId, "assignWithSeed", {
179
- accountPubkey: p.accountPubkey.toBase58(),
180
- basePubkey: p.basePubkey.toBase58(),
181
- seed: p.seed,
182
- programId: p.programId.toBase58(),
183
- });
184
- } catch {
185
- return ok("system", programId, "assignWithSeed", {});
186
- }
187
- }
188
- case "InitializeNonceAccount":
189
- case "AdvanceNonceAccount":
190
- case "WithdrawNonceAccount":
191
- case "AuthorizeNonceAccount":
192
- case "CreateWithSeed":
193
- case "UpgradeNonceAccount": {
194
- return ok("system", programId, t, {});
195
- }
196
- default:
197
- return ok("system", programId, t, {});
198
- }
199
- } catch {
200
- // If we cannot even decode the instruction type, fallthrough to raw
201
- }
202
- }
203
-
204
- // Compute Budget
205
- try {
206
- const t = ComputeBudgetInstruction.decodeInstructionType(ix);
207
- switch (t) {
208
- case "SetComputeUnitLimit": {
209
- const p = ComputeBudgetInstruction.decodeSetComputeUnitLimit(ix);
210
- return ok("computeBudget", programId, "setComputeUnitLimit", {
211
- units: Number(p.units),
212
- });
213
- }
214
- case "SetComputeUnitPrice": {
215
- const p = ComputeBudgetInstruction.decodeSetComputeUnitPrice(ix);
216
- return ok("computeBudget", programId, "setComputeUnitPrice", {
217
- microLamports: Number(p.microLamports),
218
- });
219
- }
220
- case "RequestHeapFrame": {
221
- const p = ComputeBudgetInstruction.decodeRequestHeapFrame(ix);
222
- return ok("computeBudget", programId, "requestHeapFrame", {
223
- bytes: Number(p.bytes),
224
- });
225
- }
226
- case "RequestUnits": {
227
- const p = ComputeBudgetInstruction.decodeRequestUnits(ix);
228
- return ok("computeBudget", programId, "requestUnits", {
229
- units: Number(p.units),
230
- additionalFee: Number(p.additionalFee),
231
- });
232
- }
233
- }
234
- } catch {}
235
-
236
- // Stake
237
- try {
238
- const t = StakeInstruction.decodeInstructionType(ix);
239
- switch (t) {
240
- case "Initialize":
241
- return ok("stake", programId, "initialize", {});
242
- case "Delegate": {
243
- const p = StakeInstruction.decodeDelegate(ix);
244
- return ok("stake", programId, "delegate", {
245
- stakePubkey: p.stakePubkey.toBase58(),
246
- votePubkey: p.votePubkey.toBase58(),
247
- authorizedPubkey: p.authorizedPubkey.toBase58(),
248
- });
249
- }
250
- case "Authorize": {
251
- const p = StakeInstruction.decodeAuthorize(ix);
252
- return ok("stake", programId, "authorize", {
253
- stakePubkey: p.stakePubkey.toBase58(),
254
- authorizedPubkey: p.authorizedPubkey.toBase58(),
255
- newAuthorizedPubkey: p.newAuthorizedPubkey.toBase58(),
256
- stakeAuthorizationType: p.stakeAuthorizationType.index,
257
- });
258
- }
259
- case "AuthorizeWithSeed":
260
- return ok("stake", programId, "authorizeWithSeed", {});
261
- case "Split":
262
- return ok("stake", programId, "split", {});
263
- case "Withdraw":
264
- return ok("stake", programId, "withdraw", {});
265
- case "Deactivate":
266
- return ok("stake", programId, "deactivate", {});
267
- case "Merge":
268
- return ok("stake", programId, "merge", {});
269
- }
270
- } catch {}
271
-
272
- // Vote
273
- try {
274
- const t = VoteInstruction.decodeInstructionType(ix);
275
- switch (t) {
276
- case "InitializeAccount":
277
- return ok("vote", programId, "initialize", {});
278
- case "Authorize":
279
- return ok("vote", programId, "authorize", {});
280
- case "AuthorizeWithSeed":
281
- return ok("vote", programId, "authorizeWithSeed", {});
282
- case "Withdraw":
283
- return ok("vote", programId, "withdraw", {});
284
- default:
285
- return ok("vote", programId, t, {});
286
- }
287
- } catch {}
288
-
289
- // Address Lookup Table
290
- try {
291
- const t = AddressLookupTableInstruction.decodeInstructionType(ix);
292
- switch (t) {
293
- case "CreateLookupTable":
294
- case "ExtendLookupTable":
295
- case "CloseLookupTable":
296
- case "FreezeLookupTable":
297
- case "DeactivateLookupTable":
298
- return ok("address-lookup-table", programId, t, {});
299
- }
300
- } catch {}
301
-
302
- // Memo program: parse utf8 memo if possible
303
- if (
304
- programId === "MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr" ||
305
- programId === "Memo1UhkJRfHyvLMcVucJwxXeuD728EqVDDwQDxFMNo"
306
- ) {
307
- try {
308
- const bytes = _decodeBase58(dataBase58);
309
- const memo = new TextDecoder().decode(bytes);
310
- return ok("spl-memo", programId, "memo", { memo });
311
- } catch {}
312
- return ok("spl-memo", programId, "memo", {});
313
- }
314
-
315
- // Fallback: unknown program, return raw
316
- return {
317
- programId,
318
- accounts: accounts.map((i) => accountKeys[i] || ""),
319
- data: dataBase58,
320
- };
321
- } catch {
322
- return {
323
- programId,
324
- accounts: accounts.map((i) => accountKeys[i] || ""),
325
- data: dataBase58,
326
- };
327
- }
328
- }
@@ -1,50 +0,0 @@
1
- import type { TransactionInstruction } from "@solana/web3.js";
2
- import { ASSOCIATED_TOKEN_PROGRAM_ID } from "@solana/spl-token";
3
-
4
- // Keep shape compatible with instruction-parser
5
- export type ParsedInstruction =
6
- | {
7
- program: string;
8
- programId: string;
9
- parsed: { type: string; info: unknown };
10
- }
11
- | { programId: string; accounts: string[]; data: string };
12
-
13
- function ok(programId: string, type: string, info: unknown): ParsedInstruction {
14
- return {
15
- program: "spl-associated-token-account",
16
- programId,
17
- parsed: { type, info },
18
- };
19
- }
20
-
21
- function asBase58(ix: TransactionInstruction, idx: number): string | undefined {
22
- try {
23
- return ix.keys[idx]?.pubkey?.toBase58();
24
- } catch {
25
- return undefined;
26
- }
27
- }
28
-
29
- export function tryParseAta(
30
- ix: TransactionInstruction,
31
- programIdStr: string,
32
- ): ParsedInstruction | null {
33
- try {
34
- if (!ix.programId.equals(ASSOCIATED_TOKEN_PROGRAM_ID)) return null;
35
- // Both create (empty) and createIdempotent ([1]) map to type "create" in explorers
36
- const type = "create";
37
- // Expected keys: [payer, associatedToken, owner, mint, systemProgram, tokenProgram]
38
- const info = {
39
- source: asBase58(ix, 0),
40
- account: asBase58(ix, 1),
41
- wallet: asBase58(ix, 2),
42
- mint: asBase58(ix, 3),
43
- systemProgram: asBase58(ix, 4),
44
- tokenProgram: asBase58(ix, 5),
45
- };
46
- return ok(programIdStr, type, info);
47
- } catch {
48
- return null;
49
- }
50
- }