├── .env ├── .gitignore ├── LICENSE ├── README.md ├── evm_wallets.json ├── fastMint.js ├── genMnemonic.js ├── genWallet.js ├── mint.js ├── mnemonic.json ├── package.json ├── printAddressByMnemonic.js ├── printPrivateKeyByMnemonic.js ├── transfer.js └── transferGasToOne.js /.env: -------------------------------------------------------------------------------- 1 | # 等号后面的都是填写示例 2 | # 自定义RPC,自己去 chainlist.org 上面找个快的 3 | NODE_URL=https://bsc-dataseed4.ninicoin.io 4 | # 链id,不知道可以去 chainlist.org 查 5 | CHAIN_ID=56 6 | # 填写助记词用来生成地址(12个词) 7 | MNEMONIC=dsjk hfj fnhajs fasjd koafb fdajob bjoasdbf nbjkoafds bjifadsb bjkb bjsd dsa 8 | # 地址生成数量 9 | GEN_NUM=100 10 | # 主账户地址,用来批量转账和归集(批量转账是一个一个个转的,有点慢。如果不担心安全问题可以去 https://cointool.app/multiSender 调用他们的合约,秒到账,就是有点贵) 11 | ADDRESS=0xfws4g5sg56s56g4s65d4g65sd4 12 | # 主账户私钥,用来批量转账 13 | PRIVATE_KEY=vm8937u589234c5m0b03948590b8n35098308093 14 | # 批量转账给每个钱包的币量 15 | MONEY=0.001 16 | # 铭文字符串 17 | MINT_STR=data:,{"p":"bsc-20","op":"mint","tick":"bsci","amt":"1000"} 18 | # 每个地址请求mint的次数 19 | NUMBER_OF_TIMES=10000 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | node_modules 3 | yarn.lock 4 | yarn-error.log -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 zyxtoworld 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. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 批量 mint EVM全链铭文脚本 2 | 3 | 本脚本批量生成钱包、批量打印地址以及批量打印私钥的规则与metamask完全相同,你可以将助记词导入到metamask并创建多个账户,顺序与脚本生成的完全一致。 4 | 5 | ## 安装 6 | ### 安装 nodejs 7 | 8 | https://nodejs.org/en/download/ 9 | 10 | ### 安装 yarn 11 | 先进入到根目录再执行 12 | ``` 13 | npm install -g yarn 14 | ``` 15 | ``` 16 | yarn install 17 | ``` 18 | 19 | ## 配置环境变量 20 | 修改 .env 文件,并填写所有信息 21 | 22 | ## 生成助记词 23 | ``` 24 | node genMnemonic.js 25 | ``` 26 | 生成助记词会保存在 mnemonic.json 文件中 27 | 28 | ## 根据助记词批量打印地址 29 | ``` 30 | node printAddressByMnemonic.js 31 | ``` 32 | 33 | ## 根据助记词批量打印私钥 34 | ``` 35 | node printPrivateKeyByMnemonic.js 36 | ``` 37 | 38 | ## 钱包批量生成 39 | 钱包批量生成所依据的助记词是在 .env 文件中配置的,如果想使用代码生成的助记词,请在 mnemonic.json 文件中找到并配置到 .env 文件中。 40 | ``` 41 | node genWallet.js 42 | ``` 43 | 生成的信息会保存在 evm_wallets.json 文件中 44 | 45 | ## 批量转账 46 | 给 evm_wallets.json 文件里的所有地址转账,如果不想用生成的地址,就按格式修改成你要转账的地址,只需改 evm_wallets.json 文件中的 address 就可以 47 | 48 | ``` 49 | node transfer.js 50 | ``` 51 | 52 | ## 批量mint 53 | 用 evm_wallets.json 里的所有地址来mint,可按格式自行添加和修改,文件里的 address 和 privateKey 必须配置正确 54 | ``` 55 | node mint.js 56 | ``` 57 | 58 | ## 快速批量mint 59 | 未经实际测试,不建议轻易使用,容易快速烧gas且不保证mint成功。 60 | 61 | 不等待交易结果,不每次请求gas,累积nonce直接发送mint请求,由于请求太快容易被节点阻止导致脚本停止运行,建议自建全节点用此脚本。 62 | 63 | 用 evm_wallets.json 里的所有地址来mint,可按格式自行添加和修改,文件里的 address 和 privateKey 必须配置正确 64 | ``` 65 | node fastMint.js 66 | ``` 67 | 68 | ## 批量归集 69 | 归集 evm_wallets.json 文件里的所有地址的 gas 币 70 | 71 | 转给 .env 文件里 ADDRESS 填写的地址 72 | 73 | ``` 74 | node transferGasToOne.js 75 | ``` -------------------------------------------------------------------------------- /evm_wallets.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "num": 1, 4 | "address": "0xcm290834908mc0875m", 5 | "privateKey": "cf7692v76mc90348056v307m6903vb8mbv36", 6 | "publicKey": "cmu690v3b8m9038m3bv31mn690v856bv137094fo43kg0-34gh3j9h0j9023jg20kfd023jfg90240gnj908324njgjn234g0n309ng3" 7 | }, 8 | { 9 | "num": 2, 10 | "address": "0xcm290834908mc0875m", 11 | "privateKey": "cf7692v76mc90348056v307m6903vb8mbv36", 12 | "publicKey": "cmu690v3b8m9038m3bv31mn690v856bv137094fo43kg0-34gh3j9h0j9023jg20kfd023jfg90240gnj908324njgjn234g0n309ng3" 13 | } 14 | ] -------------------------------------------------------------------------------- /fastMint.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config(); 2 | const {Web3} = require('web3'); 3 | const fs = require('fs'); 4 | 5 | const web3 = new Web3(process.env.NODE_URL); // 节点URL 6 | const amount = web3.utils.toWei('0', 'ether'); // 期望交易金额,单位为wei 7 | const mintStr = process.env.MINT_STR; 8 | // 将字符串转换为UTF-8编码的字节 9 | const utf8Bytes = Buffer.from(mintStr, 'utf-8'); 10 | // 将字节转换为十六进制表示的字符串 11 | const hexStr = '0x' + utf8Bytes.toString('hex'); 12 | const totalTimes = BigInt(process.env.NUMBER_OF_TIMES); 13 | 14 | // 直到出错再获取gas和nonce,不管交易结果,一直发送交易 15 | async function performTransaction(walletInfo, numberOfTimes) { 16 | const nonce = await web3.eth.getTransactionCount(walletInfo.address); 17 | const gasPrice = await web3.eth.getGasPrice(); 18 | const gasEstimate = await web3.eth.estimateGas({ 19 | to: walletInfo.address, 20 | value: amount, 21 | data: hexStr, 22 | }); 23 | let numberOfFinish = totalTimes - numberOfTimes; 24 | for (let i = 0; i < numberOfTimes; i++) { 25 | numberOfFinish = numberOfFinish + BigInt(1); 26 | try { 27 | const transaction = { 28 | to: walletInfo.address, 29 | value: amount, 30 | gasPrice: gasPrice, 31 | nonce: nonce + numberOfFinish - BigInt(1), 32 | gas: gasEstimate, 33 | data: hexStr, 34 | }; 35 | 36 | const signedTransaction = await web3.eth.accounts.signTransaction(transaction, walletInfo.privateKey); 37 | web3.eth.sendSignedTransaction(signedTransaction.rawTransaction); 38 | 39 | console.log(`第 ${walletInfo.num} 个地址 ${walletInfo.address} 第 ${numberOfFinish} 次操作成功.`); 40 | } catch (error) { 41 | console.error(`第 ${walletInfo.num} 个地址 ${walletInfo.address} 第 ${numberOfFinish} 次操作失败: `, error); 42 | await performTransaction(walletInfo, totalTimes - numberOfFinish); 43 | } 44 | } 45 | } 46 | 47 | async function main() { 48 | let walletData = []; 49 | try { 50 | walletData = JSON.parse(fs.readFileSync('evm_wallets.json', 'utf-8')); 51 | } catch (e) { 52 | console.log('未找到 evm_wallets.json 文件'); 53 | } 54 | 55 | Promise.all(walletData.map(wallet => performTransaction(wallet, totalTimes))) 56 | .then(() => { 57 | console.log("所有操作完成"); 58 | }) 59 | .catch(error => { 60 | console.error("操作中有错误发生: ", error); 61 | }); 62 | } 63 | 64 | main(); -------------------------------------------------------------------------------- /genMnemonic.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config(); 2 | const fs = require('fs'); 3 | const bip39 = require('bip39') 4 | // 生成英文助记词 5 | const mnemonicEn = bip39.generateMnemonic() 6 | // 生成中文助记词 7 | const mnemonicCn = bip39.generateMnemonic(128, null, bip39.wordlists.chinese_simplified); 8 | console.log('英文助记词:' + mnemonicEn); 9 | console.log('中文助记词:' + mnemonicCn); 10 | const mnemonicInfo = { 11 | 英文助记词: mnemonicEn, 12 | 中文助记词: mnemonicCn 13 | }; 14 | // 将助记词写入 JSON 文件 15 | fs.writeFileSync('mnemonic.json', JSON.stringify(mnemonicInfo, null, 2)); -------------------------------------------------------------------------------- /genWallet.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config(); 2 | const fs = require('fs'); 3 | const bip39 = require('bip39') 4 | const HDWallet = require('ethereum-hdwallet'); 5 | // 获取助记词 6 | const mnemonic = process.env.MNEMONIC; 7 | // 需要生成的地址数 8 | const genNum = process.env.GEN_NUM; 9 | 10 | async function getWallets(mnemonic) { 11 | 12 | const seed = await bip39.mnemonicToSeed(mnemonic); //生成种子 13 | 14 | const hdwallet = HDWallet.fromSeed(seed); 15 | 16 | const wallets = []; 17 | 18 | for (var i = 0; i < genNum; i++) { // 用同一个种子生成多个地址 19 | const key = hdwallet.derive("m/44'/60'/0'/0/" + i); // 地址路径的最后一位设置为循环变量 20 | 21 | const address = '0x' + key.getAddress().toString('hex'); //地址 22 | const privateKey = key.getPrivateKey().toString('hex'); 23 | const publicKey = key.getPublicKey().toString('hex'); 24 | 25 | const wallet = { 26 | num: i + 1, 27 | address: address, 28 | privateKey: privateKey, 29 | publicKey: publicKey 30 | }; 31 | 32 | wallets.push(wallet); 33 | 34 | console.log('=============地址' + (i + 1) + '=================') 35 | console.log("地址 = " + address); // 地址 36 | console.log("私钥 = " + privateKey); // 私钥 37 | console.log("公钥 = " + publicKey); // 公钥 38 | } 39 | // 将地址信息写入 JSON 文件 40 | fs.writeFileSync('evm_wallets.json', JSON.stringify(wallets, null, 2)); 41 | } 42 | 43 | getWallets(mnemonic); //执行函数 -------------------------------------------------------------------------------- /mint.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config(); 2 | const {Web3} = require('web3'); 3 | const fs = require('fs'); 4 | 5 | const web3 = new Web3(process.env.NODE_URL); // 节点URL 6 | const amount = web3.utils.toWei('0', 'ether'); // 期望交易金额,单位为wei 7 | const mintStr = process.env.MINT_STR; 8 | // 将字符串转换为UTF-8编码的字节 9 | const utf8Bytes = Buffer.from(mintStr, 'utf-8'); 10 | // 将字节转换为十六进制表示的字符串 11 | const hexStr = '0x' + utf8Bytes.toString('hex'); 12 | 13 | // 每次交易都获取实时gas和nonce 14 | async function performTransaction(walletInfo, numberOfTimes) { 15 | let successNum = 0; 16 | let failNum = 0; 17 | for (let i = 0; i < numberOfTimes; i++) { 18 | try { 19 | const nonce = await web3.eth.getTransactionCount(walletInfo.address); 20 | const gasPrice = await web3.eth.getGasPrice(); 21 | const gasEstimate = await web3.eth.estimateGas({ 22 | to: walletInfo.address, 23 | value: amount, 24 | data: hexStr, 25 | }); 26 | 27 | const transaction = { 28 | to: walletInfo.address, 29 | value: amount, 30 | gasPrice: gasPrice, 31 | nonce: nonce, 32 | gas: gasEstimate, 33 | data: hexStr, 34 | }; 35 | 36 | const signedTransaction = await web3.eth.accounts.signTransaction(transaction, walletInfo.privateKey); 37 | const result = await web3.eth.sendSignedTransaction(signedTransaction.rawTransaction); 38 | successNum = successNum + 1; 39 | console.log(`本次脚本运行第 ${walletInfo.num} 个地址 ${walletInfo.address} 第 ${i + 1} 次操作成功,共成功 ${successNum} 次,共失败 ${failNum} 次,交易哈希: ${result.transactionHash}`); 40 | } catch (error) { 41 | failNum = failNum + 1; 42 | console.error(`本次脚本运行第 ${walletInfo.num} 个地址 ${walletInfo.address} 第 ${i + 1} 次操作失败,共成功 ${successNum} 次,共失败 ${failNum} 次: `, error); 43 | } 44 | } 45 | } 46 | 47 | async function main() { 48 | let walletData = []; 49 | try { 50 | walletData = JSON.parse(fs.readFileSync('evm_wallets.json', 'utf-8')); 51 | } catch (e) { 52 | console.log('未找到 evm_wallets.json 文件'); 53 | } 54 | 55 | Promise.all(walletData.map(wallet => performTransaction(wallet, process.env.NUMBER_OF_TIMES))) 56 | .then(() => { 57 | console.log("所有操作完成"); 58 | }) 59 | .catch(error => { 60 | console.error("操作中有错误发生: ", error); 61 | }); 62 | } 63 | 64 | main(); -------------------------------------------------------------------------------- /mnemonic.json: -------------------------------------------------------------------------------- 1 | { 2 | "英文助记词": "step walk finger calm shrimp holiday ring early turn bottom scrap domain", 3 | "中文助记词": "奏 如 储 苏 垄 黎 叔 种 捅 豪 叹 铒" 4 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "evm_mint", 3 | "version": "1.0.0", 4 | "main": "mint.js", 5 | "license": "MIT", 6 | "dependencies": { 7 | "axios": "^1.6.2", 8 | "bip39": "^3.1.0", 9 | "dotenv": "^16.3.1", 10 | "ethereum-hdwallet": "^0.1.2", 11 | "fs": "^0.0.1-security", 12 | "web3": "^4.3.0" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /printAddressByMnemonic.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config(); 2 | const bip39 = require('bip39') 3 | const HDWallet = require('ethereum-hdwallet'); 4 | // 获取助记词 5 | const mnemonic = process.env.MNEMONIC; 6 | // 需要生成的地址数 7 | const genNum = process.env.GEN_NUM; 8 | 9 | async function getAddresses(mnemonic) { 10 | const seed = await bip39.mnemonicToSeed(mnemonic); //生成种子 11 | const hdwallet = HDWallet.fromSeed(seed); 12 | for (var i = 0; i < genNum; i++) { // 用同一个种子生成多个地址 13 | const key = hdwallet.derive("m/44'/60'/0'/0/" + i); // 地址路径的最后一位设置为循环变量 14 | const address = '0x' + key.getAddress().toString('hex'); //地址 15 | console.log(address); // 地址 16 | } 17 | } 18 | 19 | getAddresses(mnemonic); //执行函数 -------------------------------------------------------------------------------- /printPrivateKeyByMnemonic.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config(); 2 | const bip39 = require('bip39') 3 | const HDWallet = require('ethereum-hdwallet'); 4 | // 获取助记词 5 | const mnemonic = process.env.MNEMONIC; 6 | // 需要生成的地址数 7 | const genNum = process.env.GEN_NUM; 8 | 9 | async function getPrivateKeys(mnemonic) { 10 | const seed = await bip39.mnemonicToSeed(mnemonic); //生成种子 11 | const hdwallet = HDWallet.fromSeed(seed); 12 | for (var i = 0; i < genNum; i++) { // 用同一个种子生成多个地址 13 | const key = hdwallet.derive("m/44'/60'/0'/0/" + i); // 地址路径的最后一位设置为循环变量 14 | const privateKey = key.getPrivateKey().toString('hex'); 15 | console.log(privateKey); // 私钥 16 | } 17 | } 18 | 19 | getPrivateKeys(mnemonic); //执行函数 -------------------------------------------------------------------------------- /transfer.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config(); 2 | const {readFileSync} = require('fs'); 3 | const {Web3} = require('web3'); 4 | const axios = require('axios'); 5 | 6 | const nodeUrl = process.env.NODE_URL; 7 | const chainId = process.env.CHAIN_ID; 8 | 9 | // 创建Web3实例 10 | const web3 = new Web3(nodeUrl); 11 | 12 | // 发送gas币的地址和私钥 13 | const fromAddress = process.env.ADDRESS; 14 | const privateKey = process.env.PRIVATE_KEY; 15 | 16 | // 从json文件获取钱包信息 17 | const wallets = JSON.parse(readFileSync('evm_wallets.json', 'utf-8')); 18 | 19 | // 目标地址列表 20 | const toAddresses = wallets.map(wallet => wallet.address); 21 | 22 | // 转账金额(以wei为单位) 23 | const amountInWei = web3.utils.toWei(process.env.MONEY, 'ether'); 24 | 25 | // 构建交易对象 26 | const buildTransaction = async (to) => { 27 | try { 28 | // 获取实时Gas价格 29 | const gasPriceInWei = await getGasPrice(); 30 | const nonce = await web3.eth.getTransactionCount(fromAddress); 31 | 32 | // 估算gas限制 33 | const gasLimit = await web3.eth.estimateGas({ 34 | from: fromAddress, 35 | to: to, 36 | value: amountInWei, 37 | }); 38 | 39 | return { 40 | from: fromAddress, 41 | to: to, 42 | value: amountInWei, 43 | gasPrice: gasPriceInWei, 44 | gas: gasLimit, 45 | nonce: nonce, 46 | }; 47 | } catch (error) { 48 | throw new Error(`构建交易失败: ${error.message}`); 49 | } 50 | }; 51 | 52 | // 获取实时Gas价格 53 | const getGasPrice = async () => { 54 | try { 55 | const response = await axios.post(nodeUrl, { 56 | jsonrpc: '2.0', 57 | id: chainId, 58 | method: 'eth_gasPrice', 59 | params: [], 60 | }); 61 | 62 | return response.data.result; 63 | } catch (error) { 64 | throw new Error(`获取Gas价格失败: ${error.message}`); 65 | } 66 | }; 67 | 68 | // 发送交易 69 | const sendTransaction = async (transaction) => { 70 | try { 71 | const signedTransaction = await web3.eth.accounts.signTransaction(transaction, privateKey); 72 | return web3.eth.sendSignedTransaction(signedTransaction.rawTransaction); 73 | } catch (error) { 74 | throw new Error(`发送交易失败: ${error.message}`); 75 | } 76 | }; 77 | 78 | // 批量发送交易 79 | const batchSendTransactions = async () => { 80 | for (const toAddress of toAddresses) { 81 | const transaction = await buildTransaction(toAddress); 82 | try { 83 | const receipt = await sendTransaction(transaction); 84 | console.log(`交易已发送至 ${toAddress}. 交易哈希: ${receipt.transactionHash}`); 85 | } catch (error) { 86 | console.error(`发送交易至 ${toAddress} 失败: ${error.message}`); 87 | } 88 | } 89 | }; 90 | 91 | // 执行批量发送 92 | batchSendTransactions(); -------------------------------------------------------------------------------- /transferGasToOne.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config(); 2 | const {readFileSync} = require('fs'); 3 | const {Web3} = require('web3'); 4 | 5 | const nodeUrl = process.env.NODE_URL; 6 | 7 | // 创建Web3实例 8 | const web3 = new Web3(nodeUrl); 9 | 10 | // 从json文件获取钱包信息 11 | const wallets = JSON.parse(readFileSync('evm_wallets.json', 'utf-8')); 12 | 13 | // 目标地址 14 | const toAddress = process.env.ADDRESS 15 | 16 | // 构建交易对象 17 | const buildTransaction = async (wallet) => { 18 | try { 19 | const gasPrice = await web3.eth.getGasPrice(); 20 | const nonce = await web3.eth.getTransactionCount(wallet.address); 21 | // 余额(以wei为单位) 22 | const amountInWei = await web3.eth.getBalance(wallet.address); 23 | // 估算gas限制 24 | const gasLimit = await web3.eth.estimateGas({ 25 | from: wallet.address, 26 | to: toAddress, 27 | value: amountInWei, 28 | }); 29 | 30 | return { 31 | from: wallet.address, 32 | to: toAddress, 33 | value: amountInWei - gasLimit * gasPrice, 34 | gas: gasLimit, 35 | nonce: nonce, 36 | gasPrice: gasPrice 37 | }; 38 | } catch (error) { 39 | throw new Error(`构建交易失败: ${error.message}`); 40 | } 41 | }; 42 | 43 | // 发送交易 44 | const sendTransaction = async (transaction, wallet) => { 45 | try { 46 | const signedTransaction = await web3.eth.accounts.signTransaction(transaction, wallet.privateKey); 47 | return web3.eth.sendSignedTransaction(signedTransaction.rawTransaction); 48 | } catch (error) { 49 | throw new Error(`发送交易失败: ${error.message}`); 50 | } 51 | }; 52 | 53 | // gas币余额归集 54 | const batchSendTransactions = async () => { 55 | const transactionPromises = wallets.map(async (wallet) => { 56 | try { 57 | const transaction = await buildTransaction(wallet); 58 | const receipt = await sendTransaction(transaction, wallet); 59 | console.log(`第 ${wallet.num} 个地址 ${wallet.address} 转账至 ${toAddress} 成功。交易哈希: ${receipt.transactionHash}`); 60 | } catch (error) { 61 | console.error(`第 ${wallet.num} 个地址 ${wallet.address} 转账至 ${toAddress} 失败: ${error.message}`); 62 | } 63 | }); 64 | 65 | await Promise.all(transactionPromises); 66 | }; 67 | 68 | // 执行批量发送 69 | batchSendTransactions(); --------------------------------------------------------------------------------