mirror of
https://github.com/status-im/status-go.git
synced 2025-02-04 19:04:16 +00:00
21beb685b4
PR adds test flag -network to e2e pacakge, for the selection of the desired blockchain network for running tests. It updates readme to demonstrates usage of flag.
257 lines
7.3 KiB
Go
257 lines
7.3 KiB
Go
package api
|
|
|
|
import (
|
|
"context"
|
|
"sync"
|
|
|
|
gethcommon "github.com/ethereum/go-ethereum/common"
|
|
"github.com/status-im/status-go/geth/account"
|
|
"github.com/status-im/status-go/geth/common"
|
|
"github.com/status-im/status-go/geth/jail"
|
|
"github.com/status-im/status-go/geth/log"
|
|
"github.com/status-im/status-go/geth/node"
|
|
"github.com/status-im/status-go/geth/notification/fcm"
|
|
"github.com/status-im/status-go/geth/params"
|
|
"github.com/status-im/status-go/geth/signal"
|
|
"github.com/status-im/status-go/geth/txqueue"
|
|
)
|
|
|
|
const (
|
|
//todo(jeka): should be removed
|
|
fcmServerKey = "AAAAxwa-r08:APA91bFtMIToDVKGAmVCm76iEXtA4dn9MPvLdYKIZqAlNpLJbd12EgdBI9DSDSXKdqvIAgLodepmRhGVaWvhxnXJzVpE6MoIRuKedDV3kfHSVBhWFqsyoLTwXY4xeufL9Sdzb581U-lx"
|
|
)
|
|
|
|
// StatusBackend implements Status.im service
|
|
type StatusBackend struct {
|
|
sync.Mutex
|
|
nodeReady chan struct{} // channel to wait for when node is fully ready
|
|
nodeManager common.NodeManager
|
|
accountManager common.AccountManager
|
|
txQueueManager common.TxQueueManager
|
|
jailManager common.JailManager
|
|
newNotification common.NotificationConstructor
|
|
}
|
|
|
|
// NewStatusBackend create a new NewStatusBackend instance
|
|
func NewStatusBackend() *StatusBackend {
|
|
defer log.Info("Status backend initialized")
|
|
|
|
nodeManager := node.NewNodeManager()
|
|
accountManager := account.NewManager(nodeManager)
|
|
txQueueManager := txqueue.NewManager(nodeManager, accountManager)
|
|
jailManager := jail.New(nodeManager)
|
|
notificationManager := fcm.NewNotification(fcmServerKey)
|
|
|
|
return &StatusBackend{
|
|
nodeManager: nodeManager,
|
|
accountManager: accountManager,
|
|
jailManager: jailManager,
|
|
txQueueManager: txQueueManager,
|
|
newNotification: notificationManager,
|
|
}
|
|
}
|
|
|
|
// NodeManager returns reference to node manager
|
|
func (m *StatusBackend) NodeManager() common.NodeManager {
|
|
return m.nodeManager
|
|
}
|
|
|
|
// AccountManager returns reference to account manager
|
|
func (m *StatusBackend) AccountManager() common.AccountManager {
|
|
return m.accountManager
|
|
}
|
|
|
|
// JailManager returns reference to jail
|
|
func (m *StatusBackend) JailManager() common.JailManager {
|
|
return m.jailManager
|
|
}
|
|
|
|
// TxQueueManager returns reference to jail
|
|
func (m *StatusBackend) TxQueueManager() common.TxQueueManager {
|
|
return m.txQueueManager
|
|
}
|
|
|
|
// IsNodeRunning confirm that node is running
|
|
func (m *StatusBackend) IsNodeRunning() bool {
|
|
return m.nodeManager.IsNodeRunning()
|
|
}
|
|
|
|
// StartNode start Status node, fails if node is already started
|
|
func (m *StatusBackend) StartNode(config *params.NodeConfig) (<-chan struct{}, error) {
|
|
m.Lock()
|
|
defer m.Unlock()
|
|
|
|
if m.nodeReady != nil {
|
|
return nil, node.ErrNodeExists
|
|
}
|
|
|
|
nodeStarted, err := m.nodeManager.StartNode(config)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
m.txQueueManager.Start()
|
|
|
|
m.nodeReady = make(chan struct{}, 1)
|
|
go m.onNodeStart(nodeStarted, m.nodeReady) // waits on nodeStarted, writes to backendReady
|
|
|
|
return m.nodeReady, err
|
|
}
|
|
|
|
// onNodeStart does everything required to prepare backend
|
|
func (m *StatusBackend) onNodeStart(nodeStarted <-chan struct{}, backendReady chan struct{}) {
|
|
<-nodeStarted
|
|
|
|
if err := m.registerHandlers(); err != nil {
|
|
log.Error("Handler registration failed", "err", err)
|
|
}
|
|
|
|
if err := m.accountManager.ReSelectAccount(); err != nil {
|
|
log.Error("Reselect account failed", "err", err)
|
|
}
|
|
log.Info("Account reselected")
|
|
|
|
close(backendReady)
|
|
signal.Send(signal.Envelope{
|
|
Type: signal.EventNodeReady,
|
|
Event: struct{}{},
|
|
})
|
|
}
|
|
|
|
// StopNode stop Status node. Stopped node cannot be resumed.
|
|
func (m *StatusBackend) StopNode() (<-chan struct{}, error) {
|
|
m.Lock()
|
|
defer m.Unlock()
|
|
|
|
if m.nodeReady == nil {
|
|
return nil, node.ErrNoRunningNode
|
|
}
|
|
<-m.nodeReady
|
|
|
|
m.txQueueManager.Stop()
|
|
m.jailManager.Stop()
|
|
|
|
nodeStopped, err := m.nodeManager.StopNode()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
backendStopped := make(chan struct{}, 1)
|
|
go func() {
|
|
<-nodeStopped
|
|
m.Lock()
|
|
m.nodeReady = nil
|
|
m.Unlock()
|
|
close(backendStopped)
|
|
}()
|
|
|
|
return backendStopped, nil
|
|
}
|
|
|
|
// RestartNode restart running Status node, fails if node is not running
|
|
func (m *StatusBackend) RestartNode() (<-chan struct{}, error) {
|
|
m.Lock()
|
|
defer m.Unlock()
|
|
|
|
if m.nodeReady == nil {
|
|
return nil, node.ErrNoRunningNode
|
|
}
|
|
<-m.nodeReady
|
|
|
|
nodeRestarted, err := m.nodeManager.RestartNode()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
m.nodeReady = make(chan struct{}, 1)
|
|
go m.onNodeStart(nodeRestarted, m.nodeReady) // waits on nodeRestarted, writes to backendReady
|
|
|
|
return m.nodeReady, err
|
|
}
|
|
|
|
// ResetChainData remove chain data from data directory.
|
|
// Node is stopped, and new node is started, with clean data directory.
|
|
func (m *StatusBackend) ResetChainData() (<-chan struct{}, error) {
|
|
m.Lock()
|
|
defer m.Unlock()
|
|
|
|
if m.nodeReady == nil {
|
|
return nil, node.ErrNoRunningNode
|
|
}
|
|
<-m.nodeReady
|
|
|
|
nodeReset, err := m.nodeManager.ResetChainData()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
m.nodeReady = make(chan struct{}, 1)
|
|
go m.onNodeStart(nodeReset, m.nodeReady) // waits on nodeReset, writes to backendReady
|
|
|
|
return m.nodeReady, err
|
|
}
|
|
|
|
// CallRPC executes RPC request on node's in-proc RPC server
|
|
func (m *StatusBackend) CallRPC(inputJSON string) string {
|
|
client := m.nodeManager.RPCClient()
|
|
return client.CallRaw(inputJSON)
|
|
}
|
|
|
|
// SendTransaction creates a new transaction and waits until it's complete.
|
|
func (m *StatusBackend) SendTransaction(ctx context.Context, args common.SendTxArgs) (gethcommon.Hash, error) {
|
|
if ctx == nil {
|
|
ctx = context.Background()
|
|
}
|
|
|
|
tx := m.txQueueManager.CreateTransaction(ctx, args)
|
|
|
|
if err := m.txQueueManager.QueueTransaction(tx); err != nil {
|
|
return gethcommon.Hash{}, err
|
|
}
|
|
|
|
if err := m.txQueueManager.WaitForTransaction(tx); err != nil {
|
|
return gethcommon.Hash{}, err
|
|
}
|
|
|
|
return tx.Hash, nil
|
|
}
|
|
|
|
// CompleteTransaction instructs backend to complete sending of a given transaction
|
|
func (m *StatusBackend) CompleteTransaction(id common.QueuedTxID, password string) (gethcommon.Hash, error) {
|
|
return m.txQueueManager.CompleteTransaction(id, password)
|
|
}
|
|
|
|
// CompleteTransactions instructs backend to complete sending of multiple transactions
|
|
func (m *StatusBackend) CompleteTransactions(ids []common.QueuedTxID, password string) map[common.QueuedTxID]common.RawCompleteTransactionResult {
|
|
return m.txQueueManager.CompleteTransactions(ids, password)
|
|
}
|
|
|
|
// DiscardTransaction discards a given transaction from transaction queue
|
|
func (m *StatusBackend) DiscardTransaction(id common.QueuedTxID) error {
|
|
return m.txQueueManager.DiscardTransaction(id)
|
|
}
|
|
|
|
// DiscardTransactions discards given multiple transactions from transaction queue
|
|
func (m *StatusBackend) DiscardTransactions(ids []common.QueuedTxID) map[common.QueuedTxID]common.RawDiscardTransactionResult {
|
|
return m.txQueueManager.DiscardTransactions(ids)
|
|
}
|
|
|
|
// registerHandlers attaches Status callback handlers to running node
|
|
func (m *StatusBackend) registerHandlers() error {
|
|
rpcClient := m.NodeManager().RPCClient()
|
|
if rpcClient == nil {
|
|
return node.ErrRPCClient
|
|
}
|
|
|
|
rpcClient.RegisterHandler("eth_accounts", m.accountManager.AccountsRPCHandler())
|
|
rpcClient.RegisterHandler("eth_sendTransaction", m.txQueueManager.SendTransactionRPCHandler)
|
|
|
|
m.txQueueManager.SetTransactionQueueHandler(m.txQueueManager.TransactionQueueHandler())
|
|
log.Info("Registered handler", "fn", "TransactionQueueHandler")
|
|
|
|
m.txQueueManager.SetTransactionReturnHandler(m.txQueueManager.TransactionReturnHandler())
|
|
log.Info("Registered handler", "fn", "TransactionReturnHandler")
|
|
|
|
return nil
|
|
}
|