以太坊(eth)交易所钱包开发 - 3 - 零钱整理
文章目录
当用户充入eth后,我们需要定时把这部分资产转移到冷钱包。一方面是为了安全,一方面是为了更方便的管理资产。
生成交易数据
基本的流程是下面这个样子:
用户充入的eth我们都会在t_tx
表中记录,记录的大概内容是:
id | 交易id | 冲币地址 | 冲币金额 | 零钱整理状态 |
---|---|---|---|---|
1 | 0x1 | 0xa | 0.11 | 0 |
2 | 0x2 | 0xb | 0.12 | 0 |
3 | 0x3 | 0xa | 0.08 | 0 |
4 | 0x4 | 0xc | 0.17 | 0 |
这里我们可以看到有这样一种情况,id
是1和3的交易记录都是同一个地址的交易记录,为了节省手续费,我们会把这两个记录一起整理。
生成交易后,我们需要把生成的数据存入数据库,数据格式如下
|
|
- 首先我们会从数据库中检索所有还没有整理的冲币记录,也就是
零钱整理状态
为0的记录。 - 然后合并相同
冲币地址
的记录,记录为map[冲币地址]SUM(冲币金额)
。 - 合并完成后我们遍历这个map,每次处理map中的一个元素。
- 从获取
冲币地址
的私钥 - 因为转账都是需要eth
手续费
的,所以我们首先要判断该地址的冲币金额总和>转账所需手续费地址。 - 获取nonce值
- 从数据库中获取该这个地址记录的最大nonce,如果没有设置为-1,然后+1返回
- 从RPC获取该地址的nonce
- 返回两者的最大值
- 生成交易并用之前的私钥签名。
关键代码为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
// 生成tx var data []byte tx := types.NewTransaction( uint64(nonce), coldAddress, big.NewInt(sendBalance), uint64(gasLimit), big.NewInt(gasPrice), data, ) chainID, err := ethclient.RpcNetworkID(context.Background()) if err != nil { hcommon.Log.Warnf("RpcNetworkID err: [%T] %s", err, err.Error()) return } signedTx, err := types.SignTx(tx, types.NewEIP155Signer(big.NewInt(chainID)), privateKey) if err != nil { hcommon.Log.Warnf("RpcNetworkID err: [%T] %s", err, err.Error()) return } ts := types.Transactions{signedTx} rawTxBytes := ts.GetRlp(0) rawTxHex := hex.EncodeToString(rawTxBytes) txHash := strings.ToLower(signedTx.Hash().Hex())
- 遍历
冲币地址
对应的记录id- 如果索引值是0,则插入待发送数据到待发送表
- 如果索引值非0,则插入hash id,不插入具体内容
- 这样做的原因是,避免被重复整理
- 从获取
- 更新待处理记录状态为已生成交易。
发送交易
处理方式与之前类似。
- 遍历待发送数据
- 根据数据库中存储的数据序列化成交易数据
1 2 3 4 5 6 7 8 9 10 11
rawTxBytes, err := hex.DecodeString(sendRow.Hex) if err != nil { hcommon.Log.Errorf("err: [%T] %s", err, err.Error()) return } tx := new(types.Transaction) err = rlp.DecodeBytes(rawTxBytes, &tx) if err != nil { hcommon.Log.Errorf("err: [%T] %s", err, err.Error()) return }
- 调用RPC接口发送数据
1 2 3 4 5 6 7 8
txHash := common.HexToHash(txHashStr) tx, isPending, err := client.TransactionByHash(ctx, txHash) if err != nil { return nil, err } if isPending { return nil, nil }
- 根据数据库中存储的数据序列化成交易数据
- 更新待发送数据的状态为已发送
检测交易到账
- 遍历发送数据中状态为已发送的数据
- 调用RPC检测交易处理状态,如果已经打包完成,则记录到状态更改id数组中
1 2 3 4 5 6 7 8 9
txHash := common.HexToHash(txHashStr) tx, isPending, err := client.TransactionByHash(ctx, txHash) if err != nil { return nil, err } if isPending { return nil, nil } return tx, nil
- 将状态更改数据中的数据更改状态为已发送成功。
以上功能便完成了零钱整理功能。
具体实现的代码已经传到了github https://github.com/moremorefun/go-dc-wallet
功能入口在
cmd/eth_address_org/main.go
cmd/eth_raw_tx_send/main.go
cmd/eth_raw_tx_confirm/main.go
文章作者 hao
上次更新 2020-04-19