Skip to content

Commit

Permalink
Merge pull request #176 from mysteriumnetwork/swapping-possible
Browse files Browse the repository at this point in the history
Add all methods required to do simple swapping
  • Loading branch information
tomasmik authored Jan 28, 2022
2 parents 89197ee + 71b397b commit 22e569d
Show file tree
Hide file tree
Showing 4 changed files with 299 additions and 0 deletions.
8 changes: 8 additions & 0 deletions client/bc.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,14 @@ type BC interface {
TopperupperApprovedAddress(topperupperAddress common.Address, forAddress common.Address) (*ApprovedAddress, error)
TopperupperNativeLimits(topperupperAddress common.Address, forAddress common.Address) (*CurrentLimits, error)
TopperupperTokenLimits(topperupperAddress common.Address, forAddress common.Address) (*CurrentLimits, error)

MystTokenApprove(req MystApproveReq) (*types.Transaction, error)
MystAllowance(mystTokenAddress, holder, spender common.Address) (*big.Int, error)
UniswapV3ExactInputSingle(req UniswapExactInputSingleReq) (*types.Transaction, error)
UniswapV3TokenPair(poolAddress common.Address) (*SwapTokenPair, error)
UniswapV3PoolFee(poolAddress common.Address) (*big.Int, error)
WMaticBalance(holder, wmaticAddress common.Address) (*big.Int, error)
WMaticWithdraw(req WMaticWithdrawReq) (*types.Transaction, error)
}

// EtherClient interface implements all methods required for a EtherClient to work
Expand Down
207 changes: 207 additions & 0 deletions client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import (
"github.com/mysteriumnetwork/payments/bindings"
"github.com/mysteriumnetwork/payments/bindings/rewarder"
"github.com/mysteriumnetwork/payments/bindings/topperupper"
"github.com/mysteriumnetwork/payments/bindings/uniswapv3"
"github.com/mysteriumnetwork/payments/crypto"
"github.com/pkg/errors"
"github.com/rs/zerolog/log"
Expand Down Expand Up @@ -1650,3 +1651,209 @@ func (bc *Blockchain) TopperupperTopupToken(req TopperupperTopupTokenReq) (*type
req.Amount,
)
}

type MystApproveReq struct {
WriteRequest
MystAddress common.Address
Spender common.Address
Amount *big.Int
}

func (bc *Blockchain) MystTokenApprove(req MystApproveReq) (*types.Transaction, error) {
txer, err := bindings.NewMystTokenTransactor(req.MystAddress, bc.ethClient.Client())
if err != nil {
return nil, err
}

ctx, cancel := context.WithTimeout(context.Background(), bc.bcTimeout)
defer cancel()

if req.Nonce == nil {
nonce, err := bc.getNonce(req.Identity)
if err != nil {
return nil, errors.Wrap(err, "could not get nonce")
}
req.Nonce = new(big.Int).SetUint64(nonce)
}

return txer.Approve(&bind.TransactOpts{
From: req.Identity,
Signer: req.Signer,
Context: ctx,
GasLimit: req.GasLimit,
GasPrice: req.GasPrice,
Nonce: req.Nonce,
}, req.Spender, req.Amount)
}

func (bc *Blockchain) MystAllowance(mystTokenAddress, holder, spender common.Address) (*big.Int, error) {
caller, err := bindings.NewMystTokenCaller(mystTokenAddress, bc.ethClient.Client())
if err != nil {
return nil, err
}

ctx, cancel := context.WithTimeout(context.Background(), bc.bcTimeout)
defer cancel()

return caller.Allowance(&bind.CallOpts{
Context: ctx,
}, holder, spender)
}

type UniswapExactInputSingleReq struct {
WriteRequest
SwapRouterAddress common.Address

TokenIn common.Address
TokenOut common.Address
Fee *big.Int

Recipient common.Address
DeadlineSeconds uint64

AmountIn *big.Int
AmountOutMinimum *big.Int
}

