mirror of
https://github.com/status-im/status-go.git
synced 2025-01-09 14:16:21 +00:00
349103de1a
- node: signals and node reset, fixes #152 - tests update (testify is used) - node manager refactored, race conditions fixed - node wrapper has been removed, we rely on go-ethereum node now - tx queue refactored - jail refactored - backend and API introduced
195 lines
5.7 KiB
Go
195 lines
5.7 KiB
Go
package node
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/ethereum/go-ethereum/accounts/keystore"
|
|
gethcommon "github.com/ethereum/go-ethereum/common"
|
|
"github.com/ethereum/go-ethereum/les/status"
|
|
"github.com/status-im/status-go/geth/common"
|
|
)
|
|
|
|
const (
|
|
// EventTransactionQueued is triggered when send transaction request is queued
|
|
EventTransactionQueued = "transaction.queued"
|
|
|
|
// EventTransactionFailed is triggered when send transaction request fails
|
|
EventTransactionFailed = "transaction.failed"
|
|
|
|
// SendTxDefaultErrorCode is sent by default, when error is not nil, but type is unknown/unexpected.
|
|
SendTxDefaultErrorCode = SendTransactionDefaultErrorCode
|
|
)
|
|
|
|
// Send transaction response codes
|
|
const (
|
|
SendTransactionNoErrorCode = "0"
|
|
SendTransactionDefaultErrorCode = "1"
|
|
SendTransactionPasswordErrorCode = "2"
|
|
SendTransactionTimeoutErrorCode = "3"
|
|
SendTransactionDiscardedErrorCode = "4"
|
|
)
|
|
|
|
var txReturnCodes = map[error]string{ // deliberately strings, in case more meaningful codes are to be returned
|
|
nil: SendTransactionNoErrorCode,
|
|
keystore.ErrDecrypt: SendTransactionPasswordErrorCode,
|
|
status.ErrQueuedTxTimedOut: SendTransactionTimeoutErrorCode,
|
|
status.ErrQueuedTxDiscarded: SendTransactionDiscardedErrorCode,
|
|
}
|
|
|
|
// TxQueueManager provides means to manage internal Status Backend (injected into LES)
|
|
type TxQueueManager struct {
|
|
nodeManager common.NodeManager
|
|
accountManager common.AccountManager
|
|
}
|
|
|
|
func NewTxQueueManager(nodeManager common.NodeManager, accountManager common.AccountManager) *TxQueueManager {
|
|
return &TxQueueManager{
|
|
nodeManager: nodeManager,
|
|
accountManager: accountManager,
|
|
}
|
|
}
|
|
|
|
// CompleteTransaction instructs backend to complete sending of a given transaction
|
|
func (m *TxQueueManager) CompleteTransaction(id, password string) (gethcommon.Hash, error) {
|
|
lightEthereum, err := m.nodeManager.LightEthereumService()
|
|
if err != nil {
|
|
return gethcommon.Hash{}, err
|
|
}
|
|
|
|
backend := lightEthereum.StatusBackend
|
|
|
|
selectedAccount, err := m.accountManager.SelectedAccount()
|
|
if err != nil {
|
|
return gethcommon.Hash{}, err
|
|
}
|
|
|
|
ctx := context.Background()
|
|
ctx = context.WithValue(ctx, status.SelectedAccountKey, selectedAccount.Hex())
|
|
|
|
return backend.CompleteQueuedTransaction(ctx, status.QueuedTxID(id), password)
|
|
}
|
|
|
|
// CompleteTransactions instructs backend to complete sending of multiple transactions
|
|
func (m *TxQueueManager) CompleteTransactions(ids, password string) map[string]common.RawCompleteTransactionResult {
|
|
results := make(map[string]common.RawCompleteTransactionResult)
|
|
|
|
parsedIDs, err := common.ParseJSONArray(ids)
|
|
if err != nil {
|
|
results["none"] = common.RawCompleteTransactionResult{
|
|
Error: err,
|
|
}
|
|
return results
|
|
}
|
|
|
|
for _, txID := range parsedIDs {
|
|
txHash, txErr := m.CompleteTransaction(txID, password)
|
|
results[txID] = common.RawCompleteTransactionResult{
|
|
Hash: txHash,
|
|
Error: txErr,
|
|
}
|
|
}
|
|
|
|
return results
|
|
}
|
|
|
|
// DiscardTransaction discards a given transaction from transaction queue
|
|
func (m *TxQueueManager) DiscardTransaction(id string) error {
|
|
lightEthereum, err := m.nodeManager.LightEthereumService()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
backend := lightEthereum.StatusBackend
|
|
|
|
return backend.DiscardQueuedTransaction(status.QueuedTxID(id))
|
|
}
|
|
|
|
// DiscardTransactions discards given multiple transactions from transaction queue
|
|
func (m *TxQueueManager) DiscardTransactions(ids string) map[string]common.RawDiscardTransactionResult {
|
|
var parsedIDs []string
|
|
results := make(map[string]common.RawDiscardTransactionResult)
|
|
|
|
parsedIDs, err := common.ParseJSONArray(ids)
|
|
if err != nil {
|
|
results["none"] = common.RawDiscardTransactionResult{
|
|
Error: err,
|
|
}
|
|
return results
|
|
}
|
|
|
|
for _, txID := range parsedIDs {
|
|
err := m.DiscardTransaction(txID)
|
|
if err != nil {
|
|
results[txID] = common.RawDiscardTransactionResult{
|
|
Error: err,
|
|
}
|
|
}
|
|
}
|
|
|
|
return results
|
|
}
|
|
|
|
// SendTransactionEvent is a signal sent on a send transaction request
|
|
type SendTransactionEvent struct {
|
|
ID string `json:"id"`
|
|
Args status.SendTxArgs `json:"args"`
|
|
MessageID string `json:"message_id"`
|
|
}
|
|
|
|
// TransactionQueueHandler returns handler that processes incoming tx queue requests
|
|
func (m *TxQueueManager) TransactionQueueHandler() func(queuedTx status.QueuedTx) {
|
|
return func(queuedTx status.QueuedTx) {
|
|
SendSignal(SignalEnvelope{
|
|
Type: EventTransactionQueued,
|
|
Event: SendTransactionEvent{
|
|
ID: string(queuedTx.ID),
|
|
Args: queuedTx.Args,
|
|
MessageID: common.MessageIDFromContext(queuedTx.Context),
|
|
},
|
|
})
|
|
}
|
|
}
|
|
|
|
// ReturnSendTransactionEvent is a JSON returned whenever transaction send is returned
|
|
type ReturnSendTransactionEvent struct {
|
|
ID string `json:"id"`
|
|
Args status.SendTxArgs `json:"args"`
|
|
MessageID string `json:"message_id"`
|
|
ErrorMessage string `json:"error_message"`
|
|
ErrorCode string `json:"error_code"`
|
|
}
|
|
|
|
// TransactionReturnHandler returns handler that processes responses from internal tx manager
|
|
func (m *TxQueueManager) TransactionReturnHandler() func(queuedTx *status.QueuedTx, err error) {
|
|
return func(queuedTx *status.QueuedTx, err error) {
|
|
if err == nil {
|
|
return
|
|
}
|
|
|
|
// discard notifications with empty tx
|
|
if queuedTx == nil {
|
|
return
|
|
}
|
|
|
|
// error occurred, signal up to application
|
|
SendSignal(SignalEnvelope{
|
|
Type: EventTransactionFailed,
|
|
Event: ReturnSendTransactionEvent{
|
|
ID: string(queuedTx.ID),
|
|
Args: queuedTx.Args,
|
|
MessageID: common.MessageIDFromContext(queuedTx.Context),
|
|
ErrorMessage: err.Error(),
|
|
ErrorCode: m.sendTransactionErrorCode(err),
|
|
},
|
|
})
|
|
}
|
|
}
|
|
|
|
func (m *TxQueueManager) sendTransactionErrorCode(err error) string {
|
|
if code, ok := txReturnCodes[err]; ok {
|
|
return code
|
|
}
|
|
|
|
return SendTxDefaultErrorCode
|
|
}
|