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
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
import { MINT_SIZE, MintLayout } from "@solana/spl-token";
|
|
2
|
-
import { PublicKey } from "@solana/web3.js";
|
|
3
|
-
import type { RpcMethodHandler } from "../../types";
|
|
4
|
-
|
|
5
|
-
// Adopt faucet as mint authority for a given mint (LiteSVM-only, overwrites account data)
|
|
6
|
-
export const solforgeAdoptMintAuthority: RpcMethodHandler = async (
|
|
7
|
-
id,
|
|
8
|
-
params,
|
|
9
|
-
context,
|
|
10
|
-
) => {
|
|
11
|
-
try {
|
|
12
|
-
const [mintStr] = params as [string];
|
|
13
|
-
if (!mintStr)
|
|
14
|
-
return context.createErrorResponse(
|
|
15
|
-
id,
|
|
16
|
-
-32602,
|
|
17
|
-
"Invalid params: mint required",
|
|
18
|
-
);
|
|
19
|
-
const mint = new PublicKey(mintStr);
|
|
20
|
-
const acct = context.svm.getAccount(mint);
|
|
21
|
-
if (!acct)
|
|
22
|
-
return context.createErrorResponse(
|
|
23
|
-
id,
|
|
24
|
-
-32004,
|
|
25
|
-
"Mint not found in LiteSVM",
|
|
26
|
-
);
|
|
27
|
-
if (!acct.data || acct.data.length < MINT_SIZE)
|
|
28
|
-
return context.createErrorResponse(
|
|
29
|
-
id,
|
|
30
|
-
-32000,
|
|
31
|
-
"Account not a valid mint",
|
|
32
|
-
);
|
|
33
|
-
|
|
34
|
-
const faucet = context.getFaucet();
|
|
35
|
-
const buf = Buffer.from(acct.data);
|
|
36
|
-
type MintStruct = Parameters<typeof MintLayout.encode>[0];
|
|
37
|
-
const mintDecoded = MintLayout.decode(
|
|
38
|
-
buf.slice(0, MINT_SIZE),
|
|
39
|
-
) as unknown as MintStruct;
|
|
40
|
-
// Update authority fields
|
|
41
|
-
(
|
|
42
|
-
mintDecoded as unknown as { mintAuthorityOption: number }
|
|
43
|
-
).mintAuthorityOption = 1;
|
|
44
|
-
(mintDecoded as unknown as { mintAuthority: PublicKey }).mintAuthority =
|
|
45
|
-
faucet.publicKey;
|
|
46
|
-
const out = Buffer.from(buf); // preserve any extensions beyond MintLayout
|
|
47
|
-
MintLayout.encode(mintDecoded as MintStruct, out);
|
|
48
|
-
|
|
49
|
-
const ownerBase58 =
|
|
50
|
-
typeof acct.owner === "string"
|
|
51
|
-
? new PublicKey(acct.owner).toBase58()
|
|
52
|
-
: (acct.owner as PublicKey).toBase58();
|
|
53
|
-
const ownerPk = new PublicKey(ownerBase58);
|
|
54
|
-
|
|
55
|
-
context.svm.setAccount(mint, {
|
|
56
|
-
lamports: Number(acct.lamports || 0n),
|
|
57
|
-
data: new Uint8Array(out),
|
|
58
|
-
owner: ownerPk,
|
|
59
|
-
executable: false,
|
|
60
|
-
rentEpoch: 0,
|
|
61
|
-
});
|
|
62
|
-
try {
|
|
63
|
-
context.registerMint?.(mint);
|
|
64
|
-
} catch {}
|
|
65
|
-
try {
|
|
66
|
-
await context.store?.upsertAccounts([
|
|
67
|
-
{
|
|
68
|
-
address: mint.toBase58(),
|
|
69
|
-
lamports: Number(acct.lamports || 0n),
|
|
70
|
-
ownerProgram: ownerBase58,
|
|
71
|
-
executable: false,
|
|
72
|
-
rentEpoch: 0,
|
|
73
|
-
dataLen: out.length,
|
|
74
|
-
dataBase64: undefined,
|
|
75
|
-
lastSlot: Number(context.slot),
|
|
76
|
-
},
|
|
77
|
-
]);
|
|
78
|
-
} catch {}
|
|
79
|
-
return context.createSuccessResponse(id, {
|
|
80
|
-
ok: true,
|
|
81
|
-
mint: mintStr,
|
|
82
|
-
authority: faucet.publicKey.toBase58(),
|
|
83
|
-
});
|
|
84
|
-
} catch (e) {
|
|
85
|
-
return context.createErrorResponse(
|
|
86
|
-
id,
|
|
87
|
-
-32603,
|
|
88
|
-
"Adopt mint authority failed",
|
|
89
|
-
(e as Error)?.message || String(e),
|
|
90
|
-
);
|
|
91
|
-
}
|
|
92
|
-
};
|
|
93
|
-
|
|
94
|
-
export type { RpcMethodHandler } from "../../types";
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import { Connection, PublicKey } from "@solana/web3.js";
|
|
2
|
-
import type { RpcMethodHandler } from "../../types";
|
|
3
|
-
|
|
4
|
-
export const solforgeAdminCloneProgramAccounts: RpcMethodHandler = async (
|
|
5
|
-
id,
|
|
6
|
-
params,
|
|
7
|
-
context,
|
|
8
|
-
) => {
|
|
9
|
-
const [programId, options] = params as [
|
|
10
|
-
string,
|
|
11
|
-
{ endpoint?: string; limit?: number; filters?: unknown[] }?,
|
|
12
|
-
];
|
|
13
|
-
if (!programId)
|
|
14
|
-
return context.createErrorResponse(
|
|
15
|
-
id,
|
|
16
|
-
-32602,
|
|
17
|
-
"Invalid params: programId required",
|
|
18
|
-
);
|
|
19
|
-
const endpoint = options?.endpoint || "https://api.mainnet-beta.solana.com";
|
|
20
|
-
const limit = options?.limit
|
|
21
|
-
? Math.max(1, Math.min(10000, options.limit))
|
|
22
|
-
: undefined;
|
|
23
|
-
try {
|
|
24
|
-
const conn = new Connection(endpoint, "confirmed");
|
|
25
|
-
const pid = new PublicKey(programId);
|
|
26
|
-
const list = await conn.getProgramAccounts(pid, {
|
|
27
|
-
commitment: "confirmed",
|
|
28
|
-
// @ts-expect-error: filters type is loose
|
|
29
|
-
filters: Array.isArray(options?.filters) ? options?.filters : undefined,
|
|
30
|
-
});
|
|
31
|
-
let count = 0;
|
|
32
|
-
for (const { pubkey, account } of list.slice(0, limit ?? list.length)) {
|
|
33
|
-
try {
|
|
34
|
-
context.svm.setAccount(pubkey, {
|
|
35
|
-
data: new Uint8Array(account.data as Buffer),
|
|
36
|
-
executable: account.executable,
|
|
37
|
-
lamports: Number(account.lamports),
|
|
38
|
-
owner: account.owner,
|
|
39
|
-
rentEpoch: 0,
|
|
40
|
-
});
|
|
41
|
-
count++;
|
|
42
|
-
} catch {}
|
|
43
|
-
}
|
|
44
|
-
return context.createSuccessResponse(id, { ok: true, count });
|
|
45
|
-
} catch (e) {
|
|
46
|
-
return context.createErrorResponse(
|
|
47
|
-
id,
|
|
48
|
-
-32603,
|
|
49
|
-
"Clone program accounts failed",
|
|
50
|
-
(e as Error)?.message || String(e),
|
|
51
|
-
);
|
|
52
|
-
}
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
export type { RpcMethodHandler } from "../../types";
|
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
import { Connection, PublicKey } from "@solana/web3.js";
|
|
2
|
-
import type { RpcMethodHandler } from "../../types";
|
|
3
|
-
import { parseUpgradeableLoader } from "../account/parsers/loader-upgradeable";
|
|
4
|
-
|
|
5
|
-
export const solforgeAdminCloneProgram: RpcMethodHandler = async (
|
|
6
|
-
id,
|
|
7
|
-
params,
|
|
8
|
-
context,
|
|
9
|
-
) => {
|
|
10
|
-
const [programId, options] = params as [
|
|
11
|
-
string,
|
|
12
|
-
{ endpoint?: string; withAccounts?: boolean; accountsLimit?: number }?,
|
|
13
|
-
];
|
|
14
|
-
if (!programId)
|
|
15
|
-
return context.createErrorResponse(
|
|
16
|
-
id,
|
|
17
|
-
-32602,
|
|
18
|
-
"Invalid params: programId required",
|
|
19
|
-
);
|
|
20
|
-
const endpoint = options?.endpoint || "https://api.mainnet-beta.solana.com";
|
|
21
|
-
try {
|
|
22
|
-
const conn = new Connection(endpoint, "confirmed");
|
|
23
|
-
const pid = new PublicKey(programId);
|
|
24
|
-
const info = await conn.getAccountInfo(pid, "confirmed");
|
|
25
|
-
if (!info)
|
|
26
|
-
return context.createErrorResponse(
|
|
27
|
-
id,
|
|
28
|
-
-32004,
|
|
29
|
-
"Program account not found on endpoint",
|
|
30
|
-
{ programId, endpoint },
|
|
31
|
-
);
|
|
32
|
-
|
|
33
|
-
console.log("[admin] clone program start", {
|
|
34
|
-
programId: pid.toBase58(),
|
|
35
|
-
owner: info.owner.toBase58(),
|
|
36
|
-
exec: info.executable,
|
|
37
|
-
dataLen: info.data?.length ?? 0,
|
|
38
|
-
});
|
|
39
|
-
const ownerStr = info.owner.toBase58();
|
|
40
|
-
let addSource: "programData" | "program" | null = null;
|
|
41
|
-
|
|
42
|
-
// If upgradeable loader: fetch program data, extract ELF and addProgram
|
|
43
|
-
const parsed = parseUpgradeableLoader(
|
|
44
|
-
ownerStr,
|
|
45
|
-
new Uint8Array(info.data),
|
|
46
|
-
context,
|
|
47
|
-
);
|
|
48
|
-
if (parsed?.parsed?.type === "program") {
|
|
49
|
-
const programDataAddr = parsed.parsed.info?.programData as
|
|
50
|
-
| string
|
|
51
|
-
| undefined;
|
|
52
|
-
if (programDataAddr) {
|
|
53
|
-
const pda = new PublicKey(programDataAddr);
|
|
54
|
-
const pinfo = await conn.getAccountInfo(pda, "confirmed");
|
|
55
|
-
if (pinfo) {
|
|
56
|
-
const pdataParsed = parseUpgradeableLoader(
|
|
57
|
-
ownerStr,
|
|
58
|
-
new Uint8Array(pinfo.data),
|
|
59
|
-
context,
|
|
60
|
-
);
|
|
61
|
-
const base64 = pdataParsed?.parsed?.info?.data?.[0] as
|
|
62
|
-
| string
|
|
63
|
-
| undefined;
|
|
64
|
-
if (base64) {
|
|
65
|
-
const bytes = Uint8Array.from(Buffer.from(base64, "base64"));
|
|
66
|
-
try {
|
|
67
|
-
context.svm.addProgram(pid, bytes);
|
|
68
|
-
addSource = "programData";
|
|
69
|
-
} catch (e) {
|
|
70
|
-
console.warn("[admin] addProgram failed (programData bytes)", e);
|
|
71
|
-
return context.createErrorResponse(
|
|
72
|
-
id,
|
|
73
|
-
-32603,
|
|
74
|
-
"Clone program failed",
|
|
75
|
-
{
|
|
76
|
-
message: String(e),
|
|
77
|
-
programId,
|
|
78
|
-
endpoint,
|
|
79
|
-
source: "programData",
|
|
80
|
-
},
|
|
81
|
-
);
|
|
82
|
-
}
|
|
83
|
-
} else {
|
|
84
|
-
console.warn("[admin] programData bytes missing");
|
|
85
|
-
return context.createErrorResponse(
|
|
86
|
-
id,
|
|
87
|
-
-32603,
|
|
88
|
-
"Clone program failed",
|
|
89
|
-
{
|
|
90
|
-
message: "ProgramData bytes missing",
|
|
91
|
-
programId,
|
|
92
|
-
endpoint,
|
|
93
|
-
},
|
|
94
|
-
);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
} else {
|
|
99
|
-
// Legacy loaders keep ELF in the program account directly
|
|
100
|
-
try {
|
|
101
|
-
context.svm.addProgram(pid, new Uint8Array(info.data));
|
|
102
|
-
addSource = "program";
|
|
103
|
-
} catch (e) {
|
|
104
|
-
console.warn("[admin] addProgram failed (program account data)", e);
|
|
105
|
-
return context.createErrorResponse(id, -32603, "Clone program failed", {
|
|
106
|
-
message: String(e),
|
|
107
|
-
programId,
|
|
108
|
-
endpoint,
|
|
109
|
-
source: "program",
|
|
110
|
-
});
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
// Optionally clone owned accounts
|
|
115
|
-
if (options?.withAccounts) {
|
|
116
|
-
const { solforgeAdminCloneProgramAccounts } = await import(
|
|
117
|
-
"./clone-program-accounts"
|
|
118
|
-
);
|
|
119
|
-
const res = await solforgeAdminCloneProgramAccounts(
|
|
120
|
-
id,
|
|
121
|
-
[programId, { endpoint, limit: options.accountsLimit }],
|
|
122
|
-
context,
|
|
123
|
-
);
|
|
124
|
-
void res;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
console.log("[admin] clone program done", {
|
|
128
|
-
programId: pid.toBase58(),
|
|
129
|
-
added: true,
|
|
130
|
-
source: addSource,
|
|
131
|
-
});
|
|
132
|
-
try {
|
|
133
|
-
context.registerProgram?.(pid);
|
|
134
|
-
} catch {}
|
|
135
|
-
return context.createSuccessResponse(id, {
|
|
136
|
-
ok: true,
|
|
137
|
-
programId,
|
|
138
|
-
added: true,
|
|
139
|
-
source: addSource,
|
|
140
|
-
});
|
|
141
|
-
} catch (e) {
|
|
142
|
-
console.error("[admin] clone program error", e);
|
|
143
|
-
return context.createErrorResponse(id, -32603, "Clone program failed", {
|
|
144
|
-
message: (e as Error)?.message || String(e),
|
|
145
|
-
stack: (e as Error)?.stack,
|
|
146
|
-
programId,
|
|
147
|
-
endpoint,
|
|
148
|
-
});
|
|
149
|
-
}
|
|
150
|
-
};
|
|
151
|
-
|
|
152
|
-
export type { RpcMethodHandler } from "../../types";
|
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
import { TOKEN_PROGRAM_ID } from "@solana/spl-token";
|
|
2
|
-
import { Connection, PublicKey } from "@solana/web3.js";
|
|
3
|
-
import type { RpcMethodHandler } from "../../types";
|
|
4
|
-
|
|
5
|
-
export const solforgeAdminCloneTokenAccounts: RpcMethodHandler = async (
|
|
6
|
-
id,
|
|
7
|
-
params,
|
|
8
|
-
context,
|
|
9
|
-
) => {
|
|
10
|
-
const [mint, options] = params as [
|
|
11
|
-
string,
|
|
12
|
-
{ endpoint?: string; holders?: number; allAccounts?: boolean }?,
|
|
13
|
-
];
|
|
14
|
-
if (!mint)
|
|
15
|
-
return context.createErrorResponse(
|
|
16
|
-
id,
|
|
17
|
-
-32602,
|
|
18
|
-
"Invalid params: mint required",
|
|
19
|
-
);
|
|
20
|
-
const endpoint = options?.endpoint || "https://api.mainnet-beta.solana.com";
|
|
21
|
-
const limit =
|
|
22
|
-
options?.holders && !options?.allAccounts
|
|
23
|
-
? Math.max(1, Math.min(10000, options.holders))
|
|
24
|
-
: undefined;
|
|
25
|
-
try {
|
|
26
|
-
const conn = new Connection(endpoint, "confirmed");
|
|
27
|
-
const mintPk = new PublicKey(mint);
|
|
28
|
-
let accounts: Array<{
|
|
29
|
-
pubkey: PublicKey;
|
|
30
|
-
data: Buffer;
|
|
31
|
-
lamports: number;
|
|
32
|
-
owner: PublicKey;
|
|
33
|
-
executable: boolean;
|
|
34
|
-
rentEpoch: number;
|
|
35
|
-
}>;
|
|
36
|
-
if (options?.allAccounts) {
|
|
37
|
-
const list = await conn.getProgramAccounts(TOKEN_PROGRAM_ID, {
|
|
38
|
-
commitment: "confirmed",
|
|
39
|
-
filters: [
|
|
40
|
-
{ dataSize: 165 },
|
|
41
|
-
{ memcmp: { offset: 0, bytes: mintPk.toBase58() } },
|
|
42
|
-
],
|
|
43
|
-
});
|
|
44
|
-
accounts = list.map(({ pubkey, account }) => ({
|
|
45
|
-
pubkey,
|
|
46
|
-
data: account.data as Buffer,
|
|
47
|
-
lamports: account.lamports,
|
|
48
|
-
owner: account.owner,
|
|
49
|
-
executable: account.executable,
|
|
50
|
-
rentEpoch: account.rentEpoch,
|
|
51
|
-
}));
|
|
52
|
-
} else if (typeof limit === "number") {
|
|
53
|
-
const largest = await conn.getTokenLargestAccounts(mintPk, "confirmed");
|
|
54
|
-
const addrs = largest.value.slice(0, limit).map((x) => x.address);
|
|
55
|
-
const multi = await conn.getMultipleAccountsInfo(addrs, {
|
|
56
|
-
commitment: "confirmed",
|
|
57
|
-
});
|
|
58
|
-
accounts = [];
|
|
59
|
-
for (let i = 0; i < addrs.length; i++) {
|
|
60
|
-
const info = multi[i];
|
|
61
|
-
const pk = addrs[i];
|
|
62
|
-
if (!info || !pk) continue;
|
|
63
|
-
accounts.push({
|
|
64
|
-
pubkey: pk,
|
|
65
|
-
data: info.data as Buffer,
|
|
66
|
-
lamports: info.lamports,
|
|
67
|
-
owner: info.owner,
|
|
68
|
-
executable: info.executable,
|
|
69
|
-
rentEpoch: info.rentEpoch,
|
|
70
|
-
});
|
|
71
|
-
}
|
|
72
|
-
} else {
|
|
73
|
-
const largest = await conn.getTokenLargestAccounts(mintPk, "confirmed");
|
|
74
|
-
const addrs = largest.value.slice(0, 100).map((x) => x.address);
|
|
75
|
-
const multi = await conn.getMultipleAccountsInfo(addrs, {
|
|
76
|
-
commitment: "confirmed",
|
|
77
|
-
});
|
|
78
|
-
accounts = [];
|
|
79
|
-
for (let i = 0; i < addrs.length; i++) {
|
|
80
|
-
const info = multi[i];
|
|
81
|
-
const pk = addrs[i];
|
|
82
|
-
if (!info || !pk) continue;
|
|
83
|
-
accounts.push({
|
|
84
|
-
pubkey: pk,
|
|
85
|
-
data: info.data as Buffer,
|
|
86
|
-
lamports: info.lamports,
|
|
87
|
-
owner: info.owner,
|
|
88
|
-
executable: info.executable,
|
|
89
|
-
rentEpoch: info.rentEpoch,
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
let count = 0;
|
|
94
|
-
for (const a of accounts) {
|
|
95
|
-
try {
|
|
96
|
-
context.svm.setAccount(a.pubkey, {
|
|
97
|
-
data: new Uint8Array(a.data),
|
|
98
|
-
executable: a.executable,
|
|
99
|
-
lamports: Number(a.lamports),
|
|
100
|
-
owner: a.owner,
|
|
101
|
-
rentEpoch: 0,
|
|
102
|
-
});
|
|
103
|
-
count++;
|
|
104
|
-
} catch {}
|
|
105
|
-
}
|
|
106
|
-
return context.createSuccessResponse(id, { ok: true, count });
|
|
107
|
-
} catch (e) {
|
|
108
|
-
return context.createErrorResponse(
|
|
109
|
-
id,
|
|
110
|
-
-32603,
|
|
111
|
-
"Clone token accounts failed",
|
|
112
|
-
(e as Error)?.message || String(e),
|
|
113
|
-
);
|
|
114
|
-
}
|
|
115
|
-
};
|
|
116
|
-
|
|
117
|
-
export type { RpcMethodHandler } from "../../types";
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
import { MINT_SIZE, MintLayout } from "@solana/spl-token";
|
|
2
|
-
import type { AccountInfo } from "@solana/web3.js";
|
|
3
|
-
import { Connection, PublicKey } from "@solana/web3.js";
|
|
4
|
-
import type { RpcMethodHandler } from "../../types";
|
|
5
|
-
import { cloneMintExtensionAccounts } from "./helpers";
|
|
6
|
-
|
|
7
|
-
export const solforgeAdminCloneTokenMint: RpcMethodHandler = async (
|
|
8
|
-
id,
|
|
9
|
-
params,
|
|
10
|
-
context,
|
|
11
|
-
) => {
|
|
12
|
-
const [mint, options] = params as [string, { endpoint?: string }?];
|
|
13
|
-
if (!mint)
|
|
14
|
-
return context.createErrorResponse(
|
|
15
|
-
id,
|
|
16
|
-
-32602,
|
|
17
|
-
"Invalid params: mint required",
|
|
18
|
-
);
|
|
19
|
-
const endpoint = options?.endpoint || "https://api.mainnet-beta.solana.com";
|
|
20
|
-
try {
|
|
21
|
-
const conn = new Connection(endpoint, "confirmed");
|
|
22
|
-
const mintPk = new PublicKey(mint);
|
|
23
|
-
console.log(`[admin] clone mint start`, {
|
|
24
|
-
mint: mintPk.toBase58(),
|
|
25
|
-
endpoint,
|
|
26
|
-
});
|
|
27
|
-
const info = await conn.getAccountInfo(mintPk, "confirmed");
|
|
28
|
-
if (!info) {
|
|
29
|
-
console.warn(`[admin] clone mint: account not found`, {
|
|
30
|
-
mint: mintPk.toBase58(),
|
|
31
|
-
endpoint,
|
|
32
|
-
});
|
|
33
|
-
return context.createErrorResponse(
|
|
34
|
-
id,
|
|
35
|
-
-32004,
|
|
36
|
-
"Mint account not found on endpoint",
|
|
37
|
-
{ endpoint, mint },
|
|
38
|
-
);
|
|
39
|
-
}
|
|
40
|
-
try {
|
|
41
|
-
const dec = MintLayout.decode(
|
|
42
|
-
(info.data as Buffer).slice(0, MINT_SIZE),
|
|
43
|
-
).decimals;
|
|
44
|
-
console.log(`[admin] clone mint fetched`, {
|
|
45
|
-
owner: info.owner.toBase58(),
|
|
46
|
-
dataLen: info.data.length,
|
|
47
|
-
decimals: dec,
|
|
48
|
-
lamports: info.lamports,
|
|
49
|
-
});
|
|
50
|
-
} catch {}
|
|
51
|
-
// Write raw account into LiteSVM
|
|
52
|
-
context.svm.setAccount(mintPk, {
|
|
53
|
-
data: new Uint8Array(info.data),
|
|
54
|
-
executable: info.executable,
|
|
55
|
-
lamports: Number(info.lamports),
|
|
56
|
-
owner: info.owner,
|
|
57
|
-
rentEpoch: 0,
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
await cloneMintExtensionAccounts(
|
|
61
|
-
conn,
|
|
62
|
-
context,
|
|
63
|
-
mintPk,
|
|
64
|
-
info as AccountInfo<Buffer>,
|
|
65
|
-
);
|
|
66
|
-
try {
|
|
67
|
-
context.registerMint?.(mintPk);
|
|
68
|
-
} catch {}
|
|
69
|
-
console.log(`[admin] clone mint done`, { mint: mintPk.toBase58() });
|
|
70
|
-
return context.createSuccessResponse(id, { ok: true, address: mint });
|
|
71
|
-
} catch (e) {
|
|
72
|
-
console.error(`[admin] clone mint error`, e);
|
|
73
|
-
return context.createErrorResponse(id, -32603, "Clone mint failed", {
|
|
74
|
-
message: (e as Error)?.message || String(e),
|
|
75
|
-
stack: (e as Error)?.stack,
|
|
76
|
-
endpoint,
|
|
77
|
-
mint,
|
|
78
|
-
});
|
|
79
|
-
}
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
export type { RpcMethodHandler } from "../../types";
|
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
import { MINT_SIZE, MintLayout, TOKEN_PROGRAM_ID } from "@solana/spl-token";
|
|
2
|
-
import { PublicKey } from "@solana/web3.js";
|
|
3
|
-
import type { RpcMethodHandler } from "../../types";
|
|
4
|
-
|
|
5
|
-
// Create a new SPL Mint locally with given decimals and mint authority
|
|
6
|
-
export const solforgeCreateMint: RpcMethodHandler = async (
|
|
7
|
-
id,
|
|
8
|
-
params,
|
|
9
|
-
context,
|
|
10
|
-
) => {
|
|
11
|
-
try {
|
|
12
|
-
const [mintStr, decimals, authorityStr] = params as [
|
|
13
|
-
string | null | undefined,
|
|
14
|
-
number,
|
|
15
|
-
string | null | undefined,
|
|
16
|
-
];
|
|
17
|
-
if (typeof decimals !== "number" || decimals < 0 || decimals > 18)
|
|
18
|
-
return context.createErrorResponse(
|
|
19
|
-
id,
|
|
20
|
-
-32602,
|
|
21
|
-
"Invalid params: decimals required (0-18)",
|
|
22
|
-
);
|
|
23
|
-
const authority = authorityStr
|
|
24
|
-
? new PublicKey(authorityStr)
|
|
25
|
-
: context.getFaucet().publicKey;
|
|
26
|
-
const mintPk = mintStr ? new PublicKey(mintStr) : PublicKey.unique();
|
|
27
|
-
|
|
28
|
-
const buf = Buffer.alloc(MINT_SIZE);
|
|
29
|
-
type MintStruct = Parameters<typeof MintLayout.encode>[0];
|
|
30
|
-
const initialMint = {
|
|
31
|
-
mintAuthorityOption: 1,
|
|
32
|
-
mintAuthority: authority,
|
|
33
|
-
supply: 0n,
|
|
34
|
-
decimals,
|
|
35
|
-
isInitialized: true,
|
|
36
|
-
freezeAuthorityOption: 0,
|
|
37
|
-
freezeAuthority: PublicKey.default,
|
|
38
|
-
} satisfies Partial<MintStruct> as MintStruct;
|
|
39
|
-
MintLayout.encode(initialMint, buf);
|
|
40
|
-
|
|
41
|
-
const rentLamports = Number(
|
|
42
|
-
context.svm.minimumBalanceForRentExemption(BigInt(MINT_SIZE)),
|
|
43
|
-
);
|
|
44
|
-
context.svm.setAccount(mintPk, {
|
|
45
|
-
lamports: rentLamports,
|
|
46
|
-
data: new Uint8Array(buf),
|
|
47
|
-
owner: TOKEN_PROGRAM_ID,
|
|
48
|
-
executable: false,
|
|
49
|
-
rentEpoch: 0,
|
|
50
|
-
});
|
|
51
|
-
try {
|
|
52
|
-
context.registerMint?.(mintPk);
|
|
53
|
-
} catch {}
|
|
54
|
-
try {
|
|
55
|
-
await context.store?.upsertAccounts([
|
|
56
|
-
{
|
|
57
|
-
address: mintPk.toBase58(),
|
|
58
|
-
lamports: rentLamports,
|
|
59
|
-
ownerProgram: TOKEN_PROGRAM_ID.toBase58(),
|
|
60
|
-
executable: false,
|
|
61
|
-
rentEpoch: 0,
|
|
62
|
-
dataLen: MINT_SIZE,
|
|
63
|
-
dataBase64: undefined,
|
|
64
|
-
lastSlot: Number(context.slot),
|
|
65
|
-
},
|
|
66
|
-
]);
|
|
67
|
-
} catch {}
|
|
68
|
-
// Synthetic transaction for explorers
|
|
69
|
-
try {
|
|
70
|
-
const sig = `admin:create-mint:${mintPk.toBase58()}:${Date.now()}`;
|
|
71
|
-
await context.store?.insertTransactionBundle({
|
|
72
|
-
signature: sig,
|
|
73
|
-
slot: Number(context.slot),
|
|
74
|
-
blockTime: Math.floor(Date.now() / 1000),
|
|
75
|
-
version: "legacy",
|
|
76
|
-
fee: 0,
|
|
77
|
-
err: null,
|
|
78
|
-
rawBase64: "",
|
|
79
|
-
preBalances: [],
|
|
80
|
-
postBalances: [],
|
|
81
|
-
logs: ["admin create mint"],
|
|
82
|
-
accounts: [
|
|
83
|
-
{
|
|
84
|
-
address: mintPk.toBase58(),
|
|
85
|
-
index: 0,
|
|
86
|
-
signer: false,
|
|
87
|
-
writable: true,
|
|
88
|
-
},
|
|
89
|
-
{
|
|
90
|
-
address: authority.toBase58(),
|
|
91
|
-
index: 1,
|
|
92
|
-
signer: false,
|
|
93
|
-
writable: false,
|
|
94
|
-
},
|
|
95
|
-
],
|
|
96
|
-
});
|
|
97
|
-
} catch {}
|
|
98
|
-
return context.createSuccessResponse(id, {
|
|
99
|
-
ok: true,
|
|
100
|
-
mint: mintPk.toBase58(),
|
|
101
|
-
decimals,
|
|
102
|
-
authority: authority.toBase58(),
|
|
103
|
-
});
|
|
104
|
-
} catch (e) {
|
|
105
|
-
return context.createErrorResponse(
|
|
106
|
-
id,
|
|
107
|
-
-32603,
|
|
108
|
-
"Create mint failed",
|
|
109
|
-
(e as Error)?.message || String(e),
|
|
110
|
-
);
|
|
111
|
-
}
|
|
112
|
-
};
|
|
113
|
-
|
|
114
|
-
export type { RpcMethodHandler } from "../../types";
|