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.
- package/package.json +1 -5
- package/start.cjs +19 -23
- package/docs/API.md +0 -379
- package/docs/CONFIGURATION.md +0 -407
- package/docs/bun-single-file-executable.md +0 -585
- package/docs/cli-plan.md +0 -154
- package/docs/data-indexing-plan.md +0 -214
- package/docs/gui-roadmap.md +0 -202
- package/scripts/decode-b58.ts +0 -10
- package/scripts/install.sh +0 -112
- package/server/index.ts +0 -5
- package/server/lib/base58.ts +0 -33
- package/server/lib/faucet.ts +0 -110
- package/server/lib/instruction-parser.ts +0 -328
- package/server/lib/parsers/spl-associated-token-account.ts +0 -50
- package/server/lib/parsers/spl-token.ts +0 -340
- package/server/lib/spl-token.ts +0 -57
- package/server/methods/TEMPLATE.md +0 -117
- package/server/methods/account/get-account-info.ts +0 -86
- package/server/methods/account/get-balance.ts +0 -23
- package/server/methods/account/get-multiple-accounts.ts +0 -84
- package/server/methods/account/get-parsed-account-info.ts +0 -17
- package/server/methods/account/index.ts +0 -12
- package/server/methods/account/parsers/index.ts +0 -52
- package/server/methods/account/parsers/loader-upgradeable.ts +0 -79
- package/server/methods/account/parsers/spl-token.ts +0 -256
- package/server/methods/account/parsers/system.ts +0 -4
- package/server/methods/account/request-airdrop.ts +0 -271
- package/server/methods/admin/adopt-mint-authority.ts +0 -94
- package/server/methods/admin/clone-program-accounts.ts +0 -55
- package/server/methods/admin/clone-program.ts +0 -152
- package/server/methods/admin/clone-token-accounts.ts +0 -117
- package/server/methods/admin/clone-token-mint.ts +0 -82
- package/server/methods/admin/create-mint.ts +0 -114
- package/server/methods/admin/create-token-account.ts +0 -137
- package/server/methods/admin/helpers.ts +0 -70
- package/server/methods/admin/index.ts +0 -10
- package/server/methods/admin/list-mints.ts +0 -21
- package/server/methods/admin/load-program.ts +0 -52
- package/server/methods/admin/mint-to.ts +0 -266
- package/server/methods/block/get-block-height.ts +0 -5
- package/server/methods/block/get-block.ts +0 -31
- package/server/methods/block/get-blocks-with-limit.ts +0 -19
- package/server/methods/block/get-latest-blockhash.ts +0 -12
- package/server/methods/block/get-slot.ts +0 -5
- package/server/methods/block/index.ts +0 -6
- package/server/methods/block/is-blockhash-valid.ts +0 -19
- package/server/methods/epoch/get-cluster-nodes.ts +0 -17
- package/server/methods/epoch/get-epoch-info.ts +0 -16
- package/server/methods/epoch/get-epoch-schedule.ts +0 -15
- package/server/methods/epoch/get-highest-snapshot-slot.ts +0 -9
- package/server/methods/epoch/get-leader-schedule.ts +0 -8
- package/server/methods/epoch/get-max-retransmit-slot.ts +0 -9
- package/server/methods/epoch/get-max-shred-insert-slot.ts +0 -9
- package/server/methods/epoch/get-slot-leader.ts +0 -6
- package/server/methods/epoch/get-slot-leaders.ts +0 -9
- package/server/methods/epoch/get-stake-activation.ts +0 -9
- package/server/methods/epoch/get-stake-minimum-delegation.ts +0 -9
- package/server/methods/epoch/get-vote-accounts.ts +0 -19
- package/server/methods/epoch/index.ts +0 -13
- package/server/methods/epoch/minimum-ledger-slot.ts +0 -5
- package/server/methods/fee/get-fee-calculator-for-blockhash.ts +0 -12
- package/server/methods/fee/get-fee-for-message.ts +0 -8
- package/server/methods/fee/get-fee-rate-governor.ts +0 -16
- package/server/methods/fee/get-fees.ts +0 -14
- package/server/methods/fee/get-recent-prioritization-fees.ts +0 -22
- package/server/methods/fee/index.ts +0 -5
- package/server/methods/get-address-lookup-table.ts +0 -27
- package/server/methods/index.ts +0 -265
- package/server/methods/performance/get-recent-performance-samples.ts +0 -25
- package/server/methods/performance/get-transaction-count.ts +0 -5
- package/server/methods/performance/index.ts +0 -2
- package/server/methods/program/get-block-commitment.ts +0 -9
- package/server/methods/program/get-block-production.ts +0 -14
- package/server/methods/program/get-block-time.ts +0 -21
- package/server/methods/program/get-blocks.ts +0 -11
- package/server/methods/program/get-first-available-block.ts +0 -9
- package/server/methods/program/get-genesis-hash.ts +0 -6
- package/server/methods/program/get-identity.ts +0 -6
- package/server/methods/program/get-inflation-governor.ts +0 -15
- package/server/methods/program/get-inflation-rate.ts +0 -10
- package/server/methods/program/get-inflation-reward.ts +0 -12
- package/server/methods/program/get-largest-accounts.ts +0 -8
- package/server/methods/program/get-parsed-program-accounts.ts +0 -12
- package/server/methods/program/get-parsed-token-accounts-by-delegate.ts +0 -12
- package/server/methods/program/get-parsed-token-accounts-by-owner.ts +0 -12
- package/server/methods/program/get-program-accounts.ts +0 -221
- package/server/methods/program/get-supply.ts +0 -13
- package/server/methods/program/get-token-account-balance.ts +0 -60
- package/server/methods/program/get-token-accounts-by-delegate.ts +0 -82
- package/server/methods/program/get-token-accounts-by-owner.ts +0 -416
- package/server/methods/program/get-token-largest-accounts.ts +0 -81
- package/server/methods/program/get-token-supply.ts +0 -39
- package/server/methods/program/index.ts +0 -21
- package/server/methods/solforge/index.ts +0 -158
- package/server/methods/system/get-health.ts +0 -5
- package/server/methods/system/get-minimum-balance-for-rent-exemption.ts +0 -13
- package/server/methods/system/get-version.ts +0 -9
- package/server/methods/system/index.ts +0 -3
- package/server/methods/transaction/get-confirmed-transaction.ts +0 -11
- package/server/methods/transaction/get-parsed-transaction.ts +0 -17
- package/server/methods/transaction/get-signature-statuses.ts +0 -79
- package/server/methods/transaction/get-signatures-for-address.ts +0 -41
- package/server/methods/transaction/get-transaction.ts +0 -639
- package/server/methods/transaction/index.ts +0 -7
- package/server/methods/transaction/inner-instructions.test.ts +0 -104
- package/server/methods/transaction/send-transaction.ts +0 -469
- package/server/methods/transaction/simulate-transaction.ts +0 -57
- package/server/rpc-server.ts +0 -521
- package/server/types.ts +0 -109
- package/server/ws-server.ts +0 -178
- package/src/api-server-entry.ts +0 -109
- package/src/cli/bootstrap.ts +0 -67
- package/src/cli/commands/airdrop.ts +0 -37
- package/src/cli/commands/config.ts +0 -39
- package/src/cli/commands/mint.ts +0 -187
- package/src/cli/commands/program-clone.ts +0 -122
- package/src/cli/commands/program-load.ts +0 -64
- package/src/cli/commands/rpc-start.ts +0 -49
- package/src/cli/commands/token-adopt-authority.ts +0 -37
- package/src/cli/commands/token-clone.ts +0 -112
- package/src/cli/commands/token-create.ts +0 -81
- package/src/cli/main.ts +0 -158
- package/src/cli/run-solforge.ts +0 -112
- package/src/cli/setup-utils.ts +0 -54
- package/src/cli/setup-wizard.ts +0 -258
- package/src/cli/utils/args.ts +0 -15
- package/src/commands/add-program.ts +0 -333
- package/src/commands/init.ts +0 -122
- package/src/commands/list.ts +0 -136
- package/src/commands/mint.ts +0 -287
- package/src/commands/start.ts +0 -881
- package/src/commands/status.ts +0 -99
- package/src/commands/stop.ts +0 -405
- package/src/config/index.ts +0 -146
- package/src/config/manager.ts +0 -157
- package/src/db/index.ts +0 -83
- package/src/db/schema/accounts.ts +0 -23
- package/src/db/schema/address-signatures.ts +0 -31
- package/src/db/schema/index.ts +0 -6
- package/src/db/schema/meta-kv.ts +0 -9
- package/src/db/schema/transactions.ts +0 -36
- package/src/db/schema/tx-account-states.ts +0 -23
- package/src/db/schema/tx-accounts.ts +0 -33
- package/src/db/tx-store.ts +0 -264
- package/src/gui/public/app.css +0 -1556
- package/src/gui/public/build/main.css +0 -1569
- package/src/gui/public/build/main.js +0 -303
- package/src/gui/public/build/main.js.txt +0 -231
- package/src/gui/public/index.html +0 -19
- package/src/gui/server.ts +0 -296
- package/src/gui/src/api.ts +0 -127
- package/src/gui/src/app.tsx +0 -441
- package/src/gui/src/components/airdrop-mint-form.tsx +0 -246
- package/src/gui/src/components/clone-program-modal.tsx +0 -202
- package/src/gui/src/components/clone-token-modal.tsx +0 -230
- package/src/gui/src/components/modal.tsx +0 -134
- package/src/gui/src/components/programs-panel.tsx +0 -124
- package/src/gui/src/components/status-panel.tsx +0 -136
- package/src/gui/src/components/tokens-panel.tsx +0 -122
- package/src/gui/src/hooks/use-interval.ts +0 -17
- package/src/gui/src/index.css +0 -557
- package/src/gui/src/main.tsx +0 -17
- package/src/index.ts +0 -216
- package/src/migrations-bundled.ts +0 -23
- package/src/rpc/start.ts +0 -44
- package/src/services/api-server.ts +0 -504
- package/src/services/port-manager.ts +0 -174
- package/src/services/process-registry.ts +0 -153
- package/src/services/program-cloner.ts +0 -317
- package/src/services/token-cloner.ts +0 -811
- package/src/services/validator.ts +0 -293
- package/src/types/config.ts +0 -110
- package/src/utils/shell.ts +0 -110
- package/src/utils/token-loader.ts +0 -115
package/scripts/install.sh
DELETED
|
@@ -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
package/server/lib/base58.ts
DELETED
|
@@ -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
|
-
}
|
package/server/lib/faucet.ts
DELETED
|
@@ -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
|
-
}
|