mirror of
https://github.com/status-im/status-go.git
synced 2025-01-10 14:47:06 +00:00
653da5bcd0
Currently it is quite easy to introduce concurrency issues while working with transaction object. For example, race issue will exist every time while transaction is processed in a separate goroutine and caller will try to check for an error before event to Done channel is sent. This change removes all the data that is updated on transaction and leaves it with ID, Args and Context (which is not used at the moment). Signed-off-by: Dmitry Shulyak <yashulyak@gmail.com>
92 lines
2.9 KiB
Go
92 lines
2.9 KiB
Go
package transactions
|
|
|
|
import (
|
|
"github.com/ethereum/go-ethereum/accounts/keystore"
|
|
"github.com/status-im/status-go/geth/common"
|
|
"github.com/status-im/status-go/geth/signal"
|
|
)
|
|
|
|
const (
|
|
// EventTransactionQueued is triggered when send transaction request is queued
|
|
EventTransactionQueued = "transaction.queued"
|
|
// EventTransactionFailed is triggered when send transaction request fails
|
|
EventTransactionFailed = "transaction.failed"
|
|
)
|
|
|
|
const (
|
|
// SendTransactionNoErrorCode is sent when no error occurred.
|
|
SendTransactionNoErrorCode = iota
|
|
// SendTransactionDefaultErrorCode is every case when there is no special tx return code.
|
|
SendTransactionDefaultErrorCode
|
|
// SendTransactionPasswordErrorCode is sent when account failed verification.
|
|
SendTransactionPasswordErrorCode
|
|
// SendTransactionTimeoutErrorCode is sent when tx is timed out.
|
|
SendTransactionTimeoutErrorCode
|
|
// SendTransactionDiscardedErrorCode is sent when tx was discarded.
|
|
SendTransactionDiscardedErrorCode
|
|
)
|
|
|
|
var txReturnCodes = map[error]int{
|
|
nil: SendTransactionNoErrorCode,
|
|
keystore.ErrDecrypt: SendTransactionPasswordErrorCode,
|
|
ErrQueuedTxTimedOut: SendTransactionTimeoutErrorCode,
|
|
ErrQueuedTxDiscarded: SendTransactionDiscardedErrorCode,
|
|
}
|
|
|
|
// SendTransactionEvent is a signal sent on a send transaction request
|
|
type SendTransactionEvent struct {
|
|
ID string `json:"id"`
|
|
Args common.SendTxArgs `json:"args"`
|
|
MessageID string `json:"message_id"`
|
|
}
|
|
|
|
// NotifyOnEnqueue returns handler that processes incoming tx queue requests
|
|
func NotifyOnEnqueue(queuedTx *common.QueuedTx) {
|
|
signal.Send(signal.Envelope{
|
|
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 common.SendTxArgs `json:"args"`
|
|
MessageID string `json:"message_id"`
|
|
ErrorMessage string `json:"error_message"`
|
|
ErrorCode int `json:"error_code,string"`
|
|
}
|
|
|
|
// NotifyOnReturn returns handler that processes responses from internal tx manager
|
|
func NotifyOnReturn(queuedTx *common.QueuedTx, err error) {
|
|
// we don't want to notify a user if tx was sent successfully
|
|
if err == nil {
|
|
return
|
|
}
|
|
// discard notifications with empty tx
|
|
if queuedTx == nil {
|
|
return
|
|
}
|
|
signal.Send(signal.Envelope{
|
|
Type: EventTransactionFailed,
|
|
Event: ReturnSendTransactionEvent{
|
|
ID: string(queuedTx.ID),
|
|
Args: queuedTx.Args,
|
|
MessageID: common.MessageIDFromContext(queuedTx.Context),
|
|
ErrorMessage: err.Error(),
|
|
ErrorCode: sendTransactionErrorCode(err),
|
|
},
|
|
})
|
|
}
|
|
|
|
func sendTransactionErrorCode(err error) int {
|
|
if code, ok := txReturnCodes[err]; ok {
|
|
return code
|
|
}
|
|
return SendTxDefaultErrorCode
|
|
}
|