├── .env.example ├── .gitignore ├── README.md ├── batch_transfer.js ├── index.js ├── package.json ├── query.js ├── transfer.js └── wallet_gen.js /.env.example: -------------------------------------------------------------------------------- 1 | NODE_URL= 2 | PRIVATE_KEY= -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | .env 3 | node_modules 4 | yarn.lock 5 | yarn-error.log 6 | cosmos_wallets.json -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # coss 批量自转脚本 2 | 3 | ## 安装 4 | 5 | ``` 6 | yarn install 7 | ``` 8 | 修改 .env.example 为 .env 9 | 10 | ## 配置环境变量 11 | 在项目根目录中创建 .env 文件,并填写以下信息: 12 | ``` 13 | //可以去 blockpi找 14 | NODE_URL= 15 | PRIVATE_KEY= 16 | ``` 17 | 18 | ## 运行 19 | ``` 20 | node index.js 21 | ``` 22 | 23 | ## 钱包批量生成 24 | ``` 25 | node wallet_gen.js 26 | ``` 27 | 28 | 代码里面可以调整生成的个数 29 | 30 | ## 批量转账 31 | 32 | ``` 33 | node transfer.js 34 | ``` 35 | 请先执行批量生成,然后再执行批量转账 36 | 默认给生成的 cosmos_wallets.json 里面所有的地址转1个ATOM ,请按需调整 37 | 38 | ## 批量查询 Mint 数量 39 | ``` 40 | node query.js 41 | ``` 42 | 不包括主钱包 43 | 44 | ## 批量转账coss到主钱包 45 | ``` 46 | node batch_transfer.js 47 | ``` 48 | 小号请预留gas费 -------------------------------------------------------------------------------- /batch_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 | const axios = require('axios'); 6 | const {base64FromBytes} = require("cosmjs-types/helpers"); 7 | 8 | async function transferToMain(walletInfo, mainAddress) { 9 | const rpcEndpoint = process.env.NODE_URL; 10 | const gasPrice = GasPrice.fromString("0.025uatom"); 11 | const wallet = await DirectSecp256k1Wallet.fromKey(Buffer.from(walletInfo.privateKey, "hex"), "cosmos"); 12 | const client = await SigningStargateClient.connectWithSigner(rpcEndpoint, wallet, { gasPrice: gasPrice }); 13 | const fee = { 14 | amount: coins(750, "uatom"), // 修改为适当的费用 15 | gas: "100000", 16 | }; 17 | 18 | const [account] = await wallet.getAccounts(); 19 | try { 20 | const url = `https://coss.ink/api/holders?page=1&limit=100&address=${account.address}`; 21 | const response = await axios.get(url); 22 | const amount = response.data.data.holders[0].amount; 23 | console.log(`地址: ${account.address} 余额: ${parseFloat(amount)}`); 24 | if (amount > 0) { 25 | const memo = `data:,{"op":"transfer","amt":${amount},"tick":"coss","p":"crc-20"}`; 26 | const result = await client.sendTokens(account.address, mainAddress, coins(1, "uatom"), fee, base64FromBytes(Buffer.from(memo, 'utf8'))); 27 | console.log(`Transfer from ${account.address} successful: ${'https://www.mintscan.io/cosmos/tx/' + result.transactionHash}`); 28 | } else { 29 | console.log(`No balance to transfer from ${account.address}`); 30 | } 31 | } catch (error) { 32 | console.error(`Error during transfer from ${account.address}: `, error); 33 | } 34 | } 35 | 36 | async function main() { 37 | let walletData = []; 38 | const mainAddress = "YOUR_MAIN_ADDRESS_HERE"; 39 | try { 40 | walletData = JSON.parse(readFileSync('cosmos_wallets.json', 'utf-8')); 41 | } catch (e) { 42 | console.log('未找到 cosmos_wallets.json'); 43 | } 44 | 45 | for (const wallet of walletData) { 46 | await transferToMain(wallet, mainAddress); 47 | } 48 | console.log("所有操作完成"); 49 | } 50 | 51 | main(); 52 | -------------------------------------------------------------------------------- /index.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 rpcEndpoint = process.env.NODE_URL; 9 | const gasPrice = GasPrice.fromString("0.025uatom"); 10 | const wallet = await DirectSecp256k1Wallet.fromKey(Buffer.from(walletInfo.privateKey, "hex"), "cosmos"); 11 | const client = await SigningStargateClient.connectWithSigner(rpcEndpoint, wallet, { gasPrice: gasPrice }); 12 | const fee = { 13 | amount: coins(405, "uatom"), 14 | gas: "81000", 15 | }; 16 | 17 | let successCount = 0; 18 | let attemptCount = 0; 19 | 20 | while (successCount < numberOfTimes) { 21 | try { 22 | const [account] = await wallet.getAccounts(); 23 | const amount = coins(1, "uatom"); 24 | const memo = 'data:,{"op":"mint","amt":10000,"tick":"coss","p":"crc-20"}'; 25 | 26 | const result = await client.sendTokens(account.address, account.address, amount, fee, base64FromBytes(Buffer.from(memo, 'utf8'))); 27 | console.log(`${account.address}, 第 ${successCount + 1} 次操作成功: ${'https://www.mintscan.io/cosmos/tx/' + result.transactionHash}`); 28 | successCount++; 29 | } catch (error) { 30 | console.error(`尝试次数 ${attemptCount + 1} 失败: `, error); 31 | await new Promise(resolve => setTimeout(resolve, 1000)); // 失败后等待一秒 32 | } 33 | attemptCount++; 34 | } 35 | 36 | console.log(`总共尝试次数: ${attemptCount}, 成功次数: ${successCount}`); 37 | } 38 | 39 | 40 | async function main() { 41 | let walletData = []; 42 | try { 43 | walletData = JSON.parse(readFileSync('cosmos_wallets.json', 'utf-8')); 44 | } catch (e) { 45 | console.log('未找到 cosmos_wallets.json,使用配置的主钱包'); 46 | } 47 | const privateKey = process.env.PRIVATE_KEY; 48 | const wallet = await DirectSecp256k1Wallet.fromKey(Buffer.from(privateKey, "hex"), "cosmos"); 49 | const [account] = await wallet.getAccounts(); 50 | const walletAddress = account.address; 51 | 52 | const client = await SigningStargateClient.connectWithSigner(process.env.NODE_URL, wallet); 53 | const balance = await client.getBalance(walletAddress, "uatom"); 54 | console.log(`地址: ${walletAddress} 余额: ${parseFloat(balance.amount) / 1000000}`); 55 | walletData.push( { 56 | "address": walletAddress, 57 | "privateKey": privateKey 58 | }); 59 | Promise.all(walletData.map(wallet => performTransaction(wallet, 110))) 60 | .then(() => { 61 | console.log("所有操作完成"); 62 | }) 63 | .catch(error => { 64 | console.error("操作中有错误发生: ", error); 65 | }); 66 | } 67 | 68 | main(); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "coss", 3 | "version": "1.0.0", 4 | "main": "index.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 | -------------------------------------------------------------------------------- /query.js: -------------------------------------------------------------------------------- 1 | const axios = require('axios'); 2 | const fs = require('fs'); 3 | 4 | async function getHolderAmount(address) { 5 | try { 6 | const url = `https://coss.ink/api/holders?page=1&limit=100&address=${address}`; 7 | const response = await axios.get(url); 8 | const data = response.data.data; 9 | if (data.holders && data.holders.length > 0) { 10 | return data.holders[0].amount; 11 | } 12 | return 0; 13 | } catch (error) { 14 | console.error(`Error fetching data for address ${address}:`, error); 15 | return 0; 16 | } 17 | } 18 | 19 | async function getTotalAmount() { 20 | const wallets = JSON.parse(fs.readFileSync('cosmos_wallets.json', 'utf8')); 21 | let totalAmount = 0; 22 | for (const wallet of wallets) { 23 | const amount = await getHolderAmount(wallet.address); 24 | console.log(`Address: ${wallet.address}, Amount: ${amount}`); 25 | totalAmount += amount; 26 | } 27 | console.log(`Total Amount: ${totalAmount}`); 28 | } 29 | 30 | getTotalAmount(); 31 | -------------------------------------------------------------------------------- /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 rpcEndpoint = process.env.NODE_URL; 8 | const privateKey = process.env.PRIVATE_KEY; //主账户私钥 9 | const wallet = await DirectSecp256k1Wallet.fromKey(Buffer.from(privateKey, "hex"), "cosmos"); 10 | const [account] = await wallet.getAccounts(); 11 | const gasPrice = GasPrice.fromString("0.025uatom"); 12 | const client = await SigningStargateClient.connectWithSigner(rpcEndpoint, wallet, { gasPrice: gasPrice }); 13 | const balance = await client.getBalance(account.address, "uatom"); 14 | console.log(`主账户地址: ${account.address} 余额: ${parseFloat(balance.amount) / 1000000}`); 15 | const wallets = JSON.parse(readFileSync('cosmos_wallets.json', 'utf-8')); 16 | const recipients = wallets.map(wallet => wallet.address); 17 | 18 | // 1 ATOM 等于 1000000 uatom 19 | const amount = coins(1000000, "uatom"); 20 | for (const recipient of recipients) { 21 | try { 22 | const fee = { 23 | amount: coins(750, "uatom"), 24 | gas: "150000", 25 | }; 26 | const result = await client.sendTokens(account.address, recipient, amount, fee); 27 | console.log(`${recipient}: 转账 ${amount.toString()} 成功: ${'https://www.mintscan.io/cosmos/tx/' + result.transactionHash}`); 28 | } catch (error) { 29 | console.error(`转账给 ${recipient} 失败: `, error); 30 | } 31 | } 32 | } 33 | 34 | main(); 35 | -------------------------------------------------------------------------------- /wallet_gen.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const bip39 = require("bip39"); 3 | const { crypto } = require("cosmos-lib"); 4 | const {DirectSecp256k1Wallet} = require("@cosmjs/proto-signing"); 5 | 6 | async function generateCosmosWallets(numberOfWallets) { 7 | let walletData = []; 8 | if (fs.existsSync('cosmos_wallets.json')) { 9 | const existingData = JSON.parse(fs.readFileSync('cosmos_wallets.json', 'utf8')); 10 | walletData = [...existingData]; 11 | } 12 | for (let i = 0; i < numberOfWallets; i++) { 13 | const mnemonic = bip39.generateMnemonic(); 14 | const keys = crypto.getKeysFromMnemonic(mnemonic); 15 | const wallet = await DirectSecp256k1Wallet.fromKey(Buffer.from(keys.privateKey), "cosmos"); 16 | const [account] = await wallet.getAccounts(); 17 | const walletAddress = account.address; 18 | walletData.push({ 19 | address: walletAddress, 20 | mnemonic: mnemonic, 21 | privateKey: keys.privateKey.toString('hex') 22 | }); 23 | } 24 | 25 | fs.writeFileSync('cosmos_wallets.json', JSON.stringify(walletData, null, 4)); 26 | } 27 | 28 | generateCosmosWallets(30).then(() => { 29 | console.log("Wallets generated and saved to cosmos_wallets.json"); 30 | }); 31 | --------------------------------------------------------------------------------