naracli 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/README.md +155 -0
- package/bin/nara-cli.ts +32 -0
- package/dist/nara-cli.mjs +2631 -0
- package/dist/quest/nara_quest.json +534 -0
- package/dist/zk/answer_proof.wasm +0 -0
- package/dist/zk/answer_proof_final.zkey +0 -0
- package/index.ts +76 -0
- package/package.json +54 -0
- package/src/cli/commands/config.ts +125 -0
- package/src/cli/commands/migrate.ts +270 -0
- package/src/cli/commands/pool.ts +364 -0
- package/src/cli/commands/quest.ts +312 -0
- package/src/cli/commands/swap.ts +349 -0
- package/src/cli/commands/wallet.ts +719 -0
- package/src/cli/index.ts +25 -0
- package/src/cli/quest/nara_quest.json +534 -0
- package/src/cli/quest/nara_quest_types.ts +540 -0
- package/src/cli/types.ts +207 -0
- package/src/cli/utils/output.ts +110 -0
- package/src/cli/utils/transaction.ts +146 -0
- package/src/cli/utils/validation.ts +120 -0
- package/src/cli/utils/wallet.ts +72 -0
- package/src/cli/zk/answer_proof.wasm +0 -0
- package/src/cli/zk/answer_proof_final.zkey +0 -0
- package/src/client.ts +96 -0
- package/src/config.ts +132 -0
- package/src/constants.ts +29 -0
- package/src/migrate.ts +222 -0
- package/src/pool.ts +259 -0
- package/src/quest.ts +379 -0
- package/src/swap.ts +608 -0
- package/src/types/snarkjs.d.ts +9 -0
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Config commands
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { Command } from "commander";
|
|
6
|
+
import { NaraSDK } from "../../client";
|
|
7
|
+
import { createConfig } from "../../config";
|
|
8
|
+
import { loadWallet, getRpcUrl } from "../utils/wallet";
|
|
9
|
+
import { validatePublicKey } from "../utils/validation";
|
|
10
|
+
import {
|
|
11
|
+
handleTransaction,
|
|
12
|
+
printTransactionResult,
|
|
13
|
+
} from "../utils/transaction";
|
|
14
|
+
import { formatOutput, printError, printInfo } from "../utils/output";
|
|
15
|
+
import type { ConfigCreateOptions } from "../types";
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Register config commands
|
|
19
|
+
* @param program Commander program
|
|
20
|
+
*/
|
|
21
|
+
export function registerConfigCommands(program: Command): void {
|
|
22
|
+
const config = program
|
|
23
|
+
.command("config")
|
|
24
|
+
.description("Configuration management commands");
|
|
25
|
+
|
|
26
|
+
// config create
|
|
27
|
+
config
|
|
28
|
+
.command("create")
|
|
29
|
+
.description("Create a bonding curve configuration")
|
|
30
|
+
.option("--fee-claimer <address>", "Fee claimer wallet address")
|
|
31
|
+
.option(
|
|
32
|
+
"--leftover-receiver <address>",
|
|
33
|
+
"Leftover token receiver wallet address"
|
|
34
|
+
)
|
|
35
|
+
.option(
|
|
36
|
+
"--total-supply <number>",
|
|
37
|
+
"Total token supply",
|
|
38
|
+
"1000000000"
|
|
39
|
+
)
|
|
40
|
+
.option("--initial-mcap <number>", "Initial market cap", "30")
|
|
41
|
+
.option("--migration-mcap <number>", "Migration market cap", "540")
|
|
42
|
+
.option("-e, --export-tx", "Export unsigned transaction", false)
|
|
43
|
+
.action(async (options: ConfigCreateOptions) => {
|
|
44
|
+
try {
|
|
45
|
+
await handleConfigCreate(options);
|
|
46
|
+
} catch (error: any) {
|
|
47
|
+
printError(error.message);
|
|
48
|
+
process.exit(1);
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Handle config create command
|
|
55
|
+
* @param options Command options
|
|
56
|
+
*/
|
|
57
|
+
async function handleConfigCreate(
|
|
58
|
+
options: ConfigCreateOptions
|
|
59
|
+
): Promise<void> {
|
|
60
|
+
// Load wallet
|
|
61
|
+
const wallet = await loadWallet(options.wallet);
|
|
62
|
+
const rpcUrl = getRpcUrl(options.rpcUrl);
|
|
63
|
+
|
|
64
|
+
printInfo(`Using RPC: ${rpcUrl}`);
|
|
65
|
+
printInfo(`Wallet: ${wallet.publicKey.toBase58()}`);
|
|
66
|
+
|
|
67
|
+
// Initialize SDK
|
|
68
|
+
const sdk = new NaraSDK({
|
|
69
|
+
rpcUrl,
|
|
70
|
+
commitment: "confirmed",
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
// Parse addresses
|
|
74
|
+
const feeClaimer = options.feeClaimer
|
|
75
|
+
? validatePublicKey(options.feeClaimer)
|
|
76
|
+
: wallet.publicKey;
|
|
77
|
+
const leftoverReceiver = options.leftoverReceiver
|
|
78
|
+
? validatePublicKey(options.leftoverReceiver)
|
|
79
|
+
: wallet.publicKey;
|
|
80
|
+
|
|
81
|
+
// Parse numeric options
|
|
82
|
+
const totalTokenSupply = parseInt(String(options.totalSupply || "1000000000"));
|
|
83
|
+
const initialMarketCap = parseFloat(String(options.initialMcap || "30"));
|
|
84
|
+
const migrationMarketCap = parseFloat(String(options.migrationMcap || "540"));
|
|
85
|
+
|
|
86
|
+
printInfo("Creating bonding curve configuration...");
|
|
87
|
+
|
|
88
|
+
// Create config
|
|
89
|
+
const result = await createConfig(sdk, {
|
|
90
|
+
feeClaimer,
|
|
91
|
+
leftoverReceiver,
|
|
92
|
+
payer: wallet.publicKey,
|
|
93
|
+
totalTokenSupply,
|
|
94
|
+
initialMarketCap,
|
|
95
|
+
migrationMarketCap,
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
printInfo(`Config address: ${result.configAddress}`);
|
|
99
|
+
|
|
100
|
+
// Handle transaction
|
|
101
|
+
const txResult = await handleTransaction(
|
|
102
|
+
sdk,
|
|
103
|
+
result.transaction,
|
|
104
|
+
[wallet, result.configKeypair], // Both wallet and config keypair need to sign
|
|
105
|
+
options.exportTx || false
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
// Output result
|
|
109
|
+
if (options.json) {
|
|
110
|
+
const output = {
|
|
111
|
+
configAddress: result.configAddress,
|
|
112
|
+
...(txResult.signature && { signature: txResult.signature }),
|
|
113
|
+
...(txResult.base64 && { transaction: txResult.base64 }),
|
|
114
|
+
};
|
|
115
|
+
console.log(JSON.stringify(output, null, 2));
|
|
116
|
+
} else {
|
|
117
|
+
console.log(`\nConfig Address: ${result.configAddress}`);
|
|
118
|
+
printTransactionResult(txResult, false);
|
|
119
|
+
|
|
120
|
+
if (txResult.signature) {
|
|
121
|
+
printInfo("\nSave this DBC config address for creating pools:");
|
|
122
|
+
console.log(`export DBC_CONFIG_ADDRESS="${result.configAddress}"`);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Migration commands
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { Command } from "commander";
|
|
6
|
+
import { NaraSDK } from "../../client";
|
|
7
|
+
import { migrateToDAMMV2, createLocker, canMigrate } from "../../migrate";
|
|
8
|
+
import { loadWallet, getRpcUrl } from "../utils/wallet";
|
|
9
|
+
import { validatePublicKey } from "../utils/validation";
|
|
10
|
+
import {
|
|
11
|
+
handleTransaction,
|
|
12
|
+
printTransactionResult,
|
|
13
|
+
} from "../utils/transaction";
|
|
14
|
+
import { formatOutput, printError, printInfo, printSuccess, printWarning } from "../utils/output";
|
|
15
|
+
import type {
|
|
16
|
+
MigrateLaunchOptions,
|
|
17
|
+
MigrateCreateLockerOptions,
|
|
18
|
+
MigrateCheckOptions,
|
|
19
|
+
} from "../types";
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Register migration commands
|
|
23
|
+
* @param program Commander program
|
|
24
|
+
*/
|
|
25
|
+
export function registerMigrateCommands(program: Command): void {
|
|
26
|
+
const migrate = program
|
|
27
|
+
.command("migrate")
|
|
28
|
+
.description("Pool migration commands");
|
|
29
|
+
|
|
30
|
+
// migrate launch
|
|
31
|
+
migrate
|
|
32
|
+
.command("launch <token-address>")
|
|
33
|
+
.description("Migrate pool to DAMM V2 (graduation)")
|
|
34
|
+
.option("-e, --export-tx", "Export unsigned transaction", false)
|
|
35
|
+
.action(
|
|
36
|
+
async (
|
|
37
|
+
tokenAddress: string,
|
|
38
|
+
options: Omit<MigrateLaunchOptions, "tokenAddress">
|
|
39
|
+
) => {
|
|
40
|
+
try {
|
|
41
|
+
await handleMigrateLaunch(tokenAddress, options);
|
|
42
|
+
} catch (error: any) {
|
|
43
|
+
printError(error.message);
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
// migrate create-locker
|
|
50
|
+
migrate
|
|
51
|
+
.command("create-locker <token-address>")
|
|
52
|
+
.description("Create locker for pools with vesting")
|
|
53
|
+
.option("-e, --export-tx", "Export unsigned transaction", false)
|
|
54
|
+
.action(
|
|
55
|
+
async (
|
|
56
|
+
tokenAddress: string,
|
|
57
|
+
options: Omit<MigrateCreateLockerOptions, "tokenAddress">
|
|
58
|
+
) => {
|
|
59
|
+
try {
|
|
60
|
+
await handleMigrateCreateLocker(tokenAddress, options);
|
|
61
|
+
} catch (error: any) {
|
|
62
|
+
printError(error.message);
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
// migrate check
|
|
69
|
+
migrate
|
|
70
|
+
.command("check <token-address>")
|
|
71
|
+
.description("Check if pool can be migrated")
|
|
72
|
+
.action(
|
|
73
|
+
async (
|
|
74
|
+
tokenAddress: string,
|
|
75
|
+
options: Omit<MigrateCheckOptions, "tokenAddress">
|
|
76
|
+
) => {
|
|
77
|
+
try {
|
|
78
|
+
await handleMigrateCheck(tokenAddress, options);
|
|
79
|
+
} catch (error: any) {
|
|
80
|
+
printError(error.message);
|
|
81
|
+
process.exit(1);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Handle migrate launch command
|
|
89
|
+
* @param tokenAddress Token address
|
|
90
|
+
* @param options Command options
|
|
91
|
+
*/
|
|
92
|
+
async function handleMigrateLaunch(
|
|
93
|
+
tokenAddress: string,
|
|
94
|
+
options: Omit<MigrateLaunchOptions, "tokenAddress">
|
|
95
|
+
): Promise<void> {
|
|
96
|
+
// Load wallet
|
|
97
|
+
const wallet = await loadWallet(options.wallet);
|
|
98
|
+
const rpcUrl = getRpcUrl(options.rpcUrl);
|
|
99
|
+
|
|
100
|
+
printInfo(`Using RPC: ${rpcUrl}`);
|
|
101
|
+
printInfo(`Wallet: ${wallet.publicKey.toBase58()}`);
|
|
102
|
+
|
|
103
|
+
// Validate address
|
|
104
|
+
validatePublicKey(tokenAddress);
|
|
105
|
+
|
|
106
|
+
// Initialize SDK
|
|
107
|
+
const sdk = new NaraSDK({
|
|
108
|
+
rpcUrl,
|
|
109
|
+
commitment: "confirmed",
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
// Check if migration is possible
|
|
113
|
+
printInfo("Checking if pool can be migrated...");
|
|
114
|
+
const checkResult = await canMigrate(sdk, tokenAddress);
|
|
115
|
+
|
|
116
|
+
if (!checkResult.canMigrate) {
|
|
117
|
+
printError(`Cannot migrate: ${checkResult.reason}`);
|
|
118
|
+
process.exit(1);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
printSuccess("Pool is ready for migration!");
|
|
122
|
+
printInfo("Migrating pool to DAMM V2...");
|
|
123
|
+
|
|
124
|
+
// Migrate to DAMM V2
|
|
125
|
+
const result = await migrateToDAMMV2(sdk, {
|
|
126
|
+
tokenAddress,
|
|
127
|
+
payer: wallet.publicKey,
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
printInfo(`Pool address: ${result.poolAddress}`);
|
|
131
|
+
|
|
132
|
+
// Handle transaction
|
|
133
|
+
// Migration requires three signatures: wallet, firstPositionNftKeypair, secondPositionNftKeypair
|
|
134
|
+
const txResult = await handleTransaction(
|
|
135
|
+
sdk,
|
|
136
|
+
result.transaction,
|
|
137
|
+
[wallet, result.firstPositionNftKeypair, result.secondPositionNftKeypair],
|
|
138
|
+
options.exportTx || false
|
|
139
|
+
);
|
|
140
|
+
|
|
141
|
+
// Output result
|
|
142
|
+
if (options.json) {
|
|
143
|
+
const output = {
|
|
144
|
+
poolAddress: result.poolAddress,
|
|
145
|
+
...(txResult.signature && { signature: txResult.signature }),
|
|
146
|
+
...(txResult.base64 && { transaction: txResult.base64 }),
|
|
147
|
+
};
|
|
148
|
+
console.log(JSON.stringify(output, null, 2));
|
|
149
|
+
} else {
|
|
150
|
+
console.log(`\nPool Address: ${result.poolAddress}`);
|
|
151
|
+
printTransactionResult(txResult, false);
|
|
152
|
+
|
|
153
|
+
if (txResult.signature) {
|
|
154
|
+
printSuccess("\nPool successfully migrated to DAMM V2!");
|
|
155
|
+
printInfo("Pool is now a constant product AMM with full liquidity.");
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Handle migrate create-locker command
|
|
162
|
+
* @param tokenAddress Token address
|
|
163
|
+
* @param options Command options
|
|
164
|
+
*/
|
|
165
|
+
async function handleMigrateCreateLocker(
|
|
166
|
+
tokenAddress: string,
|
|
167
|
+
options: Omit<MigrateCreateLockerOptions, "tokenAddress">
|
|
168
|
+
): Promise<void> {
|
|
169
|
+
// Load wallet
|
|
170
|
+
const wallet = await loadWallet(options.wallet);
|
|
171
|
+
const rpcUrl = getRpcUrl(options.rpcUrl);
|
|
172
|
+
|
|
173
|
+
printInfo(`Using RPC: ${rpcUrl}`);
|
|
174
|
+
printInfo(`Wallet: ${wallet.publicKey.toBase58()}`);
|
|
175
|
+
|
|
176
|
+
// Validate address
|
|
177
|
+
validatePublicKey(tokenAddress);
|
|
178
|
+
|
|
179
|
+
// Initialize SDK
|
|
180
|
+
const sdk = new NaraSDK({
|
|
181
|
+
rpcUrl,
|
|
182
|
+
commitment: "confirmed",
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
printInfo("Creating locker for pool with vesting parameters...");
|
|
186
|
+
|
|
187
|
+
// Create locker
|
|
188
|
+
const result = await createLocker(sdk, {
|
|
189
|
+
tokenAddress,
|
|
190
|
+
payer: wallet.publicKey,
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
printInfo(`Pool address: ${result.poolAddress}`);
|
|
194
|
+
|
|
195
|
+
// Handle transaction
|
|
196
|
+
const txResult = await handleTransaction(
|
|
197
|
+
sdk,
|
|
198
|
+
result.transaction,
|
|
199
|
+
[wallet],
|
|
200
|
+
options.exportTx || false
|
|
201
|
+
);
|
|
202
|
+
|
|
203
|
+
// Output result
|
|
204
|
+
if (options.json) {
|
|
205
|
+
const output = {
|
|
206
|
+
poolAddress: result.poolAddress,
|
|
207
|
+
...(txResult.signature && { signature: txResult.signature }),
|
|
208
|
+
...(txResult.base64 && { transaction: txResult.base64 }),
|
|
209
|
+
};
|
|
210
|
+
console.log(JSON.stringify(output, null, 2));
|
|
211
|
+
} else {
|
|
212
|
+
console.log(`\nPool Address: ${result.poolAddress}`);
|
|
213
|
+
printTransactionResult(txResult, false);
|
|
214
|
+
|
|
215
|
+
if (txResult.signature) {
|
|
216
|
+
printSuccess("\nLocker created successfully!");
|
|
217
|
+
printInfo("You can now proceed with migrating the pool.");
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Handle migrate check command
|
|
224
|
+
* @param tokenAddress Token address
|
|
225
|
+
* @param options Command options
|
|
226
|
+
*/
|
|
227
|
+
async function handleMigrateCheck(
|
|
228
|
+
tokenAddress: string,
|
|
229
|
+
options: Omit<MigrateCheckOptions, "tokenAddress">
|
|
230
|
+
): Promise<void> {
|
|
231
|
+
const rpcUrl = getRpcUrl(options.rpcUrl);
|
|
232
|
+
|
|
233
|
+
printInfo(`Using RPC: ${rpcUrl}`);
|
|
234
|
+
|
|
235
|
+
// Validate address
|
|
236
|
+
validatePublicKey(tokenAddress);
|
|
237
|
+
|
|
238
|
+
// Initialize SDK
|
|
239
|
+
const sdk = new NaraSDK({
|
|
240
|
+
rpcUrl,
|
|
241
|
+
commitment: "confirmed",
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
printInfo("Checking migration status...");
|
|
245
|
+
|
|
246
|
+
// Check if can migrate
|
|
247
|
+
const result = await canMigrate(sdk, tokenAddress);
|
|
248
|
+
|
|
249
|
+
// Output result
|
|
250
|
+
if (options.json) {
|
|
251
|
+
console.log(JSON.stringify(result, null, 2));
|
|
252
|
+
} else {
|
|
253
|
+
console.log(`\nMigration Status:`);
|
|
254
|
+
console.log(` Can Migrate: ${result.canMigrate ? "Yes" : "No"}`);
|
|
255
|
+
console.log(` Progress: ${(result.progress * 100).toFixed(2)}%`);
|
|
256
|
+
if (result.reason) {
|
|
257
|
+
console.log(` Reason: ${result.reason}`);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
if (result.canMigrate) {
|
|
261
|
+
printSuccess("\nPool is ready for migration!");
|
|
262
|
+
printInfo("Run: nara-cli migrate launch <token-address>");
|
|
263
|
+
} else {
|
|
264
|
+
printWarning("\nPool is not ready for migration yet.");
|
|
265
|
+
if (result.progress < 1.0) {
|
|
266
|
+
printInfo(`Curve completion required: 100% (current: ${(result.progress * 100).toFixed(2)}%)`);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|