dipcoin-cli 1.1.1 → 1.2.1
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 +30 -9
- package/dist/cli.cjs +156 -0
- package/dist/cli.cjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -20,23 +20,36 @@ npm install -g dipcoin-cli
|
|
|
20
20
|
|
|
21
21
|
### Configuration
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
Credentials live in `~/.config/dipcoin/env`. Set them up with one of the two built-in commands — both write the file with `chmod 600` and never echo your private key to the terminal.
|
|
24
|
+
|
|
25
|
+
**Import an existing Sui wallet:**
|
|
24
26
|
|
|
25
27
|
```bash
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
DIPCOIN_PRIVATE_KEY=suiprivkey1...
|
|
29
|
-
DIPCOIN_NETWORK=mainnet
|
|
30
|
-
EOF
|
|
28
|
+
dipcoin-cli setup import # mainnet (default)
|
|
29
|
+
dipcoin-cli setup import --network testnet
|
|
31
30
|
```
|
|
32
31
|
|
|
32
|
+
You'll be prompted for your `suiprivkey1...` private key with hidden input.
|
|
33
|
+
|
|
34
|
+
**Or generate a new wallet:**
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
dipcoin-cli setup generate # mainnet (default)
|
|
38
|
+
dipcoin-cli setup generate --network testnet
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
A new Ed25519 keypair is created and saved; the command prints the public Sui address. Transfer USDC on Sui to that address, then run `dipcoin-cli account deposit <amount>` to fund the DEX.
|
|
42
|
+
|
|
43
|
+
#### Config file format
|
|
44
|
+
|
|
45
|
+
The generated `~/.config/dipcoin/env` contains:
|
|
46
|
+
|
|
33
47
|
| Variable | Required | Description |
|
|
34
48
|
|----------|----------|-------------|
|
|
35
|
-
| `DIPCOIN_PRIVATE_KEY` |
|
|
36
|
-
| `DIPCOIN_MNEMONIC` | is required | 12-word Sui mnemonic phrase (derives keypair at `m/44'/784'/0'/0'/0'`) |
|
|
49
|
+
| `DIPCOIN_PRIVATE_KEY` | Yes | Sui private key (`suiprivkey1...`), supports ED25519/Secp256k1/Secp256r1 |
|
|
37
50
|
| `DIPCOIN_NETWORK` | No | `mainnet` or `testnet` (default: `mainnet`) |
|
|
38
51
|
|
|
39
|
-
|
|
52
|
+
Manual editing is supported but discouraged — prefer the `setup` commands so format and permissions stay correct.
|
|
40
53
|
|
|
41
54
|
### Quick Start
|
|
42
55
|
|
|
@@ -72,6 +85,14 @@ dipcoin-cli history orders --symbol BTC-PERP
|
|
|
72
85
|
| `--json` | Output in JSON format (machine-readable) |
|
|
73
86
|
| `-V, --version` | Show version |
|
|
74
87
|
|
|
88
|
+
#### setup
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
dipcoin-cli setup import # Import existing key (hidden prompt)
|
|
92
|
+
dipcoin-cli setup generate # Generate new keypair
|
|
93
|
+
dipcoin-cli setup import --network testnet # Same, on testnet
|
|
94
|
+
```
|
|
95
|
+
|
|
75
96
|
#### market
|
|
76
97
|
|
|
77
98
|
```bash
|
package/dist/cli.cjs
CHANGED
|
@@ -15,6 +15,7 @@ var transactions = require('@mysten/sui/transactions');
|
|
|
15
15
|
var pythSuiJs = require('@pythnetwork/pyth-sui-js');
|
|
16
16
|
var child_process = require('child_process');
|
|
17
17
|
var Table = require('cli-table3');
|
|
18
|
+
var readline = require('readline');
|
|
18
19
|
|
|
19
20
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
20
21
|
|
|
@@ -24,6 +25,7 @@ var os__default = /*#__PURE__*/_interopDefaultLegacy(os);
|
|
|
24
25
|
var fs__default = /*#__PURE__*/_interopDefaultLegacy(fs);
|
|
25
26
|
var BigNumber__default = /*#__PURE__*/_interopDefaultLegacy(BigNumber);
|
|
26
27
|
var Table__default = /*#__PURE__*/_interopDefaultLegacy(Table);
|
|
28
|
+
var readline__default = /*#__PURE__*/_interopDefaultLegacy(readline);
|
|
27
29
|
|
|
28
30
|
const crypto = typeof globalThis === 'object' && 'crypto' in globalThis ? globalThis.crypto : undefined;
|
|
29
31
|
|
|
@@ -5972,6 +5974,9 @@ const bcs = {
|
|
|
5972
5974
|
}
|
|
5973
5975
|
};
|
|
5974
5976
|
|
|
5977
|
+
toBase58;
|
|
5978
|
+
fromBase58;
|
|
5979
|
+
|
|
5975
5980
|
const SUI_NS_NAME_REGEX = /^(?!.*(^(?!@)|[-.@])($|[-.@]))(?:[a-z0-9-]{0,63}(?:\.[a-z0-9-]{0,63})*)?@[a-z0-9-]{0,63}$/i;
|
|
5976
5981
|
const SUI_NS_DOMAIN_REGEX = /^(?!.*(^|[-.])($|[-.]))(?:[a-z0-9-]{0,63}\.)+sui$/i;
|
|
5977
5982
|
const MAX_SUI_NS_NAME_LENGTH = 235;
|
|
@@ -20994,6 +20999,156 @@ function registerReferralCommands(program) {
|
|
|
20994
20999
|
});
|
|
20995
21000
|
}
|
|
20996
21001
|
|
|
21002
|
+
const CONFIG_DIR = path__default["default"].join(os__default["default"].homedir(), ".config", "dipcoin");
|
|
21003
|
+
const ENV_PATH = path__default["default"].join(CONFIG_DIR, "env");
|
|
21004
|
+
function ask(question) {
|
|
21005
|
+
const rl = readline__default["default"].createInterface({ input: process.stdin, output: process.stdout });
|
|
21006
|
+
return new Promise((resolve) => rl.question(question, (answer) => {
|
|
21007
|
+
rl.close();
|
|
21008
|
+
resolve(answer);
|
|
21009
|
+
}));
|
|
21010
|
+
}
|
|
21011
|
+
async function confirmOverwrite() {
|
|
21012
|
+
if (!fs__default["default"].existsSync(ENV_PATH))
|
|
21013
|
+
return true;
|
|
21014
|
+
const answer = await ask(`${ENV_PATH} already exists. Overwrite? [y/N]: `);
|
|
21015
|
+
return /^y(es)?$/i.test(answer.trim());
|
|
21016
|
+
}
|
|
21017
|
+
function readHiddenInput(prompt) {
|
|
21018
|
+
return new Promise((resolve, reject) => {
|
|
21019
|
+
const stdin = process.stdin;
|
|
21020
|
+
if (!stdin.isTTY) {
|
|
21021
|
+
let buffer = "";
|
|
21022
|
+
stdin.setEncoding("utf8");
|
|
21023
|
+
stdin.on("data", (chunk) => {
|
|
21024
|
+
buffer += chunk;
|
|
21025
|
+
});
|
|
21026
|
+
stdin.on("end", () => {
|
|
21027
|
+
resolve(buffer.split(/\r?\n/)[0] || "");
|
|
21028
|
+
});
|
|
21029
|
+
return;
|
|
21030
|
+
}
|
|
21031
|
+
process.stdout.write(prompt);
|
|
21032
|
+
stdin.setRawMode(true);
|
|
21033
|
+
stdin.resume();
|
|
21034
|
+
stdin.setEncoding("utf8");
|
|
21035
|
+
let input = "";
|
|
21036
|
+
const onData = (chunk) => {
|
|
21037
|
+
for (const ch of chunk) {
|
|
21038
|
+
const code = ch.charCodeAt(0);
|
|
21039
|
+
if (ch === "\n" || ch === "\r") {
|
|
21040
|
+
stdin.setRawMode(false);
|
|
21041
|
+
stdin.pause();
|
|
21042
|
+
stdin.removeListener("data", onData);
|
|
21043
|
+
process.stdout.write("\n");
|
|
21044
|
+
resolve(input);
|
|
21045
|
+
return;
|
|
21046
|
+
}
|
|
21047
|
+
if (code === 3) {
|
|
21048
|
+
stdin.setRawMode(false);
|
|
21049
|
+
stdin.pause();
|
|
21050
|
+
process.stdout.write("\n");
|
|
21051
|
+
reject(new Error("Aborted"));
|
|
21052
|
+
return;
|
|
21053
|
+
}
|
|
21054
|
+
if (code === 127 || code === 8) {
|
|
21055
|
+
input = input.slice(0, -1);
|
|
21056
|
+
continue;
|
|
21057
|
+
}
|
|
21058
|
+
input += ch;
|
|
21059
|
+
}
|
|
21060
|
+
};
|
|
21061
|
+
stdin.on("data", onData);
|
|
21062
|
+
});
|
|
21063
|
+
}
|
|
21064
|
+
function writeEnvFile(privateKey, network) {
|
|
21065
|
+
fs__default["default"].mkdirSync(CONFIG_DIR, { recursive: true });
|
|
21066
|
+
const content = `DIPCOIN_PRIVATE_KEY=${privateKey}\nDIPCOIN_NETWORK=${network}\n`;
|
|
21067
|
+
fs__default["default"].writeFileSync(ENV_PATH, content, { mode: 0o600 });
|
|
21068
|
+
try {
|
|
21069
|
+
fs__default["default"].chmodSync(ENV_PATH, 0o600);
|
|
21070
|
+
}
|
|
21071
|
+
catch {
|
|
21072
|
+
// best-effort on platforms without POSIX perms
|
|
21073
|
+
}
|
|
21074
|
+
}
|
|
21075
|
+
function resolveNetwork(input) {
|
|
21076
|
+
return input === "testnet" ? "testnet" : "mainnet";
|
|
21077
|
+
}
|
|
21078
|
+
function registerSetupCommands(program) {
|
|
21079
|
+
const setup = program
|
|
21080
|
+
.command("setup")
|
|
21081
|
+
.description("Configure credentials (~/.config/dipcoin/env)");
|
|
21082
|
+
setup
|
|
21083
|
+
.command("import")
|
|
21084
|
+
.description("Import an existing Sui private key (interactive, hidden input)")
|
|
21085
|
+
.option("--network <network>", "mainnet | testnet", "mainnet")
|
|
21086
|
+
.action(async (opts) => {
|
|
21087
|
+
try {
|
|
21088
|
+
const network = resolveNetwork(opts.network);
|
|
21089
|
+
if (!(await confirmOverwrite())) {
|
|
21090
|
+
console.error("Aborted.");
|
|
21091
|
+
process.exit(1);
|
|
21092
|
+
}
|
|
21093
|
+
const key = (await readHiddenInput("Paste your Sui private key (suiprivkey1...): ")).trim();
|
|
21094
|
+
if (!key) {
|
|
21095
|
+
console.error("No input provided.");
|
|
21096
|
+
process.exit(1);
|
|
21097
|
+
}
|
|
21098
|
+
if (!key.startsWith("suiprivkey1")) {
|
|
21099
|
+
console.error("Invalid format. Sui private keys must start with 'suiprivkey1'.");
|
|
21100
|
+
process.exit(1);
|
|
21101
|
+
}
|
|
21102
|
+
let address;
|
|
21103
|
+
try {
|
|
21104
|
+
decodeSuiPrivateKey(key);
|
|
21105
|
+
address = fromExportedKeypair(key).toSuiAddress();
|
|
21106
|
+
}
|
|
21107
|
+
catch (e) {
|
|
21108
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
21109
|
+
console.error(`Failed to decode private key: ${msg}`);
|
|
21110
|
+
process.exit(1);
|
|
21111
|
+
}
|
|
21112
|
+
writeEnvFile(key, network);
|
|
21113
|
+
console.log(`Saved to ${ENV_PATH} (chmod 600).`);
|
|
21114
|
+
console.log(`Network: ${network}`);
|
|
21115
|
+
console.log(`Address: ${address}`);
|
|
21116
|
+
}
|
|
21117
|
+
catch (e) {
|
|
21118
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
21119
|
+
console.error("Error:", msg);
|
|
21120
|
+
process.exit(1);
|
|
21121
|
+
}
|
|
21122
|
+
});
|
|
21123
|
+
setup
|
|
21124
|
+
.command("generate")
|
|
21125
|
+
.description("Generate a new Sui keypair and save it as your credentials")
|
|
21126
|
+
.option("--network <network>", "mainnet | testnet", "mainnet")
|
|
21127
|
+
.action(async (opts) => {
|
|
21128
|
+
try {
|
|
21129
|
+
const network = resolveNetwork(opts.network);
|
|
21130
|
+
if (!(await confirmOverwrite())) {
|
|
21131
|
+
console.error("Aborted.");
|
|
21132
|
+
process.exit(1);
|
|
21133
|
+
}
|
|
21134
|
+
const kp = new ed25519.Ed25519Keypair();
|
|
21135
|
+
const privateKey = kp.getSecretKey();
|
|
21136
|
+
const address = kp.toSuiAddress();
|
|
21137
|
+
writeEnvFile(privateKey, network);
|
|
21138
|
+
console.log(`Generated new keypair and saved to ${ENV_PATH} (chmod 600).`);
|
|
21139
|
+
console.log(`Network: ${network}`);
|
|
21140
|
+
console.log(`Address: ${address}`);
|
|
21141
|
+
console.log("");
|
|
21142
|
+
console.log("Next: transfer USDC on Sui to the address above, then run: dipcoin-cli account deposit <amount>");
|
|
21143
|
+
}
|
|
21144
|
+
catch (e) {
|
|
21145
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
21146
|
+
console.error("Error:", msg);
|
|
21147
|
+
process.exit(1);
|
|
21148
|
+
}
|
|
21149
|
+
});
|
|
21150
|
+
}
|
|
21151
|
+
|
|
20997
21152
|
function getPackageVersion() {
|
|
20998
21153
|
try {
|
|
20999
21154
|
// Works in both ESM and CJS after bundling
|
|
@@ -21016,6 +21171,7 @@ program
|
|
|
21016
21171
|
.description("DipCoin Perpetual Trading CLI")
|
|
21017
21172
|
.version(getPackageVersion())
|
|
21018
21173
|
.option("--json", "Output in JSON format");
|
|
21174
|
+
registerSetupCommands(program);
|
|
21019
21175
|
registerAccountCommands(program);
|
|
21020
21176
|
registerTradeCommands(program);
|
|
21021
21177
|
registerPositionCommands(program);
|