import * as dotevnv from "dotenv" import {toUtf8String,parseUnits,ContractFactory, parseEther,JsonRpcProvider, Contract, JsonRpcSigner, Wallet,ContractTransactionResponse, MaxInt256 ,Transaction,formatEther, ZeroHash,ethers,keccak256,id } from 'ethers' import {Calulator} from "../inc/calc"; import axios from "axios"; import { SecurityToken, SecurityToken__factory, } from '../typechain' import chalk from "chalk"; import {checkReceipt,checkReceipt2, setProvider,getDeploymentAddresses, getElapsed, sleep,getBlockInfo} from '../inc/util' dotevnv.config(); if (!process.env.RPCURL) { console.log(`No rpcur value specified...`) } async function getNonce(addr: string): Promise { const nonce = await provider.getTransactionCount(addr); return nonce; } async function spareToken(symbol: string , amount: number = 50000) { const proxy = getDeploymentAddresses(symbol).address; console.log(`토큰 주소 : ${proxy}`); const token = new SecurityToken__factory(issuer).attach(proxy) as SecurityToken; const adminToken = await token.connect(admin); const n = await token.decimals(); const decimals = Number(n); const digit = 10 ** Number(decimals); const ops = await token.operators(); console.log(ops); let operatorRegistered = false; for(let i = 0; i < ops.length; i++) { //console.log(`${ops[i].toLocaleLowerCase()} == ${issuer.address.toLocaleLowerCase()}`) if( ops[i].toLocaleLowerCase() == issuer.address.toLocaleLowerCase()) { operatorRegistered = true; } } if(!operatorRegistered) { console.log('issuer not registered as operator .. so register'); let ret = await adminToken.grantRole( id('OPERATOR_ROLE'),issuer,{ gasLimit: 20000000}); await ret.wait(); } const partitions = await token.getDefaultPartitions(); console.log(partitions); let balance = await token.balanceOf(firstHolder); console.log(`initial balance = ${balance}`); let addressesToKyc = []; let b = await token.isTokenHolderKYC(firstHolder); if(!b) { console.log('firstHolder needs to be registered'); addressesToKyc.push(firstHolder); } b = await token.isTokenHolderKYC(holder1.address); if(!b) { console.log('holder1 needs to be registered'); addressesToKyc.push(holder1.address); } b = await token.isTokenHolderKYC(holder2.address); if(!b) { console.log('holder1 needs to be registered'); addressesToKyc.push(holder2.address); } if(addressesToKyc.length != 0) { let r = await token.KYCtokenHolders(addressesToKyc); await r.wait(); } balance = await token.balanceOf(holder1); let fixedBalance = (1/digit) * Number(balance); console.log(`holder1(${holder1.address}) balance = ${fixedBalance.toFixed(decimals)}`); if(Number(balance) == 0) { console.log('holder1 needs to be filled..'); let r = await token.operatorTransferByPartition(partitions[0],firstHolder,holder1, amount * digit,ZeroHash,ZeroHash,{gasLimit: 20000000}); await r.wait(); } balance = await token.balanceOf(holder2); fixedBalance = (1/digit) * Number(balance); console.log(`holder2(${holder2.address}) balance = ${fixedBalance.toFixed(decimals)}`); if(Number(balance) == 0) { console.log('holder2 needs to be filled..'); let r = await token.operatorTransferByPartition(partitions[0],firstHolder,holder2, amount * digit,ZeroHash,ZeroHash,{gasLimit: 20000000}); await r.wait(); } } function getAuthHeader(token: string) : any{ return { headers: { 'Content-Type': 'application/json;charset=UTF-8', 'Access-Control-Allow-Origin': '*', 'Authorization': `Bearer ${token}` } }; } async function getBalance(symbol: string, address: string ): Promise { const path = `holders/${address}/tokens/${symbol}/balance`; const ret = await axios.get(gateWay + path, getAuthHeader(authToken)); return ret.data; } async function getTx(signerAddress:string, tokenSymbol: string, from: string, to: string, value: number) : Promise { const path = 'transfer/tx/data'; const ret = await axios.post(gateWay + path, { signerAddress, tokenSymbol, transfers : [{ partitionName:'초기', from, to, value, data:'0x0000000000000000000000000000000000000000000000000000000000000000', operatorData:'0x0000000000000000000000000000000000000000000000000000000000000000' }] },getAuthHeader(authToken)); return ret; } async function send(signedTransaction: string) { const path = 'transaction/send'; const ret = await axios.post(gateWay + path, { signedTransaction },getAuthHeader(authToken)); return ret; } async function sign(tx: Transaction,signer: Wallet) : Promise { const signed = await signer.signTransaction(tx); return {nonce: tx.nonce, sig: signed , txid: keccak256(signed)} } async function transfer(signer: Wallet,symbol:string,from: Wallet, to: Wallet, amount: number = 1, count: number = 10) { const proxy = getDeploymentAddresses(symbol).address; console.log(`토큰 주소 : ${proxy}`); const token = new SecurityToken__factory(issuer).attach(proxy) as SecurityToken; const decimals = await token.decimals(); const digit = 10 ** Number(decimals); let fb = await getBalance(symbol,from.address); let tb = await getBalance(symbol,to.address); fb = (1/digit) * fb; tb = (1/digit) * tb; console.log(chalk.yellow('###################### 전송전 잔고 ###################################')) console.log(`balance of sender(${from.address}) = ${fb.toFixed(Number(decimals))}\r\nbalance of receiver(${to.address}) = ${tb.toFixed(Number(decimals))}`); let firstTx:string = null; let lastTx:string = null; let start = Date.now(); console.log(chalk.cyan(`전송시작 시간 : ${new Date(start).toUTCString()}`)); let unsignedProms = []; for(let i = 0; i < count; i++) { unsignedProms.push(getTx(signer.address,symbol,from.address,to.address, amount * digit)); } let txMap = new Map(); let unsigned = await Promise.all(unsignedProms); let signedProms = []; unsigned.forEach(u => { const tx = Transaction.from(u.data); signedProms.push(sign(tx,signer)); }); let signedData = await Promise.all(signedProms); const elapsed = getElapsed(start,1000); console.log(`TxPrepared within ${elapsed} seconds`); console.log(chalk.yellow(`sending ${count} transactions`)); start = Date.now(); console.log(chalk.cyan(`실제 전송시작 시간 : ${new Date(start).toUTCString()}`)); let proms = []; for(let i = 0; i < count; i++) { //console.log(`sending ${i} , nonce : ${signedData[i].nonce}`); proms.push(send(signedData[i].sig)); } let resolved = await Promise.all(proms); resolved.forEach(tx => { txMap.set(tx.data.transactionHash,false) //console.log(tx.data.transactionHash); }); console.log(`sent txid count = ${txMap.size}`); let nonce = 0; signedData.forEach( tx => { if(tx.nonce > nonce) { lastTx = tx.txid; } }) const blockHashes = await checkReceipt2(txMap,[firstTx as string, lastTx as string], 'wait for receipt...'); //const firstBlockHash = blockHashes.get(firstTx); const lastBlockHash = blockHashes.get(lastTx); //console.log(`firstBlockHash = ${firstBlockHash} \nlastBlockHash = ${lastBlockHash}`); console.log(`lastBlockHash = ${lastBlockHash}`); fb = await getBalance(symbol,from.address); tb = await getBalance(symbol,to.address); fb = (1/digit) * fb; tb = (1/digit) * tb; console.log(chalk.yellow('###################### 전송후 잔고 ###################################')) console.log(`balance of sender(${from.address}) = ${fb.toFixed(Number(decimals))}\r\nbalance of receiver(${to.address}) = ${tb.toFixed(Number(decimals))}`); const lastB = await getBlockInfo(lastBlockHash); const lastTimeStamp = parseInt(lastB.timestamp,16); console.log(`eth_getBlockByHash(${lastBlockHash}).timestamp = ${lastTimeStamp}`) const d = new Date(lastTimeStamp * 1000); console.log(chalk.cyan(`전송종료 시간(블록완결시간) : ${d.toUTCString()}`)); console.log(chalk.yellow(`start timestamp = ${start}`)); console.log(chalk.yellow(`end timestamp = ${lastTimeStamp * 1000}`)); const tps = calc.CTPS(count,start,lastTimeStamp * 1000); console.log(`CTPS = ${tps}`); } const firstHolder = '0x3050C8Eab31E2cbB6d29683f831CaB2FD52a9872'; const calc = new Calulator(); const rpcUrl = process.env.RPCURL; const gateWay = process.env.GATE_WAY; const authToken=process.env.AUTHTOKEN; const provider = new JsonRpcProvider(rpcUrl); setProvider(provider); const admin = new Wallet('0xc87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3',provider); const issuer = new Wallet('0x8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63',provider); const holder1 = new Wallet('0xae6ae8e5ccbfb04590405997ee2d52d2b330726137b875053c36d94e974d162f',provider); const holder2 = new Wallet('0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80',provider); // const signer = holder1; console.log(`목적 서버 : ${gateWay}`); async function main() { spareToken('BCG_TEST'); //transfer(holder1,'BCG_TEST',holder2, holder1,1, 1000); } main();