@yerofey/cryptowallet-cli 1.40.0 → 1.41.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 +20 -2
- package/cli.js +1 -0
- package/package.json +12 -4
- package/src/Method.js +63 -8
- package/src/Wallet.js +233 -2
- package/src/chains/ADA.json +10 -0
- package/src/chains/ETH.json +1 -1
- package/src/chains/EVM.json +1 -1
- package/src/chains/SOL.json +1 -1
- package/src/chains/XLM.json +9 -0
- package/src/chains/XRP.json +10 -0
- package/src/chains/BSC.json +0 -8
package/README.md
CHANGED
|
@@ -41,6 +41,20 @@ $ yarn global add @yerofey/cryptowallet-cli
|
|
|
41
41
|
$ bun add -g @yerofey/cryptowallet-cli
|
|
42
42
|
```
|
|
43
43
|
|
|
44
|
+
## Install (on a server)
|
|
45
|
+
|
|
46
|
+
> Recommended for generating a wallet with long prefixes/suffixes or generating a lot of wallets at once
|
|
47
|
+
|
|
48
|
+
You can rent a VDS/VPS on [aeza.net](https://aeza.net/?ref=439099) for an hour or a day and run [this](https://gist.github.com/yerofey/c1cbf80bdfacfad668f53d595f890c44) one-liner to install `cw` tool:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
# install `cw` tool on a server with all dependencies
|
|
52
|
+
bash <(curl -sL https://gist.githubusercontent.com/yerofey/c1cbf80bdfacfad668f53d595f890c44/raw/376e310ed260ca54fec83b04d4d78d7587b83d78/install-cw.sh)
|
|
53
|
+
|
|
54
|
+
# run `cw` tool
|
|
55
|
+
cw
|
|
56
|
+
```
|
|
57
|
+
|
|
44
58
|
## Usage
|
|
45
59
|
|
|
46
60
|
```bash
|
|
@@ -125,11 +139,13 @@ $ cw -l
|
|
|
125
139
|
- `EVM` (Ethereum, Base, or any EVM L1/L2/L3, etc.) **default**
|
|
126
140
|
- `BTC` (Bitcoin) [legacy, segwit, bech32, taproot]
|
|
127
141
|
- `ETH` (Ethereum)
|
|
142
|
+
- `XRP` (Ripple) **Beta**
|
|
143
|
+
- `BNB` (BNB) [BEP2, BEP20, ERC20]
|
|
128
144
|
- `SOL` (Solana)
|
|
129
|
-
- `
|
|
130
|
-
- `BSC` (Binance Smart Chain)
|
|
145
|
+
- `ADA` (Cardano)
|
|
131
146
|
- `DOGE` (Dogecoin) [legacy, segwit, bech32]
|
|
132
147
|
- `TRX` (Tron)
|
|
148
|
+
- `XLM` (Stellar)
|
|
133
149
|
- `SUI` (Sui)
|
|
134
150
|
- `TON` (The Open Network) [W5, V2-V5, simple]
|
|
135
151
|
- `LTC` (Litecoin) [legacy, segwit, bech32]
|
|
@@ -252,9 +268,11 @@ Each chain JSON file is structured to provide essential information about the bl
|
|
|
252
268
|
- `network`: The type of network or protocol the blockchain follows (e.g., EVM for Ethereum-compatible chains).
|
|
253
269
|
- `startsWith`: The set of characters that the wallet address typically starts with.
|
|
254
270
|
- `prefixTest`: A regular expression pattern that tests for valid characters that can appear in the prefix of a wallet address.
|
|
271
|
+
- `rareSymbols`: (Optional) A regular expression pattern that tests for rare symbols that can appear in the wallet address.
|
|
255
272
|
- `apps`: An array of supported wallet applications that can be used with the generated addresses.
|
|
256
273
|
- `flags`: An array of supported features for the wallet generation. Common flags include `m` for mnemonic support, `n` for generating multiple wallets, `p` for prefix support, and `s` for suffix support.
|
|
257
274
|
- `formats`: (Optional) An object defining multiple wallet formats if the blockchain supports more than one format. Each format should specify its unique properties.
|
|
275
|
+
- `beta`: (Optional) A boolean value indicating if the chain is in beta testing. If set to `true`, the chain will be marked as beta in the list of supported chains.
|
|
258
276
|
|
|
259
277
|
By following this structure, the `cw` tool can understand and support wallet generation for a wide array of blockchains.
|
|
260
278
|
|
package/cli.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yerofey/cryptowallet-cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.41.0",
|
|
4
4
|
"description": "Crypto wallet generator CLI tool",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"homepage": "https://github.com/yerofey/cryptowallet-cli",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"address": "CWsbNQRxNzAasLd2zfwkEkbBZXKxfoxva14pe8wawUju"
|
|
29
29
|
},
|
|
30
30
|
{
|
|
31
|
-
"type": "
|
|
31
|
+
"type": "trx",
|
|
32
32
|
"address": "TCW9eaRWjpivZvnZ5DwgbWxPRpoZNWbuPe"
|
|
33
33
|
},
|
|
34
34
|
{
|
|
@@ -86,6 +86,9 @@
|
|
|
86
86
|
"sui-wallet",
|
|
87
87
|
"ton",
|
|
88
88
|
"the-open-network",
|
|
89
|
+
"cardano",
|
|
90
|
+
"ripple",
|
|
91
|
+
"stellar",
|
|
89
92
|
"base",
|
|
90
93
|
"litecoin",
|
|
91
94
|
"ltc",
|
|
@@ -109,6 +112,7 @@
|
|
|
109
112
|
],
|
|
110
113
|
"dependencies": {
|
|
111
114
|
"@binance-chain/javascript-sdk": "^4.2.2",
|
|
115
|
+
"@emurgo/cardano-serialization-lib-nodejs": "^14.1.1",
|
|
112
116
|
"@harmony-js/account": "^0.1.58",
|
|
113
117
|
"@mysten/sui": "^1.18.0",
|
|
114
118
|
"@solana/web3.js": "^1.98.0",
|
|
@@ -118,10 +122,11 @@
|
|
|
118
122
|
"@yerofey/dogecoin-bip84": "^0.0.5",
|
|
119
123
|
"@yerofey/litecoin-bip84": "^0.0.5",
|
|
120
124
|
"bigint-buffer": "^1.1.5",
|
|
121
|
-
"bip39": "3.1.0",
|
|
125
|
+
"bip39": "^3.1.0",
|
|
122
126
|
"bip84": "^0.2.9",
|
|
123
127
|
"bip86": "^0.0.4",
|
|
124
128
|
"bs58": "^6.0.0",
|
|
129
|
+
"cardano-wallet-js": "^1.4.0",
|
|
125
130
|
"chalk": "5.4.1",
|
|
126
131
|
"clipboardy": "^4.0.0",
|
|
127
132
|
"coininfo": "5.2.1",
|
|
@@ -136,9 +141,12 @@
|
|
|
136
141
|
"ethereum-cryptography": "^3.1.0",
|
|
137
142
|
"ethereum-mnemonic-privatekey-utils": "1.0.5",
|
|
138
143
|
"qrcode-terminal": "^0.12.0",
|
|
144
|
+
"ripple-keypairs": "^2.0.0",
|
|
145
|
+
"stellar-hd-wallet": "^0.0.10",
|
|
139
146
|
"tezos-sign": "1.4.1",
|
|
140
147
|
"tonweb": "^0.0.66",
|
|
141
|
-
"tronweb": "^6.0.1"
|
|
148
|
+
"tronweb": "^6.0.1",
|
|
149
|
+
"xrpl": "^4.2.0"
|
|
142
150
|
},
|
|
143
151
|
"devDependencies": {
|
|
144
152
|
"ava": "^6.2.0",
|
package/src/Method.js
CHANGED
|
@@ -54,10 +54,9 @@ class Method {
|
|
|
54
54
|
for (const val of supportedChains) {
|
|
55
55
|
// eslint-disable-next-line no-undef
|
|
56
56
|
const data = await loadJson(
|
|
57
|
-
`${path.dirname(import.meta.url)}${path.sep}chains${
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
)
|
|
57
|
+
`${path.dirname(import.meta.url)}${path.sep}chains${
|
|
58
|
+
path.sep
|
|
59
|
+
}${val}.json`.replace('file://', '')
|
|
61
60
|
);
|
|
62
61
|
|
|
63
62
|
let title = data.title || '';
|
|
@@ -231,7 +230,9 @@ class Method {
|
|
|
231
230
|
);
|
|
232
231
|
} else {
|
|
233
232
|
// not supported for multiple wallets
|
|
234
|
-
log(
|
|
233
|
+
log(
|
|
234
|
+
`ℹ️ It's not supported to display QR code for multiple wallets yet`
|
|
235
|
+
);
|
|
235
236
|
log();
|
|
236
237
|
}
|
|
237
238
|
}
|
|
@@ -266,12 +267,25 @@ class Method {
|
|
|
266
267
|
for (const item of cw.wallet.addresses) {
|
|
267
268
|
if (cw.wallet.addresses.length > 1) {
|
|
268
269
|
// Display index
|
|
269
|
-
if (
|
|
270
|
+
if (
|
|
271
|
+
item.index !== undefined &&
|
|
272
|
+
(showAllAddresses ||
|
|
273
|
+
(!showAllAddresses && index == 0) ||
|
|
274
|
+
cw.prefixFoundInWallets.includes(item.address) ||
|
|
275
|
+
cw.suffixFoundInWallets.includes(item.address))
|
|
276
|
+
) {
|
|
270
277
|
log();
|
|
271
278
|
log(`🆔 ${item.index}`);
|
|
272
279
|
emptyLineAdded = true;
|
|
273
280
|
}
|
|
274
281
|
|
|
282
|
+
if (item.breakLine !== undefined && item.breakLine) {
|
|
283
|
+
log();
|
|
284
|
+
emptyLineAdded = true;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// TODO: fix situation with TON and multiple wallets labels (there are no spaces between them)
|
|
288
|
+
|
|
275
289
|
// Display address details
|
|
276
290
|
if (item.title) {
|
|
277
291
|
if (!emptyLineAdded) {
|
|
@@ -411,12 +425,21 @@ class Method {
|
|
|
411
425
|
matchingWalletsIndexes.push(index);
|
|
412
426
|
showPrivateKey = true;
|
|
413
427
|
} else {
|
|
414
|
-
if (showAllAddresses || !showAllAddresses && index == 0) {
|
|
428
|
+
if (showAllAddresses || (!showAllAddresses && index == 0) || item.show !== undefined && item.show) {
|
|
415
429
|
log(`👛 ${item.address}`);
|
|
416
430
|
}
|
|
417
431
|
}
|
|
432
|
+
// display public key or xpubkey (if exists)
|
|
433
|
+
if (item.publicKey !== undefined || item.xpubKey !== undefined) {
|
|
434
|
+
log(`🗝️ ${item.publicKey ?? item.xpubKey}`);
|
|
435
|
+
}
|
|
418
436
|
// display private key
|
|
419
|
-
if (
|
|
437
|
+
if (
|
|
438
|
+
item.privateKey !== undefined &&
|
|
439
|
+
(showAllAddresses ||
|
|
440
|
+
(!showAllAddresses && index == 0) ||
|
|
441
|
+
showPrivateKey)
|
|
442
|
+
) {
|
|
420
443
|
log(`🔑 ${item.privateKey}`);
|
|
421
444
|
}
|
|
422
445
|
// copy to clipboard if flag is set
|
|
@@ -441,6 +464,16 @@ class Method {
|
|
|
441
464
|
)
|
|
442
465
|
);
|
|
443
466
|
}
|
|
467
|
+
|
|
468
|
+
// beta
|
|
469
|
+
if (cw.row.beta !== undefined && cw.row.beta) {
|
|
470
|
+
log();
|
|
471
|
+
log(
|
|
472
|
+
yellow(
|
|
473
|
+
'🔶 This wallet generation method is in Beta - not all features are available and not everything was tested yet'
|
|
474
|
+
)
|
|
475
|
+
);
|
|
476
|
+
}
|
|
444
477
|
} else {
|
|
445
478
|
outputData.wallets = cw.wallet.addresses;
|
|
446
479
|
}
|
|
@@ -580,15 +613,37 @@ class Method {
|
|
|
580
613
|
// apps
|
|
581
614
|
if (cw.row.apps !== undefined) {
|
|
582
615
|
let apps = {
|
|
616
|
+
backpack: 'Backpack',
|
|
617
|
+
bitget: 'Bitget Wallet',
|
|
583
618
|
coinbase: 'Coinbase Wallet',
|
|
619
|
+
daedalus: 'Daedalus',
|
|
620
|
+
eternl: 'Eternl',
|
|
621
|
+
jupiter: 'Jupiter',
|
|
622
|
+
keplr: 'Keplr',
|
|
623
|
+
ledger: 'Ledger',
|
|
624
|
+
lobstr: 'Lobstr',
|
|
625
|
+
magiceden: 'Magic Eden',
|
|
584
626
|
metamask: 'MetaMask',
|
|
627
|
+
mytonwallet: 'MyTonWallet',
|
|
628
|
+
nami: 'Nami Wallet',
|
|
629
|
+
okx: 'OKX Wallet',
|
|
630
|
+
osmwallet: 'OsmWallet',
|
|
585
631
|
phantom: 'Phantom',
|
|
632
|
+
plug: 'Plug',
|
|
633
|
+
rabet: 'Rabet',
|
|
634
|
+
rainbow: 'Rainbow',
|
|
635
|
+
solar: 'Solar',
|
|
636
|
+
stellarx: 'StellarX',
|
|
586
637
|
suiet: 'Suiet',
|
|
587
638
|
suiwallet: 'Sui Wallet',
|
|
588
639
|
tonhub: 'Tonhub',
|
|
589
640
|
tonkeeper: 'Tonkeeper',
|
|
590
641
|
tronlink: 'TronLink',
|
|
591
642
|
trustwallet: 'Trust Wallet',
|
|
643
|
+
uniswap: 'Uniswap',
|
|
644
|
+
vespr: 'VESPR',
|
|
645
|
+
xumm: 'Xumm',
|
|
646
|
+
yoroi: 'Yoroi',
|
|
592
647
|
'harmony-chrome-ext': 'Harmony Chrome Extension Wallet',
|
|
593
648
|
'binance-chain-wallet': 'Binance Chain Wallet',
|
|
594
649
|
};
|
package/src/Wallet.js
CHANGED
|
@@ -37,6 +37,14 @@ import {
|
|
|
37
37
|
} from '@ton/crypto';
|
|
38
38
|
import { WalletContractV5R1 } from '@ton/ton';
|
|
39
39
|
import { Ed25519Keypair } from '@mysten/sui/keypairs/ed25519';
|
|
40
|
+
import rippleKeypairs from 'ripple-keypairs';
|
|
41
|
+
import {
|
|
42
|
+
Wallet as RippleWallet,
|
|
43
|
+
classicAddressToXAddress as RippleClassicAddressToXAddress,
|
|
44
|
+
} from 'xrpl';
|
|
45
|
+
import StellarHDWallet from 'stellar-hd-wallet';
|
|
46
|
+
import { Seed as CardanoSeed } from 'cardano-wallet-js';
|
|
47
|
+
import CardanoWasm from '@emurgo/cardano-serialization-lib-nodejs';
|
|
40
48
|
|
|
41
49
|
config();
|
|
42
50
|
|
|
@@ -262,7 +270,7 @@ class Wallet {
|
|
|
262
270
|
|
|
263
271
|
if (row.length == 0) {
|
|
264
272
|
return {
|
|
265
|
-
error: 'this
|
|
273
|
+
error: 'this coin or chain is not found',
|
|
266
274
|
};
|
|
267
275
|
}
|
|
268
276
|
|
|
@@ -279,6 +287,119 @@ class Wallet {
|
|
|
279
287
|
},
|
|
280
288
|
],
|
|
281
289
|
});
|
|
290
|
+
} else if (chain == 'ADA') {
|
|
291
|
+
try {
|
|
292
|
+
// Validate mnemonic
|
|
293
|
+
if (mnemonicString !== '' && !bip39.validateMnemonic(mnemonicString)) {
|
|
294
|
+
return {
|
|
295
|
+
error: 'mnemonic is not valid',
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
// Generate a 24-word mnemonic (recommended for Shelley wallets)
|
|
300
|
+
const mnemonic = mnemonicString || CardanoSeed.generateRecoveryPhrase();
|
|
301
|
+
|
|
302
|
+
// Convert mnemonic to a 512-bit seed
|
|
303
|
+
const entropy = bip39.mnemonicToEntropy(mnemonic);
|
|
304
|
+
|
|
305
|
+
// Generate root key from entropy
|
|
306
|
+
const rootKey = CardanoWasm.Bip32PrivateKey.from_bip39_entropy(
|
|
307
|
+
Buffer.from(entropy, 'hex'), // correct entropy input
|
|
308
|
+
Buffer.from('') // empty password
|
|
309
|
+
);
|
|
310
|
+
|
|
311
|
+
// Derive the account key (BIP44: m/1852'/1815'/0')
|
|
312
|
+
const accountKey = rootKey
|
|
313
|
+
.derive(1852 | 0x80000000) // Purpose
|
|
314
|
+
.derive(1815 | 0x80000000) // Coin type (ADA)
|
|
315
|
+
.derive(0 | 0x80000000); // First account
|
|
316
|
+
|
|
317
|
+
const generateCardanoAddress = (chainType, index) => {
|
|
318
|
+
const addressKey = accountKey
|
|
319
|
+
.derive(chainType)
|
|
320
|
+
.derive(index)
|
|
321
|
+
.to_public()
|
|
322
|
+
.to_raw_key()
|
|
323
|
+
.hash();
|
|
324
|
+
const paymentCredential =
|
|
325
|
+
CardanoWasm.Credential.from_keyhash(addressKey);
|
|
326
|
+
const stakeKey = accountKey
|
|
327
|
+
.derive(2)
|
|
328
|
+
.derive(0)
|
|
329
|
+
.to_public()
|
|
330
|
+
.to_raw_key()
|
|
331
|
+
.hash();
|
|
332
|
+
const stakeCredential = CardanoWasm.Credential.from_keyhash(stakeKey);
|
|
333
|
+
return CardanoWasm.BaseAddress.new(
|
|
334
|
+
CardanoWasm.NetworkInfo.mainnet().network_id(),
|
|
335
|
+
paymentCredential,
|
|
336
|
+
stakeCredential
|
|
337
|
+
)
|
|
338
|
+
.to_address()
|
|
339
|
+
.to_bech32();
|
|
340
|
+
};
|
|
341
|
+
|
|
342
|
+
const utxoPubKey = accountKey
|
|
343
|
+
.derive(0) // external
|
|
344
|
+
.derive(0)
|
|
345
|
+
.to_public();
|
|
346
|
+
const stakeKey = accountKey
|
|
347
|
+
.derive(2) // chimeric
|
|
348
|
+
.derive(0)
|
|
349
|
+
.to_public();
|
|
350
|
+
|
|
351
|
+
const baseAddr = CardanoWasm.BaseAddress.new(
|
|
352
|
+
CardanoWasm.NetworkInfo.mainnet().network_id(),
|
|
353
|
+
CardanoWasm.Credential.from_keyhash(utxoPubKey.to_raw_key().hash()),
|
|
354
|
+
CardanoWasm.Credential.from_keyhash(stakeKey.to_raw_key().hash())
|
|
355
|
+
);
|
|
356
|
+
|
|
357
|
+
// bootstrap address - byron-era addresses with no staking rights
|
|
358
|
+
const byronAddr = CardanoWasm.ByronAddress.icarus_from_key(
|
|
359
|
+
utxoPubKey, // Ae2* style icarus address
|
|
360
|
+
CardanoWasm.NetworkInfo.mainnet().protocol_magic()
|
|
361
|
+
);
|
|
362
|
+
|
|
363
|
+
// Generate Staking Key Hash (BIP44: m/1852'/1815'/0'/2/0)
|
|
364
|
+
const stakingKey = accountKey
|
|
365
|
+
.derive(2)
|
|
366
|
+
.derive(0)
|
|
367
|
+
.to_public()
|
|
368
|
+
.to_raw_key()
|
|
369
|
+
.hash();
|
|
370
|
+
const stakingKeyHash = Buffer.from(stakingKey.to_bytes()).toString(
|
|
371
|
+
'hex'
|
|
372
|
+
);
|
|
373
|
+
|
|
374
|
+
// Return wallet details
|
|
375
|
+
Object.assign(result, {
|
|
376
|
+
addresses: [
|
|
377
|
+
{
|
|
378
|
+
title: 'Shelley-era base address',
|
|
379
|
+
address: baseAddr.to_address().to_bech32(),
|
|
380
|
+
// publicKey: utxoPubKey.to_bech32(),
|
|
381
|
+
privateKey: rootKey.to_bech32(),
|
|
382
|
+
},
|
|
383
|
+
{
|
|
384
|
+
title: 'Byron-era bootstrap address (old style)',
|
|
385
|
+
address: byronAddr.to_base58(),
|
|
386
|
+
breakLine: true,
|
|
387
|
+
show: true,
|
|
388
|
+
},
|
|
389
|
+
{
|
|
390
|
+
title: 'Staking key hash',
|
|
391
|
+
address: stakingKeyHash,
|
|
392
|
+
breakLine: true,
|
|
393
|
+
show: true,
|
|
394
|
+
},
|
|
395
|
+
],
|
|
396
|
+
mnemonic,
|
|
397
|
+
});
|
|
398
|
+
} catch (error) {
|
|
399
|
+
return {
|
|
400
|
+
error: `Failed to generate ADA wallet: ${error.message} (${error})`,
|
|
401
|
+
};
|
|
402
|
+
}
|
|
282
403
|
} else if (chain == 'BTC') {
|
|
283
404
|
// Validate mnemonic
|
|
284
405
|
if (mnemonicString != '' && !bip39.validateMnemonic(mnemonicString)) {
|
|
@@ -578,6 +699,8 @@ class Wallet {
|
|
|
578
699
|
addresses.push({
|
|
579
700
|
title: 'v4R2 (EQ): best for smart contracts (bounceable)',
|
|
580
701
|
address: bouncableAddress,
|
|
702
|
+
breakLine: true,
|
|
703
|
+
show: true,
|
|
581
704
|
});
|
|
582
705
|
} else {
|
|
583
706
|
addresses.push({
|
|
@@ -614,6 +737,8 @@ class Wallet {
|
|
|
614
737
|
addresses.push({
|
|
615
738
|
title: 'W5 - v5R1 (EQ): best for smart contracts (bounceable)',
|
|
616
739
|
address: bouncableAddressV5,
|
|
740
|
+
breakLine: true,
|
|
741
|
+
show: true,
|
|
617
742
|
});
|
|
618
743
|
break;
|
|
619
744
|
}
|
|
@@ -652,6 +777,105 @@ class Wallet {
|
|
|
652
777
|
error: `Failed to generate TRX wallet: ${error.message} (${error})`,
|
|
653
778
|
};
|
|
654
779
|
}
|
|
780
|
+
} else if (chain == 'XLM') {
|
|
781
|
+
try {
|
|
782
|
+
// Validate mnemonic
|
|
783
|
+
if (mnemonicString !== '' && !bip39.validateMnemonic(mnemonicString)) {
|
|
784
|
+
return {
|
|
785
|
+
error: 'mnemonic is not valid',
|
|
786
|
+
};
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
// Generate mnemonic if not provided
|
|
790
|
+
const mnemonic =
|
|
791
|
+
mnemonicString ||
|
|
792
|
+
StellarHDWallet.generateMnemonic({ entropyBits: 128 });
|
|
793
|
+
// Create a Stellar HD Wallet from the mnemonic
|
|
794
|
+
const wallet = StellarHDWallet.fromMnemonic(mnemonic);
|
|
795
|
+
|
|
796
|
+
// Get the first account (Trust Wallet, Ledger, etc. use `m/44'/148'/0'`)
|
|
797
|
+
const publicKey = wallet.getPublicKey(0);
|
|
798
|
+
const secretKey = wallet.getSecret(0);
|
|
799
|
+
// const keypair = wallet.getKeypair(0); // Full keypair object
|
|
800
|
+
// const rawKey = wallet.derive(`m/44'/148'/0'`).toString('hex');
|
|
801
|
+
|
|
802
|
+
// Return wallet details
|
|
803
|
+
Object.assign(result, {
|
|
804
|
+
addresses: [
|
|
805
|
+
{
|
|
806
|
+
index: 0,
|
|
807
|
+
address: publicKey,
|
|
808
|
+
privateKey: secretKey,
|
|
809
|
+
},
|
|
810
|
+
],
|
|
811
|
+
mnemonic,
|
|
812
|
+
});
|
|
813
|
+
} catch (error) {
|
|
814
|
+
return {
|
|
815
|
+
error: `Failed to generate XLM wallet: ${error.message} (${error})`,
|
|
816
|
+
};
|
|
817
|
+
}
|
|
818
|
+
} else if (chain == 'XRP') {
|
|
819
|
+
try {
|
|
820
|
+
// Validate mnemonic
|
|
821
|
+
if (mnemonicString !== '' && !bip39.validateMnemonic(mnemonicString)) {
|
|
822
|
+
return {
|
|
823
|
+
error: 'mnemonic is not valid',
|
|
824
|
+
};
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
// Generate a 12-word mnemonic (or use provided one)
|
|
828
|
+
const mnemonic = mnemonicString || bip39.generateMnemonic(128);
|
|
829
|
+
|
|
830
|
+
// Convert mnemonic to a 512-bit seed
|
|
831
|
+
const seed = bip39.mnemonicToSeedSync(mnemonic, '');
|
|
832
|
+
|
|
833
|
+
// Extract 16 bytes from the seed (XRP entropy requirement)
|
|
834
|
+
const entropy = seed.slice(0, 16);
|
|
835
|
+
|
|
836
|
+
// Encode the entropy as a Base58-encoded XRP seed
|
|
837
|
+
const base58Seed = rippleKeypairs.generateSeed({
|
|
838
|
+
entropy,
|
|
839
|
+
algorithm: 'ecdsa-secp256k1',
|
|
840
|
+
});
|
|
841
|
+
|
|
842
|
+
// Generate a wallet from the seed
|
|
843
|
+
const wallet = RippleWallet.fromSeed(base58Seed, {
|
|
844
|
+
algorithm: 'secp256k1',
|
|
845
|
+
});
|
|
846
|
+
// console.log('wallet', wallet);
|
|
847
|
+
|
|
848
|
+
// dev
|
|
849
|
+
// const masterKey = rippleKeypairs.deriveKeypair(base58Seed, {
|
|
850
|
+
// algorithm: 'ecdsa-secp256k1',
|
|
851
|
+
// accountIndex: 0,
|
|
852
|
+
// });
|
|
853
|
+
// const address = rippleKeypairs.deriveAddress(masterKey.publicKey);
|
|
854
|
+
// console.log('masterKey', masterKey);
|
|
855
|
+
// console.log('address', address);
|
|
856
|
+
|
|
857
|
+
// Return wallet details
|
|
858
|
+
Object.assign(result, {
|
|
859
|
+
addresses: [
|
|
860
|
+
{
|
|
861
|
+
title: 'Classic',
|
|
862
|
+
address: wallet.address,
|
|
863
|
+
privateKey: wallet.privateKey,
|
|
864
|
+
},
|
|
865
|
+
{
|
|
866
|
+
title: 'X-address',
|
|
867
|
+
address: RippleClassicAddressToXAddress(wallet.address, false, false),
|
|
868
|
+
breakLine: true,
|
|
869
|
+
show: true,
|
|
870
|
+
},
|
|
871
|
+
],
|
|
872
|
+
mnemonic,
|
|
873
|
+
});
|
|
874
|
+
} catch (error) {
|
|
875
|
+
return {
|
|
876
|
+
error: `Failed to generate XRP wallet: ${error.message} (${error})`,
|
|
877
|
+
};
|
|
878
|
+
}
|
|
655
879
|
} else if (chain == 'XTZ') {
|
|
656
880
|
// TODO: generate wallet from mnemonic
|
|
657
881
|
const wallet = tezos.generateKeysNoSeed();
|
|
@@ -668,7 +892,7 @@ class Wallet {
|
|
|
668
892
|
} else {
|
|
669
893
|
return {
|
|
670
894
|
error:
|
|
671
|
-
'your desired
|
|
895
|
+
'your desired coin/chain is not supported yet, please open an issue on GitHub: https://github.com/yerofey/cryptowallet-cli/issues',
|
|
672
896
|
};
|
|
673
897
|
}
|
|
674
898
|
|
|
@@ -679,6 +903,13 @@ class Wallet {
|
|
|
679
903
|
});
|
|
680
904
|
}
|
|
681
905
|
|
|
906
|
+
// Add beta flag if needed
|
|
907
|
+
if (row.beta !== undefined && row.beta == true) {
|
|
908
|
+
Object.assign(result, {
|
|
909
|
+
beta: true,
|
|
910
|
+
});
|
|
911
|
+
}
|
|
912
|
+
|
|
682
913
|
return result;
|
|
683
914
|
}
|
|
684
915
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"title": "Cardano",
|
|
3
|
+
"startsWith": "addr1q",
|
|
4
|
+
"prefixTest": "[a-z0-9]",
|
|
5
|
+
"rareSymbols": "[a-z]",
|
|
6
|
+
"path": "m/1852'/1815'/0'/0/0",
|
|
7
|
+
"purpose": "1852'",
|
|
8
|
+
"apps": ["trustwallet", "vespr", "eternl", "nami", "yoroi", "daedalus", "ledger"],
|
|
9
|
+
"flags": ["m", "p", "s"]
|
|
10
|
+
}
|
package/src/chains/ETH.json
CHANGED
package/src/chains/EVM.json
CHANGED
package/src/chains/SOL.json
CHANGED