mirror of
https://github.com/status-im/status-go.git
synced 2025-01-20 11:40:29 +00:00
00559692bc
It's a breaking change due to errors' changes, the list of mapped old error codes: - `"WR-001"` is now `"WRR-001"` - `"WR-002"` is now `"WRR-002"` - `"WR-003"` is now `"WRR-003"` - `"WR-004"` is now `"WRR-004"` - `"WR-005"` is now `"WRR-005"` - `"WR-006"` is now `"WRR-006"` - `"WR-007"` is now `"WRR-007"` - `"WR-008"` is now `"WRR-008"` - `"WR-009"` is now `"WRR-009"` - `"WR-010"` is now `"WRR-010"` - `"WR-011"` is now `"WRR-011"` - `"WR-012"` is now `"WRR-012"` - `"WR-013"` is now `"WRR-013"` - `"WR-014"` is now `"WRR-014"` - `"WR-015"` is now `"WRR-015"` - `"WR-019"` is now `"WRR-016"` - `"WR-020"` is now `"WRR-017"` - `"WR-021"` is now `"WRR-018"` - `"WR-025"` is now `"WRR-019"` - `"WR-016"` is now `"WR-001"` - `"WR-017"` is now `"WR-002"` - `"WR-018"` is now `"WR-003"` - `"WR-022"` is now `"WR-004"` - `"WR-023"` is now `"WR-005"` - `"WR-024"` is now `"WR-006"` - `"WR-026"` is now `"WR-007"` - `"WR-027"` is now `"WR-008"` Other changes: - `RouteInputParams` type moved to `requests` package and code updated accordingly - `SuggestedFees` type moved to a new `fees` package and code updated accordingly - `SendType` type moved to a new `sendtype` package and code updated accordingly - the following functions moved to `common` package - `ArrayContainsElement` - `ArraysWithSameElements` - `SameSingleChainTransfer` - `CopyMapGeneric` - `GweiToEth` - `WeiToGwei` - the following consts moved to `common` package - `HexAddressLength` - `SupportedNetworks` - `SupportedTestNetworks`
277 lines
7.3 KiB
Go
277 lines
7.3 KiB
Go
package router
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"encoding/json"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/status-im/status-go/appdatabase"
|
|
"github.com/status-im/status-go/params"
|
|
"github.com/status-im/status-go/rpc"
|
|
"github.com/status-im/status-go/services/wallet/router/pathprocessor"
|
|
"github.com/status-im/status-go/signal"
|
|
"github.com/status-im/status-go/t/helpers"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func amountOptionEqual(a, b amountOption) bool {
|
|
return a.amount.Cmp(b.amount) == 0 && a.locked == b.locked
|
|
}
|
|
|
|
func contains(slice []amountOption, val amountOption) bool {
|
|
for _, item := range slice {
|
|
if amountOptionEqual(item, val) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func amountOptionsMapsEqual(map1, map2 map[uint64][]amountOption) bool {
|
|
if len(map1) != len(map2) {
|
|
return false
|
|
}
|
|
|
|
for key, slice1 := range map1 {
|
|
slice2, ok := map2[key]
|
|
if !ok || len(slice1) != len(slice2) {
|
|
return false
|
|
}
|
|
|
|
for _, val1 := range slice1 {
|
|
if !contains(slice2, val1) {
|
|
return false
|
|
}
|
|
}
|
|
|
|
for _, val2 := range slice2 {
|
|
if !contains(slice1, val2) {
|
|
return false
|
|
}
|
|
}
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
func assertPathsEqual(t *testing.T, expected, actual []*Path) {
|
|
assert.Equal(t, len(expected), len(actual))
|
|
if len(expected) == 0 {
|
|
return
|
|
}
|
|
|
|
for _, c := range actual {
|
|
found := false
|
|
for _, expC := range expected {
|
|
if c.ProcessorName == expC.ProcessorName &&
|
|
c.FromChain.ChainID == expC.FromChain.ChainID &&
|
|
c.ToChain.ChainID == expC.ToChain.ChainID &&
|
|
c.ApprovalRequired == expC.ApprovalRequired &&
|
|
(expC.AmountOut == nil || c.AmountOut.ToInt().Cmp(expC.AmountOut.ToInt()) == 0) {
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
|
|
assert.True(t, found)
|
|
}
|
|
}
|
|
|
|
func setupTestNetworkDB(t *testing.T) (*sql.DB, func()) {
|
|
db, cleanup, err := helpers.SetupTestSQLDB(appdatabase.DbInitializer{}, "wallet-router-tests")
|
|
require.NoError(t, err)
|
|
return db, func() { require.NoError(t, cleanup()) }
|
|
}
|
|
|
|
func setupRouter(t *testing.T) (*Router, func()) {
|
|
db, cleanTmpDb := setupTestNetworkDB(t)
|
|
|
|
client, _ := rpc.NewClient(nil, 1, params.UpstreamRPCConfig{Enabled: false, URL: ""}, defaultNetworks, db, nil)
|
|
|
|
router := NewRouter(client, nil, nil, nil, nil, nil, nil, nil)
|
|
|
|
transfer := pathprocessor.NewTransferProcessor(nil, nil)
|
|
router.AddPathProcessor(transfer)
|
|
|
|
erc721Transfer := pathprocessor.NewERC721Processor(nil, nil)
|
|
router.AddPathProcessor(erc721Transfer)
|
|
|
|
erc1155Transfer := pathprocessor.NewERC1155Processor(nil, nil)
|
|
router.AddPathProcessor(erc1155Transfer)
|
|
|
|
hop := pathprocessor.NewHopBridgeProcessor(nil, nil, nil, nil)
|
|
router.AddPathProcessor(hop)
|
|
|
|
paraswap := pathprocessor.NewSwapParaswapProcessor(nil, nil, nil)
|
|
router.AddPathProcessor(paraswap)
|
|
|
|
ensRegister := pathprocessor.NewENSReleaseProcessor(nil, nil, nil)
|
|
router.AddPathProcessor(ensRegister)
|
|
|
|
ensRelease := pathprocessor.NewENSReleaseProcessor(nil, nil, nil)
|
|
router.AddPathProcessor(ensRelease)
|
|
|
|
ensPublicKey := pathprocessor.NewENSPublicKeyProcessor(nil, nil, nil)
|
|
router.AddPathProcessor(ensPublicKey)
|
|
|
|
buyStickers := pathprocessor.NewStickersBuyProcessor(nil, nil, nil)
|
|
router.AddPathProcessor(buyStickers)
|
|
|
|
return router, cleanTmpDb
|
|
}
|
|
|
|
type suggestedRoutesResponseEnvelope struct {
|
|
Type string `json:"type"`
|
|
Routes SuggestedRoutesResponse `json:"event"`
|
|
}
|
|
|
|
func setupSignalHandler(t *testing.T) (chan SuggestedRoutesResponse, func()) {
|
|
suggestedRoutesCh := make(chan SuggestedRoutesResponse)
|
|
signalHandler := signal.MobileSignalHandler(func(data []byte) {
|
|
var envelope signal.Envelope
|
|
err := json.Unmarshal(data, &envelope)
|
|
assert.NoError(t, err)
|
|
if envelope.Type == string(signal.SuggestedRoutes) {
|
|
var response suggestedRoutesResponseEnvelope
|
|
err := json.Unmarshal(data, &response)
|
|
assert.NoError(t, err)
|
|
|
|
suggestedRoutesCh <- response.Routes
|
|
}
|
|
})
|
|
signal.SetMobileSignalHandler(signalHandler)
|
|
t.Cleanup(signal.ResetMobileSignalHandler)
|
|
|
|
closeFn := func() {
|
|
close(suggestedRoutesCh)
|
|
}
|
|
|
|
return suggestedRoutesCh, closeFn
|
|
}
|
|
|
|
func TestRouter(t *testing.T) {
|
|
router, cleanTmpDb := setupRouter(t)
|
|
defer cleanTmpDb()
|
|
|
|
suggestedRoutesCh, closeSignalHandler := setupSignalHandler(t)
|
|
defer closeSignalHandler()
|
|
|
|
tests := getNormalTestParamsList()
|
|
|
|
// Test blocking endpoints
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
routes, err := router.SuggestedRoutes(context.Background(), tt.input)
|
|
|
|
if tt.expectedError != nil {
|
|
assert.Error(t, err)
|
|
assert.Equal(t, tt.expectedError.Error(), err.Error())
|
|
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)
|
|
}
|
|
})
|
|
}
|
|
|
|
// Test async endpoints
|
|
for _, tt := range tests {
|
|
router.SuggestedRoutesAsync(tt.input)
|
|
|
|
select {
|
|
case asyncRoutes := <-suggestedRoutesCh:
|
|
assert.Equal(t, tt.input.Uuid, asyncRoutes.Uuid)
|
|
assert.Equal(t, tt.expectedError, asyncRoutes.ErrorResponse)
|
|
assertPathsEqual(t, tt.expectedCandidates, asyncRoutes.Candidates)
|
|
break
|
|
case <-time.After(10 * time.Second):
|
|
t.FailNow()
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestNoBalanceForTheBestRouteRouter(t *testing.T) {
|
|
router, cleanTmpDb := setupRouter(t)
|
|
defer cleanTmpDb()
|
|
|
|
suggestedRoutesCh, closeSignalHandler := setupSignalHandler(t)
|
|
defer closeSignalHandler()
|
|
|
|
tests := getNoBalanceTestParamsList()
|
|
|
|
// Test blocking endpoints
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
routes, err := router.SuggestedRoutes(context.Background(), tt.input)
|
|
|
|
if tt.expectedError != nil {
|
|
assert.Error(t, err)
|
|
assert.Equal(t, tt.expectedError.Error(), err.Error())
|
|
if tt.expectedError == ErrNoPositiveBalance {
|
|
assert.Nil(t, routes)
|
|
} else {
|
|
assert.NotNil(t, routes)
|
|
assertPathsEqual(t, tt.expectedCandidates, routes.Candidates)
|
|
}
|
|
} else {
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, len(tt.expectedCandidates), len(routes.Candidates))
|
|
assert.Equal(t, len(tt.expectedBest), len(routes.Best))
|
|
assertPathsEqual(t, tt.expectedCandidates, routes.Candidates)
|
|
assertPathsEqual(t, tt.expectedBest, routes.Best)
|
|
}
|
|
})
|
|
}
|
|
|
|
// Test async endpoints
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
router.SuggestedRoutesAsync(tt.input)
|
|
|
|
select {
|
|
case asyncRoutes := <-suggestedRoutesCh:
|
|
assert.Equal(t, tt.input.Uuid, asyncRoutes.Uuid)
|
|
assert.Equal(t, tt.expectedError, asyncRoutes.ErrorResponse)
|
|
assertPathsEqual(t, tt.expectedCandidates, asyncRoutes.Candidates)
|
|
if tt.expectedError == nil {
|
|
assertPathsEqual(t, tt.expectedBest, asyncRoutes.Best)
|
|
}
|
|
break
|
|
case <-time.After(10 * time.Second):
|
|
t.FailNow()
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestAmountOptions(t *testing.T) {
|
|
router, cleanTmpDb := setupRouter(t)
|
|
defer cleanTmpDb()
|
|
|
|
tests := getAmountOptionsTestParamsList()
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
selectedFromChains, _, err := router.getSelectedChains(tt.input)
|
|
assert.NoError(t, err)
|
|
|
|
amountOptions, err := router.findOptionsForSendingAmount(tt.input, selectedFromChains, tt.input.TestParams.BalanceMap)
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, len(tt.expectedAmountOptions), len(amountOptions))
|
|
assert.True(t, amountOptionsMapsEqual(tt.expectedAmountOptions, amountOptions))
|
|
})
|
|
}
|
|
}
|