Skip to content

Commit

Permalink
chore(wallet)_: from and to chains added to send details
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
saledjenic authored and alaibe committed Dec 13, 2024
1 parent 74db631 commit c27c773
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 21 deletions.
8 changes: 7 additions & 1 deletion services/wallet/responses/router_transactions.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand All @@ -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
}
23 changes: 17 additions & 6 deletions services/wallet/routeexecution/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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{
Expand All @@ -105,6 +108,9 @@ func (m *Manager) BuildTransactionsFromRoute(ctx context.Context, buildInputPara
SlippagePercentage: buildInputParams.SlippagePercentage,
},
)
if err != nil {
response.SendDetails.UpdateFields(routeInputParams, fromChainID, toChainID)
}
}()
}

Expand All @@ -114,6 +120,7 @@ func (m *Manager) SendRouterTransactionsWithSignatures(ctx context.Context, send

var (
err error
route routes.Route
routeInputParams requests.RouteInputParams
)
response := &responses.RouterSentTransactions{
Expand Down Expand Up @@ -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()

response.SendDetails.UpdateFields(routeInputParams, fromChainID, toChainID)

err = m.transactionManager.ValidateAndAddSignaturesToRouterTransactions(sendInputParams.Signatures)
fromChainID, toChainID, err = m.transactionManager.ValidateAndAddSignaturesToRouterTransactions(sendInputParams.Signatures)
if err != nil {
response.SendDetails.UpdateFields(routeInputParams, fromChainID, toChainID)
return
}

Expand Down Expand Up @@ -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
Expand Down
13 changes: 13 additions & 0 deletions services/wallet/router/routes/route.go
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
28 changes: 15 additions & 13 deletions services/wallet/transfer/transaction_manager_route.go
Original file line number Diff line number Diff line change
Expand Up @@ -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{
Expand All @@ -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)

Expand All @@ -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) {
Expand Down Expand Up @@ -309,26 +309,26 @@ 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
var err error
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(
Expand All @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion transactions/pendingtxtracker.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down

0 comments on commit c27c773

Please sign in to comment.