From b927854098df84cadb6146a71d618a0e5b8136e8 Mon Sep 17 00:00:00 2001 From: Laurent Le Houerou Date: Tue, 9 Nov 2021 08:11:05 +0400 Subject: [PATCH] wip --- bsc/wbnb.go | 4 ++-- client.go | 20 +++++++------------- pancakeswap/masterchef.go | 8 ++++---- pancakeswap/nftmarket.go | 15 ++++++--------- token.go | 12 ++++++------ transactionoptions.go | 19 +++++++++++++++++++ uniswaprouter.go | 8 ++++---- 7 files changed, 48 insertions(+), 38 deletions(-) diff --git a/bsc/wbnb.go b/bsc/wbnb.go index 4711578..20fc033 100644 --- a/bsc/wbnb.go +++ b/bsc/wbnb.go @@ -34,8 +34,8 @@ func NewWBNB(address string, client evm.Client) (*WBNB, error) { }, 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.contract.Withdraw(opts.TransactOpts, w.ValueToBigInt(amount)) - }) + }, opts...) } diff --git a/client.go b/client.go index dda7a9b..2a068ad 100644 --- a/client.go +++ b/client.go @@ -24,22 +24,21 @@ type Client interface { PublicAddressAsHexString() string PendingNonce(context.Context) (uint64, 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 NativeTokenBalance(context.Context) (decimal.Decimal, error) CurrentBlockNumber(context.Context) (uint64, error) CurrentBlock(context.Context) (*types.Block, error) - SetPendingTransactionCheckPeriod(duration time.Duration) TransactionByHash(context.Context, common.Hash) (*types.Transaction, bool, error) TokenService() TokenService } -type ClientOption func(c Client) (Client, error) +type ClientOption func(c *client) (*client, error) func WithPendingTransactionWaitResolution(duration time.Duration) ClientOption { - return func(c Client) (Client, error) { - c.SetPendingTransactionCheckPeriod(duration) + return func(c *client) (*client, error) { + c.pendingTransactionCheckPeriod = duration 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") } - ires := Client(res) for _, option := range options { - ires, err = option(ires) + res, err = option(res) if err != nil { return nil, errors.Wrap(err, "applying option") } } - return ires, nil + return res, nil } func (c *client) PublicAddress() common.Address { return c.fromAddress } -func (c *client) SetPendingTransactionCheckPeriod(period time.Duration) { - c.pendingTransactionCheckPeriod = period -} - func (c *client) PendingNonce(ctx context.Context) (uint64, error) { return c.PendingNonceAt(ctx, c.PublicAddress()) } @@ -117,7 +111,7 @@ func (c *client) NewTransactor() (*bind.TransactOpts, error) { 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() defer c.transactionlock.Unlock() localctx, cancel := context.WithTimeout(ctx, c.defaultTimeout) diff --git a/pancakeswap/masterchef.go b/pancakeswap/masterchef.go index 48db338..08a76df 100644 --- a/pancakeswap/masterchef.go +++ b/pancakeswap/masterchef.go @@ -50,13 +50,13 @@ func (m *MasterChef) PendingCakeOfAddress(pid int64, address common.Address) (de 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.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) if err != nil { 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 { return nil, errors.Wrap(err, "getting cake balance") } - return m.EnterStaking(ctx, pending.Add(balance)) + return m.EnterStaking(ctx, pending.Add(balance), opts...) } diff --git a/pancakeswap/nftmarket.go b/pancakeswap/nftmarket.go index 59e47b6..8833953 100644 --- a/pancakeswap/nftmarket.go +++ b/pancakeswap/nftmarket.go @@ -51,25 +51,22 @@ func (m *NftMarket) GetAskPriceForToken(collection common.Address, tokenid int) 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) { - opts.SetValue(price) - opts.SetGasPrice(gas) opts.SetGasLimit(1000000) 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) { - opts.SetGasPrice(gas) opts.SetGasLimit(1000000) 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.contract.CreateAskOrder(opts.TransactOpts, collection, big.NewInt(int64(tokenid)), m.wbnb.ValueToBigInt(price)) - }) + }, opts...) } diff --git a/token.go b/token.go index 30c6f68..b6dfef7 100644 --- a/token.go +++ b/token.go @@ -21,8 +21,8 @@ type Token interface { BalanceOf(common.Address) (decimal.Decimal, error) Balance() (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) - Transfer(ctx context.Context, to 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, opts ...ExecutionOption) (Transaction, error) ValueToBigInt(value decimal.Decimal) *big.Int 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 } -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.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.contract.Transfer(options.TransactOpts, to, t.ValueToBigInt(value)) - }) + }, opts...) } func (t *baseToken) Address() common.Address { diff --git a/transactionoptions.go b/transactionoptions.go index e1135ef..661c105 100644 --- a/transactionoptions.go +++ b/transactionoptions.go @@ -2,6 +2,7 @@ package evm import ( "context" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/shopspring/decimal" ) @@ -37,3 +38,21 @@ func (o *TransactOpts) SetGasPrice(gasprice decimal.Decimal) *TransactOpts { o.GasPrice = gasprice.Shift(9).BigInt() 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) + } +} diff --git a/uniswaprouter.go b/uniswaprouter.go index 6623200..2f9726c 100644 --- a/uniswaprouter.go +++ b/uniswaprouter.go @@ -49,7 +49,7 @@ func (s *UniswapRouter) Name() string { 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 { 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, s.client.PublicAddress(), s.getDeadline()) - }) + }, opts...) if err != nil { 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 } -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.contract.AddLiquidity( 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)))), s.client.PublicAddress(), s.getDeadline()) - }) + }, opts...) }