chore_: rework transaction code to make it more reusable
This commit is contained in:
parent
cfcef92e64
commit
414e08b283
|
@ -2,6 +2,7 @@ package routes
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"math/big"
|
"math/big"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
|
@ -169,3 +170,9 @@ func (p *Path) Copy() *Path {
|
||||||
|
|
||||||
return newPath
|
return newPath
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ID that uniquely identifies a path in a given route
|
||||||
|
func (p *Path) ID() string {
|
||||||
|
// A route will contain at most a single path from a given processor for a given origin chain
|
||||||
|
return p.ProcessorName + "-" + strconv.Itoa(int(p.FromChain.ChainID))
|
||||||
|
}
|
||||||
|
|
|
@ -43,26 +43,30 @@ type TransactionDescription struct {
|
||||||
signature []byte
|
signature []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
type RouterTransactionDetails struct {
|
type TransactionData struct {
|
||||||
RouterPath *routes.Path
|
|
||||||
TxArgs *transactions.SendTxArgs
|
TxArgs *transactions.SendTxArgs
|
||||||
Tx *ethTypes.Transaction
|
Tx *ethTypes.Transaction
|
||||||
TxHashToSign types.Hash
|
HashToSign types.Hash
|
||||||
TxSignature []byte
|
Signature []byte
|
||||||
TxSentHash types.Hash
|
SentHash types.Hash
|
||||||
ApprovalTxArgs *transactions.SendTxArgs
|
}
|
||||||
ApprovalTx *ethTypes.Transaction
|
|
||||||
ApprovalHashToSign types.Hash
|
func (txd *TransactionData) IsTxPlaced() bool {
|
||||||
ApprovalSignature []byte
|
return txd.SentHash != types.Hash(wallet_common.ZeroHash())
|
||||||
ApprovalTxSentHash types.Hash
|
}
|
||||||
|
|
||||||
|
type RouterTransactionDetails struct {
|
||||||
|
RouterPath *routes.Path
|
||||||
|
TxData *TransactionData
|
||||||
|
ApprovalTxData *TransactionData
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rtd *RouterTransactionDetails) IsTxPlaced() bool {
|
func (rtd *RouterTransactionDetails) IsTxPlaced() bool {
|
||||||
return rtd.TxSentHash != types.Hash(wallet_common.ZeroHash())
|
return rtd.TxData != nil && rtd.TxData.IsTxPlaced()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rtd *RouterTransactionDetails) IsApprovalPlaced() bool {
|
func (rtd *RouterTransactionDetails) IsApprovalPlaced() bool {
|
||||||
return rtd.ApprovalTxSentHash != types.Hash(wallet_common.ZeroHash())
|
return rtd.ApprovalTxData != nil && rtd.ApprovalTxData.IsTxPlaced()
|
||||||
}
|
}
|
||||||
|
|
||||||
type TransactionManager struct {
|
type TransactionManager struct {
|
||||||
|
|
|
@ -60,8 +60,23 @@ func (tm *TransactionManager) TxPlacedForPath(pathProcessorName string) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tm *TransactionManager) buildApprovalTxForPath(path *routes.Path, addressFrom common.Address,
|
func (tm *TransactionManager) getOrInitDetailsForPath(path *routes.Path) *RouterTransactionDetails {
|
||||||
usedNonces map[uint64]int64, signer ethTypes.Signer) (types.Hash, error) {
|
for _, desc := range tm.routerTransactions {
|
||||||
|
if desc.RouterPath.ID() == path.ID() {
|
||||||
|
return desc
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
newDetails := &RouterTransactionDetails{
|
||||||
|
RouterPath: path,
|
||||||
|
}
|
||||||
|
tm.routerTransactions = append(tm.routerTransactions, newDetails)
|
||||||
|
|
||||||
|
return newDetails
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildApprovalTxForPath(transactor transactions.TransactorIface, path *routes.Path, addressFrom common.Address,
|
||||||
|
usedNonces map[uint64]int64, signer ethTypes.Signer) (*TransactionData, error) {
|
||||||
lastUsedNonce := int64(-1)
|
lastUsedNonce := int64(-1)
|
||||||
if nonce, ok := usedNonces[path.FromChain.ChainID]; ok {
|
if nonce, ok := usedNonces[path.FromChain.ChainID]; ok {
|
||||||
lastUsedNonce = nonce
|
lastUsedNonce = nonce
|
||||||
|
@ -69,7 +84,7 @@ func (tm *TransactionManager) buildApprovalTxForPath(path *routes.Path, addressF
|
||||||
|
|
||||||
data, err := walletCommon.PackApprovalInputData(path.AmountIn.ToInt(), path.ApprovalContractAddress)
|
data, err := walletCommon.PackApprovalInputData(path.AmountIn.ToInt(), path.ApprovalContractAddress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return types.Hash{}, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
addrTo := types.Address(path.FromToken.Address)
|
addrTo := types.Address(path.FromToken.Address)
|
||||||
|
@ -93,25 +108,22 @@ func (tm *TransactionManager) buildApprovalTxForPath(path *routes.Path, addressF
|
||||||
approavalSendArgs.FromTokenID = path.FromToken.Symbol
|
approavalSendArgs.FromTokenID = path.FromToken.Symbol
|
||||||
}
|
}
|
||||||
|
|
||||||
builtApprovalTx, usedNonce, err := tm.transactor.ValidateAndBuildTransaction(approavalSendArgs.FromChainID, *approavalSendArgs, lastUsedNonce)
|
builtApprovalTx, usedNonce, err := transactor.ValidateAndBuildTransaction(approavalSendArgs.FromChainID, *approavalSendArgs, lastUsedNonce)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return types.Hash{}, err
|
return nil, err
|
||||||
}
|
}
|
||||||
approvalTxHash := signer.Hash(builtApprovalTx)
|
approvalTxHash := signer.Hash(builtApprovalTx)
|
||||||
usedNonces[path.FromChain.ChainID] = int64(usedNonce)
|
usedNonces[path.FromChain.ChainID] = int64(usedNonce)
|
||||||
|
|
||||||
tm.routerTransactions = append(tm.routerTransactions, &RouterTransactionDetails{
|
return &TransactionData{
|
||||||
RouterPath: path,
|
TxArgs: approavalSendArgs,
|
||||||
ApprovalTxArgs: approavalSendArgs,
|
Tx: builtApprovalTx,
|
||||||
ApprovalTx: builtApprovalTx,
|
HashToSign: types.Hash(approvalTxHash),
|
||||||
ApprovalHashToSign: types.Hash(approvalTxHash),
|
}, nil
|
||||||
})
|
|
||||||
|
|
||||||
return types.Hash(approvalTxHash), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tm *TransactionManager) buildTxForPath(path *routes.Path, pathProcessors map[string]pathprocessor.PathProcessor,
|
func buildTxForPath(transactor transactions.TransactorIface, path *routes.Path, pathProcessors map[string]pathprocessor.PathProcessor,
|
||||||
usedNonces map[uint64]int64, signer ethTypes.Signer, params BuildRouteExtraParams) (types.Hash, error) {
|
usedNonces map[uint64]int64, signer ethTypes.Signer, params BuildRouteExtraParams) (*TransactionData, error) {
|
||||||
lastUsedNonce := int64(-1)
|
lastUsedNonce := int64(-1)
|
||||||
if nonce, ok := usedNonces[path.FromChain.ChainID]; ok {
|
if nonce, ok := usedNonces[path.FromChain.ChainID]; ok {
|
||||||
lastUsedNonce = nonce
|
lastUsedNonce = nonce
|
||||||
|
@ -134,7 +146,7 @@ func (tm *TransactionManager) buildTxForPath(path *routes.Path, pathProcessors m
|
||||||
|
|
||||||
data, err := pathProcessors[path.ProcessorName].PackTxInputData(processorInputParams)
|
data, err := pathProcessors[path.ProcessorName].PackTxInputData(processorInputParams)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return types.Hash{}, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
addrTo := types.Address(params.AddressTo)
|
addrTo := types.Address(params.AddressTo)
|
||||||
|
@ -185,19 +197,16 @@ func (tm *TransactionManager) buildTxForPath(path *routes.Path, pathProcessors m
|
||||||
|
|
||||||
builtTx, usedNonce, err := pathProcessors[path.ProcessorName].BuildTransactionV2(sendArgs, lastUsedNonce)
|
builtTx, usedNonce, err := pathProcessors[path.ProcessorName].BuildTransactionV2(sendArgs, lastUsedNonce)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return types.Hash{}, err
|
return nil, err
|
||||||
}
|
}
|
||||||
txHash := signer.Hash(builtTx)
|
txHash := signer.Hash(builtTx)
|
||||||
usedNonces[path.FromChain.ChainID] = int64(usedNonce)
|
usedNonces[path.FromChain.ChainID] = int64(usedNonce)
|
||||||
|
|
||||||
tm.routerTransactions = append(tm.routerTransactions, &RouterTransactionDetails{
|
return &TransactionData{
|
||||||
RouterPath: path,
|
|
||||||
TxArgs: sendArgs,
|
TxArgs: sendArgs,
|
||||||
Tx: builtTx,
|
Tx: builtTx,
|
||||||
TxHashToSign: types.Hash(txHash),
|
HashToSign: types.Hash(txHash),
|
||||||
})
|
}, nil
|
||||||
|
|
||||||
return types.Hash(txHash), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tm *TransactionManager) BuildTransactionsFromRoute(route routes.Route, pathProcessors map[string]pathprocessor.PathProcessor,
|
func (tm *TransactionManager) BuildTransactionsFromRoute(route routes.Route, pathProcessors map[string]pathprocessor.PathProcessor,
|
||||||
|
@ -227,13 +236,15 @@ func (tm *TransactionManager) BuildTransactionsFromRoute(route routes.Route, pat
|
||||||
for _, path := range route {
|
for _, path := range route {
|
||||||
signer := ethTypes.NewLondonSigner(big.NewInt(int64(path.FromChain.ChainID)))
|
signer := ethTypes.NewLondonSigner(big.NewInt(int64(path.FromChain.ChainID)))
|
||||||
|
|
||||||
|
txDetails := tm.getOrInitDetailsForPath(path)
|
||||||
|
|
||||||
// always check for approval tx first for the path and build it if needed
|
// always check for approval tx first for the path and build it if needed
|
||||||
if path.ApprovalRequired && !tm.ApprovalPlacedForPath(path.ProcessorName) {
|
if path.ApprovalRequired && !tm.ApprovalPlacedForPath(path.ProcessorName) {
|
||||||
approvalTxHash, err := tm.buildApprovalTxForPath(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, err
|
||||||
}
|
}
|
||||||
response.Hashes = append(response.Hashes, approvalTxHash)
|
response.Hashes = append(response.Hashes, txDetails.ApprovalTxData.HashToSign)
|
||||||
|
|
||||||
// if approval is needed for swap, we cannot build the swap tx before the approval tx is mined
|
// if approval is needed for swap, we cannot build the swap tx before the approval tx is mined
|
||||||
if path.ProcessorName == pathprocessor.ProcessorSwapParaswapName {
|
if path.ProcessorName == pathprocessor.ProcessorSwapParaswapName {
|
||||||
|
@ -242,11 +253,11 @@ func (tm *TransactionManager) BuildTransactionsFromRoute(route routes.Route, pat
|
||||||
}
|
}
|
||||||
|
|
||||||
// build tx for the path
|
// build tx for the path
|
||||||
txHash, err := tm.buildTxForPath(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, err
|
||||||
}
|
}
|
||||||
response.Hashes = append(response.Hashes, txHash)
|
response.Hashes = append(response.Hashes, txDetails.TxData.HashToSign)
|
||||||
}
|
}
|
||||||
|
|
||||||
return response, nil
|
return response, nil
|
||||||
|
@ -282,51 +293,75 @@ func getSignatureForTxHash(txHash string, signatures map[string]SignatureDetails
|
||||||
return signature, nil
|
return signature, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func validateAndAddSignature(txData *TransactionData, signatures map[string]SignatureDetails) error {
|
||||||
|
if txData != nil && !txData.IsTxPlaced() {
|
||||||
|
var err error
|
||||||
|
txData.Signature, err = getSignatureForTxHash(txData.HashToSign.String(), signatures)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (tm *TransactionManager) ValidateAndAddSignaturesToRouterTransactions(signatures map[string]SignatureDetails) error {
|
func (tm *TransactionManager) ValidateAndAddSignaturesToRouterTransactions(signatures map[string]SignatureDetails) error {
|
||||||
if len(tm.routerTransactions) == 0 {
|
if len(tm.routerTransactions) == 0 {
|
||||||
return ErrNoTrsansactionsBeingBuilt
|
return ErrNoTrsansactionsBeingBuilt
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if all transactions have been signed
|
// check if all transactions have been signed
|
||||||
|
var err error
|
||||||
for _, desc := range tm.routerTransactions {
|
for _, desc := range tm.routerTransactions {
|
||||||
if desc.ApprovalTx != nil && desc.ApprovalTxSentHash == (types.Hash{}) {
|
err = validateAndAddSignature(desc.ApprovalTxData, signatures)
|
||||||
sig, err := getSignatureForTxHash(desc.ApprovalHashToSign.String(), signatures)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
desc.ApprovalSignature = sig
|
|
||||||
}
|
|
||||||
|
|
||||||
if desc.Tx != nil && desc.TxSentHash == (types.Hash{}) {
|
err = validateAndAddSignature(desc.TxData, signatures)
|
||||||
sig, err := getSignatureForTxHash(desc.TxHashToSign.String(), signatures)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
desc.TxSignature = sig
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func addSignatureAndSendTransaction(
|
||||||
|
transactor transactions.TransactorIface,
|
||||||
|
txData *TransactionData,
|
||||||
|
multiTransactionID walletCommon.MultiTransactionIDType,
|
||||||
|
isApproval bool) (*responses.RouterSentTransaction, error) {
|
||||||
|
var txWithSignature *ethTypes.Transaction
|
||||||
|
var err error
|
||||||
|
|
||||||
|
txWithSignature, err = transactor.AddSignatureToTransaction(txData.TxArgs.FromChainID, txData.Tx, txData.Signature)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
txData.Tx = txWithSignature
|
||||||
|
|
||||||
|
txData.SentHash, err = transactor.SendTransactionWithSignature(common.Address(txData.TxArgs.From), txData.TxArgs.FromTokenID, multiTransactionID, txWithSignature)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
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, 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 {
|
||||||
if desc.ApprovalTx != nil && !desc.IsApprovalPlaced() {
|
if desc.ApprovalTxData != nil && !desc.IsApprovalPlaced() {
|
||||||
var approvalTxWithSignature *ethTypes.Transaction
|
var response *responses.RouterSentTransaction
|
||||||
approvalTxWithSignature, err = tm.transactor.AddSignatureToTransaction(desc.ApprovalTxArgs.FromChainID, desc.ApprovalTx, desc.ApprovalSignature)
|
response, err = addSignatureAndSendTransaction(tm.transactor, desc.ApprovalTxData, multiTx.ID, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
desc.ApprovalTxSentHash, err = tm.transactor.SendTransactionWithSignature(common.Address(desc.ApprovalTxArgs.From), desc.ApprovalTxArgs.FromTokenID, multiTx.ID, approvalTxWithSignature)
|
transactions = append(transactions, response)
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
transactions = append(transactions, responses.NewRouterSentTransaction(desc.ApprovalTxArgs, desc.ApprovalTxSentHash, true))
|
|
||||||
|
|
||||||
// if approval is needed for swap, then we need to wait for the approval tx to be mined before sending the swap tx
|
// if approval is needed for swap, then we need to wait for the approval tx to be mined before sending the swap tx
|
||||||
if desc.RouterPath.ProcessorName == pathprocessor.ProcessorSwapParaswapName {
|
if desc.RouterPath.ProcessorName == pathprocessor.ProcessorSwapParaswapName {
|
||||||
|
@ -334,19 +369,14 @@ func (tm *TransactionManager) SendRouterTransactions(ctx context.Context, multiT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if desc.Tx != nil && !desc.IsTxPlaced() {
|
if desc.TxData != nil && !desc.IsTxPlaced() {
|
||||||
var txWithSignature *ethTypes.Transaction
|
var response *responses.RouterSentTransaction
|
||||||
txWithSignature, err = tm.transactor.AddSignatureToTransaction(desc.TxArgs.FromChainID, desc.Tx, desc.TxSignature)
|
response, err = addSignatureAndSendTransaction(tm.transactor, desc.TxData, multiTx.ID, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
desc.TxSentHash, err = tm.transactor.SendTransactionWithSignature(common.Address(desc.TxArgs.From), desc.TxArgs.FromTokenID, multiTx.ID, txWithSignature)
|
transactions = append(transactions, response)
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
transactions = append(transactions, responses.NewRouterSentTransaction(desc.TxArgs, desc.TxSentHash, false))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue