You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
255 lines
6.2 KiB
255 lines
6.2 KiB
package data
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"errors"
|
|
"github.com/fbsobreira/gotron-sdk/pkg/address"
|
|
"github.com/fbsobreira/gotron-sdk/pkg/proto/api"
|
|
"github.com/go-kratos/kratos/v2/log"
|
|
"math/big"
|
|
"wallet-system/internal/biz"
|
|
"wallet-system/internal/pkg/logging/applogger"
|
|
"wallet-system/internal/pkg/wallet/tron"
|
|
"wallet-system/internal/pkg/wallet/tron/sign"
|
|
)
|
|
|
|
// walletRepo
|
|
// @Description:
|
|
type walletRepo struct {
|
|
data *Data
|
|
|
|
log *log.Helper
|
|
}
|
|
|
|
// NewWalletRepo
|
|
//
|
|
// @Description:
|
|
// @param data
|
|
// @param logger
|
|
// @return biz.WalletRepo
|
|
func NewWalletRepo(data *Data, logger log.Logger) biz.WalletRepo {
|
|
return &walletRepo{
|
|
data: data,
|
|
log: log.NewHelper(logger),
|
|
}
|
|
}
|
|
|
|
/*
|
|
GenerateAddress Private key encryption management
|
|
1、KMS encryption
|
|
2、Leveldb storage
|
|
3、S3 storage
|
|
*/
|
|
func (r *walletRepo) GenerateAddress(ctx context.Context, wallet string, number uint32) ([]string, error) {
|
|
var addressList []string
|
|
for i := 1; i <= int(number); i++ {
|
|
walletAddress, privateKey, err := tron.TronWalletAddress()
|
|
if err != nil {
|
|
applogger.Error("Error generating wallet address and private key:%v", err)
|
|
return []string{}, err
|
|
}
|
|
|
|
encryptByte, err := r.data.kmsC.Encrypt(r.data.aws.Set.Key, privateKey)
|
|
if err != nil {
|
|
applogger.Error("GenerateAddress.Encrypt err:%v", err)
|
|
return nil, err
|
|
}
|
|
applogger.Debug("AWS-KMS encrypted data:%v", encryptByte)
|
|
|
|
if err = r.data.s3C.Storage(encryptByte, r.data.aws.Set.Bucket, walletAddress); err != nil {
|
|
applogger.Error("GenerateAddress.storage err:%v", err)
|
|
return nil, err
|
|
}
|
|
|
|
if err = r.data.levelC.WriteDB(ctx, walletAddress, encryptByte); err != nil {
|
|
applogger.Error("Error writing wallet cache address:%v", err)
|
|
return []string{}, err
|
|
}
|
|
|
|
addressList = append(addressList, walletAddress)
|
|
}
|
|
|
|
return addressList, nil
|
|
}
|
|
|
|
/*
|
|
SignatureTrc20Grpc 钱包签名转账上链
|
|
1、Determine signature type
|
|
2、Obtain wallet private key
|
|
3、Decrypting private keys
|
|
4、signature
|
|
5、Upper chain
|
|
6、Return status and transaction hash
|
|
*/
|
|
func (r *walletRepo) SignatureTrc20Grpc(ctx context.Context, wallet *biz.Wallet) (bool, string, error) {
|
|
// 获取钱包私钥地址
|
|
private, err := r.data.levelC.ReadPrivateKeyByAddress(ctx, wallet.From)
|
|
if err != nil {
|
|
return false, "", err
|
|
}
|
|
|
|
// 解密私钥
|
|
pky, err := r.data.kmsC.Decrypt(private)
|
|
if err != nil {
|
|
return false, "", err
|
|
}
|
|
privateKey := string(pky)
|
|
|
|
// 发送者地址
|
|
from, err := address.Base58ToAddress(wallet.From)
|
|
if err != nil {
|
|
return false, "", err
|
|
}
|
|
|
|
// 接受者地址
|
|
to, err := address.Base58ToAddress(wallet.To)
|
|
if err != nil {
|
|
return false, "", err
|
|
}
|
|
|
|
var contract address.Address // 转账合约地址
|
|
var tx *api.TransactionExtention // 创建交易信息
|
|
|
|
switch wallet.TrcCheck {
|
|
case tron.Trx:
|
|
tx, err = r.data.grpcT.Transfer(from.String(), to.String(), tron.AmountInt(int(wallet.Amount)))
|
|
if err != nil {
|
|
applogger.Error("SignatureTrc20Grpc.Transfer err:%v", err)
|
|
return false, "", err
|
|
}
|
|
|
|
return r.SignTransactionAndBroadcastTransaction(ctx, tx, privateKey)
|
|
case tron.Trc20:
|
|
contract, err = address.Base58ToAddress(wallet.Contract)
|
|
if err != nil {
|
|
return false, "", err
|
|
}
|
|
|
|
tx, err = r.data.grpcT.TransferTrc20(from.String(), to.String(), contract.String(), tron.AmountBigInt(int(wallet.Amount)), tron.FeeLimitInt(int(wallet.FeeLimit)))
|
|
if err != nil {
|
|
applogger.Error("SignatureTrc20Grpc.TransferTrc20 err:%v", err)
|
|
return false, "", err
|
|
}
|
|
|
|
return r.SignTransactionAndBroadcastTransaction(ctx, tx, privateKey)
|
|
default:
|
|
return false, "", errors.New("Please enter the correct signature type.")
|
|
}
|
|
}
|
|
|
|
/*
|
|
WalletApprove
|
|
1、Determine signature type
|
|
2、Obtain wallet private key
|
|
3、Decrypting private keys
|
|
4、signature
|
|
5、Upper chain
|
|
6、Return status and transaction hash
|
|
*/
|
|
func (r *walletRepo) WalletApprove(ctx context.Context, wallet *biz.Wallet) (bool, []byte, error) {
|
|
tx, err := r.data.grpcT.TRC20Approve(wallet.From, wallet.To, wallet.Contract, big.NewInt(int64(wallet.Amount)), tron.FeeLimitInt(int(wallet.FeeLimit)))
|
|
if err != nil {
|
|
applogger.Error("TRC20Approve err:%v", err)
|
|
return false, []byte{}, err
|
|
}
|
|
|
|
jms, err := json.Marshal(tx)
|
|
if err != nil {
|
|
return false, []byte{}, err
|
|
}
|
|
|
|
return false, jms, nil
|
|
}
|
|
|
|
// GetAllAddress
|
|
//
|
|
// @Description:
|
|
// @receiver r
|
|
// @param ctx
|
|
// @return []string
|
|
// @return error
|
|
func (r *walletRepo) GetAllAddress(ctx context.Context) ([]string, error) {
|
|
listAddress, err := r.data.levelC.ReadWalletAddrList(ctx)
|
|
if err != nil {
|
|
return []string{}, err
|
|
}
|
|
return listAddress, nil
|
|
}
|
|
|
|
// GetAllAddressAndPrivateKey
|
|
//
|
|
// @Description:
|
|
// @receiver r
|
|
// @param ctx
|
|
// @return map[string][]byte
|
|
// @return error
|
|
func (r *walletRepo) GetAllAddressAndPrivateKey(ctx context.Context) (map[string][]byte, error) {
|
|
listAddress, err := r.data.levelC.ReadWalletAddressPrivateKeyList(ctx)
|
|
if err != nil {
|
|
return map[string][]byte{}, err
|
|
}
|
|
|
|
return listAddress, nil
|
|
}
|
|
|
|
// GetPrivateKeyByAddress
|
|
//
|
|
// @Description:
|
|
// @receiver r
|
|
// @param ctx
|
|
// @param address
|
|
// @return []byte
|
|
// @return error
|
|
func (r *walletRepo) GetPrivateKeyByAddress(ctx context.Context, address string) (string, error) {
|
|
private, err := r.data.levelC.ReadPrivateKeyByAddress(ctx, address)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
pky, err := r.data.kmsC.Decrypt(private)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
privateKey := string(pky)
|
|
|
|
return privateKey, nil
|
|
}
|
|
|
|
// DeleteAddress
|
|
//
|
|
// @Description:
|
|
// @receiver r
|
|
// @param ctx
|
|
// @return error
|
|
func (r *walletRepo) DeleteAddress(ctx context.Context) error {
|
|
if err := r.data.levelC.DeleteAllByKey(ctx); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// SignTransactionAndBroadcastTransaction
|
|
//
|
|
// @Description:
|
|
// @receiver r
|
|
// @param ctx
|
|
// @param tx
|
|
// @param privateKey
|
|
// @return bool
|
|
// @return string
|
|
// @return error
|
|
func (r *walletRepo) SignTransactionAndBroadcastTransaction(ctx context.Context, tx *api.TransactionExtention, privateKey string) (bool, string, error) {
|
|
signTx, err := sign.SignTransaction(tx.Transaction, privateKey)
|
|
if err != nil {
|
|
applogger.Error("SignTransactionAndBroadcastTransaction err:%v", err)
|
|
return false, "", err
|
|
}
|
|
|
|
if err := r.data.grpcT.BroadcastTransaction(signTx); err != nil {
|
|
return false, "", err
|
|
}
|
|
|
|
return true, tron.Encode(tx.GetTxid()), nil
|
|
}
|
|
|