This commit is contained in:
Laurent Le Houerou 2021-11-09 08:11:05 +04:00
parent c3908948ec
commit b927854098
7 changed files with 48 additions and 38 deletions

View File

@ -34,8 +34,8 @@ func NewWBNB(address string, client evm.Client) (*WBNB, error) {
}, nil }, nil
} }
func (w *WBNB) UnwrapWBNB(ctx context.Context, amount decimal.Decimal) (evm.Transaction, error) { func (w *WBNB) UnwrapWBNB(ctx context.Context, amount decimal.Decimal, opts ...evm.ExecutionOption) (evm.Transaction, error) {
return w.client.Execute(ctx, func(ctx context.Context, opts *evm.TransactOpts) (*types.Transaction, error) { return w.client.Execute(ctx, func(ctx context.Context, opts *evm.TransactOpts) (*types.Transaction, error) {
return w.contract.Withdraw(opts.TransactOpts, w.ValueToBigInt(amount)) return w.contract.Withdraw(opts.TransactOpts, w.ValueToBigInt(amount))
}) }, opts...)
} }

View File

@ -24,22 +24,21 @@ type Client interface {
PublicAddressAsHexString() string PublicAddressAsHexString() string
PendingNonce(context.Context) (uint64, error) PendingNonce(context.Context) (uint64, error)
NewTransactor() (*bind.TransactOpts, error) NewTransactor() (*bind.TransactOpts, error)
Execute(context.Context, func(context.Context, *TransactOpts) (*types.Transaction, error)) (Transaction, error) Execute(context.Context, func(context.Context, *TransactOpts) (*types.Transaction, error), ...ExecutionOption) (Transaction, error)
ExecuteAndWait(context.Context, func(context.Context) (Transaction, error)) error ExecuteAndWait(context.Context, func(context.Context) (Transaction, error)) error
NativeTokenBalance(context.Context) (decimal.Decimal, error) NativeTokenBalance(context.Context) (decimal.Decimal, error)
CurrentBlockNumber(context.Context) (uint64, error) CurrentBlockNumber(context.Context) (uint64, error)
CurrentBlock(context.Context) (*types.Block, error) CurrentBlock(context.Context) (*types.Block, error)
SetPendingTransactionCheckPeriod(duration time.Duration)
TransactionByHash(context.Context, common.Hash) (*types.Transaction, bool, error) TransactionByHash(context.Context, common.Hash) (*types.Transaction, bool, error)
TokenService() TokenService TokenService() TokenService
} }
type ClientOption func(c Client) (Client, error) type ClientOption func(c *client) (*client, error)
func WithPendingTransactionWaitResolution(duration time.Duration) ClientOption { func WithPendingTransactionWaitResolution(duration time.Duration) ClientOption {
return func(c Client) (Client, error) { return func(c *client) (*client, error) {
c.SetPendingTransactionCheckPeriod(duration) c.pendingTransactionCheckPeriod = duration
return c, nil return c, nil
} }
} }
@ -87,24 +86,19 @@ func NewClient(ctx context.Context, rpcurl string, privatekey string, tm TokenMa
return nil, errors.Wrap(err, "retrieving chain id") return nil, errors.Wrap(err, "retrieving chain id")
} }
ires := Client(res)
for _, option := range options { for _, option := range options {
ires, err = option(ires) res, err = option(res)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "applying option") return nil, errors.Wrap(err, "applying option")
} }
} }
return ires, nil return res, nil
} }
func (c *client) PublicAddress() common.Address { func (c *client) PublicAddress() common.Address {
return c.fromAddress return c.fromAddress
} }
func (c *client) SetPendingTransactionCheckPeriod(period time.Duration) {
c.pendingTransactionCheckPeriod = period
}
func (c *client) PendingNonce(ctx context.Context) (uint64, error) { func (c *client) PendingNonce(ctx context.Context) (uint64, error) {
return c.PendingNonceAt(ctx, c.PublicAddress()) return c.PendingNonceAt(ctx, c.PublicAddress())
} }
@ -117,7 +111,7 @@ func (c *client) NewTransactor() (*bind.TransactOpts, error) {
return bind.NewKeyedTransactorWithChainID(c.privateKey, c.chainId) return bind.NewKeyedTransactorWithChainID(c.privateKey, c.chainId)
} }
func (c *client) Execute(ctx context.Context, action func(context.Context, *TransactOpts) (*types.Transaction, error)) (Transaction, error) { func (c *client) Execute(ctx context.Context, action func(context.Context, *TransactOpts) (*types.Transaction, error), opts ...ExecutionOption) (Transaction, error) {
c.transactionlock.Lock() c.transactionlock.Lock()
defer c.transactionlock.Unlock() defer c.transactionlock.Unlock()
localctx, cancel := context.WithTimeout(ctx, c.defaultTimeout) localctx, cancel := context.WithTimeout(ctx, c.defaultTimeout)

View File

@ -50,13 +50,13 @@ func (m *MasterChef) PendingCakeOfAddress(pid int64, address common.Address) (de
return m.cake.ValueFromBigInt(raw), nil return m.cake.ValueFromBigInt(raw), nil
} }
func (m *MasterChef) EnterStaking(ctx context.Context, amount decimal.Decimal) (evm.Transaction, error) { func (m *MasterChef) EnterStaking(ctx context.Context, amount decimal.Decimal, opts ...evm.ExecutionOption) (evm.Transaction, error) {
return m.client.Execute(ctx, func(ctx context.Context, opts *evm.TransactOpts) (*types.Transaction, error) { return m.client.Execute(ctx, func(ctx context.Context, opts *evm.TransactOpts) (*types.Transaction, error) {
return m.contract.EnterStaking(opts.TransactOpts, m.cake.ValueToBigInt(amount)) return m.contract.EnterStaking(opts.TransactOpts, m.cake.ValueToBigInt(amount))
}) }, opts...)
} }
func (m *MasterChef) CompoundAndAddCakeBalance(ctx context.Context) (evm.Transaction, error) { func (m *MasterChef) CompoundAndAddCakeBalance(ctx context.Context, opts ...evm.ExecutionOption) (evm.Transaction, error) {
pending, err := m.PendingCake(0) pending, err := m.PendingCake(0)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "getting pending cake reward") return nil, errors.Wrap(err, "getting pending cake reward")
@ -65,5 +65,5 @@ func (m *MasterChef) CompoundAndAddCakeBalance(ctx context.Context) (evm.Transac
if err != nil { if err != nil {
return nil, errors.Wrap(err, "getting cake balance") return nil, errors.Wrap(err, "getting cake balance")
} }
return m.EnterStaking(ctx, pending.Add(balance)) return m.EnterStaking(ctx, pending.Add(balance), opts...)
} }

View File

@ -51,25 +51,22 @@ func (m *NftMarket) GetAskPriceForToken(collection common.Address, tokenid int)
return m.wbnb.ValueFromBigInt(res.AskInfo[0].Price), nil return m.wbnb.ValueFromBigInt(res.AskInfo[0].Price), nil
} }
func (m *NftMarket) BuyTokenWithBNB(ctx context.Context, collection common.Address, tokenid int, price decimal.Decimal, gas decimal.Decimal) (evm.Transaction, error) { func (m *NftMarket) BuyTokenWithBNB(ctx context.Context, collection common.Address, tokenid int, opts ...evm.ExecutionOption) (evm.Transaction, error) {
return m.client.Execute(ctx, func(ctx context.Context, opts *evm.TransactOpts) (*types.Transaction, error) { return m.client.Execute(ctx, func(ctx context.Context, opts *evm.TransactOpts) (*types.Transaction, error) {
opts.SetValue(price)
opts.SetGasPrice(gas)
opts.SetGasLimit(1000000) opts.SetGasLimit(1000000)
return m.contract.BuyTokenUsingBNB(opts.TransactOpts, collection, big.NewInt(int64(tokenid))) return m.contract.BuyTokenUsingBNB(opts.TransactOpts, collection, big.NewInt(int64(tokenid)))
}) }, opts...)
} }
func (m *NftMarket) BuyTokenWithWBNB(ctx context.Context, collection common.Address, tokenid int, price decimal.Decimal, gas decimal.Decimal) (evm.Transaction, error) { func (m *NftMarket) BuyTokenWithWBNB(ctx context.Context, collection common.Address, tokenid int, price decimal.Decimal, opts ...evm.ExecutionOption) (evm.Transaction, error) {
return m.client.Execute(ctx, func(ctx context.Context, opts *evm.TransactOpts) (*types.Transaction, error) { return m.client.Execute(ctx, func(ctx context.Context, opts *evm.TransactOpts) (*types.Transaction, error) {
opts.SetGasPrice(gas)
opts.SetGasLimit(1000000) opts.SetGasLimit(1000000)
return m.contract.BuyTokenUsingWBNB(opts.TransactOpts, collection, big.NewInt(int64(tokenid)), m.wbnb.ValueToBigInt(price)) return m.contract.BuyTokenUsingWBNB(opts.TransactOpts, collection, big.NewInt(int64(tokenid)), m.wbnb.ValueToBigInt(price))
}) }, opts...)
} }
func (m *NftMarket) CreateAskOrder(ctx context.Context, collection common.Address, tokenid int, price decimal.Decimal) (evm.Transaction, error) { func (m *NftMarket) CreateAskOrder(ctx context.Context, collection common.Address, tokenid int, price decimal.Decimal, opts ...evm.ExecutionOption) (evm.Transaction, error) {
return m.client.Execute(ctx, func(ctx context.Context, opts *evm.TransactOpts) (*types.Transaction, error) { return m.client.Execute(ctx, func(ctx context.Context, opts *evm.TransactOpts) (*types.Transaction, error) {
return m.contract.CreateAskOrder(opts.TransactOpts, collection, big.NewInt(int64(tokenid)), m.wbnb.ValueToBigInt(price)) return m.contract.CreateAskOrder(opts.TransactOpts, collection, big.NewInt(int64(tokenid)), m.wbnb.ValueToBigInt(price))
}) }, opts...)
} }

