246 lines
8.0 KiB
Go
246 lines
8.0 KiB
Go
package tron
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
|
|
"github.com/ethereum/go-ethereum/core/types"
|
|
"github.com/tech/sendico/gateway/chain/internal/service/gateway/driver"
|
|
"github.com/tech/sendico/gateway/chain/internal/service/gateway/driver/evm"
|
|
"github.com/tech/sendico/gateway/chain/internal/service/gateway/shared"
|
|
"github.com/tech/sendico/gateway/chain/storage/model"
|
|
"github.com/tech/sendico/pkg/merrors"
|
|
"github.com/tech/sendico/pkg/mlogger"
|
|
moneyv1 "github.com/tech/sendico/pkg/proto/common/money/v1"
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
// Driver implements Tron-specific behavior, including address conversion.
|
|
type Driver struct {
|
|
logger mlogger.Logger
|
|
}
|
|
|
|
func New(logger mlogger.Logger) *Driver {
|
|
return &Driver{logger: logger.Named("tron")}
|
|
}
|
|
|
|
func (d *Driver) Name() string {
|
|
return "tron"
|
|
}
|
|
|
|
func (d *Driver) FormatAddress(address string) (string, error) {
|
|
d.logger.Debug("Format address", zap.String("address", address))
|
|
normalized, err := normalizeAddress(address)
|
|
if err != nil {
|
|
d.logger.Warn("Format address failed", zap.String("address", address), zap.Error(err))
|
|
}
|
|
return normalized, err
|
|
}
|
|
|
|
func (d *Driver) NormalizeAddress(address string) (string, error) {
|
|
d.logger.Debug("Normalize address", zap.String("address", address))
|
|
normalized, err := normalizeAddress(address)
|
|
if err != nil {
|
|
d.logger.Warn("normalize address failed", zap.String("address", address), zap.Error(err))
|
|
}
|
|
return normalized, err
|
|
}
|
|
|
|
func (d *Driver) Balance(ctx context.Context, deps driver.Deps, network shared.Network, wallet *model.ManagedWallet) (*moneyv1.Money, error) {
|
|
if wallet == nil {
|
|
return nil, merrors.InvalidArgument("wallet is required")
|
|
}
|
|
d.logger.Debug("Balance request", zap.String("wallet_ref", wallet.WalletRef), zap.String("network", network.Name))
|
|
rpcAddr, err := rpcAddress(wallet.DepositAddress)
|
|
if err != nil {
|
|
d.logger.Warn("Balance address conversion failed", zap.Error(err),
|
|
zap.String("wallet_ref", wallet.WalletRef),
|
|
zap.String("address", wallet.DepositAddress),
|
|
)
|
|
return nil, err
|
|
}
|
|
driverDeps := deps
|
|
driverDeps.Logger = d.logger
|
|
result, err := evm.Balance(ctx, driverDeps, network, wallet, rpcAddr)
|
|
if err != nil {
|
|
d.logger.Warn("Balance failed", zap.Error(err),
|
|
zap.String("wallet_ref", wallet.WalletRef),
|
|
zap.String("network", network.Name),
|
|
)
|
|
} else if result != nil {
|
|
d.logger.Debug("balance result",
|
|
zap.String("wallet_ref", wallet.WalletRef),
|
|
zap.String("network", network.Name),
|
|
zap.String("amount", result.Amount),
|
|
zap.String("currency", result.Currency),
|
|
)
|
|
}
|
|
return result, err
|
|
}
|
|
|
|
func (d *Driver) NativeBalance(ctx context.Context, deps driver.Deps, network shared.Network, wallet *model.ManagedWallet) (*moneyv1.Money, error) {
|
|
if wallet == nil {
|
|
return nil, merrors.InvalidArgument("wallet is required")
|
|
}
|
|
d.logger.Debug("Native balance request", zap.String("wallet_ref", wallet.WalletRef), zap.String("network", network.Name))
|
|
rpcAddr, err := rpcAddress(wallet.DepositAddress)
|
|
if err != nil {
|
|
d.logger.Warn("Native balance address conversion failed", zap.Error(err),
|
|
zap.String("wallet_ref", wallet.WalletRef),
|
|
zap.String("address", wallet.DepositAddress),
|
|
)
|
|
return nil, err
|
|
}
|
|
driverDeps := deps
|
|
driverDeps.Logger = d.logger
|
|
result, err := evm.NativeBalance(ctx, driverDeps, network, wallet, rpcAddr)
|
|
if err != nil {
|
|
d.logger.Warn("Native balance failed", zap.Error(err),
|
|
zap.String("wallet_ref", wallet.WalletRef),
|
|
zap.String("network", network.Name),
|
|
)
|
|
} else if result != nil {
|
|
d.logger.Debug("native balance result",
|
|
zap.String("wallet_ref", wallet.WalletRef),
|
|
zap.String("network", network.Name),
|
|
zap.String("amount", result.Amount),
|
|
zap.String("currency", result.Currency),
|
|
)
|
|
}
|
|
return result, err
|
|
}
|
|
|
|
func (d *Driver) EstimateFee(ctx context.Context, deps driver.Deps, network shared.Network, wallet *model.ManagedWallet, destination string, amount *moneyv1.Money) (*moneyv1.Money, error) {
|
|
if wallet == nil {
|
|
return nil, merrors.InvalidArgument("wallet is required")
|
|
}
|
|
if amount == nil {
|
|
return nil, merrors.InvalidArgument("amount is required")
|
|
}
|
|
d.logger.Debug("Estimate fee request",
|
|
zap.String("wallet_ref", wallet.WalletRef),
|
|
zap.String("network", network.Name),
|
|
zap.String("destination", destination),
|
|
)
|
|
rpcFrom, err := rpcAddress(wallet.DepositAddress)
|
|
if err != nil {
|
|
d.logger.Warn("Estimate fee address conversion failed", zap.Error(err),
|
|
zap.String("wallet_ref", wallet.WalletRef),
|
|
zap.String("address", wallet.DepositAddress),
|
|
)
|
|
return nil, err
|
|
}
|
|
rpcTo, err := rpcAddress(destination)
|
|
if err != nil {
|
|
d.logger.Warn("Estimate fee destination conversion failed", zap.Error(err),
|
|
zap.String("wallet_ref", wallet.WalletRef),
|
|
zap.String("destination", destination),
|
|
)
|
|
return nil, err
|
|
}
|
|
if rpcFrom == rpcTo {
|
|
return &moneyv1.Money{
|
|
Currency: nativeCurrency(network),
|
|
Amount: "0",
|
|
}, nil
|
|
}
|
|
driverDeps := deps
|
|
driverDeps.Logger = d.logger
|
|
result, err := evm.EstimateFee(ctx, driverDeps, network, wallet, rpcFrom, rpcTo, amount)
|
|
if err != nil {
|
|
d.logger.Warn("Estimate fee failed", zap.Error(err),
|
|
zap.String("wallet_ref", wallet.WalletRef),
|
|
zap.String("network", network.Name),
|
|
zap.String("from_address", wallet.DepositAddress),
|
|
zap.String("from_rpc", rpcFrom),
|
|
zap.String("to_address", destination),
|
|
zap.String("to_rpc", rpcTo),
|
|
)
|
|
} else if result != nil {
|
|
d.logger.Debug("Estimate fee result",
|
|
zap.String("wallet_ref", wallet.WalletRef),
|
|
zap.String("network", network.Name),
|
|
zap.String("amount", result.Amount),
|
|
zap.String("currency", result.Currency),
|
|
)
|
|
}
|
|
return result, err
|
|
}
|
|
|
|
func (d *Driver) SubmitTransfer(ctx context.Context, deps driver.Deps, network shared.Network, transfer *model.Transfer, source *model.ManagedWallet, destination string) (string, error) {
|
|
if source == nil {
|
|
return "", merrors.InvalidArgument("source wallet is required")
|
|
}
|
|
d.logger.Debug("Submit transfer request",
|
|
zap.String("transfer_ref", transfer.TransferRef),
|
|
zap.String("network", network.Name),
|
|
zap.String("destination", destination),
|
|
)
|
|
rpcFrom, err := rpcAddress(source.DepositAddress)
|
|
if err != nil {
|
|
d.logger.Warn("Submit transfer address conversion failed", zap.Error(err),
|
|
zap.String("wallet_ref", source.WalletRef),
|
|
zap.String("address", source.DepositAddress),
|
|
)
|
|
return "", err
|
|
}
|
|
rpcTo, err := rpcAddress(destination)
|
|
if err != nil {
|
|
d.logger.Warn("Submit transfer destination conversion failed", zap.Error(err),
|
|
zap.String("transfer_ref", transfer.TransferRef),
|
|
zap.String("destination", destination),
|
|
)
|
|
return "", err
|
|
}
|
|
driverDeps := deps
|
|
driverDeps.Logger = d.logger
|
|
txHash, err := evm.SubmitTransfer(ctx, driverDeps, network, transfer, source, rpcFrom, rpcTo)
|
|
if err != nil {
|
|
d.logger.Warn("submit transfer failed", zap.Error(err),
|
|
zap.String("transfer_ref", transfer.TransferRef),
|
|
zap.String("network", network.Name),
|
|
)
|
|
} else {
|
|
d.logger.Debug("Submit transfer result",
|
|
zap.String("transfer_ref", transfer.TransferRef),
|
|
zap.String("network", network.Name),
|
|
zap.String("tx_hash", txHash),
|
|
)
|
|
}
|
|
return txHash, err
|
|
}
|
|
|
|
func (d *Driver) AwaitConfirmation(ctx context.Context, deps driver.Deps, network shared.Network, txHash string) (*types.Receipt, error) {
|
|
d.logger.Debug("Awaiting confirmation",
|
|
zap.String("tx_hash", txHash),
|
|
zap.String("network", network.Name),
|
|
)
|
|
driverDeps := deps
|
|
driverDeps.Logger = d.logger
|
|
receipt, err := evm.AwaitConfirmation(ctx, driverDeps, network, txHash)
|
|
if err != nil {
|
|
d.logger.Warn("Awaiting of confirmation failed", zap.Error(err),
|
|
zap.String("tx_hash", txHash),
|
|
zap.String("network", network.Name),
|
|
)
|
|
} else if receipt != nil {
|
|
d.logger.Debug("Await confirmation result",
|
|
zap.String("tx_hash", txHash),
|
|
zap.String("network", network.Name),
|
|
zap.Uint64("block_number", receipt.BlockNumber.Uint64()),
|
|
zap.Uint64("status", receipt.Status),
|
|
)
|
|
}
|
|
return receipt, err
|
|
}
|
|
|
|
func nativeCurrency(network shared.Network) string {
|
|
currency := strings.ToUpper(strings.TrimSpace(network.NativeToken))
|
|
if currency == "" {
|
|
currency = strings.ToUpper(strings.TrimSpace(network.Name))
|
|
}
|
|
return currency
|
|
}
|
|
|
|
var _ driver.Driver = (*Driver)(nil)
|