152 lines
5.2 KiB
Go
152 lines
5.2 KiB
Go
package transfer
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/ethereum/go-ethereum/log"
|
|
"github.com/status-im/status-go/account"
|
|
"github.com/status-im/status-go/eth-node/types"
|
|
"github.com/status-im/status-go/services/wallet/bridge"
|
|
wallet_common "github.com/status-im/status-go/services/wallet/common"
|
|
"github.com/status-im/status-go/signal"
|
|
)
|
|
|
|
const multiTransactionColumns = "id, from_network_id, from_tx_hash, from_address, from_asset, from_amount, to_network_id, to_tx_hash, to_address, to_asset, to_amount, type, cross_tx_id, timestamp"
|
|
const selectMultiTransactionColumns = "id, COALESCE(from_network_id, 0), from_tx_hash, from_address, from_asset, from_amount, COALESCE(to_network_id, 0), to_tx_hash, to_address, to_asset, to_amount, type, cross_tx_id, timestamp"
|
|
|
|
func (tm *TransactionManager) InsertMultiTransaction(multiTransaction *MultiTransaction) (wallet_common.MultiTransactionIDType, error) {
|
|
return multiTransaction.ID, tm.storage.CreateMultiTransaction(multiTransaction)
|
|
}
|
|
|
|
func (tm *TransactionManager) UpdateMultiTransaction(multiTransaction *MultiTransaction) error {
|
|
return tm.storage.UpdateMultiTransaction(multiTransaction)
|
|
}
|
|
|
|
func (tm *TransactionManager) CreateMultiTransactionFromCommand(command *MultiTransactionCommand,
|
|
data []*bridge.TransactionBridge) (*MultiTransaction, error) {
|
|
|
|
multiTransaction := multiTransactionFromCommand(command)
|
|
|
|
if multiTransaction.Type == MultiTransactionSend && multiTransaction.FromNetworkID == 0 && len(data) == 1 {
|
|
multiTransaction.FromNetworkID = data[0].ChainID
|
|
}
|
|
|
|
return multiTransaction, nil
|
|
}
|
|
|
|
func (tm *TransactionManager) SendTransactionForSigningToKeycard(ctx context.Context, multiTransaction *MultiTransaction, data []*bridge.TransactionBridge, bridges map[string]bridge.Bridge) error {
|
|
acc, err := tm.accountsDB.GetAccountByAddress(types.Address(multiTransaction.FromAddress))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
kp, err := tm.accountsDB.GetKeypairByKeyUID(acc.KeyUID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if !kp.MigratedToKeycard() {
|
|
return fmt.Errorf("account being used is not migrated to a keycard, password is required")
|
|
}
|
|
|
|
tm.multiTransactionForKeycardSigning = multiTransaction
|
|
tm.transactionsBridgeData = data
|
|
hashes, err := tm.buildTransactions(bridges)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
signal.SendTransactionsForSigningEvent(hashes)
|
|
|
|
return nil
|
|
}
|
|
|
|
func (tm *TransactionManager) SendTransactions(ctx context.Context, multiTransaction *MultiTransaction, data []*bridge.TransactionBridge, bridges map[string]bridge.Bridge, account *account.SelectedExtKey) (*MultiTransactionCommandResult, error) {
|
|
updateDataFromMultiTx(data, multiTransaction)
|
|
hashes, err := sendTransactions(data, bridges, account)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &MultiTransactionCommandResult{
|
|
ID: int64(multiTransaction.ID),
|
|
Hashes: hashes,
|
|
}, nil
|
|
}
|
|
|
|
func (tm *TransactionManager) ProceedWithTransactionsSignatures(ctx context.Context, signatures map[string]SignatureDetails) (*MultiTransactionCommandResult, error) {
|
|
if err := addSignaturesToTransactions(tm.transactionsForKeycardSigning, signatures); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// send transactions
|
|
hashes := make(map[uint64][]types.Hash)
|
|
for _, desc := range tm.transactionsForKeycardSigning {
|
|
txWithSignature, err := tm.transactor.AddSignatureToTransaction(desc.chainID, desc.builtTx, desc.signature)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
hash, err := tm.transactor.SendTransactionWithSignature(desc.from, tm.multiTransactionForKeycardSigning.FromAsset, tm.multiTransactionForKeycardSigning.ID, txWithSignature)
|
|
if err != nil {
|
|
return nil, err // TODO: One of transfers within transaction could have been sent. Need to notify user about it
|
|
}
|
|
hashes[desc.chainID] = append(hashes[desc.chainID], hash)
|
|
}
|
|
|
|
_, err := tm.InsertMultiTransaction(tm.multiTransactionForKeycardSigning)
|
|
if err != nil {
|
|
log.Error("failed to insert multi transaction", "err", err)
|
|
}
|
|
|
|
return &MultiTransactionCommandResult{
|
|
ID: int64(tm.multiTransactionForKeycardSigning.ID),
|
|
Hashes: hashes,
|
|
}, nil
|
|
}
|
|
|
|
func (tm *TransactionManager) GetMultiTransactions(ctx context.Context, ids []wallet_common.MultiTransactionIDType) ([]*MultiTransaction, error) {
|
|
return tm.storage.ReadMultiTransactions(&MultiTxDetails{IDs: ids})
|
|
}
|
|
|
|
func (tm *TransactionManager) GetBridgeOriginMultiTransaction(ctx context.Context, toChainID uint64, crossTxID string) (*MultiTransaction, error) {
|
|
details := NewMultiTxDetails()
|
|
details.ToChainID = toChainID
|
|
details.CrossTxID = crossTxID
|
|
|
|
multiTxs, err := tm.storage.ReadMultiTransactions(details)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
for _, multiTx := range multiTxs {
|
|
// Origin MultiTxs will have a missing "ToTxHash"
|
|
if multiTx.ToTxHash == emptyHash {
|
|
return multiTx, nil
|
|
}
|
|
}
|
|
|
|
return nil, nil
|
|
}
|
|
|
|
func (tm *TransactionManager) GetBridgeDestinationMultiTransaction(ctx context.Context, toChainID uint64, crossTxID string) (*MultiTransaction, error) {
|
|
details := NewMultiTxDetails()
|
|
details.ToChainID = toChainID
|
|
details.CrossTxID = crossTxID
|
|
|
|
multiTxs, err := tm.storage.ReadMultiTransactions(details)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
for _, multiTx := range multiTxs {
|
|
// Destination MultiTxs will have a missing "FromTxHash"
|
|
if multiTx.FromTxHash == emptyHash {
|
|
return multiTx, nil
|
|
}
|
|
}
|
|
|
|
return nil, nil
|
|
}
|