github.com/status-im/status-go@v1.1.0/services/wallet/transfer/multi_transaction_db.go (about)

     1  package transfer
     2  
     3  import (
     4  	"database/sql"
     5  	"fmt"
     6  	"strings"
     7  
     8  	"github.com/ethereum/go-ethereum/common"
     9  	wallet_common "github.com/status-im/status-go/services/wallet/common"
    10  )
    11  
    12  // Since we already use MultitransactionIDType in DB, and its default value is 0 (Send)
    13  // this type is used to with default value 0 to represent invalid type to avoid bugs
    14  // when devs forget to call NewMultiTxDetails()
    15  type MultiTransactionDBType MultiTransactionType
    16  
    17  const (
    18  	MultiTransactionDBTypeInvalid = 0
    19  	MultiTransactionDBSend        = iota
    20  	MultiTransactionDBSwap
    21  	MultiTransactionDBBridge
    22  	MultiTransactionDBApprove
    23  )
    24  
    25  func mtDBTypeToMTType(mtDBType MultiTransactionDBType) MultiTransactionType {
    26  	if mtDBType == MultiTransactionDBTypeInvalid {
    27  		return MultiTransactionTypeInvalid
    28  	}
    29  
    30  	return MultiTransactionType(mtDBType - 1)
    31  }
    32  
    33  type MultiTxDetails struct {
    34  	IDs         []wallet_common.MultiTransactionIDType
    35  	AnyAddress  common.Address
    36  	FromAddress common.Address
    37  	ToAddress   common.Address
    38  	ToChainID   uint64
    39  	CrossTxID   string
    40  	Type        MultiTransactionDBType
    41  }
    42  
    43  func NewMultiTxDetails() *MultiTxDetails {
    44  	return &MultiTxDetails{}
    45  }
    46  
    47  type MultiTransactionDB struct {
    48  	db *sql.DB
    49  }
    50  
    51  func NewMultiTransactionDB(db *sql.DB) *MultiTransactionDB {
    52  	return &MultiTransactionDB{
    53  		db: db,
    54  	}
    55  }
    56  
    57  func (mtDB *MultiTransactionDB) CreateMultiTransaction(multiTransaction *MultiTransaction) error {
    58  	insert, err := mtDB.db.Prepare(fmt.Sprintf(`INSERT INTO multi_transactions (%s)
    59  											VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, multiTransactionColumns))
    60  	if err != nil {
    61  		return err
    62  	}
    63  	_, err = insert.Exec(
    64  		multiTransaction.ID,
    65  		multiTransaction.FromNetworkID,
    66  		multiTransaction.FromTxHash,
    67  		multiTransaction.FromAddress,
    68  		multiTransaction.FromAsset,
    69  		multiTransaction.FromAmount.String(),
    70  		multiTransaction.ToNetworkID,
    71  		multiTransaction.ToTxHash,
    72  		multiTransaction.ToAddress,
    73  		multiTransaction.ToAsset,
    74  		multiTransaction.ToAmount.String(),
    75  		multiTransaction.Type,
    76  		multiTransaction.CrossTxID,
    77  		multiTransaction.Timestamp,
    78  	)
    79  	if err != nil {
    80  		return err
    81  	}
    82  	defer insert.Close()
    83  
    84  	return err
    85  }
    86  
    87  func (mtDB *MultiTransactionDB) ReadMultiTransactions(details *MultiTxDetails) ([]*MultiTransaction, error) {
    88  	if details == nil {
    89  		return nil, fmt.Errorf("details is nil")
    90  	}
    91  
    92  	whereClause := ""
    93  
    94  	args := []interface{}{}
    95  
    96  	if len(details.IDs) > 0 {
    97  		placeholders := make([]string, len(details.IDs))
    98  		for i, v := range details.IDs {
    99  			placeholders[i] = "?"
   100  			args = append(args, v)
   101  		}
   102  		whereClause += fmt.Sprintf("id in (%s) AND ", strings.Join(placeholders, ","))
   103  	}
   104  	if (details.AnyAddress != common.Address{}) {
   105  		whereClause += "(from_address=? OR to_address=?) AND "
   106  		args = append(args, details.AnyAddress, details.AnyAddress)
   107  	}
   108  	if (details.FromAddress != common.Address{}) {
   109  		whereClause += "from_address=? AND "
   110  		args = append(args, details.FromAddress)
   111  	}
   112  	if (details.ToAddress != common.Address{}) {
   113  		whereClause += "to_address=? AND "
   114  		args = append(args, details.ToAddress)
   115  	}
   116  	if details.ToChainID != 0 {
   117  		whereClause += "to_network_id=? AND "
   118  		args = append(args, details.ToChainID)
   119  	}
   120  	if details.CrossTxID != "" {
   121  		whereClause += "cross_tx_id=? AND "
   122  		args = append(args, details.CrossTxID)
   123  	}
   124  	if details.Type != MultiTransactionDBTypeInvalid {
   125  		whereClause += "type=? AND "
   126  		args = append(args, mtDBTypeToMTType(details.Type))
   127  	}
   128  
   129  	stmt, err := mtDB.db.Prepare(fmt.Sprintf(`SELECT %s
   130  											FROM multi_transactions
   131  											WHERE %s`,
   132  		selectMultiTransactionColumns, whereClause[:len(whereClause)-5]))
   133  	if err != nil {
   134  		return nil, err
   135  	}
   136  	defer stmt.Close()
   137  
   138  	rows, err := stmt.Query(args...)
   139  	if err != nil {
   140  		return nil, err
   141  	}
   142  	defer rows.Close()
   143  
   144  	return rowsToMultiTransactions(rows)
   145  }
   146  
   147  func (mtDB *MultiTransactionDB) UpdateMultiTransaction(multiTransaction *MultiTransaction) error {
   148  	if multiTransaction.ID == wallet_common.NoMultiTransactionID {
   149  		return fmt.Errorf("no multitransaction ID")
   150  	}
   151  
   152  	update, err := mtDB.db.Prepare(fmt.Sprintf(`REPLACE INTO multi_transactions (%s)
   153  	VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, multiTransactionColumns))
   154  
   155  	if err != nil {
   156  		return err
   157  	}
   158  	_, err = update.Exec(
   159  		multiTransaction.ID,
   160  		multiTransaction.FromNetworkID,
   161  		multiTransaction.FromTxHash,
   162  		multiTransaction.FromAddress,
   163  		multiTransaction.FromAsset,
   164  		multiTransaction.FromAmount.String(),
   165  		multiTransaction.ToNetworkID,
   166  		multiTransaction.ToTxHash,
   167  		multiTransaction.ToAddress,
   168  		multiTransaction.ToAsset,
   169  		multiTransaction.ToAmount.String(),
   170  		multiTransaction.Type,
   171  		multiTransaction.CrossTxID,
   172  		multiTransaction.Timestamp,
   173  	)
   174  	if err != nil {
   175  		return err
   176  	}
   177  	return update.Close()
   178  }
   179  
   180  func (mtDB *MultiTransactionDB) DeleteMultiTransaction(id wallet_common.MultiTransactionIDType) error {
   181  	_, err := mtDB.db.Exec(`DELETE FROM multi_transactions WHERE id=?`, id)
   182  	return err
   183  }