github.com/ethersphere/bee/v2@v2.2.0/pkg/transaction/mock/transaction.go (about) 1 // Copyright 2020 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 mock 6 7 import ( 8 "bytes" 9 "context" 10 "errors" 11 "fmt" 12 "math/big" 13 14 "github.com/ethereum/go-ethereum/accounts/abi" 15 "github.com/ethereum/go-ethereum/common" 16 "github.com/ethereum/go-ethereum/core/types" 17 "github.com/ethersphere/bee/v2/pkg/transaction" 18 ) 19 20 type transactionServiceMock struct { 21 send func(ctx context.Context, request *transaction.TxRequest, boost int) (txHash common.Hash, err error) 22 waitForReceipt func(ctx context.Context, txHash common.Hash) (receipt *types.Receipt, err error) 23 watchSentTransaction func(txHash common.Hash) (chan types.Receipt, chan error, error) 24 call func(ctx context.Context, request *transaction.TxRequest) (result []byte, err error) 25 pendingTransactions func() ([]common.Hash, error) 26 resendTransaction func(ctx context.Context, txHash common.Hash) error 27 storedTransaction func(txHash common.Hash) (*transaction.StoredTransaction, error) 28 cancelTransaction func(ctx context.Context, originalTxHash common.Hash) (common.Hash, error) 29 transactionFee func(ctx context.Context, txHash common.Hash) (*big.Int, error) 30 } 31 32 func (m *transactionServiceMock) Send(ctx context.Context, request *transaction.TxRequest, boostPercent int) (txHash common.Hash, err error) { 33 if m.send != nil { 34 return m.send(ctx, request, boostPercent) 35 } 36 return common.Hash{}, errors.New("not implemented") 37 } 38 39 func (m *transactionServiceMock) WaitForReceipt(ctx context.Context, txHash common.Hash) (receipt *types.Receipt, err error) { 40 if m.waitForReceipt != nil { 41 return m.waitForReceipt(ctx, txHash) 42 } 43 return nil, errors.New("not implemented") 44 } 45 46 func (m *transactionServiceMock) WatchSentTransaction(txHash common.Hash) (<-chan types.Receipt, <-chan error, error) { 47 if m.watchSentTransaction != nil { 48 return m.watchSentTransaction(txHash) 49 } 50 return nil, nil, errors.New("not implemented") 51 } 52 53 func (m *transactionServiceMock) Call(ctx context.Context, request *transaction.TxRequest) (result []byte, err error) { 54 if m.call != nil { 55 return m.call(ctx, request) 56 } 57 return nil, errors.New("not implemented") 58 } 59 60 func (m *transactionServiceMock) PendingTransactions() ([]common.Hash, error) { 61 if m.pendingTransactions != nil { 62 return m.pendingTransactions() 63 } 64 return nil, errors.New("not implemented") 65 } 66 67 func (m *transactionServiceMock) ResendTransaction(ctx context.Context, txHash common.Hash) error { 68 if m.resendTransaction != nil { 69 return m.resendTransaction(ctx, txHash) 70 } 71 return errors.New("not implemented") 72 } 73 74 func (m *transactionServiceMock) StoredTransaction(txHash common.Hash) (*transaction.StoredTransaction, error) { 75 if m.storedTransaction != nil { 76 return m.storedTransaction(txHash) 77 } 78 return nil, errors.New("not implemented") 79 } 80 81 func (m *transactionServiceMock) CancelTransaction(ctx context.Context, originalTxHash common.Hash) (common.Hash, error) { 82 if m.cancelTransaction != nil { 83 return m.cancelTransaction(ctx, originalTxHash) 84 } 85 return common.Hash{}, errors.New("not implemented") 86 } 87 88 func (m *transactionServiceMock) Close() error { 89 return nil 90 } 91 92 // TransactionFee returns fee of transaction 93 func (m *transactionServiceMock) TransactionFee(ctx context.Context, txHash common.Hash) (*big.Int, error) { 94 if m.transactionFee != nil { 95 return m.transactionFee(ctx, txHash) 96 } 97 return big.NewInt(0), nil 98 } 99 100 func (m *transactionServiceMock) UnwrapABIError(_ context.Context, _ *transaction.TxRequest, err error, _ map[string]abi.Error) error { 101 return err 102 } 103 104 // Option is the option passed to the mock Chequebook service 105 type Option interface { 106 apply(*transactionServiceMock) 107 } 108 109 type optionFunc func(*transactionServiceMock) 110 111 func (f optionFunc) apply(r *transactionServiceMock) { f(r) } 112 113 func WithSendFunc(f func(context.Context, *transaction.TxRequest, int) (txHash common.Hash, err error)) Option { 114 return optionFunc(func(s *transactionServiceMock) { 115 s.send = f 116 }) 117 } 118 119 func WithWaitForReceiptFunc(f func(ctx context.Context, txHash common.Hash) (receipt *types.Receipt, err error)) Option { 120 return optionFunc(func(s *transactionServiceMock) { 121 s.waitForReceipt = f 122 }) 123 } 124 125 func WithCallFunc(f func(ctx context.Context, request *transaction.TxRequest) (result []byte, err error)) Option { 126 return optionFunc(func(s *transactionServiceMock) { 127 s.call = f 128 }) 129 } 130 131 func WithStoredTransactionFunc(f func(txHash common.Hash) (*transaction.StoredTransaction, error)) Option { 132 return optionFunc(func(s *transactionServiceMock) { 133 s.storedTransaction = f 134 }) 135 } 136 137 func WithPendingTransactionsFunc(f func() ([]common.Hash, error)) Option { 138 return optionFunc(func(s *transactionServiceMock) { 139 s.pendingTransactions = f 140 }) 141 } 142 143 func WithResendTransactionFunc(f func(ctx context.Context, txHash common.Hash) error) Option { 144 return optionFunc(func(s *transactionServiceMock) { 145 s.resendTransaction = f 146 }) 147 } 148 149 func WithCancelTransactionFunc(f func(ctx context.Context, originalTxHash common.Hash) (common.Hash, error)) Option { 150 return optionFunc(func(s *transactionServiceMock) { 151 s.cancelTransaction = f 152 }) 153 } 154 155 func WithTransactionFeeFunc(f func(ctx context.Context, txHash common.Hash) (*big.Int, error)) Option { 156 return optionFunc(func(s *transactionServiceMock) { 157 s.transactionFee = f 158 }) 159 } 160 161 func New(opts ...Option) transaction.Service { 162 mock := new(transactionServiceMock) 163 for _, o := range opts { 164 o.apply(mock) 165 } 166 return mock 167 } 168 169 type Call struct { 170 abi *abi.ABI 171 to common.Address 172 result []byte 173 method string 174 params []interface{} 175 } 176 177 func ABICall(abi *abi.ABI, to common.Address, result []byte, method string, params ...interface{}) Call { 178 return Call{ 179 to: to, 180 abi: abi, 181 result: result, 182 method: method, 183 params: params, 184 } 185 } 186 187 func WithABICallSequence(calls ...Call) Option { 188 return optionFunc(func(s *transactionServiceMock) { 189 s.call = func(ctx context.Context, request *transaction.TxRequest) ([]byte, error) { 190 if len(calls) == 0 { 191 return nil, errors.New("unexpected call") 192 } 193 194 call := calls[0] 195 196 data, err := call.abi.Pack(call.method, call.params...) 197 if err != nil { 198 return nil, err 199 } 200 201 if !bytes.Equal(data, request.Data) { 202 return nil, fmt.Errorf("wrong data. wanted %x, got %x", data, request.Data) 203 } 204 205 if request.To == nil { 206 return nil, errors.New("call with no recipient") 207 } 208 if *request.To != call.to { 209 return nil, fmt.Errorf("wrong recipient. wanted %x, got %x", call.to, *request.To) 210 } 211 212 calls = calls[1:] 213 214 return call.result, nil 215 } 216 }) 217 } 218 219 func WithABICall(abi *abi.ABI, to common.Address, result []byte, method string, params ...interface{}) Option { 220 return WithABICallSequence(ABICall(abi, to, result, method, params...)) 221 } 222 223 func WithABISend(abi *abi.ABI, txHash common.Hash, expectedAddress common.Address, expectedValue *big.Int, method string, params ...interface{}) Option { 224 return optionFunc(func(s *transactionServiceMock) { 225 s.send = func(ctx context.Context, request *transaction.TxRequest, boost int) (common.Hash, error) { 226 data, err := abi.Pack(method, params...) 227 if err != nil { 228 return common.Hash{}, err 229 } 230 231 if !bytes.Equal(data, request.Data) { 232 return common.Hash{}, fmt.Errorf("wrong data. wanted %x, got %x", data, request.Data) 233 } 234 235 if request.To != nil && *request.To != expectedAddress { 236 return common.Hash{}, fmt.Errorf("sending to wrong contract. wanted %x, got %x", expectedAddress, request.To) 237 } 238 if request.Value.Cmp(expectedValue) != 0 { 239 return common.Hash{}, fmt.Errorf("sending with wrong value. wanted %d, got %d", expectedValue, request.Value) 240 } 241 242 return txHash, nil 243 } 244 }) 245 }