github.com/status-im/status-go@v1.1.0/services/wallet/service.go (about) 1 package wallet 2 3 import ( 4 "database/sql" 5 "encoding/json" 6 "fmt" 7 "sync" 8 "time" 9 10 "github.com/ethereum/go-ethereum/common" 11 "github.com/ethereum/go-ethereum/event" 12 "github.com/ethereum/go-ethereum/log" 13 "github.com/ethereum/go-ethereum/p2p" 14 gethrpc "github.com/ethereum/go-ethereum/rpc" 15 16 "github.com/status-im/status-go/account" 17 "github.com/status-im/status-go/multiaccounts/accounts" 18 "github.com/status-im/status-go/params" 19 protocolCommon "github.com/status-im/status-go/protocol/common" 20 "github.com/status-im/status-go/rpc" 21 "github.com/status-im/status-go/server" 22 "github.com/status-im/status-go/services/ens" 23 "github.com/status-im/status-go/services/stickers" 24 "github.com/status-im/status-go/services/wallet/activity" 25 "github.com/status-im/status-go/services/wallet/balance" 26 "github.com/status-im/status-go/services/wallet/blockchainstate" 27 "github.com/status-im/status-go/services/wallet/collectibles" 28 "github.com/status-im/status-go/services/wallet/community" 29 "github.com/status-im/status-go/services/wallet/currency" 30 "github.com/status-im/status-go/services/wallet/history" 31 "github.com/status-im/status-go/services/wallet/market" 32 "github.com/status-im/status-go/services/wallet/onramp" 33 "github.com/status-im/status-go/services/wallet/thirdparty" 34 "github.com/status-im/status-go/services/wallet/thirdparty/alchemy" 35 "github.com/status-im/status-go/services/wallet/thirdparty/coingecko" 36 "github.com/status-im/status-go/services/wallet/thirdparty/cryptocompare" 37 "github.com/status-im/status-go/services/wallet/thirdparty/opensea" 38 "github.com/status-im/status-go/services/wallet/thirdparty/rarible" 39 "github.com/status-im/status-go/services/wallet/token" 40 "github.com/status-im/status-go/services/wallet/transfer" 41 "github.com/status-im/status-go/services/wallet/walletevent" 42 "github.com/status-im/status-go/transactions" 43 ) 44 45 const ( 46 EventBlockchainStatusChanged walletevent.EventType = "wallet-blockchain-status-changed" 47 ) 48 49 // NewService initializes service instance. 50 func NewService( 51 db *sql.DB, 52 accountsDB *accounts.Database, 53 appDB *sql.DB, 54 rpcClient *rpc.Client, 55 accountFeed *event.Feed, 56 settingsFeed *event.Feed, 57 gethManager *account.GethManager, 58 transactor *transactions.Transactor, 59 config *params.NodeConfig, 60 ens *ens.Service, 61 stickers *stickers.Service, 62 pendingTxManager *transactions.PendingTxTracker, 63 feed *event.Feed, 64 mediaServer *server.MediaServer, 65 statusProxyStageName string, 66 ) *Service { 67 signals := &walletevent.SignalsTransmitter{ 68 Publisher: feed, 69 } 70 blockchainStatus := make(map[uint64]string) 71 mutex := sync.Mutex{} 72 rpcClient.SetWalletNotifier(func(chainID uint64, message string) { 73 mutex.Lock() 74 defer mutex.Unlock() 75 76 if len(blockchainStatus) == 0 { 77 networks, err := rpcClient.NetworkManager.Get(false) 78 if err != nil { 79 return 80 } 81 82 for _, network := range networks { 83 blockchainStatus[network.ChainID] = "up" 84 } 85 } 86 87 blockchainStatus[chainID] = message 88 encodedmessage, err := json.Marshal(blockchainStatus) 89 if err != nil { 90 return 91 } 92 93 feed.Send(walletevent.Event{ 94 Type: EventBlockchainStatusChanged, 95 Accounts: []common.Address{}, 96 Message: string(encodedmessage), 97 At: time.Now().Unix(), 98 ChainID: chainID, 99 }) 100 }) 101 102 communityManager := community.NewManager(db, mediaServer, feed) 103 balanceCacher := balance.NewCacherWithTTL(5 * time.Minute) 104 tokenManager := token.NewTokenManager(db, rpcClient, communityManager, rpcClient.NetworkManager, appDB, mediaServer, feed, accountFeed, accountsDB, token.NewPersistence(db)) 105 tokenManager.Start() 106 107 cryptoOnRampProviders := []onramp.Provider{ 108 onramp.NewMercuryoProvider(tokenManager), 109 onramp.NewRampProvider(), 110 onramp.NewMoonPayProvider(), 111 } 112 cryptoOnRampManager := onramp.NewManager(cryptoOnRampProviders) 113 114 savedAddressesManager := &SavedAddressesManager{db: db} 115 transactionManager := transfer.NewTransactionManager(transfer.NewMultiTransactionDB(db), gethManager, transactor, config, accountsDB, pendingTxManager, feed) 116 blockChainState := blockchainstate.NewBlockChainState() 117 transferController := transfer.NewTransferController(db, accountsDB, rpcClient, accountFeed, feed, transactionManager, pendingTxManager, 118 tokenManager, balanceCacher, blockChainState) 119 transferController.Start() 120 cryptoCompare := cryptocompare.NewClient() 121 coingecko := coingecko.NewClient() 122 cryptoCompareProxy := cryptocompare.NewClientWithParams(cryptocompare.Params{ 123 ID: fmt.Sprintf("%s-proxy", cryptoCompare.ID()), 124 URL: fmt.Sprintf("https://%s.api.status.im/cryptocompare/", statusProxyStageName), 125 User: config.WalletConfig.StatusProxyMarketUser, 126 Password: config.WalletConfig.StatusProxyMarketPassword, 127 }) 128 marketManager := market.NewManager([]thirdparty.MarketDataProvider{cryptoCompare, coingecko, cryptoCompareProxy}, feed) 129 reader := NewReader(tokenManager, marketManager, token.NewPersistence(db), feed) 130 history := history.NewService(db, accountsDB, accountFeed, feed, rpcClient, tokenManager, marketManager, balanceCacher.Cache()) 131 currency := currency.NewService(db, feed, tokenManager, marketManager) 132 133 openseaHTTPClient := opensea.NewHTTPClient() 134 openseaV2Client := opensea.NewClientV2(config.WalletConfig.OpenseaAPIKey, openseaHTTPClient) 135 raribleClient := rarible.NewClient(config.WalletConfig.RaribleMainnetAPIKey, config.WalletConfig.RaribleTestnetAPIKey) 136 alchemyClient := alchemy.NewClient(config.WalletConfig.AlchemyAPIKeys) 137 138 // Collectible providers in priority order (i.e. provider N+1 will be tried only if provider N fails) 139 contractOwnershipProviders := []thirdparty.CollectibleContractOwnershipProvider{ 140 raribleClient, 141 alchemyClient, 142 } 143 144 accountOwnershipProviders := []thirdparty.CollectibleAccountOwnershipProvider{ 145 raribleClient, 146 alchemyClient, 147 openseaV2Client, 148 } 149 150 collectibleDataProviders := []thirdparty.CollectibleDataProvider{ 151 raribleClient, 152 alchemyClient, 153 openseaV2Client, 154 } 155 156 collectionDataProviders := []thirdparty.CollectionDataProvider{ 157 raribleClient, 158 alchemyClient, 159 openseaV2Client, 160 } 161 162 collectibleSearchProviders := []thirdparty.CollectibleSearchProvider{ 163 raribleClient, 164 } 165 166 collectibleProviders := thirdparty.CollectibleProviders{ 167 ContractOwnershipProviders: contractOwnershipProviders, 168 AccountOwnershipProviders: accountOwnershipProviders, 169 CollectibleDataProviders: collectibleDataProviders, 170 CollectionDataProviders: collectionDataProviders, 171 SearchProviders: collectibleSearchProviders, 172 } 173 174 collectiblesManager := collectibles.NewManager( 175 db, 176 rpcClient, 177 communityManager, 178 collectibleProviders, 179 mediaServer, 180 feed, 181 ) 182 collectibles := collectibles.NewService(db, feed, accountsDB, accountFeed, settingsFeed, communityManager, rpcClient.NetworkManager, collectiblesManager) 183 184 activity := activity.NewService(db, accountsDB, tokenManager, collectiblesManager, feed, pendingTxManager) 185 186 featureFlags := &protocolCommon.FeatureFlags{} 187 if config.WalletConfig.EnableCelerBridge { 188 featureFlags.EnableCelerBridge = true 189 } 190 191 return &Service{ 192 db: db, 193 accountsDB: accountsDB, 194 rpcClient: rpcClient, 195 tokenManager: tokenManager, 196 communityManager: communityManager, 197 savedAddressesManager: savedAddressesManager, 198 transactionManager: transactionManager, 199 pendingTxManager: pendingTxManager, 200 transferController: transferController, 201 cryptoOnRampManager: cryptoOnRampManager, 202 collectiblesManager: collectiblesManager, 203 collectibles: collectibles, 204 gethManager: gethManager, 205 marketManager: marketManager, 206 transactor: transactor, 207 ens: ens, 208 stickers: stickers, 209 feed: feed, 210 signals: signals, 211 reader: reader, 212 history: history, 213 currency: currency, 214 activity: activity, 215 decoder: NewDecoder(), 216 blockChainState: blockChainState, 217 keycardPairings: NewKeycardPairings(), 218 config: config, 219 featureFlags: featureFlags, 220 } 221 } 222 223 // Service is a wallet service. 224 type Service struct { 225 db *sql.DB 226 accountsDB *accounts.Database 227 rpcClient *rpc.Client 228 savedAddressesManager *SavedAddressesManager 229 tokenManager *token.Manager 230 communityManager *community.Manager 231 transactionManager *transfer.TransactionManager 232 pendingTxManager *transactions.PendingTxTracker 233 cryptoOnRampManager *onramp.Manager 234 transferController *transfer.Controller 235 marketManager *market.Manager 236 started bool 237 collectiblesManager *collectibles.Manager 238 collectibles *collectibles.Service 239 gethManager *account.GethManager 240 transactor *transactions.Transactor 241 ens *ens.Service 242 stickers *stickers.Service 243 feed *event.Feed 244 signals *walletevent.SignalsTransmitter 245 reader *Reader 246 history *history.Service 247 currency *currency.Service 248 activity *activity.Service 249 decoder *Decoder 250 blockChainState *blockchainstate.BlockChainState 251 keycardPairings *KeycardPairings 252 config *params.NodeConfig 253 featureFlags *protocolCommon.FeatureFlags 254 } 255 256 // Start signals transmitter. 257 func (s *Service) Start() error { 258 s.transferController.Start() 259 s.currency.Start() 260 err := s.signals.Start() 261 s.history.Start() 262 s.collectibles.Start() 263 s.started = true 264 return err 265 } 266 267 // Set external Collectibles community info provider 268 func (s *Service) SetWalletCommunityInfoProvider(provider thirdparty.CommunityInfoProvider) { 269 s.communityManager.SetCommunityInfoProvider(provider) 270 } 271 272 // Stop reactor and close db. 273 func (s *Service) Stop() error { 274 log.Info("wallet will be stopped") 275 s.signals.Stop() 276 s.transferController.Stop() 277 s.currency.Stop() 278 s.reader.Stop() 279 s.history.Stop() 280 s.activity.Stop() 281 s.collectibles.Stop() 282 s.tokenManager.Stop() 283 s.started = false 284 log.Info("wallet stopped") 285 return nil 286 } 287 288 // APIs returns list of available RPC APIs. 289 func (s *Service) APIs() []gethrpc.API { 290 return []gethrpc.API{ 291 { 292 Namespace: "wallet", 293 Version: "0.1.0", 294 Service: NewAPI(s), 295 Public: true, 296 }, 297 } 298 } 299 300 // Protocols returns list of p2p protocols. 301 func (s *Service) Protocols() []p2p.Protocol { 302 return nil 303 } 304 305 func (s *Service) IsStarted() bool { 306 return s.started 307 } 308 309 func (s *Service) KeycardPairings() *KeycardPairings { 310 return s.keycardPairings 311 } 312 313 func (s *Service) Config() *params.NodeConfig { 314 return s.config 315 } 316 317 func (s *Service) FeatureFlags() *protocolCommon.FeatureFlags { 318 return s.featureFlags 319 } 320 321 func (s *Service) GetRPCClient() *rpc.Client { 322 return s.rpcClient 323 } 324 325 func (s *Service) GetTransactor() *transactions.Transactor { 326 return s.transactor 327 } 328 329 func (s *Service) GetTokenManager() *token.Manager { 330 return s.tokenManager 331 } 332 333 func (s *Service) GetMarketManager() *market.Manager { 334 return s.marketManager 335 } 336 337 func (s *Service) GetCollectiblesService() *collectibles.Service { 338 return s.collectibles 339 } 340 341 func (s *Service) GetCollectiblesManager() *collectibles.Manager { 342 return s.collectiblesManager 343 } 344 345 func (s *Service) GetEnsService() *ens.Service { 346 return s.ens 347 } 348 349 func (s *Service) GetStickersService() *stickers.Service { 350 return s.stickers 351 }