@aladas-org/cryptocalc
Version:
Cryptocurrency wallet generator
239 lines (192 loc) • 11 kB
JavaScript
// =====================================================================================
// ================================== ethereum_api.js ==================================
// =====================================================================================
;
// Generates Ethereum blockchain address
// ========== Test ajout sur Guarda.com (2024/01/02) ==========
// Test sur MEW (myetherwallet.com)
// OK: avec Private Key en hexadécimal => adresse wallet OK
// OK: avec Seedphrase 24 mots =>
// série de wallets, ***** le 1er est le même que celui reconnu dans Guarda ****
// * PK: 0x10fb87a84c1b4f41975da16a0315387a914616851e36d9dbf81435dd1d1e0f5c
// * Seedphrase: axis switch tube oblige reject patch frost reflect head board evoke vivid behave area behave short supply thank agree hill spike monitor dice mesh
// PK 4 12 mnemonics: 10fb87a84c1b4f41975da16a0315387a
// axis switch tube oblige reject patch frost reflect head board evoke vintage
// * wallet: 0xf90ff675c81027c9bed1ebea2da386df6a7d0cf2
// => ??? est ce que mnémonique est considéré comme "clé maitre"
// et que les wallets proposés en sont dérivés ("derivationPath")
//
// Test sur Guarda.com
// OK: avec Private Key en hexadécimal (avec et sans préfixe '0x')
// **** KO: avec Private Key en Base64
// **ERREUR sur Checksum (dernier mnémonique)**
// **** KO: avec Mnémoniques (adresse erronée):
// Après verification, cela semble être un bug Guarda car:
// 1. La conversion des Mnémoniques en PK_B64 ("Tool/Mnemonics to PK") => même valeur que dans '00_wallet_info.txt'
// 2. La PK_B64 convertie en Hexa == 'seed_sha256_hex' (fournie en entrée)
// et == 'Private Key(Hex)' dans '00_wallet_info.txt'
// https://levelup.gitconnected.com/generate-ethereum-address-using-node-js-a6a73f42a4cf
// https://www.npmjs.com/package/ethereumjs-wallet
const fs = require("fs");
const Wallet = require("ethereumjs-wallet").default; // NB: garder cette syntaxe précise
const EthUtil = require("ethereumjs-util");
const eip55 = require("eip55"); // Mixedcase Checksum in Wallet address
// https://ethereum.stackexchange.com/questions/50294/typeerror-web3-is-not-a-constructor-when-trying-to-use-node-js-with-truffle-con
// NB: replaces 'web3'
const { Web3 } = require('web3'); // for Sepolia (Ethereum testnet)
const { Base64 } = require('js-base64');
const { _RED_, _CYAN_, _PURPLE_,
_YELLOW_, _END_ } = require('../../util/color/color_console_codes.js');
const { pretty_func_header_log,
pretty_log } = require('../../util/log/log_utils.js');
const { NULL_COIN,
ETHEREUM,
MAINNET, TESTNET
} = require('../const_blockchains.js');
const { NULL_HEX, NULL_NET, NULL_UUID,
NULL_ADDRESS, CRYPTO_NET,
PRIVATE_KEY, PUBLIC_KEY_HEX,
ADDRESS } = require('../const_wallet.js');
const { BLOCKCHAIN, NULL_BLOCKCHAIN,
UUID, MNEMONICS, WORD_COUNT
} = require('../../const_keywords.js');
const { stringify } = require('../../util/values/string_utils.js');
const { hexWithPrefix, hexWithoutPrefix,
hexToBytes, hexToUint8Array } = require('../hex_utils.js');
const { Bip39Utils } = require('../bip39_utils.js');
class Ethereum_API {
static GetWallet( private_key, salt_uuid, blockchain, crypto_net ) {
pretty_log( ">> Ethereum_API.GetWallet", crypto_net );
if ( crypto_net == undefined ) {
crypto_net = MAINNET;
}
pretty_log( ">> Ethereum_API.GetWallet private_key", private_key );
let new_wallet = Ethereum_API.InitializeWallet();
if ( private_key == undefined ) {
pretty_log( ">> BlockchainWallet.GetWallet **ERROR** private_key", seed_SHA256_hex );
return new_wallet;
}
//----- Validité des adresses générées testées avec:
// https://github.com/Swyftx/crypto-address-validator -----
new_wallet[BLOCKCHAIN] = ETHEREUM;
new_wallet[CRYPTO_NET] = crypto_net;
new_wallet[UUID] = salt_uuid;
//========================= Ethereum =========================
let ETH_address = "";
let ETH_private_key = "";
let ETH_public_key = "";
if (new_wallet[CRYPTO_NET] == TESTNET) {
//==================== ETH TESTNET ====================
// Sepolia faucet:
// OK: https://faucets.pk910.de/ (POW utilise Carte graphique)
// KO: Coinstack: inscription + 0,001 Eth (2,54$) de frais de transaction !!!
// "A user's wallet must hold at least 0.001 ETH on Ethereum Mainnet to use the EVM faucets"
// KO: Coinbase
// "The Base Görli faucet requires at least 0.005 ETH on Ethereum This helps us prevent bots
// while preserving privacy. Transfer ETH to Ethereum on this address to use the faucet."
const web3_sepolia = new Web3("https://rpc2.sepolia.org");
// >> Sepolia (Eth testnet) wallet:
// [{ "address": "0x57b2046659302Dc596ee4a656a1Debf0f4A1599e",
// "privateKey": "0x10fb87a84c1b4f41975da16a0315387a914616851e36d9dbf81435dd1d1e0f5c" }]
// https://web3js.readthedocs.io/en/v1.2.11/web3-eth-accounts.html
let wallet = web3_sepolia.eth.accounts.wallet.add( hexWithPrefix( private_key ) );
//this is how we can access to the first account of the wallet
pretty_log( ">> Sepolia (ETH testnet):", "" );
ETH_address = wallet[0].address;
pretty_log( ">> ETH_address:", ETH_address );
ETH_private_key = wallet[0].privateKey;
pretty_log( ">> ETH_private_key:", ETH_private_key );
//---------- get ETH wallet public key ----------
// https://ethereum.stackexchange.com/questions/12571/getting-an-address-from-ethereumjs-utils-ecrecover
// NB: This is 'public key' for "ETH Mainnet" but indeed should be the same in Sepolia
const private_key_buffer = EthUtil.toBuffer( hexWithPrefix( private_key ) );
let ETH_wallet = Wallet.fromPrivateKey(private_key_buffer);
pretty_log( ">> Wallet address:", ETH_wallet.getAddressString() );
ETH_public_key = ETH_wallet.getPublicKeyString();
pretty_log( ">> ETH_public_key:", ETH_public_key );
//---------- get ETH wallet public key
}
else {
//==================== ETH MAINNET ====================
//const eth_wallet = new ethers.Wallet(private_key);
// https://piyopiyo.medium.com/generating-an-ethereum-wallet-with-an-existing-private-key-5cda690a8eb8
//const eth_wallet = EthWallet.default.generate(private_key);
const pk_buffer = EthUtil.toBuffer( hexWithPrefix ( private_key ) );
// https://ethereum.stackexchange.com/questions/96732/generating-an-ethereum-wallet-with-an-existing-private-key
const eth_wallet = Wallet.fromPrivateKey( pk_buffer );
// NB: Must keep "Mixed case Hex digits"
ETH_address = eth_wallet.getAddressString(); // toLowerCase();
ETH_private_key = eth_wallet.getPrivateKeyString();
ETH_public_key = eth_wallet.getPublicKeyString();
}
pretty_log( ">> Private Key:", ETH_private_key );
//console.log(">> Ethereum Address: " + stringify(eth_wallet.getAddressString()));
//console.log("input private_key:\n" + private_key);
//console.log("eth_wallet:\n" + stringify(eth_wallet));
//---------- private key ----------
new_wallet[PRIVATE_KEY] = private_key;
//console.log("private_key:\n" + private_key);
//---------- private key
//---------- mnemonics ----------
let mnemonics = Bip39Utils.EntropyToMnemonics( private_key );
new_wallet[MNEMONICS] = mnemonics;
//---------- mnemonics
//---------- public key ----------
new_wallet[PUBLIC_KEY_HEX] = ETH_public_key;
//---------- public key
//----------Address ----------
// Ethereum address is in Hexa
new_wallet[ADDRESS] = eip55.encode( hexWithPrefix( ETH_address.toLowerCase() ) );
//console.log(">> getBlockchainWallet ** Ethereum address:\n" + new_wallet['address']);
//---------- Address
return new_wallet;
} // Ethereum_API.GetWallet()
static InitializeWallet() {
let null_wallet = {};
null_wallet[BLOCKCHAIN] = NULL_BLOCKCHAIN;
null_wallet[CRYPTO_NET] = "Null-NET";
null_wallet[UUID] = "Null-UUID";
null_wallet[PRIVATE_KEY] = NULL_HEX;
null_wallet[PUBLIC_KEY_HEX] = NULL_HEX;
null_wallet[ADDRESS] = "Null-ADDRESS";
null_wallet[MNEMONICS] = "Null-MNEMONICS";
return null_wallet;
} // Ethereum_API.InitializeWallet()
static GetSepoliaWallet(seed_SHA256_hex) {
// https://coinsbench.com/connecting-to-the-ethereum-testnet-using-only-web3-js-and-the-console-cffe0273b184
const web3_sepolia = new Web3("https://rpc2.sepolia.org");
let seed_hex = '0x10fb87a84c1b4f41975da16a0315387a914616851e36d9dbf81435dd1d1e0f5c';
// >> Sepolia (Eth testnet) wallet:
// [{"address": "0x57b2046659302Dc596ee4a656a1Debf0f4A1599e",
// "privateKey": "0x10fb87a84c1b4f41975da16a0315387a914616851e36d9dbf81435dd1d1e0f5c"}]
// https://web3js.readthedocs.io/en/v1.2.11/web3-eth-accounts.html
let wallet = web3_sepolia.eth.accounts.wallet.add(seed_hex);
// this is how we can access to the first account of the wallet
pretty_log( "Sepolia (Eth testnet):", "" );
pretty_log( "wallet[0].address:", wallet[0].address );
pretty_log( "wallet[0].privateKey:", wallet[0].privateKey );
} // Ethereum_API.GetSepoliaWallet()
static async GetWalletWithKeyStore(seed_SHA256_hex) {
//const privateKeyString = '0x61ce8b95ca5fd6f55cd97ac60817777bdf64f1670e903758ce53efc32c3dffeb';
//let seed_hex = '0x10fb87a84c1b4f41975da16a0315387a914616851e36d9dbf81435dd1d1e0f5c';
let seed_hex = '0xa7d196f340827bbdb0d091830f35bd9338c8c532a6afe8395804d52ae6490598';
const privateKeyBuffer = EthUtil.toBuffer(seed_hex);
const wallet = Wallet.fromPrivateKey(privateKeyBuffer);
const publicKey = wallet.getPublicKeyString();
pretty_log( "", publicKey );
const address = wallet.getAddressString();
pretty_log( "", address );
const keystoreFilename = wallet.getV3Filename();
pretty_log( "", keystoreFilename );
const keystore = await wallet.toV3("");
pretty_log( "", keystore );
let filename = "keystore.json";
//console.log("> frieze_text: \n" + frieze_text);
fs.writeFileSync( "./" + filename, stringify(keystore) );
} // Ethereum_API.GetWalletWithKeyStore()
} // Ethereum_API class
// Ethereum_API.GetWalletWithKeyStore()
// Ethereum_API.GetSepoliaWallet()
if (typeof exports === 'object') {
exports.Ethereum_API = Ethereum_API
} // exports of 'ethereum_api.js'