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"`
FromAddress types.Address `json:"fromAddress"`
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"`
ToToken string `json:"toToken"`
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.FromAddress = types.Address(inputParams.AddrFrom)
sd.ToAddress = types.Address(inputParams.AddrTo)
@ -106,4 +108,8 @@ func (sd *SendDetails) UpdateFields(inputParams requests.RouteInputParams) {
if inputParams.PackID != nil {
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/router"
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/transfer"
"github.com/status-im/status-go/services/wallet/walletevent"
@ -88,12 +89,14 @@ func (m *Manager) BuildTransactionsFromRoute(ctx context.Context, buildInputPara
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)
signal.SendWalletEvent(signal.RouterSendingTransactionsStarted, response.SendDetails)
response.SigningDetails, err = m.transactionManager.BuildTransactionsFromRoute(
response.SigningDetails, fromChainID, toChainID, err = m.transactionManager.BuildTransactionsFromRoute(
route,
m.router.GetPathProcessors(),
transfer.BuildRouteExtraParams{
@ -105,6 +108,9 @@ func (m *Manager) BuildTransactionsFromRoute(ctx context.Context, buildInputPara
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 (
err error
route routes.Route
routeInputParams requests.RouteInputParams
)
response := &responses.RouterSentTransactions{
@ -150,16 +157,19 @@ func (m *Manager) SendRouterTransactionsWithSignatures(ctx context.Context, send
m.eventFeed.Send(event)
}()
_, routeInputParams = m.router.GetBestRouteAndAssociatedInputParams()
route, routeInputParams = m.router.GetBestRouteAndAssociatedInputParams()
if routeInputParams.Uuid != sendInputParams.Uuid {
err = ErrCannotResolveRouteId
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 {
response.SendDetails.UpdateFields(routeInputParams, fromChainID, toChainID)
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 {
response.SendDetails.UpdateFields(routeInputParams, fromChainID, toChainID)
log.Error("Error sending router transactions", "error", err)
// TODO #16556: Handle partially successful Tx sends?
// Don't return, store whichever transactions were successfully sent

View File

@ -17,6 +17,19 @@ func (r Route) Copy() Route {
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 {
var best Route
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,
params BuildRouteExtraParams) (*responses.SigningDetails, error) {
params BuildRouteExtraParams) (*responses.SigningDetails, uint64, uint64, error) {
if len(route) == 0 {
return nil, ErrNoRoute
return nil, 0, 0, ErrNoRoute
}
accFrom, err := tm.accountsDB.GetAccountByAddress(types.Address(params.AddressFrom))
if err != nil {
return nil, err
return nil, 0, 0, err
}
keypair, err := tm.accountsDB.GetKeypairByKeyUID(accFrom.KeyUID)
if err != nil {
return nil, err
return nil, 0, 0, err
}
response := &responses.SigningDetails{
@ -246,7 +246,7 @@ func (tm *TransactionManager) BuildTransactionsFromRoute(route routes.Route, pat
if path.ApprovalRequired && !tm.ApprovalPlacedForPath(path.ProcessorName) {
txDetails.ApprovalTxData, err = buildApprovalTxForPath(tm.transactor, path, params.AddressFrom, usedNonces, signer)
if err != nil {
return nil, err
return nil, path.FromChain.ChainID, path.ToChain.ChainID, err
}
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
txDetails.TxData, err = buildTxForPath(tm.transactor, path, pathProcessors, usedNonces, signer, params)
if err != nil {
return nil, err
return nil, path.FromChain.ChainID, path.ToChain.ChainID, err
}
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) {
@ -309,9 +309,9 @@ func validateAndAddSignature(txData *wallettypes.TransactionData, signatures map
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 {
return ErrNoTrsansactionsBeingBuilt
return 0, 0, ErrNoTrsansactionsBeingBuilt
}
// check if all transactions have been signed
@ -319,16 +319,16 @@ func (tm *TransactionManager) ValidateAndAddSignaturesToRouterTransactions(signa
for _, desc := range tm.routerTransactions {
err = validateAndAddSignature(desc.ApprovalTxData, signatures)
if err != nil {
return err
return desc.RouterPath.FromChain.ChainID, desc.RouterPath.ToChain.ChainID, err
}
err = validateAndAddSignature(desc.TxData, signatures)
if err != nil {
return err
return desc.RouterPath.FromChain.ChainID, desc.RouterPath.ToChain.ChainID, err
}
}
return nil
return 0, 0, nil
}
func addSignatureAndSendTransaction(
@ -355,11 +355,13 @@ func addSignatureAndSendTransaction(
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)
// send transactions
for _, desc := range tm.routerTransactions {
fromChainID = desc.RouterPath.FromChain.ChainID
toChainID = desc.RouterPath.ToChain.ChainID
if desc.ApprovalTxData != nil && !desc.IsApprovalPlaced() {
var response *responses.RouterSentTransaction
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.RouteInputParams != nil {
txDetails.SendDetails.UpdateFields(*routeData.RouteInputParams)
txDetails.SendDetails.UpdateFields(*routeData.RouteInputParams, 0, 0)
}
for _, pd := range routeData.PathsData {