solforge 0.2.3 → 0.2.5
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/LICENSE +2 -2
- package/README.md +323 -364
- package/cli.cjs +126 -69
- package/package.json +1 -1
- package/scripts/install.sh +112 -0
- package/scripts/postinstall.cjs +66 -58
- package/server/methods/program/get-token-accounts-by-owner.ts +7 -2
- package/server/ws-server.ts +4 -1
- package/src/api-server-entry.ts +91 -91
- package/src/cli/commands/rpc-start.ts +4 -1
- package/src/cli/main.ts +39 -14
- package/src/cli/run-solforge.ts +20 -6
- package/src/commands/add-program.ts +324 -328
- package/src/commands/init.ts +106 -106
- package/src/commands/list.ts +125 -125
- package/src/commands/mint.ts +246 -246
- package/src/commands/start.ts +834 -831
- package/src/commands/status.ts +80 -80
- package/src/commands/stop.ts +381 -382
- package/src/config/manager.ts +149 -149
- package/src/gui/public/app.css +1556 -1
- package/src/gui/public/build/main.css +1569 -1
- package/src/gui/server.ts +20 -21
- package/src/gui/src/app.tsx +56 -37
- package/src/gui/src/components/airdrop-mint-form.tsx +17 -11
- package/src/gui/src/components/clone-program-modal.tsx +6 -6
- package/src/gui/src/components/clone-token-modal.tsx +7 -7
- package/src/gui/src/components/modal.tsx +13 -11
- package/src/gui/src/components/programs-panel.tsx +27 -15
- package/src/gui/src/components/status-panel.tsx +31 -17
- package/src/gui/src/components/tokens-panel.tsx +25 -19
- package/src/gui/src/index.css +491 -463
- package/src/index.ts +161 -146
- package/src/rpc/start.ts +1 -1
- package/src/services/api-server.ts +470 -473
- package/src/services/port-manager.ts +167 -167
- package/src/services/process-registry.ts +143 -143
- package/src/services/program-cloner.ts +312 -312
- package/src/services/token-cloner.ts +799 -797
- package/src/services/validator.ts +288 -288
- package/src/types/config.ts +71 -71
- package/src/utils/shell.ts +75 -75
- package/src/utils/token-loader.ts +77 -77
|
@@ -18,20 +18,22 @@ export function StatusPanel({ status, loading, onRefresh }: Props) {
|
|
|
18
18
|
</div>
|
|
19
19
|
<div>
|
|
20
20
|
<h2 className="text-xl font-bold text-white">Network Status</h2>
|
|
21
|
-
<p className="text-xs text-gray-500">
|
|
21
|
+
<p className="text-xs text-gray-500">
|
|
22
|
+
Real-time blockchain metrics
|
|
23
|
+
</p>
|
|
22
24
|
</div>
|
|
23
25
|
</div>
|
|
24
26
|
<button
|
|
25
27
|
type="button"
|
|
26
28
|
onClick={onRefresh}
|
|
27
29
|
disabled={loading}
|
|
28
|
-
className={`btn-secondary ${loading ?
|
|
30
|
+
className={`btn-secondary ${loading ? "opacity-50 cursor-not-allowed" : ""}`}
|
|
29
31
|
>
|
|
30
|
-
<i className={`fas fa-sync-alt ${loading ?
|
|
32
|
+
<i className={`fas fa-sync-alt ${loading ? "animate-spin" : ""}`}></i>
|
|
31
33
|
<span>{loading ? "Refreshing" : "Refresh"}</span>
|
|
32
34
|
</button>
|
|
33
35
|
</div>
|
|
34
|
-
|
|
36
|
+
|
|
35
37
|
{status ? (
|
|
36
38
|
<>
|
|
37
39
|
<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-4">
|
|
@@ -64,14 +66,18 @@ export function StatusPanel({ status, loading, onRefresh }: Props) {
|
|
|
64
66
|
color="green"
|
|
65
67
|
/>
|
|
66
68
|
</div>
|
|
67
|
-
|
|
69
|
+
|
|
68
70
|
{status.latestBlockhash && (
|
|
69
71
|
<div className="mt-6 p-4 rounded-xl bg-white/5 border border-white/10">
|
|
70
72
|
<div className="flex items-center gap-2 mb-2">
|
|
71
73
|
<i className="fas fa-fingerprint text-violet-400 text-xs"></i>
|
|
72
|
-
<span className="text-xs font-semibold text-gray-400 uppercase tracking-wider">
|
|
74
|
+
<span className="text-xs font-semibold text-gray-400 uppercase tracking-wider">
|
|
75
|
+
Latest Blockhash
|
|
76
|
+
</span>
|
|
73
77
|
</div>
|
|
74
|
-
<p className="text-sm font-mono text-violet-300 break-all">
|
|
78
|
+
<p className="text-sm font-mono text-violet-300 break-all">
|
|
79
|
+
{status.latestBlockhash}
|
|
80
|
+
</p>
|
|
75
81
|
</div>
|
|
76
82
|
)}
|
|
77
83
|
</>
|
|
@@ -81,7 +87,9 @@ export function StatusPanel({ status, loading, onRefresh }: Props) {
|
|
|
81
87
|
<i className="fas fa-server text-gray-500 text-2xl"></i>
|
|
82
88
|
</div>
|
|
83
89
|
<p className="text-gray-400 mb-2">No connection to RPC</p>
|
|
84
|
-
<p className="text-sm text-gray-500">
|
|
90
|
+
<p className="text-sm text-gray-500">
|
|
91
|
+
Start the RPC server to see network status
|
|
92
|
+
</p>
|
|
85
93
|
</div>
|
|
86
94
|
)}
|
|
87
95
|
</section>
|
|
@@ -93,30 +101,36 @@ interface StatusCardProps {
|
|
|
93
101
|
value: string;
|
|
94
102
|
subtitle?: string;
|
|
95
103
|
icon: string;
|
|
96
|
-
color:
|
|
104
|
+
color: "purple" | "blue" | "amber" | "green";
|
|
97
105
|
}
|
|
98
106
|
|
|
99
107
|
const colorClasses = {
|
|
100
|
-
purple:
|
|
101
|
-
blue:
|
|
102
|
-
amber:
|
|
103
|
-
green:
|
|
108
|
+
purple: "from-purple-500/20 to-violet-500/20 text-purple-400",
|
|
109
|
+
blue: "from-blue-500/20 to-cyan-500/20 text-blue-400",
|
|
110
|
+
amber: "from-amber-500/20 to-orange-500/20 text-amber-400",
|
|
111
|
+
green: "from-green-500/20 to-emerald-500/20 text-green-400",
|
|
104
112
|
};
|
|
105
113
|
|
|
106
114
|
function StatusCard({ title, value, subtitle, icon, color }: StatusCardProps) {
|
|
107
115
|
return (
|
|
108
116
|
<div className="card group hover:scale-[1.02] transition-all duration-200">
|
|
109
117
|
<div className="flex items-start justify-between mb-3">
|
|
110
|
-
<div
|
|
118
|
+
<div
|
|
119
|
+
className={`w-10 h-10 rounded-xl bg-gradient-to-br ${colorClasses[color]} flex items-center justify-center group-hover:scale-110 transition-transform`}
|
|
120
|
+
>
|
|
111
121
|
<i className={`fas ${icon} text-sm`}></i>
|
|
112
122
|
</div>
|
|
113
123
|
<span className="status-dot online"></span>
|
|
114
124
|
</div>
|
|
115
|
-
<p className="text-xs font-semibold text-gray-500 uppercase tracking-wider mb-1">
|
|
125
|
+
<p className="text-xs font-semibold text-gray-500 uppercase tracking-wider mb-1">
|
|
126
|
+
{title}
|
|
127
|
+
</p>
|
|
116
128
|
<p className="text-2xl font-bold text-white">{value}</p>
|
|
117
129
|
{subtitle && (
|
|
118
|
-
<p className="mt-2 text-xs text-gray-500 font-mono truncate">
|
|
130
|
+
<p className="mt-2 text-xs text-gray-500 font-mono truncate">
|
|
131
|
+
{subtitle}
|
|
132
|
+
</p>
|
|
119
133
|
)}
|
|
120
134
|
</div>
|
|
121
135
|
);
|
|
122
|
-
}
|
|
136
|
+
}
|
|
@@ -17,9 +17,7 @@ export function TokensPanel({ tokens, loading, onRefresh, onAdd }: Props) {
|
|
|
17
17
|
</div>
|
|
18
18
|
<div>
|
|
19
19
|
<h2 className="text-xl font-bold text-white">Tokens</h2>
|
|
20
|
-
<p className="text-xs text-gray-500">
|
|
21
|
-
{tokens.length} SPL tokens
|
|
22
|
-
</p>
|
|
20
|
+
<p className="text-xs text-gray-500">{tokens.length} SPL tokens</p>
|
|
23
21
|
</div>
|
|
24
22
|
</div>
|
|
25
23
|
<div className="flex items-center gap-2">
|
|
@@ -27,22 +25,20 @@ export function TokensPanel({ tokens, loading, onRefresh, onAdd }: Props) {
|
|
|
27
25
|
type="button"
|
|
28
26
|
onClick={onRefresh}
|
|
29
27
|
disabled={loading}
|
|
30
|
-
className={`btn-secondary text-sm ${loading ?
|
|
28
|
+
className={`btn-secondary text-sm ${loading ? "opacity-50 cursor-not-allowed" : ""}`}
|
|
31
29
|
>
|
|
32
|
-
<i
|
|
30
|
+
<i
|
|
31
|
+
className={`fas fa-sync-alt ${loading ? "animate-spin" : ""}`}
|
|
32
|
+
></i>
|
|
33
33
|
<span>{loading ? "Refreshing" : "Refresh"}</span>
|
|
34
34
|
</button>
|
|
35
|
-
<button
|
|
36
|
-
type="button"
|
|
37
|
-
onClick={onAdd}
|
|
38
|
-
className="btn-primary text-sm"
|
|
39
|
-
>
|
|
35
|
+
<button type="button" onClick={onAdd} className="btn-primary text-sm">
|
|
40
36
|
<i className="fas fa-plus"></i>
|
|
41
37
|
<span>Add Token</span>
|
|
42
38
|
</button>
|
|
43
39
|
</div>
|
|
44
40
|
</header>
|
|
45
|
-
|
|
41
|
+
|
|
46
42
|
<div className="overflow-x-auto rounded-xl">
|
|
47
43
|
{tokens.length === 0 ? (
|
|
48
44
|
<div className="flex flex-col items-center justify-center py-12 text-center">
|
|
@@ -50,7 +46,9 @@ export function TokensPanel({ tokens, loading, onRefresh, onAdd }: Props) {
|
|
|
50
46
|
<i className="fas fa-coins text-amber-500 text-2xl"></i>
|
|
51
47
|
</div>
|
|
52
48
|
<p className="text-gray-400 mb-2">No tokens created</p>
|
|
53
|
-
<p className="text-sm text-gray-500">
|
|
49
|
+
<p className="text-sm text-gray-500">
|
|
50
|
+
Click "Add Token" to clone from mainnet
|
|
51
|
+
</p>
|
|
54
52
|
</div>
|
|
55
53
|
) : (
|
|
56
54
|
<table className="table-modern">
|
|
@@ -65,7 +63,11 @@ export function TokensPanel({ tokens, loading, onRefresh, onAdd }: Props) {
|
|
|
65
63
|
</thead>
|
|
66
64
|
<tbody>
|
|
67
65
|
{tokens.map((token, index) => (
|
|
68
|
-
<tr
|
|
66
|
+
<tr
|
|
67
|
+
key={token.mint}
|
|
68
|
+
style={{ animationDelay: `${index * 50}ms` }}
|
|
69
|
+
className="animate-fadeIn"
|
|
70
|
+
>
|
|
69
71
|
<td>
|
|
70
72
|
<div className="flex items-center gap-2">
|
|
71
73
|
<i className="fas fa-coin text-amber-400 text-xs"></i>
|
|
@@ -83,9 +85,7 @@ export function TokensPanel({ tokens, loading, onRefresh, onAdd }: Props) {
|
|
|
83
85
|
</div>
|
|
84
86
|
</td>
|
|
85
87
|
<td>
|
|
86
|
-
<span className="badge">
|
|
87
|
-
{token.decimals}
|
|
88
|
-
</span>
|
|
88
|
+
<span className="badge">{token.decimals}</span>
|
|
89
89
|
</td>
|
|
90
90
|
<td>
|
|
91
91
|
{token.mintAuthority ? (
|
|
@@ -96,12 +96,18 @@ export function TokensPanel({ tokens, loading, onRefresh, onAdd }: Props) {
|
|
|
96
96
|
</span>
|
|
97
97
|
</div>
|
|
98
98
|
) : (
|
|
99
|
-
<span className="text-gray-500 text-sm">
|
|
99
|
+
<span className="text-gray-500 text-sm">
|
|
100
|
+
No authority
|
|
101
|
+
</span>
|
|
100
102
|
)}
|
|
101
103
|
</td>
|
|
102
104
|
<td>
|
|
103
|
-
<span
|
|
104
|
-
|
|
105
|
+
<span
|
|
106
|
+
className={`badge ${token.isInitialized ? "badge-success" : "badge-warning"}`}
|
|
107
|
+
>
|
|
108
|
+
<i
|
|
109
|
+
className={`fas fa-${token.isInitialized ? "check-circle" : "clock"} text-xs`}
|
|
110
|
+
></i>
|
|
105
111
|
<span>{token.isInitialized ? "Active" : "Pending"}</span>
|
|
106
112
|
</span>
|
|
107
113
|
</td>
|