chore(wallet)_: from and to chains added to send details

From and to chains added to SendDetails type that can be used on the client side if the sending fails
that we can display appropriate ephemeral notifications, saying sending from which chain has failed.
This commit is contained in:
Sale Djenic 2024-12-12 16:03:00 +01:00 committed by Anthony Laibe
parent 74db631435
commit c27c773c27
5 changed files with 53 additions and 21 deletions

View File

@ -15,6 +15,8 @@ type SendDetails struct {
SendType int `json:"sendType"` SendType int `json:"sendType"`
FromAddress types.Address `json:"fromAddress"` FromAddress types.Address `json:"fromAddress"`
ToAddress types.Address `json:"toAddress"` ToAddress types.Address `json:"toAddress"`
FromChain uint64 `json:"fromChain"` // this chain should be used only if en error occurred while sending a transaction
ToChain uint64 `json:"toChain"` // this chain should be used only if en error occurred while sending a transaction
FromToken string `json:"fromToken"` FromToken string `json:"fromToken"`
ToToken string `json:"toToken"` ToToken string `json:"toToken"`
FromAmount string `json:"fromAmount"` // total amount FromAmount string `json:"fromAmount"` // total amount
@ -88,7 +90,7 @@ func NewRouterSentTransaction(sendArgs *wallettypes.SendTxArgs, hash types.Hash,
} }
} }
func (sd *SendDetails) UpdateFields(inputParams requests.RouteInputParams) { func (sd *SendDetails) UpdateFields(inputParams requests.RouteInputParams, fromChain uint64, toChain uint64) {
sd.SendType = int(inputParams.SendType) sd.SendType = int(inputParams.SendType)
sd.FromAddress = types.Address(inputParams.AddrFrom) sd.FromAddress = types.Address(inputParams.AddrFrom)
sd.ToAddress = types.Address(inputParams.AddrTo) sd.ToAddress = types.Address(inputParams.AddrTo)
@ -106,4 +108,8 @@ func (sd *SendDetails) UpdateFields(inputParams requests.RouteInputParams) {
if inputParams.PackID != nil { if inputParams.PackID != nil {
sd.PackID = inputParams.PackID.String() sd.PackID = inputParams.PackID.String()
} }
// Set chain IDs, in case of an error while sending a transaction
sd.FromChain = fromChain
sd.ToChain = toChain
} }

View File

@ -20,6 +20,7 @@ import (
"github.com/status-im/status-go/services/wallet/routeexecution/storage" "github.com/status-im/status-go/services/wallet/routeexecution/storage"
"github.com/status-im/status-go/services/wallet/router" "github.com/status-im/status-go/services/wallet/router"
pathProcessorCommon "github.com/status-im/status-go/services/wallet/router/pathprocessor/common" pathProcessorCommon "github.com/status-im/status-go/services/wallet/router/pathprocessor/common"
"github.com/status-im/status-go/services/wallet/router/routes"
"github.com/status-im/status-go/services/wallet/router/sendtype" "github.com/status-im/status-go/services/wallet/router/sendtype"
"github.com/status-im/status-go/services/wallet/transfer" "github.com/status-im/status-go/services/wallet/transfer"
"github.com/status-im/status-go/services/wallet/walletevent" "github.com/status-im/status-go/services/wallet/walletevent"
@ -88,12 +89,14 @@ func (m *Manager) BuildTransactionsFromRoute(ctx context.Context, buildInputPara
m.buildInputParams = buildInputParams m.buildInputParams = buildInputParams
response.SendDetails.UpdateFields(routeInputParams) fromChainID, toChainID := route.GetFirstPathChains()
response.SendDetails.UpdateFields(routeInputParams, fromChainID, toChainID)
// notify client that sending transactions started (has 3 steps, building txs, signing txs, sending txs) // notify client that sending transactions started (has 3 steps, building txs, signing txs, sending txs)
signal.SendWalletEvent(signal.RouterSendingTransactionsStarted, response.SendDetails) signal.SendWalletEvent(signal.RouterSendingTransactionsStarted, response.SendDetails)
response.SigningDetails, err = m.transactionManager.BuildTransactionsFromRoute( response.SigningDetails, fromChainID, toChainID, err = m.transactionManager.BuildTransactionsFromRoute(
route, route,
m.router.GetPathProcessors(), m.router.GetPathProcessors(),
transfer.BuildRouteExtraParams{ transfer.BuildRouteExtraParams{
@ -105,6 +108,9 @@ func (m *Manager) BuildTransactionsFromRoute(ctx context.Context, buildInputPara
SlippagePercentage: buildInputParams.SlippagePercentage, SlippagePercentage: buildInputParams.SlippagePercentage,
}, },
) )
if err != nil {
response.SendDetails.UpdateFields(routeInputParams, fromChainID, toChainID)
}
}() }()
} }
@ -114,6 +120,7 @@ func (m *Manager) SendRouterTransactionsWithSignatures(ctx context.Context, send
var ( var (
err error err error
route routes.Route
routeInputParams requests.RouteInputParams routeInputParams requests.RouteInputParams
) )
response := &responses.RouterSentTransactions{ response := &responses.RouterSentTransactions{
@ -150,16 +157,19 @@ func (m *Manager) SendRouterTransactionsWithSignatures(ctx context.Context, send
m.eventFeed.Send(event) m.eventFeed.Send(event)
}() }()
_, routeInputParams = m.router.GetBestRouteAndAssociatedInputParams() route, routeInputParams = m.router.GetBestRouteAndAssociatedInputParams()
if routeInputParams.Uuid != sendInputParams.Uuid { if routeInputParams.Uuid != sendInputParams.Uuid {
err = ErrCannotResolveRouteId err = ErrCannotResolveRouteId
return return
} }
response.SendDetails.UpdateFields(routeInputParams) fromChainID, toChainID := route.GetFirstPathChains()
err = m.transactionManager.ValidateAndAddSignaturesToRouterTransactions(sendInputParams.Signatures) response.SendDetails.UpdateFields(routeInputParams, fromChainID, toChainID)
fromChainID, toChainID, err = m.transactionManager.ValidateAndAddSignaturesToRouterTransactions(sendInputParams.Signatures)
if err != nil { if err != nil {
response.SendDetails.UpdateFields(routeInputParams, fromChainID, toChainID)
return return
} }
@ -194,8 +204,9 @@ func (m *Manager) SendRouterTransactionsWithSignatures(ctx context.Context, send
} }
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
response.SentTransactions, err = m.transactionManager.SendRouterTransactions(ctx, multiTx) response.SentTransactions, fromChainID, toChainID, err = m.transactionManager.SendRouterTransactions(ctx, multiTx)
if err != nil { if err != nil {
response.SendDetails.UpdateFields(routeInputParams, fromChainID, toChainID)
log.Error("Error sending router transactions", "error", err) log.Error("Error sending router transactions", "error", err)
// TODO #16556: Handle partially successful Tx sends? // TODO #16556: Handle partially successful Tx sends?
// Don't return, store whichever transactions were successfully sent // Don't return, store whichever transactions were successfully sent

View File

@ -17,6 +17,19 @@ func (r Route) Copy() Route {
return newRoute return newRoute
} }
// GetFirstPathChains returns the chain IDs (from and to) of the first path in the route
// If certain tx fails or succeeds status--go will send from/to chains along with other tx details to client to let
// thc client know about failed/successful tx. But if an error occurs before the first path, during the preparation
// of the route, the client will not have the chain IDs to know where the tx was supposed to be sent. This function
// is used to get the chain IDs of the first path in the route to send them to the client in case of an error.
func (r Route) GetFirstPathChains() (uint64, uint64) {
if len(r) == 0 {
return 0, 0
}
return r[0].FromChain.ChainID, r[0].ToChain.ChainID
}
func FindBestRoute(routes []Route, tokenPrice float64, nativeTokenPrice float64) Route { func FindBestRoute(routes []Route, tokenPrice float64, nativeTokenPrice float64) Route {
var best Route var best Route
bestCost := big.NewFloat(math.Inf(1)) bestCost := big.NewFloat(math.Inf(1))

View File

@ -214,19 +214,19 @@ func buildTxForPath(transactor transactions.TransactorIface, path *routes.Path,
} }
func (tm *TransactionManager) BuildTransactionsFromRoute(route routes.Route, pathProcessors map[string]pathprocessor.PathProcessor, func (tm *TransactionManager) BuildTransactionsFromRoute(route routes.Route, pathProcessors map[string]pathprocessor.PathProcessor,
params BuildRouteExtraParams) (*responses.SigningDetails, error) { params BuildRouteExtraParams) (*responses.SigningDetails, uint64, uint64, error) {
if len(route) == 0 { if len(route) == 0 {
return nil, ErrNoRoute return nil, 0, 0, ErrNoRoute
} }
accFrom, err := tm.accountsDB.GetAccountByAddress(types.Address(params.AddressFrom)) accFrom, err := tm.accountsDB.GetAccountByAddress(types.Address(params.AddressFrom))
if err != nil { if err != nil {
return nil, err return nil, 0, 0, err
} }
keypair, err := tm.accountsDB.GetKeypairByKeyUID(accFrom.KeyUID) keypair, err := tm.accountsDB.GetKeypairByKeyUID(accFrom.KeyUID)
if err != nil { if err != nil {
return nil, err return nil, 0, 0, err
} }
response := &responses.SigningDetails{ response := &responses.SigningDetails{
@ -246,7 +246,7 @@ func (tm *TransactionManager) BuildTransactionsFromRoute(route routes.Route, pat
if path.ApprovalRequired && !tm.ApprovalPlacedForPath(path.ProcessorName) { if path.ApprovalRequired && !tm.ApprovalPlacedForPath(path.ProcessorName) {
txDetails.ApprovalTxData, err = buildApprovalTxForPath(tm.transactor, path, params.AddressFrom, usedNonces, signer) txDetails.ApprovalTxData, err = buildApprovalTxForPath(tm.transactor, path, params.AddressFrom, usedNonces, signer)
if err != nil { if err != nil {
return nil, err return nil, path.FromChain.ChainID, path.ToChain.ChainID, err
} }
response.Hashes = append(response.Hashes, txDetails.ApprovalTxData.HashToSign) response.Hashes = append(response.Hashes, txDetails.ApprovalTxData.HashToSign)
@ -259,12 +259,12 @@ func (tm *TransactionManager) BuildTransactionsFromRoute(route routes.Route, pat
// build tx for the path // build tx for the path
txDetails.TxData, err = buildTxForPath(tm.transactor, path, pathProcessors, usedNonces, signer, params) txDetails.TxData, err = buildTxForPath(tm.transactor, path, pathProcessors, usedNonces, signer, params)
if err != nil { if err != nil {
return nil, err return nil, path.FromChain.ChainID, path.ToChain.ChainID, err
} }
response.Hashes = append(response.Hashes, txDetails.TxData.HashToSign) response.Hashes = append(response.Hashes, txDetails.TxData.HashToSign)
} }
return response, nil return response, 0, 0, nil
} }
func getSignatureForTxHash(txHash string, signatures map[string]requests.SignatureDetails) ([]byte, error) { func getSignatureForTxHash(txHash string, signatures map[string]requests.SignatureDetails) ([]byte, error) {
@ -309,9 +309,9 @@ func validateAndAddSignature(txData *wallettypes.TransactionData, signatures map
return nil return nil
} }
func (tm *TransactionManager) ValidateAndAddSignaturesToRouterTransactions(signatures map[string]requests.SignatureDetails) error { func (tm *TransactionManager) ValidateAndAddSignaturesToRouterTransactions(signatures map[string]requests.SignatureDetails) (uint64, uint64, error) {
if len(tm.routerTransactions) == 0 { if len(tm.routerTransactions) == 0 {
return ErrNoTrsansactionsBeingBuilt return 0, 0, ErrNoTrsansactionsBeingBuilt
} }
// check if all transactions have been signed // check if all transactions have been signed
@ -319,16 +319,16 @@ func (tm *TransactionManager) ValidateAndAddSignaturesToRouterTransactions(signa
for _, desc := range tm.routerTransactions { for _, desc := range tm.routerTransactions {
err = validateAndAddSignature(desc.ApprovalTxData, signatures) err = validateAndAddSignature(desc.ApprovalTxData, signatures)
if err != nil { if err != nil {
return err return desc.RouterPath.FromChain.ChainID, desc.RouterPath.ToChain.ChainID, err
} }
err = validateAndAddSignature(desc.TxData, signatures) err = validateAndAddSignature(desc.TxData, signatures)
if err != nil { if err != nil {
return err return desc.RouterPath.FromChain.ChainID, desc.RouterPath.ToChain.ChainID, err
} }
} }
return nil return 0, 0, nil
} }
func addSignatureAndSendTransaction( func addSignatureAndSendTransaction(
@ -355,11 +355,13 @@ func addSignatureAndSendTransaction(
return responses.NewRouterSentTransaction(txData.TxArgs, txData.SentHash, isApproval), nil return responses.NewRouterSentTransaction(txData.TxArgs, txData.SentHash, isApproval), nil
} }
func (tm *TransactionManager) SendRouterTransactions(ctx context.Context, multiTx *MultiTransaction) (transactions []*responses.RouterSentTransaction, err error) { func (tm *TransactionManager) SendRouterTransactions(ctx context.Context, multiTx *MultiTransaction) (transactions []*responses.RouterSentTransaction, fromChainID uint64, toChainID uint64, err error) {
transactions = make([]*responses.RouterSentTransaction, 0) transactions = make([]*responses.RouterSentTransaction, 0)
// send transactions // send transactions
for _, desc := range tm.routerTransactions { for _, desc := range tm.routerTransactions {
fromChainID = desc.RouterPath.FromChain.ChainID
toChainID = desc.RouterPath.ToChain.ChainID
if desc.ApprovalTxData != nil && !desc.IsApprovalPlaced() { if desc.ApprovalTxData != nil && !desc.IsApprovalPlaced() {
var response *responses.RouterSentTransaction var response *responses.RouterSentTransaction
response, err = addSignatureAndSendTransaction(tm.transactor, desc.ApprovalTxData, multiTx.ID, true) response, err = addSignatureAndSendTransaction(tm.transactor, desc.ApprovalTxData, multiTx.ID, true)

View File

@ -358,7 +358,7 @@ func (tm *PendingTxTracker) updateTxDetails(txDetails *TxDetails, chainID uint64
} }
if routeData != nil { if routeData != nil {
if routeData.RouteInputParams != nil { if routeData.RouteInputParams != nil {
txDetails.SendDetails.UpdateFields(*routeData.RouteInputParams) txDetails.SendDetails.UpdateFields(*routeData.RouteInputParams, 0, 0)
} }
for _, pd := range routeData.PathsData { for _, pd := range routeData.PathsData {