1.工作计划
- 闪电空投的开发(已完成,测试中)
- gas消耗机制(构思中)
- 数据切割机制(构思中)
- 交易失败处理机制(构思中)
- log日志(构思中)
- 合约地址,参数等处理(开发中)
2. 工作记录
闪电端,(后续要处理分片发送)
const fs = require("fs");
const xlsx = require('node-xlsx');
const Web3 = require("web3");
const log4js = require('log4js')
const ajax = require('ajax');
const http = require('http');
const queryString = require('querystring');
const logger = log4js.getLogger();
let web3 = new Web3();
//init
//业务action
var Action_Methods = {
//初始化参数
Init:()=>{
console.log("*********Starting*********");
//ALL < TRACE < DEBUG < INFO < WARN < ERROR < FATAL < MARK < OFF
logger.level = 'info';
//其他初始化配置
},
//读取文件
ReadFile:()=>{
// let Filesdata = fs.readFileSync('testdemo1.xlsx');
let Filesdata = fs.readFileSync('test05.xlsx');
logger.info("读取文件成功");
//返回
return Filesdata;
},
//序列化文件
Serializedfile:(data)=>{
let Workdata = xlsx.parse(data);
logger.info("序列化数据成功");
//返回,这里要做处理,就是在要获取对象里面的data而不是data
let cData =Workdata[0].data;
return cData;
},
//校验数据
CheckData:(data)=>{
//
let lengths = data.length;
// 结果集
let result = {
State: 0, //0 1 3
Tote: lengths,
Valid: 0,
UnValid: 0,
ValidData: [],
UnValidData: [],
Bz: [],
sData:{
address:[],
value:[],
state:[]
}
}
// 01. 首先判断数据长度
if (data.length <= 0) {
//对象长度小于0
logger.error("数据长度小于0");
result.State = 7; //
return result;
}
//02. 判断地址和内容是否为空
for (let i = 0; i < lengths; i++) {
//01.首先判断2个参数都为空
if ((data[i][0] == null ||data[i][0] == undefined ||data[i][0] == '') && (data[i][1] == null || data[i][1] == undefined || data[i][1] == '')) {
//01.如果两位数据都是空
result.UnValid += 1;
//对象保存 序号:数据
let rows = {
no: i,
address:data[i][0],
value: data[i][1],
state: 1
}
result.UnValidData.push(rows);
//
continue;
} else {
//02. 判断地址为空的情况
if (data[i][0] == null ||data[i][0] == undefined ||data[i][0] == '') {
result.UnValid += 1;
//对象保存 序号:数据
let rows = {
no: i,
address:data[i][0],
value: data[i][1],
state: 3
}
result.UnValidData.push(rows);
continue;
} else if (data[i][1] == null || data[i][1] == undefined || data[i][1] == '') {
result.UnValidData += 1;
//对象保存 序号:数据
let rows = {
no: i,
address:data[i][0],
value: data[i][1],
state: 5
}
result.UnValidData.push(rows);
continue;
}
}
//02. 判断地址是否合法
if (!web3.isAddress(data[i][0])) {
//如果不是有效地址
result.UnValid += 1;
//对象保存 序号:数据
let rows = {
no: i,
address:data[i][0],
value: data[i][1],
state: 7
}
result.UnValidData.push(rows);
continue;
} else {
//如果是有效地址
result.Valid += 1;
//对象保存 序号:数据
let rows = {
no: i,
address:data[i][0],
value: data[i][1],
state: 2
}
result.ValidData.push(rows);
//分开追加数据
result.sData.address.push(data[i][0]);
console.log(parseInt(data[i][1]*100000000));
result.sData.value.push(parseInt(data[i][1]*100000000));
}
//数据处理完成后,返回参数
//处理完标志
result.State = 3;
}
return result;
},
//发送数据
SendData:(data)=>{
let cData = '2';
let opt = {
host:'127.0.0.1', //注意:不用协议部分(http://)
port:'3003',
path: '/Bolt/flyDrop', //斜杠开头
method:'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'} //设置content-type 头部
};
let body = '';
let req = http.request(opt, function(res){
res.statusCode == 200 && console.log('REQUEST OK..' );
res.setEncoding('utf8');//res为ClientResponse的实例,是readableStream, 设置字符编码
res.on('data', function(chunk){
body += chunk;
}).on('end', function(){
console.log('Got data: ', body);//end事件中 打印全部响应数据
});
}).on('error', function(err){
console.log('error: ', err.message);
cData = err.message;
return err;
});
let cdata = data;
let data1 = JSON.stringify(data);
let data2 = queryString.stringify(cdata); //注意 querystring.stringify 和 JSON.stringify的区别
// console.log(data1);
// console.log(data2);
req.write(data2); //req为ClientRequest的实例,是writableStream,写数据到流中
req.end();//结束请求
return cData;
}
}
//一级启动
var Action_Start ={
init:(data)=>{
console.log(data);
//
Action_Starting.init();
},
web_init:()=>{
console.log("---");
}
}
//二级启动
var Action_Starting = {
//
init:()=>{
Action_Methods.Init();
let FileData = Action_Methods.ReadFile();
let FuData = Action_Methods.Serializedfile(FileData);
let ResultData = Action_Methods.CheckData(FuData);
//
let Rest = Action_Methods.SendData(ResultData.sData);
logger.info("代币空投成功...............");
}
}
//参数
const JSON_LIST = {
FileName:{
File_01:"testdemo1.xlsx",
File_02:"testdemo1.xlsx"
}
}
//启动
Action_Start.init("----");
路由端
//闪电空投
router.post('/Bolt/flyDrop', (ctx, next) => {
// TODO:
ctx.body = "M_flyDrop";
//01. 这里有一个大的改变就是校验的话放到他本地了,如果要加上服务端校验,
// TODO:
// console.log("接收到闪电空投的数据是:",ctx);
console.log("接收到闪电空投的数据是:", ctx.request.body);
//
let cData = ctx.request.body;
//
// TODO: 数据校验省略,
// 发送请求
deploy = async (data, next) => {
let result = await Actions_Contrant_Drop.D_boltDrop({
data:data
});
console.log("1111=>", result);
return result;
}
deploy(cData).then(res => {
ctx.body = "调用/Bolt/flyDrop结果是=>" + res;
});
return cData;
});
}
action D_boltDrop
//闪电空投
D_boltDrop: async (data) => {
// TODO:
let result;
let cData = data;
console.log("调用合约方法-Token-D_boltDrop...", cData);
let parsm = cData.data;
console.log("D_multiSend的数据:address",parsm.address);
console.log("D_multiSend的数据:value",parsm.value);
// TODO: 切割数据
//参数
let resultData ={
Sum:0,
Normal:0,
Unnormal:0,
Data:[],
unData:[]
}; //结果集
let Parames_data = {
Type: {
param1: "address _form",
param2: "address _to",
param3: "uint256 _value"
},
Value: {
param1: data.from,
param2: data.to,
param3: data.value
}
}
// let data;
let Parames_address = {
//合约地址
contractAddress: "0x66A4F55B53Cfd0563a16F40BE7EDF8A07796F692",
//发送者
fromAddress: "0x38a8DC14edE1DEf9C437bB3647445eEec06fF105",
//调用者
toAddress: "0xd2580AB2EB3313B0972e9e47b05eE4c15320A6D1"
}
//序列化数据
let Parames_row = {
Tx_nonce: web3.toHex(web3.eth.getTransactionCount(Parames_address.fromAddress)),
Tx_gasPrice: web3.toHex(web3.eth.gasPrice),
Tx_gasLimit: web3.toHex(8000000),
Tx_from: Parames_address.fromAddress,
Tx_to: Parames_address.contractAddress,
Tx_value: "0x0",
TODO:
Tx_data: Contract_Drop.multiSend.getData(parsm.address,parsm.value, {
from: Parames_address.fromAddress
})
}
// 05. 对接数据
let rawTx = {
nonce: Parames_row.Tx_nonce,
gasPrice: Parames_row.Tx_gasPrice, // TODO:
gasLimit: Parames_row.Tx_gasLimit,
from: Parames_row.Tx_from,
to: Parames_row.Tx_to,
value: Parames_row.Tx_value, // TODO:
data: Parames_row.Tx_data
}
// 06.签名编译
let SignData = Actions_CommonTool.Tool_SignData({//3483
rawTx: rawTx,
key: Json_list.PRIVATEKEY.Drop_privateKey
});
// result = await web3.eth.sendRawTransaction(SignData);
web3.eth.sendRawTransaction(SignData,(err,hash)=>{
if (!err){
console.log("hash-----------",hash);
}else{
console.log("err",err);
}
})
console.log("----发送交易返回数据是:",result);
return result;
},
3.存在问题
- gas的消耗机制还是有点模糊,考虑多合约多批转账情况
- 数据分割的判断条件,动态调整,后面还有手续费
- 事件的回退机制log,重新发送机制
- 之前的代码整理
- 说明文档的编写
4.明日计划
- gas的消耗机制搞清楚,为了数据切割而准备
- 数据分割机制做出来,为了后面联调准备
- 参数配置接口写好,整备测试环境测试
- 备用其他