@@ -3,12 +3,17 @@ package ownership_test
33import (
44 "context"
55 "math/big"
6+ "sync/atomic"
67 "testing"
78 "time"
89
910 "github.com/ethereum/go-ethereum/common"
11+ coretypes "github.com/ethereum/go-ethereum/core/types"
1012
1113 "github.com/status-im/go-wallet-sdk/pkg/balance/multistandardfetcher"
14+ "github.com/status-im/go-wallet-sdk/pkg/contracts/erc1155"
15+ "github.com/status-im/go-wallet-sdk/pkg/contracts/erc721"
16+ "github.com/status-im/go-wallet-sdk/pkg/eventlog"
1217
1318 "github.com/stretchr/testify/require"
1419
@@ -25,6 +30,7 @@ import (
2530 walletCommon "github.com/status-im/status-go/services/wallet/common"
2631 "github.com/status-im/status-go/services/wallet/multistandardbalance"
2732 "github.com/status-im/status-go/services/wallet/thirdparty"
33+ "github.com/status-im/status-go/services/wallet/transferdetector"
2834
2935 "go.uber.org/mock/gomock"
3036 "go.uber.org/zap"
@@ -805,3 +811,128 @@ func TestControllerPeriodicalLoads(t *testing.T) {
805811
806812 controller .Stop ()
807813}
814+
815+ func TestControllerTransferDetectionEvents (t * testing.T ) {
816+ mockCtrl := gomock .NewController (t )
817+ defer mockCtrl .Finish ()
818+
819+ accountsProvider := mock_ownership .NewMockAccountsProvider (mockCtrl )
820+ fakeAddress := types .HexToAddress ("0x123" )
821+ accountsProvider .EXPECT ().GetWalletAddresses ().Return ([]types.Address {fakeAddress }, nil ).AnyTimes ()
822+
823+ accountsPublisher := pubsub .NewPublisher ()
824+ networksProvider := mock_ownership .NewMockNetworksProvider (mockCtrl )
825+ networksPublisher := pubsub .NewPublisher ()
826+
827+ networksProvider .EXPECT ().GetActiveNetworks ().Return ([]* params.Network {
828+ {ChainID : 1 , IsActive : true },
829+ }, nil ).AnyTimes ()
830+ networksProvider .EXPECT ().GetPublisher ().Return (networksPublisher ).AnyTimes ()
831+
832+ walletDB , err := testutils .SetupTestMemorySQLDB (walletdatabase.DbInitializer {})
833+ require .NoError (t , err )
834+
835+ emptyCollectiblesContainer := & thirdparty.CollectibleOwnershipContainer {
836+ Items : []thirdparty.CollectibleIDBalance {},
837+ NextCursor : "" ,
838+ PreviousCursor : "" ,
839+ Provider : "mockProvider" ,
840+ }
841+ ownershipFetcher := mock_ownership .NewMockCollectibleOwnershipFetcher (mockCtrl )
842+ ownershipFetcher .EXPECT ().FetchCollectibleOwnershipByOwner (gomock .Any (), gomock .Any (), gomock .Any (), gomock .Any (), gomock .Any (), gomock .Any ()).DoAndReturn (
843+ func (ctx context.Context , chainID walletCommon.ChainID , owner common.Address , cursor string , limit int , providerID string ) (* thirdparty.CollectibleOwnershipContainer , error ) {
844+ return emptyCollectiblesContainer , nil
845+ }).AnyTimes ()
846+
847+ multistandardBalancePublisher := pubsub .NewPublisher ()
848+ transferDetectorPublisher := pubsub .NewPublisher ()
849+ blockChainStateProvider := mock_ownership .NewMockBlockChainStateProvider (mockCtrl )
850+ var estimatedBlockCalls atomic.Int32
851+ blockChainStateProvider .EXPECT ().GetEstimatedBlockTime (gomock .Any (), uint64 (1 ), gomock .Any ()).DoAndReturn (
852+ func (ctx context.Context , chainID uint64 , blockNumber uint64 ) (time.Time , error ) {
853+ estimatedBlockCalls .Add (1 )
854+ return time .Now (), nil
855+ },
856+ ).AnyTimes ()
857+
858+ publisher := pubsub .NewPublisher ()
859+ logger := zaptest .NewLogger (t ).WithOptions (zap .AddCallerSkip (1 ))
860+
861+ controller := ownership .NewController (
862+ ownership .NewOwnershipDB (walletDB ),
863+ accountsProvider ,
864+ accountsPublisher ,
865+ networksProvider ,
866+ multistandardBalancePublisher ,
867+ transferDetectorPublisher ,
868+ blockChainStateProvider ,
869+ ownershipFetcher ,
870+ publisher ,
871+ logger ,
872+ )
873+
874+ params := ownership.PeriodicalLoaderParams {
875+ StartDelay : 1 * time .Second ,
876+ LoadInterval : 10 * time .Second ,
877+ LoaderParams : ownership.LoaderParams {
878+ LoadDelay : 0 * time .Second ,
879+ FetchLimit : 50 ,
880+ },
881+ }
882+ controller .StartWithLoaderParams (params )
883+ defer controller .Stop ()
884+
885+ // Ensure initial load completed so ownership timestamp exists.
886+ require .Eventually (t , func () bool {
887+ return controller .GetLoaderState (walletCommon .ChainID (1 ), common .Address (fakeAddress )) == ownership .LoaderStateIdle
888+ }, 2 * time .Second , 50 * time .Millisecond )
889+
890+ otherAddress := common .HexToAddress ("0x456" )
891+ msg := transferdetector.EventTransferDetectionFinished {
892+ ChainID : 1 ,
893+ Accounts : []common.Address {common .Address (fakeAddress )},
894+ FromBlock : 100 ,
895+ ToBlock : 200 ,
896+ Events : []eventlog.Event {
897+ {
898+ EventKey : eventlog .ERC721Transfer ,
899+ Unpacked : erc721.Erc721Transfer {
900+ From : common .Address (fakeAddress ),
901+ To : otherAddress ,
902+ Raw : coretypes.Log {
903+ BlockNumber : 123 ,
904+ },
905+ },
906+ },
907+ {
908+ EventKey : eventlog .ERC1155TransferSingle ,
909+ Unpacked : erc1155.Erc1155TransferSingle {
910+ From : common .Address (fakeAddress ),
911+ To : otherAddress ,
912+ Raw : coretypes.Log {
913+ BlockNumber : 124 ,
914+ },
915+ },
916+ },
917+ {
918+ EventKey : eventlog .ERC1155TransferBatch ,
919+ Unpacked : erc1155.Erc1155TransferBatch {
920+ From : common .Address (fakeAddress ),
921+ To : otherAddress ,
922+ Raw : coretypes.Log {
923+ BlockNumber : 125 ,
924+ },
925+ },
926+ },
927+ {
928+ EventKey : eventlog .ERC721Transfer ,
929+ Unpacked : struct {}{},
930+ },
931+ },
932+ }
933+ pubsub .Publish (transferDetectorPublisher , msg )
934+
935+ require .Eventually (t , func () bool {
936+ return estimatedBlockCalls .Load () >= 3
937+ }, 2 * time .Second , 50 * time .Millisecond )
938+ }
0 commit comments