persolator-cli 0.1.0
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 +21 -0
- package/README.md +255 -0
- package/dist/commands/airdrop.d.ts +7 -0
- package/dist/commands/airdrop.d.ts.map +1 -0
- package/dist/commands/airdrop.js +55 -0
- package/dist/commands/airdrop.js.map +1 -0
- package/dist/commands/create-token.d.ts +10 -0
- package/dist/commands/create-token.d.ts.map +1 -0
- package/dist/commands/create-token.js +91 -0
- package/dist/commands/create-token.js.map +1 -0
- package/dist/commands/markets.d.ts +5 -0
- package/dist/commands/markets.d.ts.map +1 -0
- package/dist/commands/markets.js +53 -0
- package/dist/commands/markets.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +37 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/keypair.d.ts +4 -0
- package/dist/lib/keypair.d.ts.map +1 -0
- package/dist/lib/keypair.js +29 -0
- package/dist/lib/keypair.js.map +1 -0
- package/dist/lib/logger.d.ts +8 -0
- package/dist/lib/logger.d.ts.map +1 -0
- package/dist/lib/logger.js +28 -0
- package/dist/lib/logger.js.map +1 -0
- package/package.json +53 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Persolator (https://persolator.xyz)
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
# persolator-cli
|
|
2
|
+
|
|
3
|
+
> Official CLI for [Persolator](https://persolator.xyz) — permissionless perpetual futures on Solana Devnet.
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
PERSOLATOR · CLI · Solana Devnet Tooling
|
|
7
|
+
https://persolator.xyz
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
## What is this?
|
|
11
|
+
|
|
12
|
+
`persolator-cli` lets you interact with the Persolator protocol from your terminal:
|
|
13
|
+
|
|
14
|
+
- **Create SPL tokens** on Solana devnet — ready to launch as perpetual futures markets
|
|
15
|
+
- **Request devnet SOL** airdrops to pay for transaction fees
|
|
16
|
+
- **List active markets** from the Persolator protocol
|
|
17
|
+
|
|
18
|
+
No VPS or server required. Everything runs on your local machine against Solana devnet.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Installation
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
npm install -g persolator-cli
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Or use without installing:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
npx persolator-cli --help
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## Requirements
|
|
37
|
+
|
|
38
|
+
- **Node.js** >= 18
|
|
39
|
+
- **Solana keypair** — generate one with the Solana CLI:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
# Install Solana CLI
|
|
43
|
+
sh -c "$(curl -sSfL https://release.solana.com/stable/install)"
|
|
44
|
+
|
|
45
|
+
# Generate a new keypair (saved to ~/.config/solana/id.json)
|
|
46
|
+
solana-keygen new
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## Commands
|
|
52
|
+
|
|
53
|
+
### `persolator airdrop`
|
|
54
|
+
|
|
55
|
+
Request devnet SOL to your wallet (needed to pay for transaction fees).
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
persolator airdrop
|
|
59
|
+
# Requests 2 SOL by default
|
|
60
|
+
|
|
61
|
+
persolator airdrop --amount 5
|
|
62
|
+
# Max 5 SOL per request (Solana devnet limit)
|
|
63
|
+
|
|
64
|
+
persolator airdrop --keypair ./my-wallet.json
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
**Options:**
|
|
68
|
+
|
|
69
|
+
| Flag | Default | Description |
|
|
70
|
+
|------|---------|-------------|
|
|
71
|
+
| `-a, --amount <sol>` | `2` | SOL amount (0.1 – 5) |
|
|
72
|
+
| `-k, --keypair <path>` | `~/.config/solana/id.json` | Path to keypair file |
|
|
73
|
+
| `--rpc <url>` | Solana devnet | Custom RPC endpoint |
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
### `persolator create-token`
|
|
78
|
+
|
|
79
|
+
Create a new SPL token on Solana devnet. The mint address it generates can be used to launch a perpetual futures market on Persolator.
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
# Minimal — just name and symbol
|
|
83
|
+
persolator create-token --name "My Token" --symbol MTK
|
|
84
|
+
|
|
85
|
+
# With initial supply (minted to your wallet)
|
|
86
|
+
persolator create-token \
|
|
87
|
+
--name "Test USDC" \
|
|
88
|
+
--symbol tUSDC \
|
|
89
|
+
--decimals 6 \
|
|
90
|
+
--supply 1000000
|
|
91
|
+
|
|
92
|
+
# Custom keypair
|
|
93
|
+
persolator create-token \
|
|
94
|
+
--name "My Token" \
|
|
95
|
+
--symbol MTK \
|
|
96
|
+
--keypair ./deployer.json
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
**Options:**
|
|
100
|
+
|
|
101
|
+
| Flag | Default | Description |
|
|
102
|
+
|------|---------|-------------|
|
|
103
|
+
| `-n, --name <name>` | required | Token name |
|
|
104
|
+
| `-s, --symbol <symbol>` | required | Token symbol (e.g. MTK) |
|
|
105
|
+
| `-d, --decimals <n>` | `9` | Number of decimal places |
|
|
106
|
+
| `--supply <amount>` | — | Initial token supply (optional) |
|
|
107
|
+
| `-k, --keypair <path>` | `~/.config/solana/id.json` | Path to keypair file |
|
|
108
|
+
| `--rpc <url>` | Solana devnet | Custom RPC endpoint |
|
|
109
|
+
|
|
110
|
+
**Output example:**
|
|
111
|
+
|
|
112
|
+
```
|
|
113
|
+
─────────────────────────────────────────────────────
|
|
114
|
+
→ Token Created Successfully
|
|
115
|
+
─────────────────────────────────────────────────────
|
|
116
|
+
Name My Token
|
|
117
|
+
Symbol MTK
|
|
118
|
+
Mint Address 7xK4mPqR...YZab
|
|
119
|
+
Decimals 9
|
|
120
|
+
Authority 8Fgh3...mNop
|
|
121
|
+
Explorer https://explorer.solana.com/address/7xK4...?cluster=devnet
|
|
122
|
+
─────────────────────────────────────────────────────
|
|
123
|
+
|
|
124
|
+
✓ Mint address ready to use on Persolator!
|
|
125
|
+
|
|
126
|
+
→ Next step — launch a perpetual market on Persolator:
|
|
127
|
+
→ https://persolator.xyz/launch
|
|
128
|
+
→ Paste this mint address: 7xK4mPqR...YZab
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
### `persolator markets`
|
|
134
|
+
|
|
135
|
+
List all active markets on the Persolator protocol.
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
persolator markets
|
|
139
|
+
|
|
140
|
+
# Point to a self-hosted instance
|
|
141
|
+
persolator markets --api https://api.persolator.xyz
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
**Options:**
|
|
145
|
+
|
|
146
|
+
| Flag | Default | Description |
|
|
147
|
+
|------|---------|-------------|
|
|
148
|
+
| `--api <url>` | `https://api.persolator.xyz` | Persolator API base URL |
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
## Full Workflow: From Zero to Market
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
# 1. Install the CLI
|
|
156
|
+
npm install -g persolator-cli
|
|
157
|
+
|
|
158
|
+
# 2. Generate a Solana keypair (skip if you already have one)
|
|
159
|
+
solana-keygen new
|
|
160
|
+
# Saves to: ~/.config/solana/id.json
|
|
161
|
+
|
|
162
|
+
# 3. Get devnet SOL for transaction fees
|
|
163
|
+
persolator airdrop --amount 2
|
|
164
|
+
|
|
165
|
+
# 4. Create your SPL token
|
|
166
|
+
persolator create-token \
|
|
167
|
+
--name "My Project Token" \
|
|
168
|
+
--symbol MPT \
|
|
169
|
+
--decimals 9
|
|
170
|
+
|
|
171
|
+
# 5. Copy the mint address from the output, then go to:
|
|
172
|
+
# https://persolator.xyz/launch
|
|
173
|
+
# Paste the mint address → configure leverage, fees → sign & deploy
|
|
174
|
+
|
|
175
|
+
# 6. Verify your market is live
|
|
176
|
+
persolator markets
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## Keypair Options
|
|
182
|
+
|
|
183
|
+
The CLI looks for a keypair in this order:
|
|
184
|
+
|
|
185
|
+
1. `--keypair <path>` flag
|
|
186
|
+
2. `$SOLANA_KEYPAIR` environment variable
|
|
187
|
+
3. `~/.config/solana/id.json` (Solana CLI default)
|
|
188
|
+
|
|
189
|
+
```bash
|
|
190
|
+
# Use environment variable
|
|
191
|
+
export SOLANA_KEYPAIR=/path/to/id.json
|
|
192
|
+
persolator create-token --name "Test" --symbol TST
|
|
193
|
+
|
|
194
|
+
# Use flag
|
|
195
|
+
persolator create-token --name "Test" --symbol TST --keypair ./my-key.json
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
## Custom RPC
|
|
201
|
+
|
|
202
|
+
By default the CLI connects to Solana's public devnet RPC. For better performance you can use a private endpoint:
|
|
203
|
+
|
|
204
|
+
```bash
|
|
205
|
+
persolator create-token \
|
|
206
|
+
--name "Test" \
|
|
207
|
+
--symbol TST \
|
|
208
|
+
--rpc https://api.devnet.solana.com
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
Free devnet RPC providers: [Helius](https://helius.dev), [QuickNode](https://quicknode.com), [Alchemy](https://alchemy.com)
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
## Programmatic Usage
|
|
216
|
+
|
|
217
|
+
The CLI is also importable as a library:
|
|
218
|
+
|
|
219
|
+
```ts
|
|
220
|
+
import { cmdCreateToken } from "persolator-cli/commands/create-token";
|
|
221
|
+
|
|
222
|
+
await cmdCreateToken({
|
|
223
|
+
name: "My Token",
|
|
224
|
+
symbol: "MTK",
|
|
225
|
+
decimals: "9",
|
|
226
|
+
supply: "1000000",
|
|
227
|
+
keypair: "./id.json",
|
|
228
|
+
});
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
---
|
|
232
|
+
|
|
233
|
+
## Security
|
|
234
|
+
|
|
235
|
+
- **Never share your keypair file.** It contains your private key.
|
|
236
|
+
- The CLI only connects to Solana **devnet** by default — no real funds are at risk.
|
|
237
|
+
- All source code is open source: [github.com/persolator/persolator-cli](https://github.com/persolator/persolator-cli)
|
|
238
|
+
|
|
239
|
+
---
|
|
240
|
+
|
|
241
|
+
## Links
|
|
242
|
+
|
|
243
|
+
| | |
|
|
244
|
+
|--|--|
|
|
245
|
+
| Website | https://persolator.xyz |
|
|
246
|
+
| App | https://persolator.xyz/markets |
|
|
247
|
+
| GitHub | https://github.com/persolator |
|
|
248
|
+
| X / Twitter | https://x.com/persolator_xyz |
|
|
249
|
+
| npm | https://npmjs.com/package/persolator-cli |
|
|
250
|
+
|
|
251
|
+
---
|
|
252
|
+
|
|
253
|
+
## License
|
|
254
|
+
|
|
255
|
+
MIT © [Persolator](https://persolator.xyz)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"airdrop.d.ts","sourceRoot":"","sources":["../../src/commands/airdrop.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,wBAAsB,UAAU,CAAC,IAAI,EAAE,cAAc,iBA2DpD"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { Connection, LAMPORTS_PER_SOL, clusterApiUrl } from "@solana/web3.js";
|
|
2
|
+
import { loadKeypair } from "../lib/keypair.js";
|
|
3
|
+
import { header, success, info, error, label, divider } from "../lib/logger.js";
|
|
4
|
+
import ora from "ora";
|
|
5
|
+
export async function cmdAirdrop(opts) {
|
|
6
|
+
header();
|
|
7
|
+
const amount = parseFloat(opts.amount);
|
|
8
|
+
if (isNaN(amount) || amount <= 0 || amount > 5) {
|
|
9
|
+
error("Amount must be between 0.1 and 5 SOL (devnet limit)");
|
|
10
|
+
process.exit(1);
|
|
11
|
+
}
|
|
12
|
+
let keypair;
|
|
13
|
+
try {
|
|
14
|
+
keypair = loadKeypair(opts.keypair);
|
|
15
|
+
}
|
|
16
|
+
catch (e) {
|
|
17
|
+
error(e.message);
|
|
18
|
+
process.exit(1);
|
|
19
|
+
}
|
|
20
|
+
const rpcUrl = opts.rpc ?? clusterApiUrl("devnet");
|
|
21
|
+
const connection = new Connection(rpcUrl, "confirmed");
|
|
22
|
+
const balanceBefore = await connection.getBalance(keypair.publicKey);
|
|
23
|
+
const spinner = ora({
|
|
24
|
+
text: `Requesting ${amount} SOL airdrop on devnet...`,
|
|
25
|
+
color: "cyan",
|
|
26
|
+
}).start();
|
|
27
|
+
try {
|
|
28
|
+
const sig = await connection.requestAirdrop(keypair.publicKey, amount * LAMPORTS_PER_SOL);
|
|
29
|
+
spinner.text = "Confirming airdrop transaction...";
|
|
30
|
+
const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash();
|
|
31
|
+
await connection.confirmTransaction({ signature: sig, blockhash, lastValidBlockHeight }, "confirmed");
|
|
32
|
+
const balanceAfter = await connection.getBalance(keypair.publicKey);
|
|
33
|
+
spinner.succeed("Airdrop confirmed!");
|
|
34
|
+
console.log("");
|
|
35
|
+
divider();
|
|
36
|
+
info("Airdrop Details");
|
|
37
|
+
divider();
|
|
38
|
+
label("Wallet", keypair.publicKey.toBase58());
|
|
39
|
+
label("Amount", `${amount} SOL`);
|
|
40
|
+
label("Balance before", `${(balanceBefore / LAMPORTS_PER_SOL).toFixed(4)} SOL`);
|
|
41
|
+
label("Balance after", `${(balanceAfter / LAMPORTS_PER_SOL).toFixed(4)} SOL`);
|
|
42
|
+
label("Tx Signature", sig);
|
|
43
|
+
label("Explorer", `https://explorer.solana.com/tx/${sig}?cluster=devnet`);
|
|
44
|
+
divider();
|
|
45
|
+
console.log("");
|
|
46
|
+
success("Airdrop complete! You can now create tokens and launch markets.");
|
|
47
|
+
console.log("");
|
|
48
|
+
}
|
|
49
|
+
catch (e) {
|
|
50
|
+
spinner.fail("Airdrop failed");
|
|
51
|
+
error(e.message ?? String(e));
|
|
52
|
+
process.exit(1);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=airdrop.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"airdrop.js","sourceRoot":"","sources":["../../src/commands/airdrop.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface CreateTokenOptions {
|
|
2
|
+
name: string;
|
|
3
|
+
symbol: string;
|
|
4
|
+
decimals: string;
|
|
5
|
+
supply?: string;
|
|
6
|
+
keypair?: string;
|
|
7
|
+
rpc?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function cmdCreateToken(opts: CreateTokenOptions): Promise<void>;
|
|
10
|
+
//# sourceMappingURL=create-token.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-token.d.ts","sourceRoot":"","sources":["../../src/commands/create-token.ts"],"names":[],"mappings":"AAgBA,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,wBAAsB,cAAc,CAAC,IAAI,EAAE,kBAAkB,iBAqG5D"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { Connection, LAMPORTS_PER_SOL, clusterApiUrl, } from "@solana/web3.js";
|
|
2
|
+
import { createMint, getOrCreateAssociatedTokenAccount, mintTo, getMint, } from "@solana/spl-token";
|
|
3
|
+
import { loadKeypair } from "../lib/keypair.js";
|
|
4
|
+
import { header, success, info, error, warn, label, divider } from "../lib/logger.js";
|
|
5
|
+
import ora from "ora";
|
|
6
|
+
export async function cmdCreateToken(opts) {
|
|
7
|
+
header();
|
|
8
|
+
const decimals = parseInt(opts.decimals, 10);
|
|
9
|
+
if (isNaN(decimals) || decimals < 0 || decimals > 18) {
|
|
10
|
+
error("Decimals must be between 0 and 18");
|
|
11
|
+
process.exit(1);
|
|
12
|
+
}
|
|
13
|
+
const supply = opts.supply ? parseFloat(opts.supply) : 0;
|
|
14
|
+
let payer;
|
|
15
|
+
try {
|
|
16
|
+
payer = loadKeypair(opts.keypair);
|
|
17
|
+
}
|
|
18
|
+
catch (e) {
|
|
19
|
+
error(e.message);
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
22
|
+
const rpcUrl = opts.rpc ?? clusterApiUrl("devnet");
|
|
23
|
+
const connection = new Connection(rpcUrl, "confirmed");
|
|
24
|
+
// Check balance
|
|
25
|
+
const balance = await connection.getBalance(payer.publicKey);
|
|
26
|
+
if (balance < 0.01 * LAMPORTS_PER_SOL) {
|
|
27
|
+
error(`Insufficient SOL balance: ${(balance / LAMPORTS_PER_SOL).toFixed(4)} SOL`);
|
|
28
|
+
warn('Run: persolator airdrop --amount 2');
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
31
|
+
info(`Creating SPL token on Solana devnet...`);
|
|
32
|
+
info(` Name: ${opts.name}`);
|
|
33
|
+
info(` Symbol: ${opts.symbol}`);
|
|
34
|
+
info(` Decimals: ${decimals}`);
|
|
35
|
+
if (supply > 0)
|
|
36
|
+
info(` Supply: ${supply.toLocaleString()} tokens`);
|
|
37
|
+
console.log("");
|
|
38
|
+
// 1. Create mint
|
|
39
|
+
const spinner = ora({ text: "Creating mint account...", color: "magenta" }).start();
|
|
40
|
+
let mint;
|
|
41
|
+
try {
|
|
42
|
+
mint = await createMint(connection, payer, payer.publicKey, payer.publicKey, decimals);
|
|
43
|
+
spinner.succeed(`Mint created: ${mint.toBase58()}`);
|
|
44
|
+
}
|
|
45
|
+
catch (e) {
|
|
46
|
+
spinner.fail("Failed to create mint");
|
|
47
|
+
error(e.message ?? String(e));
|
|
48
|
+
process.exit(1);
|
|
49
|
+
}
|
|
50
|
+
// 2. Optional: mint initial supply
|
|
51
|
+
let ataAddress;
|
|
52
|
+
if (supply > 0) {
|
|
53
|
+
const spinner2 = ora({ text: "Creating token account & minting supply...", color: "cyan" }).start();
|
|
54
|
+
try {
|
|
55
|
+
const ata = await getOrCreateAssociatedTokenAccount(connection, payer, mint, payer.publicKey);
|
|
56
|
+
const amount = BigInt(Math.round(supply * Math.pow(10, decimals)));
|
|
57
|
+
await mintTo(connection, payer, mint, ata.address, payer, amount);
|
|
58
|
+
ataAddress = ata.address.toBase58();
|
|
59
|
+
spinner2.succeed(`Minted ${supply.toLocaleString()} ${opts.symbol} to your wallet`);
|
|
60
|
+
}
|
|
61
|
+
catch (e) {
|
|
62
|
+
spinner2.warn("Supply minting failed (token was still created)");
|
|
63
|
+
warn(e.message ?? String(e));
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
// 3. Verify
|
|
67
|
+
const mintInfo = await getMint(connection, mint);
|
|
68
|
+
console.log("");
|
|
69
|
+
divider();
|
|
70
|
+
info("Token Created Successfully");
|
|
71
|
+
divider();
|
|
72
|
+
label("Name", opts.name);
|
|
73
|
+
label("Symbol", opts.symbol);
|
|
74
|
+
label("Mint Address", mint.toBase58());
|
|
75
|
+
label("Decimals", mintInfo.decimals.toString());
|
|
76
|
+
label("Authority", mintInfo.mintAuthority?.toBase58() ?? "none");
|
|
77
|
+
if (ataAddress) {
|
|
78
|
+
label("Token Account", ataAddress);
|
|
79
|
+
label("Supply", `${supply.toLocaleString()} ${opts.symbol}`);
|
|
80
|
+
}
|
|
81
|
+
label("Explorer", `https://explorer.solana.com/address/${mint.toBase58()}?cluster=devnet`);
|
|
82
|
+
divider();
|
|
83
|
+
console.log("");
|
|
84
|
+
success("Mint address ready to use on Persolator!");
|
|
85
|
+
console.log("");
|
|
86
|
+
info("Next step — launch a perpetual market on Persolator:");
|
|
87
|
+
info(` https://persolator.xyz/launch`);
|
|
88
|
+
info(` Paste this mint address: ${mint.toBase58()}`);
|
|
89
|
+
console.log("");
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=create-token.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-token.js","sourceRoot":"","sources":["../../src/commands/create-token.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,gBAAgB,EAChB,aAAa,GAEd,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,UAAU,EACV,iCAAiC,EACjC,MAAM,EACN,OAAO,GACR,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AACtF,OAAO,GAAG,MAAM,KAAK,CAAC;AAWtB,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,IAAwB;IAC3D,MAAM,EAAE,CAAC;IAET,MAAM,QAAQ,GAAG,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IAC7C,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,QAAQ,GAAG,CAAC,IAAI,QAAQ,GAAG,EAAE,EAAE,CAAC;QACrD,KAAK,CAAC,mCAAmC,CAAC,CAAC;QAC3C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAEzD,IAAI,KAAc,CAAC;IACnB,IAAI,CAAC;QACH,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACpC,CAAC;IAAC,OAAO,CAAM,EAAE,CAAC;QAChB,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;QACjB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,IAAI,aAAa,CAAC,QAAQ,CAAC,CAAC;IACnD,MAAM,UAAU,GAAG,IAAI,UAAU,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAEvD,gBAAgB;IAChB,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,UAAU,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IAC7D,IAAI,OAAO,GAAG,IAAI,GAAG,gBAAgB,EAAE,CAAC;QACtC,KAAK,CAAC,6BAA6B,CAAC,OAAO,GAAG,gBAAgB,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;QAClF,IAAI,CAAC,oCAAoC,CAAC,CAAC;QAC3C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,CAAC,wCAAwC,CAAC,CAAC;IAC/C,IAAI,CAAC,eAAe,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IACjC,IAAI,CAAC,eAAe,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;IACnC,IAAI,CAAC,eAAe,QAAQ,EAAE,CAAC,CAAC;IAChC,IAAI,MAAM,GAAG,CAAC;QAAE,IAAI,CAAC,eAAe,MAAM,CAAC,cAAc,EAAE,SAAS,CAAC,CAAC;IACtE,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAEhB,iBAAiB;IACjB,MAAM,OAAO,GAAG,GAAG,CAAC,EAAE,IAAI,EAAE,0BAA0B,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC;IACpF,IAAI,IAAI,CAAC;IACT,IAAI,CAAC;QACH,IAAI,GAAG,MAAM,UAAU,CACrB,UAAU,EACV,KAAK,EACL,KAAK,CAAC,SAAS,EACf,KAAK,CAAC,SAAS,EACf,QAAQ,CACT,CAAC;QACF,OAAO,CAAC,OAAO,CAAC,iBAAiB,IAAI,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IACtD,CAAC;IAAC,OAAO,CAAM,EAAE,CAAC;QAChB,OAAO,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;QACtC,KAAK,CAAC,CAAC,CAAC,OAAO,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,mCAAmC;IACnC,IAAI,UAA8B,CAAC;IACnC,IAAI,MAAM,GAAG,CAAC,EAAE,CAAC;QACf,MAAM,QAAQ,GAAG,GAAG,CAAC,EAAE,IAAI,EAAE,4CAA4C,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC;QACpG,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,iCAAiC,CACjD,UAAU,EACV,KAAK,EACL,IAAI,EACJ,KAAK,CAAC,SAAS,CAChB,CAAC;YACF,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC;YACnE,MAAM,MAAM,CAAC,UAAU,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,CAAC,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;YAClE,UAAU,GAAG,GAAG,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;YACpC,QAAQ,CAAC,OAAO,CAAC,UAAU,MAAM,CAAC,cAAc,EAAE,IAAI,IAAI,CAAC,MAAM,iBAAiB,CAAC,CAAC;QACtF,CAAC;QAAC,OAAO,CAAM,EAAE,CAAC;YAChB,QAAQ,CAAC,IAAI,CAAC,iDAAiD,CAAC,CAAC;YACjE,IAAI,CAAC,CAAC,CAAC,OAAO,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QAC/B,CAAC;IACH,CAAC;IAED,YAAY;IACZ,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;IAEjD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,EAAE,CAAC;IACV,IAAI,CAAC,4BAA4B,CAAC,CAAC;IACnC,OAAO,EAAE,CAAC;IACV,KAAK,CAAC,MAAM,EAAW,IAAI,CAAC,IAAI,CAAC,CAAC;IAClC,KAAK,CAAC,QAAQ,EAAS,IAAI,CAAC,MAAM,CAAC,CAAC;IACpC,KAAK,CAAC,cAAc,EAAG,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;IACxC,KAAK,CAAC,UAAU,EAAO,QAAQ,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC;IACrD,KAAK,CAAC,WAAW,EAAM,QAAQ,CAAC,aAAa,EAAE,QAAQ,EAAE,IAAI,MAAM,CAAC,CAAC;IACrE,IAAI,UAAU,EAAE,CAAC;QACf,KAAK,CAAC,eAAe,EAAE,UAAU,CAAC,CAAC;QACnC,KAAK,CAAC,QAAQ,EAAS,GAAG,MAAM,CAAC,cAAc,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;IACtE,CAAC;IACD,KAAK,CAAC,UAAU,EAAE,uCAAuC,IAAI,CAAC,QAAQ,EAAE,iBAAiB,CAAC,CAAC;IAC3F,OAAO,EAAE,CAAC;IACV,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,0CAA0C,CAAC,CAAC;IACpD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,IAAI,CAAC,sDAAsD,CAAC,CAAC;IAC7D,IAAI,CAAC,iCAAiC,CAAC,CAAC;IACxC,IAAI,CAAC,8BAA8B,IAAI,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IACtD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markets.d.ts","sourceRoot":"","sources":["../../src/commands/markets.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,cAAc;IAC7B,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,wBAAsB,UAAU,CAAC,IAAI,EAAE,cAAc,iBAsDpD"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { header, info, label, divider, error, success } from "../lib/logger.js";
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
export async function cmdMarkets(opts) {
|
|
4
|
+
header();
|
|
5
|
+
const base = (opts.api ?? "https://api.persolator.xyz").replace(/\/$/, "");
|
|
6
|
+
const spinner = (await import("ora")).default({
|
|
7
|
+
text: `Fetching markets from ${base}...`,
|
|
8
|
+
color: "cyan",
|
|
9
|
+
}).start();
|
|
10
|
+
let markets;
|
|
11
|
+
try {
|
|
12
|
+
const res = await fetch(`${base}/api/markets`);
|
|
13
|
+
if (!res.ok)
|
|
14
|
+
throw new Error(`HTTP ${res.status}: ${res.statusText}`);
|
|
15
|
+
const data = await res.json();
|
|
16
|
+
markets = data.markets ?? [];
|
|
17
|
+
spinner.succeed(`Found ${markets.length} active market${markets.length !== 1 ? "s" : ""}`);
|
|
18
|
+
}
|
|
19
|
+
catch (e) {
|
|
20
|
+
spinner.fail("Failed to fetch markets");
|
|
21
|
+
error(e.message ?? String(e));
|
|
22
|
+
process.exit(1);
|
|
23
|
+
}
|
|
24
|
+
if (markets.length === 0) {
|
|
25
|
+
info("No markets found. Be the first to launch one!");
|
|
26
|
+
info(" persolator launch (coming soon)");
|
|
27
|
+
info(` https://persolator.xyz/launch`);
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
console.log("");
|
|
31
|
+
divider();
|
|
32
|
+
info("Persolator Markets");
|
|
33
|
+
divider();
|
|
34
|
+
for (const m of markets) {
|
|
35
|
+
const change = m.priceChange24h ?? 0;
|
|
36
|
+
const color = change >= 0 ? chalk.hex("#22c55e") : chalk.hex("#ef4444");
|
|
37
|
+
const arrow = change >= 0 ? "↑" : "↓";
|
|
38
|
+
console.log("");
|
|
39
|
+
label("Market", m.symbol);
|
|
40
|
+
label("Price", `$${Number(m.price ?? 0).toFixed(4)}`);
|
|
41
|
+
label("24h", color(`${arrow} ${Math.abs(change).toFixed(2)}%`));
|
|
42
|
+
label("Volume", `$${Number(m.volume24h ?? 0).toLocaleString()}`);
|
|
43
|
+
label("Open Int.", `$${Number(m.openInterest ?? 0).toLocaleString()}`);
|
|
44
|
+
label("Max Lev", `${m.maxLeverage ?? "—"}x`);
|
|
45
|
+
label("Creator", m.creatorWallet ? `${m.creatorWallet.slice(0, 8)}...` : "—");
|
|
46
|
+
}
|
|
47
|
+
console.log("");
|
|
48
|
+
divider();
|
|
49
|
+
console.log("");
|
|
50
|
+
success(`Trade at https://persolator.xyz/markets`);
|
|
51
|
+
console.log("");
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=markets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markets.js","sourceRoot":"","sources":["../../src/commands/markets.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from "commander";
|
|
3
|
+
import { cmdCreateToken } from "./commands/create-token.js";
|
|
4
|
+
import { cmdAirdrop } from "./commands/airdrop.js";
|
|
5
|
+
import { cmdMarkets } from "./commands/markets.js";
|
|
6
|
+
const program = new Command();
|
|
7
|
+
program
|
|
8
|
+
.name("persolator")
|
|
9
|
+
.description("Official CLI for Persolator — permissionless perpetual futures on Solana")
|
|
10
|
+
.version("0.1.0");
|
|
11
|
+
// ── create-token ──────────────────────────────────────────────────────────────
|
|
12
|
+
program
|
|
13
|
+
.command("create-token")
|
|
14
|
+
.description("Create a new SPL token on Solana devnet (ready to use as a Persolator market)")
|
|
15
|
+
.requiredOption("-n, --name <name>", "Token name (e.g. \"My Test Token\")")
|
|
16
|
+
.requiredOption("-s, --symbol <symbol>", "Token symbol (e.g. MTT)")
|
|
17
|
+
.option("-d, --decimals <n>", "Token decimals", "9")
|
|
18
|
+
.option("--supply <amount>", "Initial supply to mint to your wallet (optional)")
|
|
19
|
+
.option("-k, --keypair <path>", "Path to Solana keypair JSON file")
|
|
20
|
+
.option("--rpc <url>", "Custom Solana RPC endpoint (default: devnet)")
|
|
21
|
+
.action(cmdCreateToken);
|
|
22
|
+
// ── airdrop ───────────────────────────────────────────────────────────────────
|
|
23
|
+
program
|
|
24
|
+
.command("airdrop")
|
|
25
|
+
.description("Request a devnet SOL airdrop (max 5 SOL per request)")
|
|
26
|
+
.option("-a, --amount <sol>", "Amount of SOL to request", "2")
|
|
27
|
+
.option("-k, --keypair <path>", "Path to Solana keypair JSON file")
|
|
28
|
+
.option("--rpc <url>", "Custom Solana RPC endpoint (default: devnet)")
|
|
29
|
+
.action(cmdAirdrop);
|
|
30
|
+
// ── markets ───────────────────────────────────────────────────────────────────
|
|
31
|
+
program
|
|
32
|
+
.command("markets")
|
|
33
|
+
.description("List all active Persolator markets")
|
|
34
|
+
.option("--api <url>", "Persolator API base URL", "https://api.persolator.xyz")
|
|
35
|
+
.action(cmdMarkets);
|
|
36
|
+
program.parse();
|
|
37
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,UAAU,EAAE,MAAU,uBAAuB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAU,uBAAuB,CAAC;AAEvD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,YAAY,CAAC;KAClB,WAAW,CAAC,0EAA0E,CAAC;KACvF,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,iFAAiF;AAEjF,OAAO;KACJ,OAAO,CAAC,cAAc,CAAC;KACvB,WAAW,CAAC,+EAA+E,CAAC;KAC5F,cAAc,CAAC,mBAAmB,EAAU,sCAAsC,CAAC;KACnF,cAAc,CAAC,uBAAuB,EAAM,yBAAyB,CAAC;KACtE,MAAM,CAAC,oBAAoB,EAAiB,gBAAgB,EAAE,GAAG,CAAC;KAClE,MAAM,CAAC,mBAAmB,EAAkB,kDAAkD,CAAC;KAC/F,MAAM,CAAC,sBAAsB,EAAe,kCAAkC,CAAC;KAC/E,MAAM,CAAC,aAAa,EAAwB,8CAA8C,CAAC;KAC3F,MAAM,CAAC,cAAc,CAAC,CAAC;AAE1B,iFAAiF;AAEjF,OAAO;KACJ,OAAO,CAAC,SAAS,CAAC;KAClB,WAAW,CAAC,sDAAsD,CAAC;KACnE,MAAM,CAAC,oBAAoB,EAAiB,0BAA0B,EAAE,GAAG,CAAC;KAC5E,MAAM,CAAC,sBAAsB,EAAe,kCAAkC,CAAC;KAC/E,MAAM,CAAC,aAAa,EAAwB,8CAA8C,CAAC;KAC3F,MAAM,CAAC,UAAU,CAAC,CAAC;AAEtB,iFAAiF;AAEjF,OAAO;KACJ,OAAO,CAAC,SAAS,CAAC;KAClB,WAAW,CAAC,oCAAoC,CAAC;KACjD,MAAM,CAAC,aAAa,EAAwB,yBAAyB,EAAE,4BAA4B,CAAC;KACpG,MAAM,CAAC,UAAU,CAAC,CAAC;AAEtB,OAAO,CAAC,KAAK,EAAE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keypair.d.ts","sourceRoot":"","sources":["../../src/lib/keypair.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAK1C,wBAAgB,WAAW,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAoBtD;AAED,wBAAgB,WAAW,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAIrD"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Keypair } from "@solana/web3.js";
|
|
2
|
+
import { readFileSync, existsSync } from "fs";
|
|
3
|
+
import { resolve, join } from "path";
|
|
4
|
+
import { homedir } from "os";
|
|
5
|
+
export function loadKeypair(filePath) {
|
|
6
|
+
const paths = [
|
|
7
|
+
filePath && resolve(filePath),
|
|
8
|
+
process.env.SOLANA_KEYPAIR,
|
|
9
|
+
join(homedir(), ".config", "solana", "id.json"),
|
|
10
|
+
].filter(Boolean);
|
|
11
|
+
for (const p of paths) {
|
|
12
|
+
if (existsSync(p)) {
|
|
13
|
+
const raw = readFileSync(p, "utf8");
|
|
14
|
+
const arr = JSON.parse(raw);
|
|
15
|
+
return Keypair.fromSecretKey(Uint8Array.from(arr));
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
throw new Error("No keypair found.\n" +
|
|
19
|
+
" Generate one: solana-keygen new\n" +
|
|
20
|
+
" Or pass: --keypair /path/to/id.json");
|
|
21
|
+
}
|
|
22
|
+
export function keypairPath(filePath) {
|
|
23
|
+
if (filePath)
|
|
24
|
+
return resolve(filePath);
|
|
25
|
+
if (process.env.SOLANA_KEYPAIR)
|
|
26
|
+
return process.env.SOLANA_KEYPAIR;
|
|
27
|
+
return join(homedir(), ".config", "solana", "id.json");
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=keypair.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keypair.js","sourceRoot":"","sources":["../../src/lib/keypair.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAC9C,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAE7B,MAAM,UAAU,WAAW,CAAC,QAAiB;IAC3C,MAAM,KAAK,GAAG;QACZ,QAAQ,IAAI,OAAO,CAAC,QAAQ,CAAC;QAC7B,OAAO,CAAC,GAAG,CAAC,cAAc;QAC1B,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,CAAC;KAChD,CAAC,MAAM,CAAC,OAAO,CAAa,CAAC;IAE9B,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,IAAI,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;YAClB,MAAM,GAAG,GAAG,YAAY,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;YACpC,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAa,CAAC;YACxC,OAAO,OAAO,CAAC,aAAa,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QACrD,CAAC;IACH,CAAC;IAED,MAAM,IAAI,KAAK,CACb,qBAAqB;QACrB,sCAAsC;QACtC,6CAA6C,CAC9C,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,QAAiB;IAC3C,IAAI,QAAQ;QAAE,OAAO,OAAO,CAAC,QAAQ,CAAC,CAAC;IACvC,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc;QAAE,OAAO,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;IAClE,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC;AACzD,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare function header(): void;
|
|
2
|
+
export declare function success(msg: string): void;
|
|
3
|
+
export declare function info(msg: string): void;
|
|
4
|
+
export declare function warn(msg: string): void;
|
|
5
|
+
export declare function error(msg: string): void;
|
|
6
|
+
export declare function label(key: string, value: string): void;
|
|
7
|
+
export declare function divider(): void;
|
|
8
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/lib/logger.ts"],"names":[],"mappings":"AAKA,wBAAgB,MAAM,SAKrB;AAED,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,QAElC;AAED,wBAAgB,IAAI,CAAC,GAAG,EAAE,MAAM,QAE/B;AAED,wBAAgB,IAAI,CAAC,GAAG,EAAE,MAAM,QAE/B;AAED,wBAAgB,KAAK,CAAC,GAAG,EAAE,MAAM,QAEhC;AAED,wBAAgB,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAE/C;AAED,wBAAgB,OAAO,SAEtB"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
const BRAND = chalk.hex("#e040fb").bold("PERSOLATOR");
|
|
3
|
+
const SEP = chalk.white.dim("·");
|
|
4
|
+
export function header() {
|
|
5
|
+
console.log("");
|
|
6
|
+
console.log(` ${BRAND} ${SEP} ${chalk.hex("#22d3ee")("CLI")} ${SEP} ${chalk.hex("#00ff88").dim("Solana Devnet Tooling")}`);
|
|
7
|
+
console.log(` ${chalk.dim("https://persolator.xyz")}`);
|
|
8
|
+
console.log("");
|
|
9
|
+
}
|
|
10
|
+
export function success(msg) {
|
|
11
|
+
console.log(` ${chalk.hex("#00ff88")("✓")} ${msg}`);
|
|
12
|
+
}
|
|
13
|
+
export function info(msg) {
|
|
14
|
+
console.log(` ${chalk.hex("#22d3ee")("→")} ${msg}`);
|
|
15
|
+
}
|
|
16
|
+
export function warn(msg) {
|
|
17
|
+
console.log(` ${chalk.yellow("!")} ${chalk.yellow(msg)}`);
|
|
18
|
+
}
|
|
19
|
+
export function error(msg) {
|
|
20
|
+
console.log(` ${chalk.red("✗")} ${chalk.red(msg)}`);
|
|
21
|
+
}
|
|
22
|
+
export function label(key, value) {
|
|
23
|
+
console.log(` ${chalk.dim(key.padEnd(20))} ${chalk.white(value)}`);
|
|
24
|
+
}
|
|
25
|
+
export function divider() {
|
|
26
|
+
console.log(` ${chalk.dim("─".repeat(52))}`);
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/lib/logger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;AACtD,MAAM,GAAG,GAAK,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAEnC,MAAM,UAAU,MAAM;IACpB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,IAAI,GAAG,IAAI,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC,IAAI,GAAG,IAAI,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,uBAAuB,CAAC,EAAE,CAAC,CAAC;IAC5H,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,GAAG,CAAC,wBAAwB,CAAC,EAAE,CAAC,CAAC;IACxD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,GAAW;IACjC,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC;AACvD,CAAC;AAED,MAAM,UAAU,IAAI,CAAC,GAAW;IAC9B,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC;AACvD,CAAC;AAED,MAAM,UAAU,IAAI,CAAC,GAAW;IAC9B,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AAC7D,CAAC;AAED,MAAM,UAAU,KAAK,CAAC,GAAW;IAC/B,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AACvD,CAAC;AAED,MAAM,UAAU,KAAK,CAAC,GAAW,EAAE,KAAa;IAC9C,OAAO,CAAC,GAAG,CAAC,OAAO,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;AACxE,CAAC;AAED,MAAM,UAAU,OAAO;IACrB,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;AAChD,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "persolator-cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Official CLI for Persolator — create SPL tokens on Solana devnet, manage markets, and interact with the Persolator perpetual futures protocol",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"persolator",
|
|
7
|
+
"solana",
|
|
8
|
+
"spl-token",
|
|
9
|
+
"devnet",
|
|
10
|
+
"perpetual",
|
|
11
|
+
"defi",
|
|
12
|
+
"cli"
|
|
13
|
+
],
|
|
14
|
+
"author": "Persolator <dev@persolator.xyz> (https://persolator.xyz)",
|
|
15
|
+
"license": "MIT",
|
|
16
|
+
"homepage": "https://persolator.xyz",
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "https://github.com/persolator/persolator-cli.git"
|
|
20
|
+
},
|
|
21
|
+
"bugs": {
|
|
22
|
+
"url": "https://github.com/persolator/persolator-cli/issues"
|
|
23
|
+
},
|
|
24
|
+
"type": "module",
|
|
25
|
+
"bin": {
|
|
26
|
+
"persolator": "./dist/index.js"
|
|
27
|
+
},
|
|
28
|
+
"files": [
|
|
29
|
+
"dist",
|
|
30
|
+
"README.md",
|
|
31
|
+
"LICENSE"
|
|
32
|
+
],
|
|
33
|
+
"scripts": {
|
|
34
|
+
"build": "tsc --project tsconfig.json && node scripts/postbuild.js",
|
|
35
|
+
"dev": "tsx src/index.ts",
|
|
36
|
+
"prepublishOnly": "pnpm build"
|
|
37
|
+
},
|
|
38
|
+
"engines": {
|
|
39
|
+
"node": ">=18.0.0"
|
|
40
|
+
},
|
|
41
|
+
"dependencies": {
|
|
42
|
+
"@solana/spl-token": "^0.4.13",
|
|
43
|
+
"@solana/web3.js": "^1.98.0",
|
|
44
|
+
"chalk": "^5.4.1",
|
|
45
|
+
"commander": "^13.1.0",
|
|
46
|
+
"ora": "^8.2.0"
|
|
47
|
+
},
|
|
48
|
+
"devDependencies": {
|
|
49
|
+
"@types/node": "^22.0.0",
|
|
50
|
+
"tsx": "^4.19.0",
|
|
51
|
+
"typescript": "^5.7.0"
|
|
52
|
+
}
|
|
53
|
+
}
|