├── .env.example ├── .gitignore ├── LICENSE ├── README.md ├── mint.js ├── package.json ├── transfer.js └── wallet_gen.js /.env.example: -------------------------------------------------------------------------------- 1 | # rpc配置, 可以从 https://atomscan.com/directory/celestia 找到自己喜欢的节点服务器 2 | NODE_URL=https://public-celestia-rpc.numia.xyz 3 | # NODE_URL=https://celestia-rpc.mesa.newmetric.xyz 4 | 5 | # 主钱包(资金钱包)私钥, 用于转账给其它真正用来 Mint 的钱包 6 | PRIVATE_KEY= 7 | 8 | # 生成钱包配置,按需配置 9 | # 生成多少个 Mint 钱包 10 | NUM_OF_WALLETS=5 11 | # 真正 Mint 的钱包文件,所有生成的钱包都在这个文件里 12 | WALLET_JSON_FILE=wallets.json 13 | 14 | # celestia配置(可以不用动) 15 | CHAIN_SYMBOL=celestia 16 | TOKEN_DENOM=utia 17 | TOKEN_DECIMAL=1000000 18 | 19 | # 从主钱包(资金钱包)转多少个 TIA 到 每个真正 Mint 的钱包 20 | TOKEN_TRANSFER_AMOUNT=2 21 | 22 | # gas 配置, 按需修改 23 | GAS_PRICE=10000 24 | GAS_LIMIT=100000 25 | 26 | # mint配置, 一定要根据官方参数配置 27 | MINT_AMOUNT=10000 28 | # 铭文代币名称 29 | TICK=cias 30 | # 协议类型 31 | PROTOCOL=cia-20 32 | 33 | # 每个钱包 mint 次数 34 | MINT_TIMES=10 35 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | .env 3 | node_modules 4 | yarn.lock 5 | yarn-error.log 6 | *wallet*.json -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 zefzhou 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 | # Celestia(tia) 公链铭文 cias mint 脚本 2 | 3 | ## 代码参考 [qzz0518/coss](https://github.com/qzz0518/coss) 4 | 5 | ### Step 1: 安装 6 | 7 | ``` 8 | git clone https://github.com/sfter/cias-mint 9 | yarn install 10 | cp .env.example .env 11 | ``` 12 | 13 | ### Step 2: 配置环境变量 14 | 15 | 在脚本源代码目录下修改 .env 文件 16 | 17 | ```bash 18 | # rpc配置, 可以从 https://atomscan.com/directory/celestia 找到自己喜欢的节点服务器 19 | NODE_URL=https://public-celestia-rpc.numia.xyz 20 | # NODE_URL=https://celestia-rpc.mesa.newmetric.xyz 21 | 22 | # 主钱包(资金钱包)私钥, 用于转账给其它真正用来 Mint 的钱包 23 | PRIVATE_KEY= 24 | 25 | # 生成钱包配置,按需配置 26 | # 生成多少个 Mint 钱包 27 | NUM_OF_WALLETS=5 28 | # 真正 Mint 的钱包文件,所有生成的钱包都在这个文件里 29 | WALLET_JSON_FILE=wallets.json 30 | 31 | # celestia配置(可以不用动) 32 | CHAIN_SYMBOL=celestia 33 | TOKEN_DENOM=utia 34 | TOKEN_DECIMAL=1000000 35 | 36 | # 从主钱包(资金钱包)转多少个 TIA 到 每个真正 Mint 的钱包 37 | TOKEN_TRANSFER_AMOUNT=2 38 | 39 | # gas 配置, 按需修改 40 | GAS_PRICE=10000 41 | GAS_LIMIT=100000 42 | 43 | # mint配置, 一定要根据官方参数配置 44 | MINT_AMOUNT=10000 45 | # 铭文代币名称 46 | TICK=cias 47 | # 协议类型 48 | PROTOCOL=cia-20 49 | 50 | # 每个钱包 mint 次数 51 | MINT_TIMES=10 52 | 53 | ``` 54 | 55 | ### Step 3: 批量生成 Mint 钱包 56 | 57 | ```bash 58 | node wallet_gen.js 59 | ``` 60 | 61 | ### Step 4: 从主钱包(资金钱包)批量转帐到 Mint 钱包 62 | 63 | ```bash 64 | node transfer.js 65 | ``` 66 | 67 | ### Step 5: 运行 Mint 程序开始 Mint 68 | 69 | ```bash 70 | node mint.js 71 | ``` 72 | 73 | ### 特别说明 74 | 如果 keplr 钱包导不出私钥,可以通过如下方法来做 75 | > - 先把 .env 文件配置好,PRIVATE_KEY 留空。 76 | > 77 | > 78 | > - 使用 node wallet_gen.js 生成钱包 79 | > 80 | > 81 | > - 打开当前目录下的 wallet.json 文件 82 | > 83 | > 84 | > - 选择其中任意一个钱包做为主钱包。 85 | > 86 | > 87 | > - 打开 keplr 钱包,向你在上面第4步选择的钱包地址转一些 $TIA 进去。 88 | > 89 | > 90 | > - 将上面第4步选择的钱包地址配置到 .env 文件里的 PRIVATE_KEY 字段里。 91 | > 92 | > 93 | > - 执行 node transfer.js 将会从上面第4步选择的钱包向其它 Mint 的钱包批量转帐。 94 | > 95 | > 96 | > - 执行 node mint.js 开始批量 Mint,完成 OK。 97 | -------------------------------------------------------------------------------- /mint.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config(); 2 | const { SigningStargateClient, GasPrice, coins } = require("@cosmjs/stargate"); 3 | const { DirectSecp256k1Wallet } = require('@cosmjs/proto-signing'); 4 | const { readFileSync } = require("fs"); 5 | const {base64FromBytes} = require("cosmjs-types/helpers"); 6 | 7 | async function performTransaction(walletInfo, numberOfTimes) { 8 | const denom = process.env.TOKEN_DENOM; 9 | const chain = process.env.CHAIN_SYMBOL; 10 | const rpcEndpoint = process.env.NODE_URL; 11 | const gasPrice = GasPrice.fromString(`0.025${denom}`); 12 | const wallet = await DirectSecp256k1Wallet.fromKey(Buffer.from(walletInfo.privateKey, "hex"), chain); 13 | const client = await SigningStargateClient.connectWithSigner(rpcEndpoint, wallet, { gasPrice: gasPrice }); 14 | const fee = { 15 | amount: coins(process.env.GAS_PRICE, denom), 16 | gas: process.env.GAS_LIMIT, 17 | }; 18 | console.log(`init`); 19 | let successCount = 0; 20 | let attemptCount = 0; 21 | 22 | const tick = process.env.TICK 23 | const protocol = process.env.PROTOCOL 24 | const mintAmount = parseInt(process.env.MINT_AMOUNT) 25 | 26 | while (successCount < numberOfTimes) { 27 | try { 28 | const [account] = await wallet.getAccounts(); 29 | const amount = coins(1, denom); // 自转1,按需修改 30 | const memo = `data:,{"op":"mint","amt":${mintAmount},"tick":"${tick}","p":"${protocol}"}`; // 这里可能会变化 31 | console.log(`memo = ${memo}`); 32 | 33 | const result = await client.sendTokens(account.address, account.address, amount, fee, base64FromBytes(Buffer.from(memo, 'utf8'))); 34 | console.log(`${account.address}, 第 ${successCount + 1} 次操作成功: ${`https://www.mintscan.io/${chain}/tx/` + result.transactionHash}`); 35 | successCount++; 36 | } catch (error) { 37 | console.error(`尝试次数 ${attemptCount + 1} 失败: `, error); 38 | attemptCount++; 39 | await new Promise(resolve => setTimeout(resolve, 1000)); // 失败后等待一秒 40 | } 41 | } 42 | 43 | console.log(`总共尝试次数: ${attemptCount}, 成功次数: ${successCount}`); 44 | } 45 | 46 | 47 | async function main() { 48 | const walletsFile = process.env.WALLET_JSON_FILE; 49 | const tokenDecimal = parseInt(process.env.TOKEN_DECIMAL); 50 | const chain = process.env.CHAIN_SYMBOL; 51 | const denom = process.env.TOKEN_DENOM; 52 | let walletData = []; 53 | try { 54 | walletData = JSON.parse(readFileSync(walletsFile, 'utf-8')); 55 | } catch (e) { 56 | console.log(`未找到 ${walletsFile}, 仅使用配置的主钱包`); 57 | } 58 | 59 | const privateKey = process.env.PRIVATE_KEY; 60 | const wallet = await DirectSecp256k1Wallet.fromKey(Buffer.from(privateKey, "hex"), chain); 61 | const [account] = await wallet.getAccounts(); 62 | const walletAddress = account.address; 63 | 64 | const client = await SigningStargateClient.connectWithSigner(process.env.NODE_URL, wallet); 65 | const balance = await client.getBalance(walletAddress, denom); 66 | console.log(`资金钱包: ${walletAddress} 余额: ${parseFloat(balance.amount) / tokenDecimal}`); 67 | 68 | walletData.push({ 69 | "address": walletAddress, 70 | "privateKey": privateKey 71 | }); 72 | Promise.all(walletData.map(wallet => performTransaction(wallet, parseInt(process.env.MINT_TIMES)))) 73 | .then(() => { 74 | console.log("所有操作完成"); 75 | }) 76 | .catch(error => { 77 | console.error("操作中有错误发生: ", error); 78 | }); 79 | } 80 | 81 | main(); 82 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cias", 3 | "version": "1.0.0", 4 | "main": "mint.js", 5 | "license": "MIT", 6 | "dependencies": { 7 | "@cosmjs/crypto": "^0.32.0", 8 | "@cosmjs/encoding": "^0.32.0", 9 | "@cosmjs/proto-signing": "^0.32.0", 10 | "@cosmjs/stargate": "^0.32.0", 11 | "axios": "^1.6.2", 12 | "bip39": "^3.1.0", 13 | "cosmjs-types": "^0.9.0", 14 | "cosmos-lib": "^1.1.0", 15 | "dotenv": "^16.3.1", 16 | "fs": "^0.0.1-security" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /transfer.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config(); 2 | const { SigningStargateClient, GasPrice, coins } = require("@cosmjs/stargate"); 3 | const { DirectSecp256k1Wallet } = require('@cosmjs/proto-signing'); 4 | const {readFileSync} = require("fs"); 5 | 6 | async function main() { 7 | const denom = process.env.TOKEN_DENOM; 8 | const chain = process.env.CHAIN_SYMBOL; 9 | const walletsFile = process.env.WALLET_JSON_FILE; 10 | const tokenDecimal = parseInt(process.env.TOKEN_DECIMAL); 11 | const rpcEndpoint = process.env.NODE_URL; 12 | const privateKey = process.env.PRIVATE_KEY; //主账户私钥 13 | const wallet = await DirectSecp256k1Wallet.fromKey(Buffer.from(privateKey, "hex"), chain); 14 | const [account] = await wallet.getAccounts(); 15 | const gasPrice = GasPrice.fromString(`0.025${denom}`); // no need 16 | const client = await SigningStargateClient.connectWithSigner(rpcEndpoint, wallet, { gasPrice: gasPrice }); 17 | const balance = await client.getBalance(account.address, denom); 18 | // const balance = await client.getBalance('celestia1x8pl6xa3sxj49du4758cf8mutk4cu7uha04eyc', denom); 19 | console.log(`主账户地址: ${account.address} 余额: ${ balance.amount / tokenDecimal }`); 20 | const wallets = JSON.parse(readFileSync(walletsFile, 'utf-8')); 21 | const recipients = wallets.map(wallet => wallet.address); 22 | 23 | const amount = coins(parseInt(parseFloat(process.env.TOKEN_TRANSFER_AMOUNT) * tokenDecimal) ,denom); 24 | for (const recipient of recipients) { 25 | try { 26 | const fee = { 27 | amount: coins(process.env.GAS_PRICE, denom), 28 | gas: process.env.GAS_LIMIT, 29 | }; 30 | const result = await client.sendTokens(account.address, recipient, amount, fee); 31 | console.log(`${recipient}: 转账 ${amount.toString()} 成功: ${`https://www.mintscan.io/${chain}/tx/` + result.transactionHash}`); 32 | } catch (error) { 33 | console.error(`转账给 ${recipient} 失败: `, error); 34 | } 35 | } 36 | } 37 | 38 | main(); 39 | -------------------------------------------------------------------------------- /wallet_gen.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config(); 2 | const fs = require('fs'); 3 | const bip39 = require("bip39"); 4 | const { crypto } = require("cosmos-lib"); 5 | const {DirectSecp256k1Wallet} = require("@cosmjs/proto-signing"); 6 | 7 | async function generateCosmosWallets() { 8 | let walletData = []; 9 | let walletsFile = process.env.WALLET_JSON_FILE 10 | if (fs.existsSync(walletsFile)) { 11 | const existingData = JSON.parse(fs.readFileSync(walletsFile, 'utf8')); 12 | walletData = [...existingData]; 13 | } 14 | for (let i = 0; i < process.env.NUM_OF_WALLETS; i++) { 15 | const mnemonic = bip39.generateMnemonic(); 16 | const keys = crypto.getKeysFromMnemonic(mnemonic); 17 | const wallet = await DirectSecp256k1Wallet.fromKey(Buffer.from(keys.privateKey), "celestia"); 18 | const [account] = await wallet.getAccounts(); 19 | const walletAddress = account.address; 20 | walletData.push({ 21 | address: walletAddress, 22 | mnemonic: mnemonic, 23 | privateKey: keys.privateKey.toString('hex') 24 | }); 25 | } 26 | 27 | fs.writeFileSync(walletsFile, JSON.stringify(walletData, null, 4)); 28 | } 29 | 30 | generateCosmosWallets().then(() => { 31 | console.log(`Wallets generated and saved to ${ process.env.WALLET_JSON_FILE}`); 32 | }); 33 | --------------------------------------------------------------------------------