func (bc *Blockchain) UniswapV3ExactInputSingle(req UniswapExactInputSingleReq) (*types.Transaction, error) {
txer, err := uniswapv3.NewSwapRouterTransactor(req.SwapRouterAddress, bc.ethClient.Client())
if err != nil {
return nil, err
}

ctx, cancel := context.WithTimeout(context.Background(), bc.bcTimeout)
defer cancel()

if req.Nonce == nil {
nonce, err := bc.getNonce(req.Identity)
if err != nil {
return nil, errors.Wrap(err, "could not get nonce")
}
req.Nonce = new(big.Int).SetUint64(nonce)
}

b, err := bc.ethClient.Client().BlockByNumber(ctx, nil)
if err != nil {
return nil, err
}

return txer.ExactInputSingle(&bind.TransactOpts{
From: req.Identity,
Signer: req.Signer,
Context: ctx,
GasLimit: req.GasLimit,
GasPrice: req.GasPrice,
Nonce: req.Nonce,
}, uniswapv3.ISwapRouterExactInputSingleParams{
TokenIn: req.TokenIn,
TokenOut: req.TokenOut,
Fee: req.Fee,

Recipient: req.Recipient,
Deadline: big.NewInt(0).SetUint64(b.Time() + req.DeadlineSeconds),

AmountIn: req.AmountIn,
AmountOutMinimum: req.AmountOutMinimum,

SqrtPriceLimitX96: big.NewInt(0), // We can mostly ignore it for our purposes.
})
}

type SwapTokenPair struct {
Token0 common.Address
Token1 common.Address
}

func (bc *Blockchain) UniswapV3TokenPair(poolAddress common.Address) (*SwapTokenPair, error) {
caller, err := uniswapv3.NewPoolCaller(poolAddress, bc.ethClient.Client())
if err != nil {
return nil, err
}

ctx, cancel := context.WithTimeout(context.Background(), bc.bcTimeout)
defer cancel()

res := &SwapTokenPair{}

res.Token0, err = caller.Token0(&bind.CallOpts{
Context: ctx,
})
if err != nil {
return nil, err
}

res.Token1, err = caller.Token1(&bind.CallOpts{
Context: ctx,
})
if err != nil {
return nil, err
}

return res, nil
}

func (bc *Blockchain) UniswapV3PoolFee(poolAddress common.Address) (*big.Int, error) {
caller, err := uniswapv3.NewPoolCaller(poolAddress, bc.ethClient.Client())
if err != nil {
return nil, err
}

ctx, cancel := context.WithTimeout(context.Background(), bc.bcTimeout)
defer cancel()

return caller.Fee(&bind.CallOpts{
Context: ctx,
})
}

func (bc *Blockchain) WMaticBalance(holder, wmaticAddress common.Address) (*big.Int, error) {
caller, err := uniswapv3.NewWmaticCaller(wmaticAddress, bc.ethClient.Client())
if err != nil {
return nil, err
}

ctx, cancel := context.WithTimeout(context.Background(), bc.bcTimeout)
defer cancel()

return caller.BalanceOf(&bind.CallOpts{
Context: ctx,
}, holder)
}

type WMaticWithdrawReq struct {
WriteRequest
WMaticAddress common.Address

// Amount describes how much should be withdrawn.
// If `nil` all balance is withdrawn.
Amount *big.Int
}

func (bc *Blockchain) WMaticWithdraw(req WMaticWithdrawReq) (*types.Transaction, error) {
caller, err := uniswapv3.NewWmaticTransactor(req.WMaticAddress, bc.ethClient.Client())
if err != nil {
return nil, err
}

ctx, cancel := context.WithTimeout(context.Background(), bc.bcTimeout)
defer cancel()

amount := req.Amount
if amount == nil {
all, err := bc.WMaticBalance(req.Identity, req.WMaticAddress)
if err != nil {
return nil, fmt.Errorf("tried to pull wmatic balance, but failed: %w", err)
}

amount = all
}

return caller.Withdraw(&bind.TransactOpts{
From: req.Identity,
Signer: req.Signer,
Context: ctx,
GasLimit: req.GasLimit,
GasPrice: req.GasPrice,
Nonce: req.Nonce,
}, amount)
}
56 changes: 56 additions & 0 deletions client/multichain_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -602,3 +602,59 @@ func (mbc *MultichainBlockchainClient) TopperupperTokenLimits(chainID int64, top
}
return bc.TopperupperTokenLimits(topperupperAddress, forAddress)
}

