github.com/ethersphere/bee/v2@v2.2.0/pkg/settlement/swap/erc20/erc20.go (about)

     1  // Copyright 2021 The Swarm Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package erc20
     6  
     7  import (
     8  	"context"
     9  	"errors"
    10  	"math/big"
    11  
    12  	"github.com/ethereum/go-ethereum/accounts/abi"
    13  	"github.com/ethereum/go-ethereum/common"
    14  	"github.com/ethersphere/bee/v2/pkg/sctx"
    15  	"github.com/ethersphere/bee/v2/pkg/transaction"
    16  	"github.com/ethersphere/bee/v2/pkg/util/abiutil"
    17  	"github.com/ethersphere/go-sw3-abi/sw3abi"
    18  )
    19  
    20  var (
    21  	erc20ABI     = abiutil.MustParseABI(sw3abi.ERC20ABIv0_6_5)
    22  	errDecodeABI = errors.New("could not decode abi data")
    23  )
    24  
    25  type Service interface {
    26  	BalanceOf(ctx context.Context, address common.Address) (*big.Int, error)
    27  	Transfer(ctx context.Context, address common.Address, value *big.Int) (common.Hash, error)
    28  }
    29  
    30  type erc20Service struct {
    31  	transactionService transaction.Service
    32  	address            common.Address
    33  }
    34  
    35  func New(transactionService transaction.Service, address common.Address) Service {
    36  	return &erc20Service{
    37  		transactionService: transactionService,
    38  		address:            address,
    39  	}
    40  }
    41  
    42  func (c *erc20Service) BalanceOf(ctx context.Context, address common.Address) (*big.Int, error) {
    43  	callData, err := erc20ABI.Pack("balanceOf", address)
    44  	if err != nil {
    45  		return nil, err
    46  	}
    47  
    48  	output, err := c.transactionService.Call(ctx, &transaction.TxRequest{
    49  		To:   &c.address,
    50  		Data: callData,
    51  	})
    52  	if err != nil {
    53  		return nil, err
    54  	}
    55  
    56  	results, err := erc20ABI.Unpack("balanceOf", output)
    57  	if err != nil {
    58  		return nil, err
    59  	}
    60  
    61  	if len(results) != 1 {
    62  		return nil, errDecodeABI
    63  	}
    64  
    65  	balance, ok := abi.ConvertType(results[0], new(big.Int)).(*big.Int)
    66  	if !ok || balance == nil {
    67  		return nil, errDecodeABI
    68  	}
    69  	return balance, nil
    70  }
    71  
    72  func (c *erc20Service) Transfer(ctx context.Context, address common.Address, value *big.Int) (common.Hash, error) {
    73  	callData, err := erc20ABI.Pack("transfer", address, value)
    74  	if err != nil {
    75  		return common.Hash{}, err
    76  	}
    77  
    78  	request := &transaction.TxRequest{
    79  		To:          &c.address,
    80  		Data:        callData,
    81  		GasPrice:    sctx.GetGasPrice(ctx),
    82  		GasLimit:    90000,
    83  		Value:       big.NewInt(0),
    84  		Description: "token transfer",
    85  	}
    86  
    87  	txHash, err := c.transactionService.Send(ctx, request, transaction.DefaultTipBoostPercent)
    88  	if err != nil {
    89  		return common.Hash{}, err
    90  	}
    91  
    92  	return txHash, nil
    93  }