View File

@ -21,8 +21,8 @@ type Token interface {
BalanceOf(common.Address) (decimal.Decimal, error) BalanceOf(common.Address) (decimal.Decimal, error)
Balance() (decimal.Decimal, error) Balance() (decimal.Decimal, error)
Allowance(owner common.Address, spender common.Address) (decimal.Decimal, error) Allowance(owner common.Address, spender common.Address) (decimal.Decimal, error)
Approve(ctx context.Context, spender common.Address, value decimal.Decimal) (Transaction, error) Approve(ctx context.Context, spender common.Address, value decimal.Decimal, opts ...ExecutionOption) (Transaction, error)
Transfer(ctx context.Context, to common.Address, value decimal.Decimal) (Transaction, error) Transfer(ctx context.Context, to common.Address, value decimal.Decimal, opts ...ExecutionOption) (Transaction, error)
ValueToBigInt(value decimal.Decimal) *big.Int ValueToBigInt(value decimal.Decimal) *big.Int
ValueFromBigInt(value *big.Int) decimal.Decimal ValueFromBigInt(value *big.Int) decimal.Decimal
@ -89,16 +89,16 @@ func (t *baseToken) Allowance(owner common.Address, spender common.Address) (dec
return t.ValueFromBigInt(a), nil return t.ValueFromBigInt(a), nil
} }
func (t *baseToken) Approve(ctx context.Context, spender common.Address, value decimal.Decimal) (Transaction, error) { func (t *baseToken) Approve(ctx context.Context, spender common.Address, value decimal.Decimal, opts ...ExecutionOption) (Transaction, error) {
return t.client.Execute(ctx, func(ctx context.Context, options *TransactOpts) (*types.Transaction, error) { return t.client.Execute(ctx, func(ctx context.Context, options *TransactOpts) (*types.Transaction, error) {
return t.contract.Approve(options.TransactOpts, spender, t.ValueToBigInt(value)) return t.contract.Approve(options.TransactOpts, spender, t.ValueToBigInt(value))
}) }, opts...)
} }
func (t *baseToken) Transfer(ctx context.Context, to common.Address, value decimal.Decimal) (Transaction, error) { func (t *baseToken) Transfer(ctx context.Context, to common.Address, value decimal.Decimal, opts ...ExecutionOption) (Transaction, error) {
return t.client.Execute(ctx, func(ctx context.Context, options *TransactOpts) (*types.Transaction, error) { return t.client.Execute(ctx, func(ctx context.Context, options *TransactOpts) (*types.Transaction, error) {
return t.contract.Transfer(options.TransactOpts, to, t.ValueToBigInt(value)) return t.contract.Transfer(options.TransactOpts, to, t.ValueToBigInt(value))
}) }, opts...)
} }
func (t *baseToken) Address() common.Address { func (t *baseToken) Address() common.Address {

View File

@ -2,6 +2,7 @@ package evm
import ( import (
"context" "context"
"github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/shopspring/decimal" "github.com/shopspring/decimal"
) )
@ -37,3 +38,21 @@ func (o *TransactOpts) SetGasPrice(gasprice decimal.Decimal) *TransactOpts {
o.GasPrice = gasprice.Shift(9).BigInt() o.GasPrice = gasprice.Shift(9).BigInt()
return o return o
} }
type ExecutionOption func(*TransactOpts) *TransactOpts
func WithGasPrice(gasprice decimal.Decimal) ExecutionOption {
return func(opts *TransactOpts) *TransactOpts {
return opts.SetGasPrice(gasprice)
}
}
func WithGasLimit(gaslimit uint64) ExecutionOption {
return func(opts *TransactOpts) *TransactOpts {
return opts.SetGasLimit(gaslimit)
}
}
func WithValue(value decimal.Decimal) ExecutionOption {
return func(opts *TransactOpts) *TransactOpts {
return opts.SetValue(value)
}
}

View File

@ -49,7 +49,7 @@ func (s *UniswapRouter) Name() string {
return s.name return s.name
} }
func (s *UniswapRouter) SwapTokenToToken(ctx context.Context, path []common.Address, amount decimal.Decimal, slippage decimal.Decimal) (Transaction, error) { func (s *UniswapRouter) SwapTokenToToken(ctx context.Context, path []common.Address, amount decimal.Decimal, slippage decimal.Decimal, opts ...ExecutionOption) (Transaction, error) {
if len(path) < 2 { if len(path) < 2 {
return nil, errors.Errorf("swap path must contain at least 2 addresses, currently %d", len(path)) return nil, errors.Errorf("swap path must contain at least 2 addresses, currently %d", len(path))
} }
@ -94,7 +94,7 @@ func (s *UniswapRouter) SwapTokenToToken(ctx context.Context, path []common.Addr
path, path,
s.client.PublicAddress(), s.client.PublicAddress(),
s.getDeadline()) s.getDeadline())
}) }, opts...)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "swaping") return nil, errors.Wrap(err, "swaping")
} }
@ -134,7 +134,7 @@ func (s *UniswapRouter) GetAmountRate(token0 Token, token1 Token, amount decimal
return token1.ValueFromBigInt(expectedout[len(expectedout)-1]), nil return token1.ValueFromBigInt(expectedout[len(expectedout)-1]), nil
} }
func (s *UniswapRouter) AddLiquidity(ctx context.Context, token1 Token, token2 Token, amounttoken1 decimal.Decimal, amounttoken2 decimal.Decimal) (Transaction, error) { func (s *UniswapRouter) AddLiquidity(ctx context.Context, token1 Token, token2 Token, amounttoken1 decimal.Decimal, amounttoken2 decimal.Decimal, opts ...ExecutionOption) (Transaction, error) {
return s.client.Execute(ctx, func(ctx context.Context, options *TransactOpts) (*types.Transaction, error) { return s.client.Execute(ctx, func(ctx context.Context, options *TransactOpts) (*types.Transaction, error) {
return s.contract.AddLiquidity( return s.contract.AddLiquidity(
options.TransactOpts, options.TransactOpts,
@ -146,5 +146,5 @@ func (s *UniswapRouter) AddLiquidity(ctx context.Context, token1 Token, token2 T
token2.ValueToBigInt(amounttoken2.Sub(amounttoken2.Mul(decimal.NewFromFloat(0.01)))), token2.ValueToBigInt(amounttoken2.Sub(amounttoken2.Mul(decimal.NewFromFloat(0.01)))),
s.client.PublicAddress(), s.client.PublicAddress(),
s.getDeadline()) s.getDeadline())
}) }, opts...)
} }