feat(wallet)_: enrich status changed and tx update signals' payload with tx route data
This commit is contained in:
parent
0994cc4865
commit
ffc4243622
|
@ -1,8 +1,12 @@
|
|||
package responses
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/status-im/status-go/errors"
|
||||
"github.com/status-im/status-go/eth-node/types"
|
||||
"github.com/status-im/status-go/services/wallet/requests"
|
||||
"github.com/status-im/status-go/services/wallet/wallettypes"
|
||||
)
|
||||
|
||||
|
@ -59,6 +63,15 @@ func NewRouterSentTransaction(sendArgs *wallettypes.SendTxArgs, hash types.Hash,
|
|||
if sendArgs.To != nil {
|
||||
addr = *sendArgs.To
|
||||
}
|
||||
if sendArgs.Value == nil {
|
||||
sendArgs.Value = (*hexutil.Big)(big.NewInt(0))
|
||||
}
|
||||
if sendArgs.ValueIn == nil {
|
||||
sendArgs.ValueIn = (*hexutil.Big)(big.NewInt(0))
|
||||
}
|
||||
if sendArgs.ValueOut == nil {
|
||||
sendArgs.ValueOut = (*hexutil.Big)(big.NewInt(0))
|
||||
}
|
||||
return &RouterSentTransaction{
|
||||
FromAddress: sendArgs.From,
|
||||
ToAddress: addr,
|
||||
|
@ -72,3 +85,23 @@ func NewRouterSentTransaction(sendArgs *wallettypes.SendTxArgs, hash types.Hash,
|
|||
ApprovalTx: approvalTx,
|
||||
}
|
||||
}
|
||||
|
||||
func (sd *SendDetails) UpdateFields(inputParams requests.RouteInputParams) {
|
||||
sd.SendType = int(inputParams.SendType)
|
||||
sd.FromAddress = types.Address(inputParams.AddrFrom)
|
||||
sd.ToAddress = types.Address(inputParams.AddrTo)
|
||||
sd.FromToken = inputParams.TokenID
|
||||
sd.ToToken = inputParams.ToTokenID
|
||||
if inputParams.AmountIn != nil {
|
||||
sd.FromAmount = inputParams.AmountIn.String()
|
||||
}
|
||||
if inputParams.AmountOut != nil {
|
||||
sd.ToAmount = inputParams.AmountOut.String()
|
||||
}
|
||||
sd.OwnerTokenBeingSent = inputParams.TokenIDIsOwnerToken
|
||||
sd.Username = inputParams.Username
|
||||
sd.PublicKey = inputParams.PublicKey
|
||||
if inputParams.PackID != nil {
|
||||
sd.PackID = inputParams.PackID.String()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,6 @@ import (
|
|||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
|
||||
"github.com/status-im/status-go/eth-node/types"
|
||||
"github.com/status-im/status-go/logutils"
|
||||
|
||||
status_common "github.com/status-im/status-go/common"
|
||||
|
@ -81,7 +80,7 @@ func (m *Manager) BuildTransactionsFromRoute(ctx context.Context, buildInputPara
|
|||
|
||||
m.buildInputParams = buildInputParams
|
||||
|
||||
updateFields(response.SendDetails, routeInputParams)
|
||||
response.SendDetails.UpdateFields(routeInputParams)
|
||||
|
||||
// notify client that sending transactions started (has 3 steps, building txs, signing txs, sending txs)
|
||||
signal.SendWalletEvent(signal.RouterSendingTransactionsStarted, response.SendDetails)
|
||||
|
@ -143,7 +142,7 @@ func (m *Manager) SendRouterTransactionsWithSignatures(ctx context.Context, send
|
|||
return
|
||||
}
|
||||
|
||||
updateFields(response.SendDetails, routeInputParams)
|
||||
response.SendDetails.UpdateFields(routeInputParams)
|
||||
|
||||
err = m.transactionManager.ValidateAndAddSignaturesToRouterTransactions(sendInputParams.Signatures)
|
||||
if err != nil {
|
||||
|
@ -219,23 +218,3 @@ func (m *Manager) SendRouterTransactionsWithSignatures(ctx context.Context, send
|
|||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func updateFields(sd *responses.SendDetails, inputParams requests.RouteInputParams) {
|
||||
sd.SendType = int(inputParams.SendType)
|
||||
sd.FromAddress = types.Address(inputParams.AddrFrom)
|
||||
sd.ToAddress = types.Address(inputParams.AddrTo)
|
||||
sd.FromToken = inputParams.TokenID
|
||||
sd.ToToken = inputParams.ToTokenID
|
||||
if inputParams.AmountIn != nil {
|
||||
sd.FromAmount = inputParams.AmountIn.String()
|
||||
}
|
||||
if inputParams.AmountOut != nil {
|
||||
sd.ToAmount = inputParams.AmountOut.String()
|
||||
}
|
||||
sd.OwnerTokenBeingSent = inputParams.TokenIDIsOwnerToken
|
||||
sd.Username = inputParams.Username
|
||||
sd.PublicKey = inputParams.PublicKey
|
||||
if inputParams.PackID != nil {
|
||||
sd.PackID = inputParams.PackID.String()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,6 +55,14 @@ func (db *DB) GetRouteData(uuid string) (*wallettypes.RouteData, error) {
|
|||
return getRouteData(db.db, uuid)
|
||||
}
|
||||
|
||||
func (db *DB) GetRouteDataByHash(chainID uint64, txHash types.Hash) (*wallettypes.RouteData, error) {
|
||||
uuid, err := getUuidForTxOnChain(db.db, chainID, txHash)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return db.GetRouteData(uuid)
|
||||
}
|
||||
|
||||
func putRouteInputParams(creator sqlite.StatementCreator, p *requests.RouteInputParams) error {
|
||||
q := sq.Replace("route_input_parameters").
|
||||
SetMap(sq.Eq{"route_input_params_json": &sqlite.JSONBlob{Data: p}})
|
||||
|
@ -394,3 +402,24 @@ func getPathTransaction(creator sqlite.StatementCreator, uuid string, pathIdx in
|
|||
|
||||
return tx, nil
|
||||
}
|
||||
|
||||
func getUuidForTxOnChain(creator sqlite.StatementCreator, chainID uint64, txHash types.Hash) (string, error) {
|
||||
var uuid string
|
||||
q := sq.Select("uuid").
|
||||
From("route_path_transactions").
|
||||
Where(sq.Eq{"chain_id": chainID, "tx_hash": txHash[:]})
|
||||
|
||||
query, args, err := q.ToSql()
|
||||
if err != nil {
|
||||
return uuid, err
|
||||
}
|
||||
|
||||
stmt, err := creator.Prepare(query)
|
||||
if err != nil {
|
||||
return uuid, err
|
||||
}
|
||||
defer stmt.Close()
|
||||
|
||||
err = stmt.QueryRow(args...).Scan(&uuid)
|
||||
return uuid, err
|
||||
}
|
||||
|
|
|
@ -44,6 +44,20 @@ func Test_PutRouteData(t *testing.T) {
|
|||
readRouteData, err := routeDB.GetRouteData(routeData.RouteInputParams.Uuid)
|
||||
require.NoError(t, err)
|
||||
require.EqualExportedValues(t, routeData, readRouteData)
|
||||
|
||||
for _, pathData := range routeData.PathsData {
|
||||
if pathData.IsTxPlaced() {
|
||||
readRouteData, err = routeDB.GetRouteDataByHash(pathData.RouterPath.FromChain.ChainID, pathData.TxData.SentHash)
|
||||
require.NoError(t, err)
|
||||
require.EqualExportedValues(t, routeData, readRouteData)
|
||||
}
|
||||
|
||||
if pathData.IsApprovalPlaced() {
|
||||
readRouteData, err = routeDB.GetRouteDataByHash(pathData.RouterPath.FromChain.ChainID, pathData.ApprovalTxData.SentHash)
|
||||
require.NoError(t, err)
|
||||
require.EqualExportedValues(t, routeData, readRouteData)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -66,16 +66,16 @@ type SendTxArgs struct {
|
|||
|
||||
// additional data - version SendTxArgsVersion0
|
||||
MultiTransactionID wallet_common.MultiTransactionIDType `json:"multiTransactionID"`
|
||||
Symbol string `json:"-"`
|
||||
Symbol string `json:"symbol"`
|
||||
// additional data - version SendTxArgsVersion1
|
||||
ValueIn *hexutil.Big `json:"-"`
|
||||
ValueOut *hexutil.Big `json:"-"`
|
||||
FromChainID uint64 `json:"-"`
|
||||
ToChainID uint64 `json:"-"`
|
||||
FromTokenID string `json:"-"`
|
||||
ToTokenID string `json:"-"`
|
||||
ToContractAddress types.Address `json:"-"` // represents address of the contract that needs to be used in order to send assets, like ERC721 or ERC1155 tx
|
||||
SlippagePercentage float32 `json:"-"`
|
||||
ValueIn *hexutil.Big `json:"valueIn"`
|
||||
ValueOut *hexutil.Big `json:"valueOut"`
|
||||
FromChainID uint64 `json:"fromChainID"`
|
||||
ToChainID uint64 `json:"toChainID"`
|
||||
FromTokenID string `json:"fromTokenID"`
|
||||
ToTokenID string `json:"toTokenID"`
|
||||
ToContractAddress types.Address `json:"toContractAddress"` // represents address of the contract that needs to be used in order to send assets, like ERC721 or ERC1155 tx
|
||||
SlippagePercentage float32 `json:"slippagePercentage"`
|
||||
}
|
||||
|
||||
// Valid checks whether this structure is filled in correctly.
|
||||
|
|
|
@ -17,6 +17,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/event"
|
||||
"github.com/ethereum/go-ethereum/p2p"
|
||||
ethrpc "github.com/ethereum/go-ethereum/rpc"
|
||||
ethTypes "github.com/status-im/status-go/eth-node/types"
|
||||
|
||||
"github.com/status-im/status-go/logutils"
|
||||
"github.com/status-im/status-go/rpc"
|
||||
|
@ -24,6 +25,8 @@ import (
|
|||
"github.com/status-im/status-go/services/wallet/bigint"
|
||||
"github.com/status-im/status-go/services/wallet/common"
|
||||
wallet_common "github.com/status-im/status-go/services/wallet/common"
|
||||
"github.com/status-im/status-go/services/wallet/responses"
|
||||
"github.com/status-im/status-go/services/wallet/routeexecution/storage"
|
||||
"github.com/status-im/status-go/services/wallet/walletevent"
|
||||
)
|
||||
|
||||
|
@ -63,21 +66,29 @@ type TxIdentity struct {
|
|||
Hash eth.Hash `json:"hash"`
|
||||
}
|
||||
|
||||
type TxDetails struct {
|
||||
SendDetails *responses.SendDetails `json:"sendDetails"`
|
||||
SentTransactions []*responses.RouterSentTransaction `json:"sentTransactions"`
|
||||
}
|
||||
|
||||
type PendingTxUpdatePayload struct {
|
||||
TxIdentity
|
||||
TxDetails
|
||||
Deleted bool `json:"deleted"`
|
||||
}
|
||||
|
||||
type StatusChangedPayload struct {
|
||||
TxIdentity
|
||||
TxDetails
|
||||
Status TxStatus `json:"status"`
|
||||
}
|
||||
|
||||
// PendingTxTracker implements StatusService in common/status_node_service.go
|
||||
type PendingTxTracker struct {
|
||||
db *sql.DB
|
||||
trackedTxDB *DB
|
||||
rpcClient rpc.ClientInterface
|
||||
db *sql.DB
|
||||
routeExecutionStorage *storage.DB
|
||||
trackedTxDB *DB
|
||||
rpcClient rpc.ClientInterface
|
||||
|
||||
rpcFilter *rpcfilters.Service
|
||||
eventFeed *event.Feed
|
||||
|
@ -88,12 +99,13 @@ type PendingTxTracker struct {
|
|||
|
||||
func NewPendingTxTracker(db *sql.DB, rpcClient rpc.ClientInterface, rpcFilter *rpcfilters.Service, eventFeed *event.Feed, checkInterval time.Duration) *PendingTxTracker {
|
||||
tm := &PendingTxTracker{
|
||||
db: db,
|
||||
trackedTxDB: NewDB(db),
|
||||
rpcClient: rpcClient,
|
||||
eventFeed: eventFeed,
|
||||
rpcFilter: rpcFilter,
|
||||
logger: logutils.ZapLogger().Named("PendingTxTracker"),
|
||||
db: db,
|
||||
routeExecutionStorage: storage.NewDB(db),
|
||||
trackedTxDB: NewDB(db),
|
||||
rpcClient: rpcClient,
|
||||
eventFeed: eventFeed,
|
||||
rpcFilter: rpcFilter,
|
||||
logger: logutils.ZapLogger().Named("PendingTxTracker"),
|
||||
}
|
||||
tm.taskRunner = NewConditionalRepeater(checkInterval, func(ctx context.Context) bool {
|
||||
return tm.fetchAndUpdateDB(ctx)
|
||||
|
@ -335,6 +347,37 @@ func (tm *PendingTxTracker) updateDBStatus(ctx context.Context, chainID common.C
|
|||
return res, nil
|
||||
}
|
||||
|
||||
func (tm *PendingTxTracker) updateTxDetails(txDetails *TxDetails, chainID uint64, txHash ethTypes.Hash) {
|
||||
if txDetails == nil {
|
||||
txDetails = &TxDetails{}
|
||||
}
|
||||
txDetails.SendDetails = &responses.SendDetails{}
|
||||
routeData, err := tm.routeExecutionStorage.GetRouteDataByHash(chainID, txHash)
|
||||
if err != nil {
|
||||
tm.logger.Warn("Missing tx data ", zap.Stringer("hash", txHash), zap.Error(err))
|
||||
}
|
||||
if routeData != nil {
|
||||
if routeData.RouteInputParams != nil {
|
||||
txDetails.SendDetails.UpdateFields(*routeData.RouteInputParams)
|
||||
}
|
||||
|
||||
for _, pd := range routeData.PathsData {
|
||||
if pd.IsApprovalPlaced() && pd.ApprovalTxData.SentHash == txHash {
|
||||
txDetails.SentTransactions = append(txDetails.SentTransactions, responses.NewRouterSentTransaction(
|
||||
pd.ApprovalTxData.TxArgs,
|
||||
pd.ApprovalTxData.SentHash,
|
||||
true))
|
||||
}
|
||||
if pd.IsTxPlaced() && pd.TxData.SentHash == txHash {
|
||||
txDetails.SentTransactions = append(txDetails.SentTransactions, responses.NewRouterSentTransaction(
|
||||
pd.TxData.TxArgs,
|
||||
pd.TxData.SentHash,
|
||||
false))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (tm *PendingTxTracker) emitNotifications(chainID common.ChainID, changes []txStatusRes) {
|
||||
if tm.eventFeed != nil {
|
||||
for _, change := range changes {
|
||||
|
@ -346,6 +389,8 @@ func (tm *PendingTxTracker) emitNotifications(chainID common.ChainID, changes []
|
|||
Status: change.Status,
|
||||
}
|
||||
|
||||
tm.updateTxDetails(&payload.TxDetails, chainID.ToUint(), ethTypes.Hash(change.hash))
|
||||
|
||||
jsonPayload, err := json.Marshal(payload)
|
||||
if err != nil {
|
||||
tm.logger.Error("Failed to marshal pending transaction status", zap.Stringer("hash", change.hash), zap.Error(err))
|
||||
|
@ -688,6 +733,8 @@ func (tm *PendingTxTracker) addPending(transaction *PendingTransaction) error {
|
|||
}
|
||||
|
||||
func (tm *PendingTxTracker) notifyPendingTransactionListeners(payload PendingTxUpdatePayload, addresses []eth.Address, timestamp uint64) {
|
||||
tm.updateTxDetails(&payload.TxDetails, payload.ChainID.ToUint(), ethTypes.Hash(payload.Hash))
|
||||
|
||||
jsonPayload, err := json.Marshal(payload)
|
||||
if err != nil {
|
||||
tm.logger.Error("Failed to marshal PendingTxUpdatePayload", zap.Stringer("hash", payload.Hash), zap.Error(err))
|
||||
|
|
Loading…
Reference in New Issue