func (mbc *MultichainBlockchainClient) MystTokenApprove(chainID int64, req MystApproveReq) (*types.Transaction, error) {
bc, err := mbc.getClientByChain(chainID)
if err != nil {
return nil, err
}
return bc.MystTokenApprove(req)
}

func (mbc *MultichainBlockchainClient) MystAllowance(chainID int64, mystTokenAddress, holder, spender common.Address) (*big.Int, error) {
bc, err := mbc.getClientByChain(chainID)
if err != nil {
return nil, err
}
return bc.MystAllowance(mystTokenAddress, holder, spender)
}

func (mbc *MultichainBlockchainClient) UniswapV3ExactInputSingle(chainID int64, req UniswapExactInputSingleReq) (*types.Transaction, error) {
bc, err := mbc.getClientByChain(chainID)
if err != nil {
return nil, err
}
return bc.UniswapV3ExactInputSingle(req)
}

func (mbc *MultichainBlockchainClient) UniswapV3TokenPair(chainID int64, poolAddress common.Address) (*SwapTokenPair, error) {
bc, err := mbc.getClientByChain(chainID)
if err != nil {
return nil, err
}
return bc.UniswapV3TokenPair(poolAddress)
}

func (mbc *MultichainBlockchainClient) UniswapV3PoolFee(chainID int64, poolAddress common.Address) (*big.Int, error) {
bc, err := mbc.getClientByChain(chainID)
if err != nil {
return nil, err
}
return bc.UniswapV3PoolFee(poolAddress)
}

func (mbc *MultichainBlockchainClient) WMaticBalance(chainID int64, holder, wmaticAddress common.Address) (*big.Int, error) {
bc, err := mbc.getClientByChain(chainID)
if err != nil {
return nil, err
}
return bc.WMaticBalance(holder, wmaticAddress)
}

func (mbc *MultichainBlockchainClient) WMaticWithdraw(chainID int64, req WMaticWithdrawReq) (*types.Transaction, error) {
bc, err := mbc.getClientByChain(chainID)
if err != nil {
return nil, err
}
return bc.WMaticWithdraw(req)
}
28 changes: 28 additions & 0 deletions client/with_dry_runs.go
Original file line number Diff line number Diff line change
Expand Up @@ -422,3 +422,31 @@ func (cwdr *WithDryRuns) PendingNonceAt(account common.Address) (uint64, error)
func (cwdr *WithDryRuns) NonceAt(account common.Address, blockNum *big.Int) (uint64, error) {
return cwdr.bc.NonceAt(account, blockNum)
}

func (cwdr *WithDryRuns) MystTokenApprove(req MystApproveReq) (*types.Transaction, error) {
return cwdr.bc.MystTokenApprove(req)
}

func (cwdr *WithDryRuns) MystAllowance(mystTokenAddress, holder, spender common.Address) (*big.Int, error) {
return cwdr.bc.MystAllowance(mystTokenAddress, holder, spender)
}

func (cwdr *WithDryRuns) UniswapV3ExactInputSingle(req UniswapExactInputSingleReq) (*types.Transaction, error) {
return cwdr.bc.UniswapV3ExactInputSingle(req)
}

func (cwdr *WithDryRuns) UniswapV3TokenPair(poolAddress common.Address) (*SwapTokenPair, error) {
return cwdr.bc.UniswapV3TokenPair(poolAddress)
}

func (cwdr *WithDryRuns) UniswapV3PoolFee(poolAddress common.Address) (*big.Int, error) {
return cwdr.bc.UniswapV3PoolFee(poolAddress)
}

func (cwdr *WithDryRuns) WMaticBalance(holder, wmaticAddress common.Address) (*big.Int, error) {
return cwdr.bc.WMaticBalance(holder, wmaticAddress)
}

func (cwdr *WithDryRuns) WMaticWithdraw(req WMaticWithdrawReq) (*types.Transaction, error) {
return cwdr.bc.WMaticWithdraw(req)
}

0 comments on commit 22e569d

Please sign in to comment.