test(router_validation)_: blended my validation with latest develop
This commit is contained in:
parent
3c1326be48
commit
5f666e6ad9
|
@ -65,7 +65,7 @@ func (p *Path) Equal(o *Path) bool {
|
|||
return p.From.ChainID == o.From.ChainID && p.To.ChainID == o.To.ChainID
|
||||
}
|
||||
|
||||
type Graph = []*Node
|
||||
type Graph []*Node
|
||||
|
||||
type Node struct {
|
||||
Path *Path
|
||||
|
|
|
@ -2,7 +2,6 @@ package router
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"math/big"
|
||||
|
@ -11,7 +10,7 @@ import (
|
|||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
sErrors "github.com/status-im/status-go/errors"
|
||||
"github.com/status-im/status-go/errors"
|
||||
"github.com/status-im/status-go/params"
|
||||
"github.com/status-im/status-go/services/ens"
|
||||
"github.com/status-im/status-go/services/wallet/async"
|
||||
|
@ -396,84 +395,59 @@ func validateInputData(input *RouteInputParams) error {
|
|||
}
|
||||
}
|
||||
|
||||
if input.FromLockedAmount != nil && len(input.FromLockedAmount) > 0 {
|
||||
suppNetworks := copyMap(supportedNetworks)
|
||||
if input.testnetMode {
|
||||
suppNetworks = copyMap(supportedTestNetworks)
|
||||
}
|
||||
|
||||
totalLockedAmount := big.NewInt(0)
|
||||
|
||||
for chainID, amount := range input.FromLockedAmount {
|
||||
if containsNetworkChainID(chainID, input.DisabledFromChainIDs) {
|
||||
return ErrDisabledChainFoundAmongLockedNetworks
|
||||
}
|
||||
if input.testnetMode {
|
||||
if !supportedTestNetworks[chainID] {
|
||||
return ErrLockedAmountNotSupportedForNetwork
|
||||
}
|
||||
} else {
|
||||
if !supportedNetworks[chainID] {
|
||||
return ErrLockedAmountNotSupportedForNetwork
|
||||
}
|
||||
}
|
||||
|
||||
delete(suppNetworks, chainID)
|
||||
|
||||
totalLockedAmount = new(big.Int).Add(totalLockedAmount, amount.ToInt())
|
||||
|
||||
if amount == nil || amount.ToInt().Sign() < 0 {
|
||||
return ErrLockedAmountNotNegative
|
||||
}
|
||||
}
|
||||
|
||||
if totalLockedAmount.Cmp(input.AmountIn.ToInt()) > 0 {
|
||||
return ErrLockedAmountExceedsTotalSendAmount
|
||||
} else if totalLockedAmount.Cmp(input.AmountIn.ToInt()) < 0 && len(suppNetworks) == 0 {
|
||||
return ErrLockedAmountLessThanSendAmountAllNetworks
|
||||
}
|
||||
}
|
||||
|
||||
return validateFromLockedAmount(input.FromLockedAmount, input.testnetMode)
|
||||
return validateFromLockedAmount(input)
|
||||
}
|
||||
|
||||
func validateFromLockedAmount(fromLockedAmount map[uint64]*hexutil.Big, isTestnetMode bool) error {
|
||||
if fromLockedAmount == nil || len(fromLockedAmount) == 0 {
|
||||
func validateFromLockedAmount(input *RouteInputParams) error {
|
||||
if input.FromLockedAmount == nil || len(input.FromLockedAmount) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
chainIDSet := make(map[uint64]bool)
|
||||
var suppNetworks map[uint64]bool
|
||||
if input.testnetMode {
|
||||
suppNetworks = copyMap(supportedTestNetworks)
|
||||
} else {
|
||||
suppNetworks = copyMap(supportedNetworks)
|
||||
}
|
||||
|
||||
totalLockedAmount := big.NewInt(0)
|
||||
excludedChainCount := 0
|
||||
|
||||
for chainID, amount := range fromLockedAmount {
|
||||
if isTestnetMode {
|
||||
for chainID, amount := range input.FromLockedAmount {
|
||||
if containsNetworkChainID(chainID, input.DisabledFromChainIDs) {
|
||||
return ErrDisabledChainFoundAmongLockedNetworks
|
||||
}
|
||||
|
||||
if input.testnetMode {
|
||||
if !supportedTestNetworks[chainID] {
|
||||
return errors.New("locked amount is not supported for the selected network")
|
||||
return ErrLockedAmountNotSupportedForNetwork
|
||||
}
|
||||
} else {
|
||||
if !supportedNetworks[chainID] {
|
||||
return errors.New("locked amount is not supported for the selected network")
|
||||
return ErrLockedAmountNotSupportedForNetwork
|
||||
}
|
||||
}
|
||||
|
||||
// Check locked amount is not negative
|
||||
if amount == nil || amount.ToInt().Sign() < 0 {
|
||||
return errors.New("locked amount must not be negative")
|
||||
return ErrLockedAmountNotNegative
|
||||
}
|
||||
|
||||
// Check if locked chain ID is a duplicate
|
||||
if _, exists := chainIDSet[chainID]; exists {
|
||||
// Handle duplicate chain ID
|
||||
return fmt.Errorf("a chain ID may only appear once, duplicate chain ID found '%d'", chainID)
|
||||
}
|
||||
chainIDSet[chainID] = amount.ToInt().Sign() > 0
|
||||
if !chainIDSet[chainID] {
|
||||
if !(amount.ToInt().Sign() > 0) {
|
||||
excludedChainCount++
|
||||
}
|
||||
delete(suppNetworks, chainID)
|
||||
totalLockedAmount = new(big.Int).Add(totalLockedAmount, amount.ToInt())
|
||||
}
|
||||
if (!isTestnetMode && excludedChainCount == len(supportedNetworks)) ||
|
||||
(isTestnetMode && excludedChainCount == len(supportedTestNetworks)) {
|
||||
return errors.New("all supported chains are excluded, routing impossible")
|
||||
|
||||
if (!input.testnetMode && excludedChainCount == len(supportedNetworks)) ||
|
||||
(input.testnetMode && excludedChainCount == len(supportedTestNetworks)) {
|
||||
return ErrLockedAmountExcludesAllSupported
|
||||
}
|
||||
|
||||
if totalLockedAmount.Cmp(input.AmountIn.ToInt()) > 0 {
|
||||
return ErrLockedAmountExceedsTotalSendAmount
|
||||
} else if totalLockedAmount.Cmp(input.AmountIn.ToInt()) < 0 && len(suppNetworks) == 0 {
|
||||
return ErrLockedAmountLessThanSendAmountAllNetworks
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -485,7 +459,7 @@ func (r *Router) SuggestedRoutesV2Async(input *RouteInputParams) {
|
|||
if err != nil {
|
||||
errResponse := &ErrorResponseWithUUID{
|
||||
Uuid: input.Uuid,
|
||||
ErrorResponse: sErrors.CreateErrorResponseFromError(err),
|
||||
ErrorResponse: errors.CreateErrorResponseFromError(err),
|
||||
}
|
||||
signal.SendWalletEvent(signal.SuggestedRoutes, errResponse)
|
||||
return
|
||||
|
@ -501,7 +475,7 @@ func (r *Router) StopSuggestedRoutesV2AsyncCalcualtion() {
|
|||
func (r *Router) SuggestedRoutesV2(ctx context.Context, input *RouteInputParams) (*SuggestedRoutesV2, error) {
|
||||
testnetMode, err := r.rpcClient.NetworkManager.GetTestNetworksEnabled()
|
||||
if err != nil {
|
||||
return nil, sErrors.CreateErrorResponseFromError(err)
|
||||
return nil, errors.CreateErrorResponseFromError(err)
|
||||
}
|
||||
|
||||
input.testnetMode = testnetMode
|
||||
|
@ -515,12 +489,12 @@ func (r *Router) SuggestedRoutesV2(ctx context.Context, input *RouteInputParams)
|
|||
|
||||
err = validateInputData(input)
|
||||
if err != nil {
|
||||
return nil, sErrors.CreateErrorResponseFromError(err)
|
||||
return nil, errors.CreateErrorResponseFromError(err)
|
||||
}
|
||||
|
||||
candidates, err := r.resolveCandidates(ctx, input)
|
||||
if err != nil {
|
||||
return nil, sErrors.CreateErrorResponseFromError(err)
|
||||
return nil, errors.CreateErrorResponseFromError(err)
|
||||
}
|
||||
|
||||
return r.resolveRoutes(ctx, input, candidates)
|
||||
|
@ -534,7 +508,7 @@ func (r *Router) resolveCandidates(ctx context.Context, input *RouteInputParams)
|
|||
|
||||
networks, err = r.rpcClient.NetworkManager.Get(false)
|
||||
if err != nil {
|
||||
return nil, sErrors.CreateErrorResponseFromError(err)
|
||||
return nil, errors.CreateErrorResponseFromError(err)
|
||||
}
|
||||
|
||||
var (
|
||||
|
@ -757,12 +731,12 @@ func (r *Router) checkBalancesForTheBestRoute(ctx context.Context, bestRoute []*
|
|||
if input.SendType == ERC1155Transfer {
|
||||
tokenBalance, err = r.getERC1155Balance(ctx, path.FromChain, path.FromToken, input.AddrFrom)
|
||||
if err != nil {
|
||||
return sErrors.CreateErrorResponseFromError(err)
|
||||
return errors.CreateErrorResponseFromError(err)
|
||||
}
|
||||
} else if input.SendType != ERC721Transfer {
|
||||
tokenBalance, err = r.getBalance(ctx, path.FromChain, path.FromToken, input.AddrFrom)
|
||||
if err != nil {
|
||||
return sErrors.CreateErrorResponseFromError(err)
|
||||
return errors.CreateErrorResponseFromError(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -783,7 +757,7 @@ func (r *Router) checkBalancesForTheBestRoute(ctx context.Context, bestRoute []*
|
|||
|
||||
nativeBalance, err = r.getBalance(ctx, path.FromChain, nativeToken, input.AddrFrom)
|
||||
if err != nil {
|
||||
return sErrors.CreateErrorResponseFromError(err)
|
||||
return errors.CreateErrorResponseFromError(err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -829,7 +803,7 @@ func (r *Router) resolveRoutes(ctx context.Context, input *RouteInputParams, can
|
|||
} else {
|
||||
prices, err = input.SendType.FetchPrices(r.marketManager, input.TokenID)
|
||||
if err != nil {
|
||||
return nil, sErrors.CreateErrorResponseFromError(err)
|
||||
return nil, errors.CreateErrorResponseFromError(err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -852,7 +826,7 @@ func (r *Router) resolveRoutes(ctx context.Context, input *RouteInputParams, can
|
|||
allRoutes = removeBestRouteFromAllRouters(allRoutes, best)
|
||||
continue
|
||||
} else {
|
||||
return suggestedRoutes, sErrors.CreateErrorResponseFromError(err)
|
||||
return suggestedRoutes, errors.CreateErrorResponseFromError(err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2668,6 +2668,39 @@ func TestValidateInputData(t *testing.T) {
|
|||
},
|
||||
expectedError: ErrENSRegisterMainnetSNTOnly,
|
||||
},
|
||||
{
|
||||
name: "ENSRegister valid data with mixed case username on mainnet",
|
||||
input: &RouteInputParams{
|
||||
SendType: ENSRegister,
|
||||
Username: "ValidUsername.eth",
|
||||
PublicKey: "validpublickey",
|
||||
TokenID: pathprocessor.SntSymbol,
|
||||
},
|
||||
expectedError: nil,
|
||||
},
|
||||
/*
|
||||
TODO we should introduce proper ENS validation
|
||||
{
|
||||
name: "ENSRegister with special characters in username",
|
||||
input: &RouteInputParams{
|
||||
SendType: ENSRegister,
|
||||
Username: "validuser!@#name.eth",
|
||||
PublicKey: "validpublickey",
|
||||
TokenID: pathprocessor.SntSymbol,
|
||||
},
|
||||
expectedError: ErrENSSetPubKeyInvalidUsername,
|
||||
},
|
||||
{
|
||||
name: "ENSRegister with leading and trailing spaces in username",
|
||||
input: &RouteInputParams{
|
||||
SendType: ENSRegister,
|
||||
Username: " validusername.eth ",
|
||||
PublicKey: "validpublickey",
|
||||
TokenID: pathprocessor.SntSymbol,
|
||||
},
|
||||
expectedError: ErrENSSetPubKeyInvalidUsername,
|
||||
},
|
||||
*/
|
||||
{
|
||||
name: "ENSRelease valid data",
|
||||
input: &RouteInputParams{
|
||||
|
@ -2771,6 +2804,46 @@ func TestValidateInputData(t *testing.T) {
|
|||
},
|
||||
expectedError: ErrSwapAmountOutMustBePositive,
|
||||
},
|
||||
{
|
||||
name: "Swap with very large amountIn",
|
||||
input: &RouteInputParams{
|
||||
SendType: Swap,
|
||||
TokenID: "token1",
|
||||
ToTokenID: "token2",
|
||||
AmountIn: (*hexutil.Big)(big.NewInt(1e18)),
|
||||
},
|
||||
expectedError: nil,
|
||||
},
|
||||
{
|
||||
name: "Swap with very large amountOut",
|
||||
input: &RouteInputParams{
|
||||
SendType: Swap,
|
||||
TokenID: "token1",
|
||||
ToTokenID: "token2",
|
||||
AmountOut: (*hexutil.Big)(big.NewInt(1e18)),
|
||||
},
|
||||
expectedError: nil,
|
||||
},
|
||||
{
|
||||
name: "Swap with very small amountIn",
|
||||
input: &RouteInputParams{
|
||||
SendType: Swap,
|
||||
TokenID: "token1",
|
||||
ToTokenID: "token2",
|
||||
AmountIn: (*hexutil.Big)(big.NewInt(1)),
|
||||
},
|
||||
expectedError: nil,
|
||||
},
|
||||
{
|
||||
name: "Swap with very small amountOut",
|
||||
input: &RouteInputParams{
|
||||
SendType: Swap,
|
||||
TokenID: "token1",
|
||||
ToTokenID: "token2",
|
||||
AmountOut: (*hexutil.Big)(big.NewInt(1)),
|
||||
},
|
||||
expectedError: nil,
|
||||
},
|
||||
{
|
||||
name: "fromLockedAmount with supported network on testnet",
|
||||
input: &RouteInputParams{
|
||||
|
@ -2778,6 +2851,7 @@ func TestValidateInputData(t *testing.T) {
|
|||
walletCommon.EthereumSepolia: (*hexutil.Big)(big.NewInt(10)),
|
||||
},
|
||||
testnetMode: true,
|
||||
AmountIn: (*hexutil.Big)(big.NewInt(20)),
|
||||
},
|
||||
expectedError: nil,
|
||||
},
|
||||
|
@ -2787,6 +2861,7 @@ func TestValidateInputData(t *testing.T) {
|
|||
FromLockedAmount: map[uint64]*hexutil.Big{
|
||||
walletCommon.EthereumMainnet: (*hexutil.Big)(big.NewInt(10)),
|
||||
},
|
||||
AmountIn: (*hexutil.Big)(big.NewInt(20)),
|
||||
},
|
||||
expectedError: nil,
|
||||
},
|
||||
|
@ -2834,6 +2909,7 @@ func TestValidateInputData(t *testing.T) {
|
|||
FromLockedAmount: map[uint64]*hexutil.Big{
|
||||
walletCommon.EthereumMainnet: (*hexutil.Big)(big.NewInt(0)),
|
||||
},
|
||||
AmountIn: (*hexutil.Big)(big.NewInt(20)),
|
||||
},
|
||||
expectedError: nil,
|
||||
},
|
||||
|
@ -2844,6 +2920,7 @@ func TestValidateInputData(t *testing.T) {
|
|||
walletCommon.EthereumMainnet: (*hexutil.Big)(big.NewInt(0)),
|
||||
walletCommon.OptimismMainnet: (*hexutil.Big)(big.NewInt(0)),
|
||||
},
|
||||
AmountIn: (*hexutil.Big)(big.NewInt(20)),
|
||||
},
|
||||
expectedError: nil,
|
||||
},
|
||||
|
@ -2855,6 +2932,7 @@ func TestValidateInputData(t *testing.T) {
|
|||
walletCommon.OptimismMainnet: (*hexutil.Big)(big.NewInt(0)),
|
||||
walletCommon.ArbitrumMainnet: (*hexutil.Big)(big.NewInt(0)),
|
||||
},
|
||||
AmountIn: (*hexutil.Big)(big.NewInt(20)),
|
||||
},
|
||||
expectedError: ErrLockedAmountExcludesAllSupported,
|
||||
},
|
||||
|
@ -2867,9 +2945,65 @@ func TestValidateInputData(t *testing.T) {
|
|||
walletCommon.ArbitrumSepolia: (*hexutil.Big)(big.NewInt(0)),
|
||||
},
|
||||
testnetMode: true,
|
||||
AmountIn: (*hexutil.Big)(big.NewInt(20)),
|
||||
},
|
||||
expectedError: ErrLockedAmountExcludesAllSupported,
|
||||
},
|
||||
{
|
||||
name: "fromLockedAmount with mixed supported and unsupported networks on testnet",
|
||||
input: &RouteInputParams{
|
||||
FromLockedAmount: map[uint64]*hexutil.Big{
|
||||
walletCommon.EthereumSepolia: (*hexutil.Big)(big.NewInt(10)),
|
||||
999: (*hexutil.Big)(big.NewInt(10)),
|
||||
},
|
||||
testnetMode: true,
|
||||
},
|
||||
expectedError: ErrLockedAmountNotSupportedForNetwork,
|
||||
},
|
||||
{
|
||||
name: "fromLockedAmount with mixed supported and unsupported networks on mainnet",
|
||||
input: &RouteInputParams{
|
||||
FromLockedAmount: map[uint64]*hexutil.Big{
|
||||
walletCommon.EthereumMainnet: (*hexutil.Big)(big.NewInt(10)),
|
||||
999: (*hexutil.Big)(big.NewInt(10)),
|
||||
},
|
||||
},
|
||||
expectedError: ErrLockedAmountNotSupportedForNetwork,
|
||||
},
|
||||
{
|
||||
name: "fromLockedAmount with null map on testnet",
|
||||
input: &RouteInputParams{
|
||||
FromLockedAmount: nil,
|
||||
testnetMode: true,
|
||||
AmountIn: (*hexutil.Big)(big.NewInt(20)),
|
||||
},
|
||||
expectedError: nil,
|
||||
},
|
||||
{
|
||||
name: "fromLockedAmount with null map on mainnet",
|
||||
input: &RouteInputParams{
|
||||
FromLockedAmount: nil,
|
||||
AmountIn: (*hexutil.Big)(big.NewInt(20)),
|
||||
},
|
||||
expectedError: nil,
|
||||
},
|
||||
{
|
||||
name: "fromLockedAmount with empty map on testnet",
|
||||
input: &RouteInputParams{
|
||||
FromLockedAmount: map[uint64]*hexutil.Big{},
|
||||
testnetMode: true,
|
||||
AmountIn: (*hexutil.Big)(big.NewInt(20)),
|
||||
},
|
||||
expectedError: nil,
|
||||
},
|
||||
{
|
||||
name: "fromLockedAmount with empty map on mainnet",
|
||||
input: &RouteInputParams{
|
||||
FromLockedAmount: map[uint64]*hexutil.Big{},
|
||||
AmountIn: (*hexutil.Big)(big.NewInt(20)),
|
||||
},
|
||||
expectedError: nil,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
|
|
Loading…
Reference in New Issue