diff --git a/errors/errors.go b/errors/errors.go index 48d225162..bc4e4020f 100644 --- a/errors/errors.go +++ b/errors/errors.go @@ -7,6 +7,8 @@ import ( // ErrorCode represents a specific error code. type ErrorCode string +const GenericErrorCode ErrorCode = "0" + // ErrorResponse represents an error response structure. type ErrorResponse struct { Code ErrorCode `json:"code"` @@ -19,6 +21,12 @@ func (e *ErrorResponse) Error() string { return string(errorJSON) } +// IsErrorResponse determines if an error is an ErrorResponse. +func IsErrorResponse(err error) bool { + _, ok := err.(*ErrorResponse) + return ok +} + // CreateErrorResponseFromError creates an ErrorResponse from a generic error. func CreateErrorResponseFromError(err error) error { if err == nil { @@ -28,7 +36,7 @@ func CreateErrorResponseFromError(err error) error { return errResp } return &ErrorResponse{ - Code: "0", + Code: GenericErrorCode, Details: err.Error(), } } diff --git a/services/wallet/router/errors.go b/services/wallet/router/errors.go index d62e403ec..fe3e2c524 100644 --- a/services/wallet/router/errors.go +++ b/services/wallet/router/errors.go @@ -28,4 +28,5 @@ var ( ErrENSSetPubKeyInvalidUsername = &errors.ErrorResponse{Code: errors.ErrorCode("WR-020"), Details: "a valid username, ending in '.eth', is required for ENSSetPubKey"} ErrLockedAmountExcludesAllSupported = &errors.ErrorResponse{Code: errors.ErrorCode("WR-021"), Details: "all supported chains are excluded, routing impossible"} ErrTokenNotFound = &errors.ErrorResponse{Code: errors.ErrorCode("WR-022"), Details: "token not found"} + ErrNoBestRouteFound = &errors.ErrorResponse{Code: errors.ErrorCode("WR-023"), Details: "no best route found"} ) diff --git a/services/wallet/router/pathprocessor/errors.go b/services/wallet/router/pathprocessor/errors.go index e62c112a9..aa7b08378 100644 --- a/services/wallet/router/pathprocessor/errors.go +++ b/services/wallet/router/pathprocessor/errors.go @@ -1,6 +1,8 @@ package pathprocessor import ( + "context" + "github.com/status-im/status-go/errors" ) @@ -30,4 +32,66 @@ var ( ErrFromAndToChainsMustBeDifferent = &errors.ErrorResponse{Code: errors.ErrorCode("WPP-022"), Details: "from and to chains must be different"} ErrFromAndToChainsMustBeSame = &errors.ErrorResponse{Code: errors.ErrorCode("WPP-023"), Details: "from and to chains must be same"} ErrFromAndToTokensMustBeDifferent = &errors.ErrorResponse{Code: errors.ErrorCode("WPP-024"), Details: "from and to tokens must be different"} + ErrTransferCustomError = &errors.ErrorResponse{Code: errors.ErrorCode("WPP-025"), Details: "Transfer custom error"} + ErrERC721TransferCustomError = &errors.ErrorResponse{Code: errors.ErrorCode("WPP-026"), Details: "ERC721Transfer custom error"} + ErrERC1155TransferCustomError = &errors.ErrorResponse{Code: errors.ErrorCode("WPP-027"), Details: "ERC1155Transfer custom error"} + ErrBridgeHopCustomError = &errors.ErrorResponse{Code: errors.ErrorCode("WPP-028"), Details: "Hop custom error"} + ErrBridgeCellerCustomError = &errors.ErrorResponse{Code: errors.ErrorCode("WPP-029"), Details: "CBridge custom error"} + ErrSwapParaswapCustomError = &errors.ErrorResponse{Code: errors.ErrorCode("WPP-030"), Details: "Paraswap custom error"} + ErrENSRegisterCustomError = &errors.ErrorResponse{Code: errors.ErrorCode("WPP-031"), Details: "ENSRegister custom error"} + ErrENSReleaseCustomError = &errors.ErrorResponse{Code: errors.ErrorCode("WPP-032"), Details: "ENSRelease custom error"} + ErrENSPublicKeyCustomError = &errors.ErrorResponse{Code: errors.ErrorCode("WPP-033"), Details: "ENSPublicKey custom error"} + ErrStickersBuyCustomError = &errors.ErrorResponse{Code: errors.ErrorCode("WPP-034"), Details: "StickersBuy custom error"} + ErrContextCancelled = &errors.ErrorResponse{Code: errors.ErrorCode("WPP-035"), Details: "context cancelled"} + ErrContextDeadlineExceeded = &errors.ErrorResponse{Code: errors.ErrorCode("WPP-036"), Details: "context deadline exceeded"} + ErrPriceTimeout = &errors.ErrorResponse{Code: errors.ErrorCode("WPP-037"), Details: "price timeout"} + ErrNotEnoughLiquidity = &errors.ErrorResponse{Code: errors.ErrorCode("WPP-038"), Details: "not enough liquidity"} ) + +func createErrorResponse(processorName string, err error) error { + if err == nil { + return nil + } + + genericErrResp := errors.CreateErrorResponseFromError(err).(*errors.ErrorResponse) + + if genericErrResp.Code != errors.GenericErrorCode { + return genericErrResp + } + + switch genericErrResp.Details { + case context.Canceled.Error(): + return ErrContextCancelled + case context.DeadlineExceeded.Error(): + return ErrContextDeadlineExceeded + } + + var customErrResp *errors.ErrorResponse + switch processorName { + case ProcessorTransferName: + customErrResp = ErrTransferCustomError + case ProcessorERC721Name: + customErrResp = ErrERC721TransferCustomError + case ProcessorERC1155Name: + customErrResp = ErrERC1155TransferCustomError + case ProcessorBridgeHopName: + customErrResp = ErrBridgeHopCustomError + case ProcessorBridgeCelerName: + customErrResp = ErrBridgeCellerCustomError + case ProcessorSwapParaswapName: + customErrResp = ErrSwapParaswapCustomError + case ProcessorENSRegisterName: + customErrResp = ErrENSRegisterCustomError + case ProcessorENSReleaseName: + customErrResp = ErrENSReleaseCustomError + case ProcessorENSPublicKeyName: + customErrResp = ErrENSPublicKeyCustomError + case ProcessorStickersBuyName: + customErrResp = ErrStickersBuyCustomError + default: + return genericErrResp + } + + customErrResp.Details = genericErrResp.Details + return customErrResp +} diff --git a/services/wallet/router/pathprocessor/errors_test.go b/services/wallet/router/pathprocessor/errors_test.go new file mode 100644 index 000000000..42236991a --- /dev/null +++ b/services/wallet/router/pathprocessor/errors_test.go @@ -0,0 +1,70 @@ +package pathprocessor + +import ( + "context" + "errors" + "testing" + + s_errors "github.com/status-im/status-go/errors" + + "github.com/stretchr/testify/require" +) + +func TestPlainError(t *testing.T) { + const errString = "plain error" + err := errors.New(errString) + + processorNames := []string{ + ProcessorTransferName, + ProcessorTransferName, + ProcessorBridgeHopName, + ProcessorBridgeCelerName, + ProcessorSwapParaswapName, + ProcessorERC721Name, + ProcessorERC1155Name, + ProcessorENSRegisterName, + ProcessorENSReleaseName, + ProcessorENSPublicKeyName, + ProcessorStickersBuyName, + } + + for _, processorName := range processorNames { + ppErrResp := createErrorResponse(processorName, err) + + castPPErrResp := ppErrResp.(*s_errors.ErrorResponse) + require.NotEqual(t, s_errors.GenericErrorCode, castPPErrResp.Code) + require.Equal(t, errString, castPPErrResp.Details) + } +} + +func TestContextErrors(t *testing.T) { + ppErrResp := createErrorResponse("Unknown", context.Canceled) + require.Equal(t, ErrContextCancelled, ppErrResp) + + ppErrResp = createErrorResponse("Unknown", context.DeadlineExceeded) + require.Equal(t, ErrContextDeadlineExceeded, ppErrResp) +} + +func TestErrorResponse(t *testing.T) { + const errString = "error response" + err := errors.New(errString) + errResp := s_errors.CreateErrorResponseFromError(err) + ppErrResp := createErrorResponse("Unknown", errResp) + + castPPErrResp := ppErrResp.(*s_errors.ErrorResponse) + require.Equal(t, s_errors.GenericErrorCode, castPPErrResp.Code) + require.Equal(t, errString, castPPErrResp.Details) +} + +func TestNonGenericErrorResponse(t *testing.T) { + errResp := &s_errors.ErrorResponse{ + Code: "Not Generic Code", + Details: "Not Generic Error Response", + } + err := s_errors.CreateErrorResponseFromError(errResp) + ppErrResp := createErrorResponse(ProcessorTransferName, err) + + castPPErrResp := ppErrResp.(*s_errors.ErrorResponse) + require.Equal(t, errResp.Code, castPPErrResp.Code) + require.Equal(t, errResp.Details, castPPErrResp.Details) +} diff --git a/services/wallet/router/pathprocessor/processor_bridge_celar.go b/services/wallet/router/pathprocessor/processor_bridge_celar.go index 44cc0f217..a0bdb6d7f 100644 --- a/services/wallet/router/pathprocessor/processor_bridge_celar.go +++ b/services/wallet/router/pathprocessor/processor_bridge_celar.go @@ -22,7 +22,6 @@ import ( "github.com/status-im/status-go/eth-node/types" "github.com/status-im/status-go/rpc" - statusErrors "github.com/status-im/status-go/errors" "github.com/status-im/status-go/params" "github.com/status-im/status-go/services/wallet/router/pathprocessor/cbridge" "github.com/status-im/status-go/services/wallet/thirdparty" @@ -63,6 +62,10 @@ func NewCelerBridgeProcessor(rpcClient *rpc.Client, transactor transactions.Tran } } +func createBridgeCellerErrorResponse(err error) error { + return createErrorResponse(ProcessorBridgeCelerName, err) +} + func (s *CelerBridgeProcessor) Name() string { return ProcessorBridgeCelerName } @@ -84,13 +87,13 @@ func (s *CelerBridgeProcessor) estimateAmt(from, to *params.Network, amountIn *b url := fmt.Sprintf("%s/v2/estimateAmt", base) response, err := s.httpClient.DoGetRequest(context.Background(), url, params) if err != nil { - return nil, statusErrors.CreateErrorResponseFromError(err) + return nil, createBridgeCellerErrorResponse(err) } var res cbridge.EstimateAmtResponse err = json.Unmarshal(response, &res) if err != nil { - return nil, statusErrors.CreateErrorResponseFromError(err) + return nil, createBridgeCellerErrorResponse(err) } return &res, nil } @@ -111,13 +114,13 @@ func (s *CelerBridgeProcessor) getTransferConfig(isTest bool) (*cbridge.GetTrans url := fmt.Sprintf("%s/v2/getTransferConfigs", base) response, err := s.httpClient.DoGetRequest(context.Background(), url, nil) if err != nil { - return nil, statusErrors.CreateErrorResponseFromError(err) + return nil, createBridgeCellerErrorResponse(err) } var res cbridge.GetTransferConfigsResponse err = json.Unmarshal(response, &res) if err != nil { - return nil, statusErrors.CreateErrorResponseFromError(err) + return nil, createBridgeCellerErrorResponse(err) } if isTest { s.testTransferConfig = &res @@ -134,10 +137,10 @@ func (s *CelerBridgeProcessor) AvailableFor(params ProcessorInputParams) (bool, transferConfig, err := s.getTransferConfig(params.FromChain.IsTest) if err != nil { - return false, statusErrors.CreateErrorResponseFromError(err) + return false, createBridgeCellerErrorResponse(err) } if transferConfig.Err != nil { - return false, statusErrors.CreateErrorResponseFromError(errors.New(transferConfig.Err.Msg)) + return false, createBridgeCellerErrorResponse(errors.New(transferConfig.Err.Msg)) } var fromAvailable *cbridge.Chain @@ -189,7 +192,7 @@ func (s *CelerBridgeProcessor) AvailableFor(params ProcessorInputParams) (bool, func (s *CelerBridgeProcessor) CalculateFees(params ProcessorInputParams) (*big.Int, *big.Int, error) { amt, err := s.estimateAmt(params.FromChain, params.ToChain, params.AmountIn, params.FromToken.Symbol) if err != nil { - return nil, nil, statusErrors.CreateErrorResponseFromError(err) + return nil, nil, createBridgeCellerErrorResponse(err) } baseFee, ok := new(big.Int).SetString(amt.BaseFee, 10) if !ok { @@ -206,7 +209,7 @@ func (s *CelerBridgeProcessor) CalculateFees(params ProcessorInputParams) (*big. func (c *CelerBridgeProcessor) PackTxInputData(params ProcessorInputParams) ([]byte, error) { abi, err := abi.JSON(strings.NewReader(celer.CelerABI)) if err != nil { - return []byte{}, statusErrors.CreateErrorResponseFromError(err) + return []byte{}, createBridgeCellerErrorResponse(err) } if params.FromToken.IsNative() { @@ -243,17 +246,17 @@ func (s *CelerBridgeProcessor) EstimateGas(params ProcessorInputParams) (uint64, input, err := s.PackTxInputData(params) if err != nil { - return 0, statusErrors.CreateErrorResponseFromError(err) + return 0, createBridgeCellerErrorResponse(err) } contractAddress, err := s.GetContractAddress(params) if err != nil { - return 0, statusErrors.CreateErrorResponseFromError(err) + return 0, createBridgeCellerErrorResponse(err) } ethClient, err := s.rpcClient.EthClient(params.FromChain.ChainID) if err != nil { - return 0, statusErrors.CreateErrorResponseFromError(err) + return 0, createBridgeCellerErrorResponse(err) } ctx := context.Background() @@ -273,7 +276,7 @@ func (s *CelerBridgeProcessor) EstimateGas(params ProcessorInputParams) (uint64, // this is an error we're facing otherwise: `execution reverted: ERC20: transfer amount exceeds allowance` estimation = 350000 } else { - return 0, statusErrors.CreateErrorResponseFromError(err) + return 0, createBridgeCellerErrorResponse(err) } } increasedEstimation := float64(estimation) * IncreaseEstimatedGasFactor @@ -304,10 +307,10 @@ func (s *CelerBridgeProcessor) BuildTx(params ProcessorInputParams) (*ethTypes.T func (s *CelerBridgeProcessor) GetContractAddress(params ProcessorInputParams) (common.Address, error) { transferConfig, err := s.getTransferConfig(params.FromChain.IsTest) if err != nil { - return common.Address{}, statusErrors.CreateErrorResponseFromError(err) + return common.Address{}, createBridgeCellerErrorResponse(err) } if transferConfig.Err != nil { - return common.Address{}, statusErrors.CreateErrorResponseFromError(errors.New(transferConfig.Err.Msg)) + return common.Address{}, createBridgeCellerErrorResponse(errors.New(transferConfig.Err.Msg)) } for _, chain := range transferConfig.Chains { @@ -332,16 +335,16 @@ func (s *CelerBridgeProcessor) sendOrBuild(sendArgs *MultipathProcessorTxArgs, s FromChain: fromChain, }) if err != nil { - return nil, statusErrors.CreateErrorResponseFromError(err) + return nil, createBridgeCellerErrorResponse(err) } backend, err := s.rpcClient.EthClient(sendArgs.ChainID) if err != nil { - return nil, statusErrors.CreateErrorResponseFromError(err) + return nil, createBridgeCellerErrorResponse(err) } contract, err := celer.NewCeler(addrs, backend) if err != nil { - return nil, statusErrors.CreateErrorResponseFromError(err) + return nil, createBridgeCellerErrorResponse(err) } var tx *ethTypes.Transaction @@ -367,11 +370,11 @@ func (s *CelerBridgeProcessor) sendOrBuild(sendArgs *MultipathProcessorTxArgs, s ) } if err != nil { - return tx, statusErrors.CreateErrorResponseFromError(err) + return tx, createBridgeCellerErrorResponse(err) } err = s.transactor.StoreAndTrackPendingTx(txOpts.From, sendArgs.CbridgeTx.Symbol, sendArgs.ChainID, sendArgs.CbridgeTx.MultiTransactionID, tx) if err != nil { - return tx, statusErrors.CreateErrorResponseFromError(err) + return tx, createBridgeCellerErrorResponse(err) } return tx, nil } @@ -379,7 +382,7 @@ func (s *CelerBridgeProcessor) sendOrBuild(sendArgs *MultipathProcessorTxArgs, s func (s *CelerBridgeProcessor) Send(sendArgs *MultipathProcessorTxArgs, verifiedAccount *account.SelectedExtKey) (types.Hash, error) { tx, err := s.sendOrBuild(sendArgs, getSigner(sendArgs.ChainID, sendArgs.CbridgeTx.From, verifiedAccount)) if err != nil { - return types.HexToHash(""), statusErrors.CreateErrorResponseFromError(err) + return types.HexToHash(""), createBridgeCellerErrorResponse(err) } return types.Hash(tx.Hash()), nil @@ -392,10 +395,10 @@ func (s *CelerBridgeProcessor) BuildTransaction(sendArgs *MultipathProcessorTxAr func (s *CelerBridgeProcessor) CalculateAmountOut(params ProcessorInputParams) (*big.Int, error) { amt, err := s.estimateAmt(params.FromChain, params.ToChain, params.AmountIn, params.FromToken.Symbol) if err != nil { - return nil, statusErrors.CreateErrorResponseFromError(err) + return nil, createBridgeCellerErrorResponse(err) } if amt.Err != nil { - return nil, statusErrors.CreateErrorResponseFromError(err) + return nil, createBridgeCellerErrorResponse(err) } amountOut, _ := new(big.Int).SetString(amt.EqValueTokenAmt, 10) return amountOut, nil diff --git a/services/wallet/router/pathprocessor/processor_bridge_hop.go b/services/wallet/router/pathprocessor/processor_bridge_hop.go index 1bbdd900e..e8d79047e 100644 --- a/services/wallet/router/pathprocessor/processor_bridge_hop.go +++ b/services/wallet/router/pathprocessor/processor_bridge_hop.go @@ -27,7 +27,6 @@ import ( hopL2ArbitrumBridge "github.com/status-im/status-go/contracts/hop/l2Contracts/l2ArbitrumBridge" hopL2CctpImplementation "github.com/status-im/status-go/contracts/hop/l2Contracts/l2CctpImplementation" hopL2OptimismBridge "github.com/status-im/status-go/contracts/hop/l2Contracts/l2OptimismBridge" - statusErrors "github.com/status-im/status-go/errors" "github.com/status-im/status-go/eth-node/types" "github.com/status-im/status-go/rpc" "github.com/status-im/status-go/rpc/chain" @@ -77,7 +76,7 @@ func (bf *BonderFee) UnmarshalJSON(data []byte) error { } if err := json.Unmarshal(data, aux); err != nil { - return statusErrors.CreateErrorResponseFromError(err) + return createBridgeHopErrorResponse(err) } bf.AmountIn = &bigint.BigInt{Int: new(big.Int)} @@ -126,6 +125,10 @@ func NewHopBridgeProcessor(rpcClient rpc.ClientInterface, transactor transaction } } +func createBridgeHopErrorResponse(err error) error { + return createErrorResponse(ProcessorBridgeHopName, err) +} + func (h *HopBridgeProcessor) Name() string { return ProcessorBridgeHopName } @@ -186,7 +189,7 @@ func (c *HopBridgeProcessor) getAppropriateABI(contractType string, chainID uint func (h *HopBridgeProcessor) PackTxInputData(params ProcessorInputParams) ([]byte, error) { _, contractType, err := hop.GetContractAddress(params.FromChain.ChainID, params.FromToken.Symbol) if err != nil { - return []byte{}, statusErrors.CreateErrorResponseFromError(err) + return []byte{}, createBridgeHopErrorResponse(err) } return h.packTxInputDataInternally(params, contractType) @@ -195,7 +198,7 @@ func (h *HopBridgeProcessor) PackTxInputData(params ProcessorInputParams) ([]byt func (h *HopBridgeProcessor) packTxInputDataInternally(params ProcessorInputParams, contractType string) ([]byte, error) { abi, err := h.getAppropriateABI(contractType, params.FromChain.ChainID, params.FromToken) if err != nil { - return []byte{}, statusErrors.CreateErrorResponseFromError(err) + return []byte{}, createBridgeHopErrorResponse(err) } bonderKey := makeKey(params.FromChain.ChainID, params.ToChain.ChainID, "", "") @@ -238,17 +241,17 @@ func (h *HopBridgeProcessor) EstimateGas(params ProcessorInputParams) (uint64, e contractAddress, contractType, err := hop.GetContractAddress(params.FromChain.ChainID, params.FromToken.Symbol) if err != nil { - return 0, statusErrors.CreateErrorResponseFromError(err) + return 0, createBridgeHopErrorResponse(err) } input, err := h.packTxInputDataInternally(params, contractType) if err != nil { - return 0, statusErrors.CreateErrorResponseFromError(err) + return 0, createBridgeHopErrorResponse(err) } ethClient, err := h.contractMaker.RPCClient.EthClient(params.FromChain.ChainID) if err != nil { - return 0, statusErrors.CreateErrorResponseFromError(err) + return 0, createBridgeHopErrorResponse(err) } msg := ethereum.CallMsg{ @@ -266,7 +269,7 @@ func (h *HopBridgeProcessor) EstimateGas(params ProcessorInputParams) (uint64, e // this is an error we're facing otherwise: `execution reverted: ERC20: transfer amount exceeds allowance` estimation = 350000 } else { - return 0, statusErrors.CreateErrorResponseFromError(err) + return 0, createBridgeHopErrorResponse(err) } } @@ -298,7 +301,7 @@ func (h *HopBridgeProcessor) BuildTx(params ProcessorInputParams) (*ethTypes.Tra func (h *HopBridgeProcessor) GetContractAddress(params ProcessorInputParams) (common.Address, error) { address, _, err := hop.GetContractAddress(params.FromChain.ChainID, params.FromToken.Symbol) - return address, statusErrors.CreateErrorResponseFromError(err) + return address, createBridgeHopErrorResponse(err) } func (h *HopBridgeProcessor) sendOrBuild(sendArgs *MultipathProcessorTxArgs, signerFn bind.SignerFn) (tx *ethTypes.Transaction, err error) { @@ -311,7 +314,7 @@ func (h *HopBridgeProcessor) sendOrBuild(sendArgs *MultipathProcessorTxArgs, sig nonce, err := h.transactor.NextNonce(h.contractMaker.RPCClient, fromChain.ChainID, sendArgs.HopTx.From) if err != nil { - return tx, statusErrors.CreateErrorResponseFromError(err) + return tx, createBridgeHopErrorResponse(err) } argNonce := hexutil.Uint64(nonce) @@ -324,12 +327,12 @@ func (h *HopBridgeProcessor) sendOrBuild(sendArgs *MultipathProcessorTxArgs, sig ethClient, err := h.contractMaker.RPCClient.EthClient(fromChain.ChainID) if err != nil { - return tx, statusErrors.CreateErrorResponseFromError(err) + return tx, createBridgeHopErrorResponse(err) } contractAddress, contractType, err := hop.GetContractAddress(fromChain.ChainID, sendArgs.HopTx.Symbol) if err != nil { - return tx, statusErrors.CreateErrorResponseFromError(err) + return tx, createBridgeHopErrorResponse(err) } bonderKey := makeKey(sendArgs.HopTx.ChainID, sendArgs.HopTx.ChainIDTo, "", "") @@ -354,11 +357,11 @@ func (h *HopBridgeProcessor) sendOrBuild(sendArgs *MultipathProcessorTxArgs, sig return tx, ErrContractTypeNotSupported } if err != nil { - return tx, statusErrors.CreateErrorResponseFromError(err) + return tx, createBridgeHopErrorResponse(err) } err = h.transactor.StoreAndTrackPendingTx(txOpts.From, sendArgs.HopTx.Symbol, sendArgs.ChainID, sendArgs.HopTx.MultiTransactionID, tx) if err != nil { - return tx, statusErrors.CreateErrorResponseFromError(err) + return tx, createBridgeHopErrorResponse(err) } return tx, nil } @@ -366,7 +369,7 @@ func (h *HopBridgeProcessor) sendOrBuild(sendArgs *MultipathProcessorTxArgs, sig func (h *HopBridgeProcessor) Send(sendArgs *MultipathProcessorTxArgs, verifiedAccount *account.SelectedExtKey) (hash types.Hash, err error) { tx, err := h.sendOrBuild(sendArgs, getSigner(sendArgs.ChainID, sendArgs.HopTx.From, verifiedAccount)) if err != nil { - return types.Hash{}, statusErrors.CreateErrorResponseFromError(err) + return types.Hash{}, createBridgeHopErrorResponse(err) } return types.Hash(tx.Hash()), nil } @@ -427,7 +430,7 @@ func (h *HopBridgeProcessor) CalculateFees(params ProcessorInputParams) (*big.In bonderFee := &BonderFee{} err = json.Unmarshal(response, bonderFee) if err != nil { - return nil, nil, statusErrors.CreateErrorResponseFromError(err) + return nil, nil, createBridgeHopErrorResponse(err) } h.bonderFee.Store(bonderKey, bonderFee) @@ -465,7 +468,7 @@ func (h *HopBridgeProcessor) sendCctpL1BridgeTx(contractAddress common.Address, ethClient, ) if err != nil { - return tx, statusErrors.CreateErrorResponseFromError(err) + return tx, createBridgeHopErrorResponse(err) } return contractInstance.Send( @@ -495,7 +498,7 @@ func (h *HopBridgeProcessor) sendL1BridgeTx(contractAddress common.Address, ethC ethClient, ) if err != nil { - return tx, statusErrors.CreateErrorResponseFromError(err) + return tx, createBridgeHopErrorResponse(err) } return contractInstance.SendToL2( @@ -515,7 +518,7 @@ func (h *HopBridgeProcessor) sendL1BridgeTx(contractAddress common.Address, ethC ethClient, ) if err != nil { - return tx, statusErrors.CreateErrorResponseFromError(err) + return tx, createBridgeHopErrorResponse(err) } return contractInstance.SendToL2( @@ -534,7 +537,7 @@ func (h *HopBridgeProcessor) sendL1BridgeTx(contractAddress common.Address, ethC ethClient, ) if err != nil { - return tx, statusErrors.CreateErrorResponseFromError(err) + return tx, createBridgeHopErrorResponse(err) } return contractInstance.SendToL2( @@ -564,7 +567,7 @@ func (h *HopBridgeProcessor) sendCctpL2BridgeTx(contractAddress common.Address, ethClient, ) if err != nil { - return tx, statusErrors.CreateErrorResponseFromError(err) + return tx, createBridgeHopErrorResponse(err) } return contractInstance.Send( @@ -595,7 +598,7 @@ func (h *HopBridgeProcessor) sendL2AmmWrapperTx(contractAddress common.Address, ethClient, ) if err != nil { - return tx, statusErrors.CreateErrorResponseFromError(err) + return tx, createBridgeHopErrorResponse(err) } return contractInstance.SwapAndSend( @@ -630,7 +633,7 @@ func (h *HopBridgeProcessor) sendL2BridgeTx(contractAddress common.Address, ethC ethClient, ) if err != nil { - return tx, statusErrors.CreateErrorResponseFromError(err) + return tx, createBridgeHopErrorResponse(err) } return contractInstance.Send( @@ -649,7 +652,7 @@ func (h *HopBridgeProcessor) sendL2BridgeTx(contractAddress common.Address, ethC ethClient, ) if err != nil { - return tx, statusErrors.CreateErrorResponseFromError(err) + return tx, createBridgeHopErrorResponse(err) } return contractInstance.Send( diff --git a/services/wallet/router/pathprocessor/processor_ens_public_key.go b/services/wallet/router/pathprocessor/processor_ens_public_key.go index 5aab2d25e..bbc2c90b3 100644 --- a/services/wallet/router/pathprocessor/processor_ens_public_key.go +++ b/services/wallet/router/pathprocessor/processor_ens_public_key.go @@ -13,7 +13,6 @@ import ( "github.com/status-im/status-go/account" "github.com/status-im/status-go/contracts" "github.com/status-im/status-go/contracts/resolver" - statusErrors "github.com/status-im/status-go/errors" "github.com/status-im/status-go/eth-node/types" "github.com/status-im/status-go/rpc" "github.com/status-im/status-go/services/ens" @@ -37,6 +36,10 @@ func NewENSPublicKeyProcessor(rpcClient *rpc.Client, transactor transactions.Tra } } +func createENSPublicKeyErrorResponse(err error) error { + return createErrorResponse(ProcessorENSPublicKeyName, err) +} + func (s *ENSPublicKeyProcessor) Name() string { return ProcessorENSPublicKeyName } @@ -52,7 +55,7 @@ func (s *ENSPublicKeyProcessor) CalculateFees(params ProcessorInputParams) (*big func (s *ENSPublicKeyProcessor) PackTxInputData(params ProcessorInputParams) ([]byte, error) { resolverABI, err := abi.JSON(strings.NewReader(resolver.PublicResolverABI)) if err != nil { - return []byte{}, statusErrors.CreateErrorResponseFromError(err) + return []byte{}, createENSPublicKeyErrorResponse(err) } x, y := ens.ExtractCoordinates(params.PublicKey) @@ -71,12 +74,12 @@ func (s *ENSPublicKeyProcessor) EstimateGas(params ProcessorInputParams) (uint64 contractAddress, err := s.GetContractAddress(params) if err != nil { - return 0, statusErrors.CreateErrorResponseFromError(err) + return 0, createENSPublicKeyErrorResponse(err) } input, err := s.PackTxInputData(params) if err != nil { - return 0, statusErrors.CreateErrorResponseFromError(err) + return 0, createENSPublicKeyErrorResponse(err) } ethClient, err := s.contractMaker.RPCClient.EthClient(params.FromChain.ChainID) @@ -93,7 +96,7 @@ func (s *ENSPublicKeyProcessor) EstimateGas(params ProcessorInputParams) (uint64 estimation, err := ethClient.EstimateGas(context.Background(), msg) if err != nil { - return 0, statusErrors.CreateErrorResponseFromError(err) + return 0, createENSPublicKeyErrorResponse(err) } increasedEstimation := float64(estimation) * IncreaseEstimatedGasFactor @@ -105,7 +108,7 @@ func (s *ENSPublicKeyProcessor) BuildTx(params ProcessorInputParams) (*ethTypes. toAddr := types.Address(params.ToAddr) inputData, err := s.PackTxInputData(params) if err != nil { - return nil, statusErrors.CreateErrorResponseFromError(err) + return nil, createENSPublicKeyErrorResponse(err) } sendArgs := &MultipathProcessorTxArgs{ @@ -136,7 +139,7 @@ func (s *ENSPublicKeyProcessor) CalculateAmountOut(params ProcessorInputParams) func (s *ENSPublicKeyProcessor) GetContractAddress(params ProcessorInputParams) (common.Address, error) { addr, err := s.ensService.API().Resolver(context.Background(), params.FromChain.ChainID, params.Username) if err != nil { - return common.Address{}, statusErrors.CreateErrorResponseFromError(err) + return common.Address{}, createENSPublicKeyErrorResponse(err) } if *addr == ZeroAddress { return common.Address{}, ErrENSResolverNotFound diff --git a/services/wallet/router/pathprocessor/processor_ens_register.go b/services/wallet/router/pathprocessor/processor_ens_register.go index 18e13d031..eac6e0c96 100644 --- a/services/wallet/router/pathprocessor/processor_ens_register.go +++ b/services/wallet/router/pathprocessor/processor_ens_register.go @@ -15,7 +15,6 @@ import ( "github.com/status-im/status-go/contracts" "github.com/status-im/status-go/contracts/registrar" "github.com/status-im/status-go/contracts/snt" - statusErrors "github.com/status-im/status-go/errors" "github.com/status-im/status-go/eth-node/types" "github.com/status-im/status-go/rpc" "github.com/status-im/status-go/services/ens" @@ -39,6 +38,10 @@ func NewENSRegisterProcessor(rpcClient *rpc.Client, transactor transactions.Tran } } +func createENSRegisterProcessorErrorResponse(err error) error { + return createErrorResponse(ProcessorENSRegisterName, err) +} + func (s *ENSRegisterProcessor) Name() string { return ProcessorENSRegisterName } @@ -46,11 +49,11 @@ func (s *ENSRegisterProcessor) Name() string { func (s *ENSRegisterProcessor) GetPriceForRegisteringEnsName(chainID uint64) (*big.Int, error) { registryAddr, err := s.ensService.API().GetRegistrarAddress(context.Background(), chainID) if err != nil { - return nil, statusErrors.CreateErrorResponseFromError(err) + return nil, createENSRegisterProcessorErrorResponse(err) } registrar, err := s.contractMaker.NewUsernameRegistrar(chainID, registryAddr) if err != nil { - return nil, statusErrors.CreateErrorResponseFromError(err) + return nil, createENSRegisterProcessorErrorResponse(err) } callOpts := &bind.CallOpts{Context: context.Background(), Pending: false} @@ -68,28 +71,28 @@ func (s *ENSRegisterProcessor) CalculateFees(params ProcessorInputParams) (*big. func (s *ENSRegisterProcessor) PackTxInputData(params ProcessorInputParams) ([]byte, error) { price, err := s.GetPriceForRegisteringEnsName(params.FromChain.ChainID) if err != nil { - return []byte{}, statusErrors.CreateErrorResponseFromError(err) + return []byte{}, createENSRegisterProcessorErrorResponse(err) } registrarABI, err := abi.JSON(strings.NewReader(registrar.UsernameRegistrarABI)) if err != nil { - return []byte{}, statusErrors.CreateErrorResponseFromError(err) + return []byte{}, createENSRegisterProcessorErrorResponse(err) } x, y := ens.ExtractCoordinates(params.PublicKey) extraData, err := registrarABI.Pack("register", ens.UsernameToLabel(params.Username), params.FromAddr, x, y) if err != nil { - return []byte{}, statusErrors.CreateErrorResponseFromError(err) + return []byte{}, createENSRegisterProcessorErrorResponse(err) } sntABI, err := abi.JSON(strings.NewReader(snt.SNTABI)) if err != nil { - return []byte{}, statusErrors.CreateErrorResponseFromError(err) + return []byte{}, createENSRegisterProcessorErrorResponse(err) } registryAddr, err := s.ensService.API().GetRegistrarAddress(context.Background(), params.FromChain.ChainID) if err != nil { - return []byte{}, statusErrors.CreateErrorResponseFromError(err) + return []byte{}, createENSRegisterProcessorErrorResponse(err) } return sntABI.Pack("approveAndCall", registryAddr, price, extraData) @@ -107,17 +110,17 @@ func (s *ENSRegisterProcessor) EstimateGas(params ProcessorInputParams) (uint64, contractAddress, err := s.GetContractAddress(params) if err != nil { - return 0, statusErrors.CreateErrorResponseFromError(err) + return 0, createENSRegisterProcessorErrorResponse(err) } input, err := s.PackTxInputData(params) if err != nil { - return 0, statusErrors.CreateErrorResponseFromError(err) + return 0, createENSRegisterProcessorErrorResponse(err) } ethClient, err := s.contractMaker.RPCClient.EthClient(params.FromChain.ChainID) if err != nil { - return 0, statusErrors.CreateErrorResponseFromError(err) + return 0, createENSRegisterProcessorErrorResponse(err) } msg := ethereum.CallMsg{ @@ -129,7 +132,7 @@ func (s *ENSRegisterProcessor) EstimateGas(params ProcessorInputParams) (uint64, estimation, err := ethClient.EstimateGas(context.Background(), msg) if err != nil { - return 0, statusErrors.CreateErrorResponseFromError(err) + return 0, createENSRegisterProcessorErrorResponse(err) } increasedEstimation := float64(estimation) * IncreaseEstimatedGasFactor @@ -141,7 +144,7 @@ func (s *ENSRegisterProcessor) BuildTx(params ProcessorInputParams) (*ethTypes.T toAddr := types.Address(params.ToAddr) inputData, err := s.PackTxInputData(params) if err != nil { - return nil, statusErrors.CreateErrorResponseFromError(err) + return nil, createENSRegisterProcessorErrorResponse(err) } sendArgs := &MultipathProcessorTxArgs{ diff --git a/services/wallet/router/pathprocessor/processor_ens_release.go b/services/wallet/router/pathprocessor/processor_ens_release.go index 39fffdd80..76a61dec5 100644 --- a/services/wallet/router/pathprocessor/processor_ens_release.go +++ b/services/wallet/router/pathprocessor/processor_ens_release.go @@ -13,7 +13,6 @@ import ( "github.com/status-im/status-go/account" "github.com/status-im/status-go/contracts" "github.com/status-im/status-go/contracts/registrar" - statusErrors "github.com/status-im/status-go/errors" "github.com/status-im/status-go/eth-node/types" "github.com/status-im/status-go/rpc" "github.com/status-im/status-go/services/ens" @@ -37,6 +36,10 @@ func NewENSReleaseProcessor(rpcClient *rpc.Client, transactor transactions.Trans } } +func createENSReleaseErrorResponse(err error) error { + return createErrorResponse(ProcessorENSReleaseName, err) +} + func (s *ENSReleaseProcessor) Name() string { return ProcessorENSReleaseName } @@ -52,7 +55,7 @@ func (s *ENSReleaseProcessor) CalculateFees(params ProcessorInputParams) (*big.I func (s *ENSReleaseProcessor) PackTxInputData(params ProcessorInputParams) ([]byte, error) { registrarABI, err := abi.JSON(strings.NewReader(registrar.UsernameRegistrarABI)) if err != nil { - return []byte{}, statusErrors.CreateErrorResponseFromError(err) + return []byte{}, createENSReleaseErrorResponse(err) } return registrarABI.Pack("release", ens.UsernameToLabel(params.Username)) @@ -70,17 +73,17 @@ func (s *ENSReleaseProcessor) EstimateGas(params ProcessorInputParams) (uint64, contractAddress, err := s.GetContractAddress(params) if err != nil { - return 0, statusErrors.CreateErrorResponseFromError(err) + return 0, createENSReleaseErrorResponse(err) } input, err := s.PackTxInputData(params) if err != nil { - return 0, statusErrors.CreateErrorResponseFromError(err) + return 0, createENSReleaseErrorResponse(err) } ethClient, err := s.contractMaker.RPCClient.EthClient(params.FromChain.ChainID) if err != nil { - return 0, statusErrors.CreateErrorResponseFromError(err) + return 0, createENSReleaseErrorResponse(err) } msg := ethereum.CallMsg{ @@ -92,7 +95,7 @@ func (s *ENSReleaseProcessor) EstimateGas(params ProcessorInputParams) (uint64, estimation, err := ethClient.EstimateGas(context.Background(), msg) if err != nil { - return 0, statusErrors.CreateErrorResponseFromError(err) + return 0, createENSReleaseErrorResponse(err) } increasedEstimation := float64(estimation) * IncreaseEstimatedGasFactor @@ -104,7 +107,7 @@ func (s *ENSReleaseProcessor) BuildTx(params ProcessorInputParams) (*ethTypes.Tr toAddr := types.Address(params.ToAddr) inputData, err := s.PackTxInputData(params) if err != nil { - return nil, statusErrors.CreateErrorResponseFromError(err) + return nil, createENSReleaseErrorResponse(err) } sendArgs := &MultipathProcessorTxArgs{ diff --git a/services/wallet/router/pathprocessor/processor_erc1155.go b/services/wallet/router/pathprocessor/processor_erc1155.go index 66ef0039e..4dd6e6b03 100644 --- a/services/wallet/router/pathprocessor/processor_erc1155.go +++ b/services/wallet/router/pathprocessor/processor_erc1155.go @@ -14,7 +14,6 @@ import ( ethTypes "github.com/ethereum/go-ethereum/core/types" "github.com/status-im/status-go/account" "github.com/status-im/status-go/contracts/ierc1155" - statusErrors "github.com/status-im/status-go/errors" "github.com/status-im/status-go/eth-node/types" "github.com/status-im/status-go/rpc" "github.com/status-im/status-go/transactions" @@ -36,6 +35,10 @@ func NewERC1155Processor(rpcClient *rpc.Client, transactor transactions.Transact return &ERC1155Processor{rpcClient: rpcClient, transactor: transactor} } +func createERC1155ErrorResponse(err error) error { + return createErrorResponse(ProcessorERC1155Name, err) +} + func (s *ERC1155Processor) Name() string { return ProcessorERC1155Name } @@ -51,12 +54,12 @@ func (s *ERC1155Processor) CalculateFees(params ProcessorInputParams) (*big.Int, func (s *ERC1155Processor) PackTxInputData(params ProcessorInputParams) ([]byte, error) { abi, err := abi.JSON(strings.NewReader(ierc1155.Ierc1155ABI)) if err != nil { - return []byte{}, statusErrors.CreateErrorResponseFromError(err) + return []byte{}, createERC1155ErrorResponse(err) } id, success := big.NewInt(0).SetString(params.FromToken.Symbol, 0) if !success { - return []byte{}, statusErrors.CreateErrorResponseFromError(fmt.Errorf("failed to convert %s to big.Int", params.FromToken.Symbol)) + return []byte{}, createERC1155ErrorResponse(fmt.Errorf("failed to convert %s to big.Int", params.FromToken.Symbol)) } return abi.Pack("safeTransferFrom", @@ -80,14 +83,14 @@ func (s *ERC1155Processor) EstimateGas(params ProcessorInputParams) (uint64, err ethClient, err := s.rpcClient.EthClient(params.FromChain.ChainID) if err != nil { - return 0, statusErrors.CreateErrorResponseFromError(err) + return 0, createERC1155ErrorResponse(err) } value := new(big.Int) input, err := s.PackTxInputData(params) if err != nil { - return 0, statusErrors.CreateErrorResponseFromError(err) + return 0, createERC1155ErrorResponse(err) } msg := ethereum.CallMsg{ @@ -99,7 +102,7 @@ func (s *ERC1155Processor) EstimateGas(params ProcessorInputParams) (uint64, err estimation, err := ethClient.EstimateGas(context.Background(), msg) if err != nil { - return 0, statusErrors.CreateErrorResponseFromError(err) + return 0, createERC1155ErrorResponse(err) } increasedEstimation := float64(estimation) * IncreaseEstimatedGasFactor return uint64(increasedEstimation), nil @@ -111,7 +114,7 @@ func (s *ERC1155Processor) BuildTx(params ProcessorInputParams) (*ethTypes.Trans // We store ERC1155 Token ID using big.Int.String() in token.Symbol tokenID, success := new(big.Int).SetString(params.FromToken.Symbol, 10) if !success { - return nil, statusErrors.CreateErrorResponseFromError(fmt.Errorf("failed to convert ERC1155's Symbol %s to big.Int", params.FromToken.Symbol)) + return nil, createERC1155ErrorResponse(fmt.Errorf("failed to convert ERC1155's Symbol %s to big.Int", params.FromToken.Symbol)) } sendArgs := &MultipathProcessorTxArgs{ @@ -135,17 +138,17 @@ func (s *ERC1155Processor) BuildTx(params ProcessorInputParams) (*ethTypes.Trans func (s *ERC1155Processor) sendOrBuild(sendArgs *MultipathProcessorTxArgs, signerFn bind.SignerFn) (tx *ethTypes.Transaction, err error) { ethClient, err := s.rpcClient.EthClient(sendArgs.ChainID) if err != nil { - return tx, statusErrors.CreateErrorResponseFromError(err) + return tx, createERC1155ErrorResponse(err) } contract, err := ierc1155.NewIerc1155(common.Address(*sendArgs.ERC1155TransferTx.To), ethClient) if err != nil { - return tx, statusErrors.CreateErrorResponseFromError(err) + return tx, createERC1155ErrorResponse(err) } nonce, err := s.transactor.NextNonce(s.rpcClient, sendArgs.ChainID, sendArgs.ERC1155TransferTx.From) if err != nil { - return tx, statusErrors.CreateErrorResponseFromError(err) + return tx, createERC1155ErrorResponse(err) } argNonce := hexutil.Uint64(nonce) @@ -160,11 +163,11 @@ func (s *ERC1155Processor) sendOrBuild(sendArgs *MultipathProcessorTxArgs, signe []byte{}, ) if err != nil { - return tx, statusErrors.CreateErrorResponseFromError(err) + return tx, createERC1155ErrorResponse(err) } err = s.transactor.StoreAndTrackPendingTx(from, sendArgs.ERC1155TransferTx.Symbol, sendArgs.ChainID, sendArgs.ERC1155TransferTx.MultiTransactionID, tx) if err != nil { - return tx, statusErrors.CreateErrorResponseFromError(err) + return tx, createERC1155ErrorResponse(err) } return tx, nil } @@ -172,7 +175,7 @@ func (s *ERC1155Processor) sendOrBuild(sendArgs *MultipathProcessorTxArgs, signe func (s *ERC1155Processor) Send(sendArgs *MultipathProcessorTxArgs, verifiedAccount *account.SelectedExtKey) (hash types.Hash, err error) { tx, err := s.sendOrBuild(sendArgs, getSigner(sendArgs.ChainID, sendArgs.ERC1155TransferTx.From, verifiedAccount)) if err != nil { - return hash, statusErrors.CreateErrorResponseFromError(err) + return hash, createERC1155ErrorResponse(err) } return types.Hash(tx.Hash()), nil } diff --git a/services/wallet/router/pathprocessor/processor_erc721.go b/services/wallet/router/pathprocessor/processor_erc721.go index 2c77f21de..b8f14557f 100644 --- a/services/wallet/router/pathprocessor/processor_erc721.go +++ b/services/wallet/router/pathprocessor/processor_erc721.go @@ -14,7 +14,6 @@ import ( ethTypes "github.com/ethereum/go-ethereum/core/types" "github.com/status-im/status-go/account" "github.com/status-im/status-go/contracts/community-tokens/collectibles" - statusErrors "github.com/status-im/status-go/errors" "github.com/status-im/status-go/eth-node/types" "github.com/status-im/status-go/rpc" "github.com/status-im/status-go/transactions" @@ -35,6 +34,10 @@ func NewERC721Processor(rpcClient *rpc.Client, transactor transactions.Transacto return &ERC721Processor{rpcClient: rpcClient, transactor: transactor} } +func createERC721ErrorResponse(err error) error { + return createErrorResponse(ProcessorERC721Name, err) +} + func (s *ERC721Processor) Name() string { return ProcessorERC721Name } @@ -50,12 +53,12 @@ func (s *ERC721Processor) CalculateFees(params ProcessorInputParams) (*big.Int, func (s *ERC721Processor) PackTxInputData(params ProcessorInputParams) ([]byte, error) { abi, err := abi.JSON(strings.NewReader(collectibles.CollectiblesMetaData.ABI)) if err != nil { - return []byte{}, statusErrors.CreateErrorResponseFromError(err) + return []byte{}, createERC721ErrorResponse(err) } id, success := big.NewInt(0).SetString(params.FromToken.Symbol, 0) if !success { - return []byte{}, statusErrors.CreateErrorResponseFromError(fmt.Errorf("failed to convert %s to big.Int", params.FromToken.Symbol)) + return []byte{}, createERC721ErrorResponse(fmt.Errorf("failed to convert %s to big.Int", params.FromToken.Symbol)) } return abi.Pack("safeTransferFrom", @@ -77,14 +80,14 @@ func (s *ERC721Processor) EstimateGas(params ProcessorInputParams) (uint64, erro ethClient, err := s.rpcClient.EthClient(params.FromChain.ChainID) if err != nil { - return 0, statusErrors.CreateErrorResponseFromError(err) + return 0, createERC721ErrorResponse(err) } value := new(big.Int) input, err := s.PackTxInputData(params) if err != nil { - return 0, statusErrors.CreateErrorResponseFromError(err) + return 0, createERC721ErrorResponse(err) } msg := ethereum.CallMsg{ @@ -96,7 +99,7 @@ func (s *ERC721Processor) EstimateGas(params ProcessorInputParams) (uint64, erro estimation, err := ethClient.EstimateGas(context.Background(), msg) if err != nil { - return 0, statusErrors.CreateErrorResponseFromError(err) + return 0, createERC721ErrorResponse(err) } increasedEstimation := float64(estimation) * IncreaseEstimatedGasFactor @@ -109,7 +112,7 @@ func (s *ERC721Processor) BuildTx(params ProcessorInputParams) (*ethTypes.Transa // We store ERC721 Token ID using big.Int.String() in token.Symbol tokenID, success := new(big.Int).SetString(params.FromToken.Symbol, 10) if !success { - return nil, statusErrors.CreateErrorResponseFromError(fmt.Errorf("failed to convert ERC721's Symbol %s to big.Int", params.FromToken.Symbol)) + return nil, createERC721ErrorResponse(fmt.Errorf("failed to convert ERC721's Symbol %s to big.Int", params.FromToken.Symbol)) } sendArgs := &MultipathProcessorTxArgs{ @@ -132,17 +135,17 @@ func (s *ERC721Processor) BuildTx(params ProcessorInputParams) (*ethTypes.Transa func (s *ERC721Processor) sendOrBuild(sendArgs *MultipathProcessorTxArgs, signerFn bind.SignerFn) (tx *ethTypes.Transaction, err error) { ethClient, err := s.rpcClient.EthClient(sendArgs.ChainID) if err != nil { - return tx, statusErrors.CreateErrorResponseFromError(err) + return tx, createERC721ErrorResponse(err) } contract, err := collectibles.NewCollectibles(common.Address(*sendArgs.ERC721TransferTx.To), ethClient) if err != nil { - return tx, statusErrors.CreateErrorResponseFromError(err) + return tx, createERC721ErrorResponse(err) } nonce, err := s.transactor.NextNonce(s.rpcClient, sendArgs.ChainID, sendArgs.ERC721TransferTx.From) if err != nil { - return tx, statusErrors.CreateErrorResponseFromError(err) + return tx, createERC721ErrorResponse(err) } argNonce := hexutil.Uint64(nonce) @@ -153,11 +156,11 @@ func (s *ERC721Processor) sendOrBuild(sendArgs *MultipathProcessorTxArgs, signer sendArgs.ERC721TransferTx.Recipient, sendArgs.ERC721TransferTx.TokenID.ToInt()) if err != nil { - return tx, statusErrors.CreateErrorResponseFromError(err) + return tx, createERC721ErrorResponse(err) } err = s.transactor.StoreAndTrackPendingTx(from, sendArgs.ERC721TransferTx.Symbol, sendArgs.ChainID, sendArgs.ERC721TransferTx.MultiTransactionID, tx) if err != nil { - return tx, statusErrors.CreateErrorResponseFromError(err) + return tx, createERC721ErrorResponse(err) } return tx, nil } @@ -165,7 +168,7 @@ func (s *ERC721Processor) sendOrBuild(sendArgs *MultipathProcessorTxArgs, signer func (s *ERC721Processor) Send(sendArgs *MultipathProcessorTxArgs, verifiedAccount *account.SelectedExtKey) (hash types.Hash, err error) { tx, err := s.sendOrBuild(sendArgs, getSigner(sendArgs.ChainID, sendArgs.ERC721TransferTx.From, verifiedAccount)) if err != nil { - return hash, statusErrors.CreateErrorResponseFromError(err) + return hash, createERC721ErrorResponse(err) } return types.Hash(tx.Hash()), nil } diff --git a/services/wallet/router/pathprocessor/processor_stickers_buy.go b/services/wallet/router/pathprocessor/processor_stickers_buy.go index 05cab94c6..c8433adfe 100644 --- a/services/wallet/router/pathprocessor/processor_stickers_buy.go +++ b/services/wallet/router/pathprocessor/processor_stickers_buy.go @@ -15,7 +15,6 @@ import ( "github.com/status-im/status-go/contracts" "github.com/status-im/status-go/contracts/snt" stickersContracts "github.com/status-im/status-go/contracts/stickers" - statusErrors "github.com/status-im/status-go/errors" "github.com/status-im/status-go/eth-node/types" "github.com/status-im/status-go/rpc" "github.com/status-im/status-go/services/stickers" @@ -39,6 +38,10 @@ func NewStickersBuyProcessor(rpcClient *rpc.Client, transactor transactions.Tran } } +func createStickersBuyErrorResponse(err error) error { + return createErrorResponse(ProcessorStickersBuyName, err) +} + func (s *StickersBuyProcessor) Name() string { return ProcessorStickersBuyName } @@ -54,34 +57,34 @@ func (s *StickersBuyProcessor) CalculateFees(params ProcessorInputParams) (*big. func (s *StickersBuyProcessor) PackTxInputData(params ProcessorInputParams) ([]byte, error) { stickerType, err := s.contractMaker.NewStickerType(params.FromChain.ChainID) if err != nil { - return []byte{}, statusErrors.CreateErrorResponseFromError(err) + return []byte{}, createStickersBuyErrorResponse(err) } callOpts := &bind.CallOpts{Context: context.Background(), Pending: false} packInfo, err := stickerType.GetPackData(callOpts, params.PackID) if err != nil { - return []byte{}, statusErrors.CreateErrorResponseFromError(err) + return []byte{}, createStickersBuyErrorResponse(err) } stickerMarketABI, err := abi.JSON(strings.NewReader(stickersContracts.StickerMarketABI)) if err != nil { - return []byte{}, statusErrors.CreateErrorResponseFromError(err) + return []byte{}, createStickersBuyErrorResponse(err) } extraData, err := stickerMarketABI.Pack("buyToken", params.PackID, params.FromAddr, packInfo.Price) if err != nil { - return []byte{}, statusErrors.CreateErrorResponseFromError(err) + return []byte{}, createStickersBuyErrorResponse(err) } sntABI, err := abi.JSON(strings.NewReader(snt.SNTABI)) if err != nil { - return []byte{}, statusErrors.CreateErrorResponseFromError(err) + return []byte{}, createStickersBuyErrorResponse(err) } stickerMarketAddress, err := stickersContracts.StickerMarketContractAddress(params.FromChain.ChainID) if err != nil { - return []byte{}, statusErrors.CreateErrorResponseFromError(err) + return []byte{}, createStickersBuyErrorResponse(err) } return sntABI.Pack("approveAndCall", stickerMarketAddress, packInfo.Price, extraData) @@ -99,17 +102,17 @@ func (s *StickersBuyProcessor) EstimateGas(params ProcessorInputParams) (uint64, contractAddress, err := s.GetContractAddress(params) if err != nil { - return 0, statusErrors.CreateErrorResponseFromError(err) + return 0, createStickersBuyErrorResponse(err) } input, err := s.PackTxInputData(params) if err != nil { - return 0, statusErrors.CreateErrorResponseFromError(err) + return 0, createStickersBuyErrorResponse(err) } ethClient, err := s.contractMaker.RPCClient.EthClient(params.FromChain.ChainID) if err != nil { - return 0, statusErrors.CreateErrorResponseFromError(err) + return 0, createStickersBuyErrorResponse(err) } msg := ethereum.CallMsg{ @@ -121,7 +124,7 @@ func (s *StickersBuyProcessor) EstimateGas(params ProcessorInputParams) (uint64, estimation, err := ethClient.EstimateGas(context.Background(), msg) if err != nil { - return 0, statusErrors.CreateErrorResponseFromError(err) + return 0, createStickersBuyErrorResponse(err) } increasedEstimation := float64(estimation) * IncreaseEstimatedGasFactor @@ -133,7 +136,7 @@ func (s *StickersBuyProcessor) BuildTx(params ProcessorInputParams) (*ethTypes.T toAddr := types.Address(params.ToAddr) inputData, err := s.PackTxInputData(params) if err != nil { - return nil, statusErrors.CreateErrorResponseFromError(err) + return nil, createStickersBuyErrorResponse(err) } sendArgs := &MultipathProcessorTxArgs{ diff --git a/services/wallet/router/pathprocessor/processor_swap_paraswap.go b/services/wallet/router/pathprocessor/processor_swap_paraswap.go index ff41e1f68..d64f43616 100644 --- a/services/wallet/router/pathprocessor/processor_swap_paraswap.go +++ b/services/wallet/router/pathprocessor/processor_swap_paraswap.go @@ -10,7 +10,6 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" ethTypes "github.com/ethereum/go-ethereum/core/types" "github.com/status-im/status-go/account" - statusErrors "github.com/status-im/status-go/errors" "github.com/status-im/status-go/eth-node/types" "github.com/status-im/status-go/rpc" walletCommon "github.com/status-im/status-go/services/wallet/common" @@ -42,6 +41,16 @@ func NewSwapParaswapProcessor(rpcClient *rpc.Client, transactor transactions.Tra } } +func createSwapParaswapErrorResponse(err error) error { + switch err.Error() { + case "Price Timeout": + return ErrPriceTimeout + case "No routes found with enough liquidity": + return ErrNotEnoughLiquidity + } + return createErrorResponse(ProcessorSwapParaswapName, err) +} + func (s *SwapParaswapProcessor) Name() string { return ProcessorSwapParaswapName } @@ -73,7 +82,7 @@ func (s *SwapParaswapProcessor) AvailableFor(params ProcessorInputParams) (bool, if searchForToToken || searchForToken { tokensList, err := s.paraswapClient.FetchTokensList(context.Background()) if err != nil { - return false, statusErrors.CreateErrorResponseFromError(err) + return false, createSwapParaswapErrorResponse(err) } for _, t := range tokensList { @@ -129,7 +138,7 @@ func (s *SwapParaswapProcessor) EstimateGas(params ProcessorInputParams) (uint64 priceRoute, err := s.paraswapClient.FetchPriceRoute(context.Background(), params.FromToken.Address, params.FromToken.Decimals, params.ToToken.Address, params.ToToken.Decimals, params.AmountIn, params.FromAddr, params.ToAddr, swapSide) if err != nil { - return 0, statusErrors.CreateErrorResponseFromError(err) + return 0, createSwapParaswapErrorResponse(err) } key := makeKey(params.FromChain.ChainID, params.ToChain.ChainID, params.FromToken.Symbol, params.ToToken.Symbol) @@ -187,7 +196,7 @@ func (s *SwapParaswapProcessor) prepareTransaction(sendArgs *MultipathProcessorT common.Address(sendArgs.SwapTx.From), common.Address(*sendArgs.SwapTx.To), priceRoute.RawPriceRoute, priceRoute.Side) if err != nil { - return statusErrors.CreateErrorResponseFromError(err) + return createSwapParaswapErrorResponse(err) } value, ok := new(big.Int).SetString(tx.Value, 10) @@ -197,7 +206,7 @@ func (s *SwapParaswapProcessor) prepareTransaction(sendArgs *MultipathProcessorT gas, err := strconv.ParseUint(tx.Gas, 10, 64) if err != nil { - return statusErrors.CreateErrorResponseFromError(err) + return createSwapParaswapErrorResponse(err) } gasPrice, ok := new(big.Int).SetString(tx.GasPrice, 10) @@ -221,7 +230,7 @@ func (s *SwapParaswapProcessor) prepareTransaction(sendArgs *MultipathProcessorT func (s *SwapParaswapProcessor) BuildTransaction(sendArgs *MultipathProcessorTxArgs) (*ethTypes.Transaction, error) { err := s.prepareTransaction(sendArgs) if err != nil { - return nil, statusErrors.CreateErrorResponseFromError(err) + return nil, createSwapParaswapErrorResponse(err) } return s.transactor.ValidateAndBuildTransaction(sendArgs.ChainID, sendArgs.SwapTx.SendTxArgs) } @@ -229,7 +238,7 @@ func (s *SwapParaswapProcessor) BuildTransaction(sendArgs *MultipathProcessorTxA func (s *SwapParaswapProcessor) Send(sendArgs *MultipathProcessorTxArgs, verifiedAccount *account.SelectedExtKey) (types.Hash, error) { err := s.prepareTransaction(sendArgs) if err != nil { - return types.Hash{}, statusErrors.CreateErrorResponseFromError(err) + return types.Hash{}, createSwapParaswapErrorResponse(err) } return s.transactor.SendTransactionWithChainID(sendArgs.ChainID, sendArgs.SwapTx.SendTxArgs, verifiedAccount) diff --git a/services/wallet/router/pathprocessor/processor_transfer.go b/services/wallet/router/pathprocessor/processor_transfer.go index ad502c209..15bb974c7 100644 --- a/services/wallet/router/pathprocessor/processor_transfer.go +++ b/services/wallet/router/pathprocessor/processor_transfer.go @@ -12,7 +12,6 @@ import ( ethTypes "github.com/ethereum/go-ethereum/core/types" "github.com/status-im/status-go/account" "github.com/status-im/status-go/contracts/ierc20" - statusErrors "github.com/status-im/status-go/errors" "github.com/status-im/status-go/eth-node/types" "github.com/status-im/status-go/rpc" "github.com/status-im/status-go/transactions" @@ -27,6 +26,10 @@ func NewTransferProcessor(rpcClient *rpc.Client, transactor transactions.Transac return &TransferProcessor{rpcClient: rpcClient, transactor: transactor} } +func createTransferErrorResponse(err error) error { + return createErrorResponse(ProcessorTransferName, err) +} + func (s *TransferProcessor) Name() string { return ProcessorTransferName } @@ -54,7 +57,7 @@ func (s *TransferProcessor) PackTxInputData(params ProcessorInputParams) ([]byte } else { abi, err := abi.JSON(strings.NewReader(ierc20.IERC20ABI)) if err != nil { - return []byte{}, statusErrors.CreateErrorResponseFromError(err) + return []byte{}, createTransferErrorResponse(err) } return abi.Pack("transfer", params.ToAddr, @@ -78,18 +81,18 @@ func (s *TransferProcessor) EstimateGas(params ProcessorInputParams) (uint64, er input, err := s.PackTxInputData(params) if err != nil { - return 0, statusErrors.CreateErrorResponseFromError(err) + return 0, createTransferErrorResponse(err) } if params.FromToken.IsNative() { estimation, err = s.transactor.EstimateGas(params.FromChain, params.FromAddr, params.ToAddr, params.AmountIn, input) if err != nil { - return 0, statusErrors.CreateErrorResponseFromError(err) + return 0, createTransferErrorResponse(err) } } else { ethClient, err := s.rpcClient.EthClient(params.FromChain.ChainID) if err != nil { - return 0, statusErrors.CreateErrorResponseFromError(err) + return 0, createTransferErrorResponse(err) } ctx := context.Background() @@ -102,7 +105,7 @@ func (s *TransferProcessor) EstimateGas(params ProcessorInputParams) (uint64, er estimation, err = ethClient.EstimateGas(ctx, msg) if err != nil { - return 0, statusErrors.CreateErrorResponseFromError(err) + return 0, createTransferErrorResponse(err) } } @@ -128,14 +131,14 @@ func (s *TransferProcessor) BuildTx(params ProcessorInputParams) (*ethTypes.Tran } abi, err := abi.JSON(strings.NewReader(ierc20.IERC20ABI)) if err != nil { - return nil, statusErrors.CreateErrorResponseFromError(err) + return nil, createTransferErrorResponse(err) } input, err := abi.Pack("transfer", params.ToAddr, params.AmountIn, ) if err != nil { - return nil, statusErrors.CreateErrorResponseFromError(err) + return nil, createTransferErrorResponse(err) } sendArgs := &MultipathProcessorTxArgs{ TransferTx: &transactions.SendTxArgs{ diff --git a/services/wallet/router/router_v2.go b/services/wallet/router/router_v2.go index 89e4df94d..c4c5e7f63 100644 --- a/services/wallet/router/router_v2.go +++ b/services/wallet/router/router_v2.go @@ -10,6 +10,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/log" "github.com/status-im/status-go/errors" "github.com/status-im/status-go/params" "github.com/status-im/status-go/services/ens" @@ -121,6 +122,11 @@ type PathV2 struct { requiredNativeBalance *big.Int } +type ProcessorError struct { + ProcessorName string + Error error +} + func (p *PathV2) Equal(o *PathV2) bool { return p.FromChain.ChainID == o.FromChain.ChainID && p.ToChain.ChainID == o.ToChain.ChainID } @@ -507,12 +513,24 @@ func (r *Router) SuggestedRoutesV2(ctx context.Context, input *RouteInputParams) return nil, errors.CreateErrorResponseFromError(err) } - candidates, err := r.resolveCandidates(ctx, input, selectedFromChains, selectedTohains, balanceMap) + candidates, processorErrors, err := r.resolveCandidates(ctx, input, selectedFromChains, selectedTohains, balanceMap) if err != nil { return nil, errors.CreateErrorResponseFromError(err) } - return r.resolveRoutes(ctx, input, candidates, balanceMap) + suggestedRoutes, err := r.resolveRoutes(ctx, input, candidates, balanceMap) + + if err == nil && (suggestedRoutes == nil || len(suggestedRoutes.Best) == 0) { + // No best route found, but no error given. + if len(processorErrors) > 0 { + // Return one of the path processor errors if present. + err = errors.CreateErrorResponseFromError(processorErrors[0].Error) + } else { + err = ErrNoBestRouteFound + } + } + + return suggestedRoutes, err } // getBalanceMapForTokenOnChains returns the balance map for passed address, where the key is in format "chainID-tokenSymbol" and @@ -722,7 +740,7 @@ func (r *Router) getSelectedChains(input *RouteInputParams) (selectedFromChains } func (r *Router) resolveCandidates(ctx context.Context, input *RouteInputParams, selectedFromChains []*params.Network, - selectedTohains []*params.Network, balanceMap map[string]*big.Int) (candidates []*PathV2, err error) { + selectedTohains []*params.Network, balanceMap map[string]*big.Int) (candidates []*PathV2, processorErrors []*ProcessorError, err error) { var ( testsMode = input.testsMode && input.testParams != nil group = async.NewAtomicGroup(ctx) @@ -731,7 +749,23 @@ func (r *Router) resolveCandidates(ctx context.Context, input *RouteInputParams, crossChainAmountOptions, err := r.findOptionsForSendingAmount(input, selectedFromChains, balanceMap) if err != nil { - return nil, errors.CreateErrorResponseFromError(err) + return nil, nil, errors.CreateErrorResponseFromError(err) + } + + appendProcessorErrorFn := func(processorName string, err error) { + log.Error("routerv2.resolveCandidates error", "processor", processorName, "err", err) + mu.Lock() + defer mu.Unlock() + processorErrors = append(processorErrors, &ProcessorError{ + ProcessorName: processorName, + Error: err, + }) + } + + appendPathFn := func(path *PathV2) { + mu.Lock() + defer mu.Unlock() + candidates = append(candidates, path) } for networkIdx := range selectedFromChains { @@ -825,26 +859,34 @@ func (r *Router) resolveCandidates(ctx context.Context, input *RouteInputParams, } can, err := pProcessor.AvailableFor(processorInputParams) - if err != nil || !can { + if err != nil { + appendProcessorErrorFn(pProcessor.Name(), err) + continue + } + if !can { continue } bonderFees, tokenFees, err := pProcessor.CalculateFees(processorInputParams) if err != nil { + appendProcessorErrorFn(pProcessor.Name(), err) continue } gasLimit, err := pProcessor.EstimateGas(processorInputParams) if err != nil { + appendProcessorErrorFn(pProcessor.Name(), err) continue } approvalContractAddress, err := pProcessor.GetContractAddress(processorInputParams) if err != nil { + appendProcessorErrorFn(pProcessor.Name(), err) continue } approvalRequired, approvalAmountRequired, approvalGasLimit, l1ApprovalFee, err := r.requireApproval(ctx, input.SendType, &approvalContractAddress, processorInputParams) if err != nil { + appendProcessorErrorFn(pProcessor.Name(), err) continue } @@ -861,6 +903,7 @@ func (r *Router) resolveCandidates(ctx context.Context, input *RouteInputParams, amountOut, err := pProcessor.CalculateAmountOut(processorInputParams) if err != nil { + appendProcessorErrorFn(pProcessor.Name(), err) continue } @@ -871,8 +914,7 @@ func (r *Router) resolveCandidates(ctx context.Context, input *RouteInputParams, estimatedTime += 1 } - mu.Lock() - candidates = append(candidates, &PathV2{ + appendPathFn(&PathV2{ ProcessorName: pProcessor.Name(), FromChain: network, ToChain: dest, @@ -901,7 +943,6 @@ func (r *Router) resolveCandidates(ctx context.Context, input *RouteInputParams, EstimatedTime: estimatedTime, }) - mu.Unlock() } } } @@ -910,7 +951,7 @@ func (r *Router) resolveCandidates(ctx context.Context, input *RouteInputParams, } group.Wait() - return candidates, nil + return candidates, processorErrors, nil } func (r *Router) checkBalancesForTheBestRoute(ctx context.Context, bestRoute []*PathV2, input *RouteInputParams, balanceMap map[string]*big.Int) (err error) { diff --git a/services/wallet/router/router_v2_test.go b/services/wallet/router/router_v2_test.go index cec978fb5..76fda581b 100644 --- a/services/wallet/router/router_v2_test.go +++ b/services/wallet/router/router_v2_test.go @@ -60,6 +60,9 @@ func amountOptionsMapsEqual(map1, map2 map[uint64][]amountOption) bool { func assertPathsEqual(t *testing.T, expected, actual []*PathV2) { assert.Equal(t, len(expected), len(actual)) + if len(expected) == 0 { + return + } for _, c := range actual { found := false @@ -167,7 +170,11 @@ func TestRouterV2(t *testing.T) { if tt.expectedError != nil { assert.Error(t, err) assert.Equal(t, tt.expectedError.Error(), err.Error()) - assert.Nil(t, routes) + if routes == nil { + assert.Empty(t, tt.expectedCandidates) + } else { + assertPathsEqual(t, tt.expectedCandidates, routes.Candidates) + } } else { assert.NoError(t, err) assertPathsEqual(t, tt.expectedCandidates, routes.Candidates) diff --git a/services/wallet/router/router_v2_test_data.go b/services/wallet/router/router_v2_test_data.go index 9a84901d7..c2541bad0 100644 --- a/services/wallet/router/router_v2_test_data.go +++ b/services/wallet/router/router_v2_test_data.go @@ -772,6 +772,7 @@ func getNormalTestParamsList() []normalTestParams { approvalL1Fee: testApprovalL1Fee, }, }, + expectedError: ErrNoBestRouteFound, expectedCandidates: []*PathV2{}, }, { @@ -1760,6 +1761,7 @@ func getNormalTestParamsList() []normalTestParams { approvalL1Fee: testApprovalL1Fee, }, }, + expectedError: ErrNoBestRouteFound, expectedCandidates: []*PathV2{}, }, { @@ -2258,6 +2260,7 @@ func getNormalTestParamsList() []normalTestParams { approvalL1Fee: testApprovalL1Fee, }, }, + expectedError: ErrNoBestRouteFound, expectedCandidates: []*PathV2{}, }, { @@ -2329,6 +2332,7 @@ func getNormalTestParamsList() []normalTestParams { approvalL1Fee: testApprovalL1Fee, }, }, + expectedError: ErrNoBestRouteFound, expectedCandidates: []*PathV2{}, }, { @@ -2445,6 +2449,7 @@ func getNormalTestParamsList() []normalTestParams { approvalL1Fee: testApprovalL1Fee, }, }, + expectedError: ErrNoBestRouteFound, expectedCandidates: []*PathV2{}, }, }