feat(wallet) extract json blobs and add custom migration support
Extended the migration process with a generic way of applying custom migration code on top of the SQL files. The implementation provides a safer way to run GO code along with the SQL migrations and possibility of rolling back the changes in case of failure to keep the database consistent. This custom GO migration is needed to extract the status from the JSON blob receipt and store it in transfers table. Other changes: - Add NULL DB value tracking to JSONBlob helper - Index status column on transfers table - Remove unnecessary panic calls - Move log_parser to wallet's common package and use to extract token identity from the logs Notes: - there is already an index on transfers table, sqlite creates one for each unique constraint therefore add only status to a new index - the planned refactoring and improvements to the database have been postponed due to time constraints. Got the time to migrate the data though, extracting it can be done later for a more efficient implementation Update status-desktop #10746
This commit is contained in:
parent
9e0a12cb32
commit
5b6f7226bb
|
@ -4,17 +4,27 @@ import (
|
|||
"database/sql"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"math/big"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
|
||||
"github.com/status-im/status-go/appdatabase/migrations"
|
||||
migrationsprevnodecfg "github.com/status-im/status-go/appdatabase/migrationsprevnodecfg"
|
||||
"github.com/status-im/status-go/nodecfg"
|
||||
"github.com/status-im/status-go/services/wallet/bigint"
|
||||
w_common "github.com/status-im/status-go/services/wallet/common"
|
||||
"github.com/status-im/status-go/sqlite"
|
||||
)
|
||||
|
||||
const nodeCfgMigrationDate = 1640111208
|
||||
|
||||
var customSteps = []sqlite.PostStep{
|
||||
{Version: 1674136690, CustomMigration: migrateEnsUsernames},
|
||||
{Version: 1686048341, CustomMigration: migrateWalletJSONBlobs, RollBackVersion: 1686041510},
|
||||
}
|
||||
|
||||
// InitializeDB creates db file at a given path and applies migrations.
|
||||
func InitializeDB(path, password string, kdfIterationsNumber int) (*sql.DB, error) {
|
||||
db, err := sqlite.OpenDB(path, password, kdfIterationsNumber)
|
||||
|
@ -22,23 +32,11 @@ func InitializeDB(path, password string, kdfIterationsNumber int) (*sql.DB, erro
|
|||
return nil, err
|
||||
}
|
||||
|
||||
// Check if the migration table exists
|
||||
row := db.QueryRow("SELECT exists(SELECT name FROM sqlite_master WHERE type='table' AND name='status_go_schema_migrations')")
|
||||
migrationTableExists := false
|
||||
err = row.Scan(&migrationTableExists)
|
||||
if err != nil && err != sql.ErrNoRows {
|
||||
lastMigration, migrationTableExists, err := sqlite.GetLastMigrationVersion(db)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var lastMigration uint64 = 0
|
||||
if migrationTableExists {
|
||||
row = db.QueryRow("SELECT version FROM status_go_schema_migrations")
|
||||
err = row.Scan(&lastMigration)
|
||||
if err != nil && err != sql.ErrNoRows {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if !migrationTableExists || (lastMigration > 0 && lastMigration < nodeCfgMigrationDate) {
|
||||
// If it's the first time migration's being run, or latest migration happened before migrating the nodecfg table
|
||||
err = migrationsprevnodecfg.Migrate(db)
|
||||
|
@ -53,13 +51,8 @@ func InitializeDB(path, password string, kdfIterationsNumber int) (*sql.DB, erro
|
|||
}
|
||||
}
|
||||
|
||||
err = migrations.Migrate(db)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Migrate `settings.usernames` here, because current SQL implementation doesn't support `json_each`
|
||||
err = MigrateEnsUsernames(db)
|
||||
// Run all the new migrations
|
||||
err = migrations.Migrate(db, customSteps)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -116,11 +109,11 @@ func GetDBFilename(db *sql.DB) (string, error) {
|
|||
return "", errors.New("no main database found")
|
||||
}
|
||||
|
||||
func MigrateEnsUsernames(db *sql.DB) error {
|
||||
func migrateEnsUsernames(sqlTx *sql.Tx) error {
|
||||
|
||||
// 1. Check if ens_usernames table already exist
|
||||
|
||||
// row := db.QueryRow("SELECT exists(SELECT name FROM sqlite_master WHERE type='table' AND name='ens_usernames')")
|
||||
// row := sqlTx.QueryRow("SELECT exists(SELECT name FROM sqlite_master WHERE type='table' AND name='ens_usernames')")
|
||||
// tableExists := false
|
||||
// err := row.Scan(&tableExists)
|
||||
|
||||
|
@ -134,7 +127,7 @@ func MigrateEnsUsernames(db *sql.DB) error {
|
|||
|
||||
// -- 1. Create new ens_usernames table
|
||||
|
||||
// _, err = db.Exec(`CREATE TABLE IF NOT EXISTS ens_usernames (
|
||||
// _, err = sqlTx.Exec(`CREATE TABLE IF NOT EXISTS ens_usernames (
|
||||
// "username" TEXT NOT NULL,
|
||||
// "chain_id" UNSIGNED BIGINT DEFAULT 1);`)
|
||||
|
||||
|
@ -149,7 +142,7 @@ func MigrateEnsUsernames(db *sql.DB) error {
|
|||
SELECT json_each.value FROM settings, json_each(usernames);
|
||||
*/
|
||||
|
||||
rows, err := db.Query(`SELECT usernames FROM settings`)
|
||||
rows, err := sqlTx.Query(`SELECT usernames FROM settings`)
|
||||
|
||||
if err != nil {
|
||||
log.Error("Migrating ens usernames: failed to query 'settings.usernames'", "err", err.Error())
|
||||
|
@ -187,7 +180,7 @@ func MigrateEnsUsernames(db *sql.DB) error {
|
|||
|
||||
var usernameAlreadyMigrated bool
|
||||
|
||||
row := db.QueryRow(`SELECT EXISTS(SELECT 1 FROM ens_usernames WHERE username=? AND chain_id=?)`, username, defaultChainID)
|
||||
row := sqlTx.QueryRow(`SELECT EXISTS(SELECT 1 FROM ens_usernames WHERE username=? AND chain_id=?)`, username, defaultChainID)
|
||||
err := row.Scan(&usernameAlreadyMigrated)
|
||||
|
||||
if err != nil {
|
||||
|
@ -198,7 +191,7 @@ func MigrateEnsUsernames(db *sql.DB) error {
|
|||
continue
|
||||
}
|
||||
|
||||
_, err = db.Exec(`INSERT INTO ens_usernames (username, chain_id) VALUES (?, ?)`, username, defaultChainID)
|
||||
_, err = sqlTx.Exec(`INSERT INTO ens_usernames (username, chain_id) VALUES (?, ?)`, username, defaultChainID)
|
||||
if err != nil {
|
||||
log.Error("Migrating ens usernames: failed to insert username into new database", "ensUsername", username, "err", err.Error())
|
||||
}
|
||||
|
@ -206,3 +199,173 @@ func MigrateEnsUsernames(db *sql.DB) error {
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
const (
|
||||
batchSize = 1000
|
||||
)
|
||||
|
||||
func migrateWalletJSONBlobs(sqlTx *sql.Tx) error {
|
||||
var batchEntries [][]interface{}
|
||||
|
||||
// Extract useful information from the receipt blob and store it as sql interpretable
|
||||
//
|
||||
// Added tx_hash because the hash column in the transfers table is not (always) the transaction hash.
|
||||
// Each entry in that table could either be: A native token (ETH) transfer or ERC20/ERC721 token transfer
|
||||
// Added block_hash because the block_hash we have is generated by us and used as block entry ID
|
||||
// Added receipt_type, the type we have only indicates if chain or token
|
||||
// Added log_index that the log data represents
|
||||
//
|
||||
// Dropped storing postState because it was replaced by the status after EIP 658
|
||||
// Dropped duplicating logs until we have a more structured way to store them.
|
||||
// They can be extracted from the transfers.receipt still
|
||||
// Dropped the bloom filter because in SQLite is not possible to use it in an
|
||||
// efficient manner
|
||||
//
|
||||
// Extract useful information from the tx blob
|
||||
//
|
||||
// Added tx_type, which might be different than the receipt type
|
||||
//
|
||||
// Dropped access_list, need a separate table for it
|
||||
// Already there chain_id
|
||||
// Dropped v, r, s because I see no way to be useful as BLOBs
|
||||
// Added BIGINT values as clamped 64 INT because we can't use 128 bits blobs/strings for int arithmetics
|
||||
// _clamped64 prefix indicate clamped 64 bits INT values might be useful for queries (sorting, filtering ...)
|
||||
// The amount is stored as a fixed length 128 bit hex string, in
|
||||
// order to be able to sort and filter by it
|
||||
newColumnsAndIndexSetup := `
|
||||
ALTER TABLE transfers ADD COLUMN status INT;
|
||||
ALTER TABLE transfers ADD COLUMN receipt_type INT;
|
||||
ALTER TABLE transfers ADD COLUMN tx_hash BLOB;
|
||||
ALTER TABLE transfers ADD COLUMN log_index INT;
|
||||
ALTER TABLE transfers ADD COLUMN block_hash BLOB;
|
||||
ALTER TABLE transfers ADD COLUMN cumulative_gas_used INT;
|
||||
ALTER TABLE transfers ADD COLUMN contract_address TEXT;
|
||||
ALTER TABLE transfers ADD COLUMN gas_used INT;
|
||||
ALTER TABLE transfers ADD COLUMN tx_index INT;
|
||||
|
||||
ALTER TABLE transfers ADD COLUMN tx_type INT;
|
||||
ALTER TABLE transfers ADD COLUMN protected BOOLEAN;
|
||||
ALTER TABLE transfers ADD COLUMN gas_limit UNSIGNED INT;
|
||||
ALTER TABLE transfers ADD COLUMN gas_price_clamped64 INT;
|
||||
ALTER TABLE transfers ADD COLUMN gas_tip_cap_clamped64 INT;
|
||||
ALTER TABLE transfers ADD COLUMN gas_fee_cap_clamped64 INT;
|
||||
ALTER TABLE transfers ADD COLUMN amount_padded128hex CHAR(32);
|
||||
ALTER TABLE transfers ADD COLUMN account_nonce INT;
|
||||
ALTER TABLE transfers ADD COLUMN size INT;
|
||||
ALTER TABLE transfers ADD COLUMN token_address BLOB;
|
||||
ALTER TABLE transfers ADD COLUMN token_id BLOB;
|
||||
|
||||
CREATE INDEX idx_transfers_filter ON transfers (status, token_address, token_id);`
|
||||
|
||||
rowIndex := 0
|
||||
mightHaveRows := true
|
||||
|
||||
_, err := sqlTx.Exec(newColumnsAndIndexSetup)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for mightHaveRows {
|
||||
var chainID uint64
|
||||
var hash common.Hash
|
||||
var address common.Address
|
||||
var entryType string
|
||||
|
||||
rows, err := sqlTx.Query(`SELECT hash, address, network_id, tx, receipt, log, type FROM transfers WHERE tx IS NOT NULL OR receipt IS NOT NULL LIMIT ? OFFSET ?`, batchSize, rowIndex)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
curProcessed := 0
|
||||
for rows.Next() {
|
||||
tx := &types.Transaction{}
|
||||
r := &types.Receipt{}
|
||||
l := &types.Log{}
|
||||
|
||||
// Scan row data into the transaction and receipt objects
|
||||
nullableTx := sqlite.JSONBlob{Data: tx}
|
||||
nullableR := sqlite.JSONBlob{Data: r}
|
||||
nullableL := sqlite.JSONBlob{Data: l}
|
||||
err = rows.Scan(&hash, &address, &chainID, &nullableTx, &nullableR, &nullableL, &entryType)
|
||||
if err != nil {
|
||||
rows.Close()
|
||||
return err
|
||||
}
|
||||
var logIndex *uint
|
||||
if nullableL.Valid {
|
||||
logIndex = new(uint)
|
||||
*logIndex = l.Index
|
||||
}
|
||||
|
||||
var currentRow []interface{}
|
||||
|
||||
// Check if the receipt is not null before transferring the receipt data
|
||||
if nullableR.Valid {
|
||||
currentRow = append(currentRow, r.Status, r.Type, r.TxHash, logIndex, r.BlockHash, r.CumulativeGasUsed, r.ContractAddress, r.GasUsed, r.TransactionIndex)
|
||||
} else {
|
||||
for i := 0; i < 9; i++ {
|
||||
currentRow = append(currentRow, nil)
|
||||
}
|
||||
}
|
||||
|
||||
if nullableTx.Valid {
|
||||
var tokenAddress *common.Address
|
||||
var correctType w_common.Type
|
||||
var tokenID, value *big.Int
|
||||
if nullableL.Valid {
|
||||
correctType, tokenAddress, tokenID, value = w_common.ExtractTokenIdentity(w_common.Type(entryType), l, tx)
|
||||
} else {
|
||||
correctType = w_common.Type(entryType)
|
||||
value = new(big.Int).Set(tx.Value())
|
||||
}
|
||||
|
||||
gasPrice := sqlite.BigIntToClampedInt64(tx.GasPrice())
|
||||
gasTipCap := sqlite.BigIntToClampedInt64(tx.GasTipCap())
|
||||
gasFeeCap := sqlite.BigIntToClampedInt64(tx.GasFeeCap())
|
||||
valueStr := sqlite.BigIntToPadded128BitsStr(value)
|
||||
|
||||
currentRow = append(currentRow, tx.Type(), tx.Protected(), tx.Gas(), gasPrice, gasTipCap, gasFeeCap, valueStr, tx.Nonce(), int64(tx.Size()), &sqlite.JSONBlob{Data: tokenAddress}, (*bigint.SQLBigIntBytes)(tokenID), correctType)
|
||||
} else {
|
||||
for i := 0; i < 11; i++ {
|
||||
currentRow = append(currentRow, nil)
|
||||
}
|
||||
currentRow = append(currentRow, w_common.EthTransfer)
|
||||
}
|
||||
currentRow = append(currentRow, hash, address, chainID)
|
||||
batchEntries = append(batchEntries, currentRow)
|
||||
|
||||
curProcessed++
|
||||
}
|
||||
rowIndex += curProcessed
|
||||
|
||||
// Check if there was an error in the last rows.Next()
|
||||
rows.Close()
|
||||
if err = rows.Err(); err != nil {
|
||||
return err
|
||||
}
|
||||
mightHaveRows = (curProcessed == batchSize)
|
||||
|
||||
// insert extracted data into the new columns
|
||||
if len(batchEntries) > 0 {
|
||||
var stmt *sql.Stmt
|
||||
stmt, err = sqlTx.Prepare(`UPDATE transfers SET status = ?, receipt_type = ?, tx_hash = ?, log_index = ?, block_hash = ?, cumulative_gas_used = ?, contract_address = ?, gas_used = ?, tx_index = ?,
|
||||
tx_type = ?, protected = ?, gas_limit = ?, gas_price_clamped64 = ?, gas_tip_cap_clamped64 = ?, gas_fee_cap_clamped64 = ?, amount_padded128hex = ?, account_nonce = ?, size = ?, token_address = ?, token_id = ?, type = ?
|
||||
WHERE hash = ? AND address = ? AND network_id = ?`)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, dataEntry := range batchEntries {
|
||||
_, err = stmt.Exec(dataEntry...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Reset placeHolders and batchEntries for the next batch
|
||||
batchEntries = [][]interface{}{}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -1,10 +1,24 @@
|
|||
package appdatabase
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
|
||||
"github.com/status-im/status-go/appdatabase/migrations"
|
||||
migrationsprevnodecfg "github.com/status-im/status-go/appdatabase/migrationsprevnodecfg"
|
||||
"github.com/status-im/status-go/nodecfg"
|
||||
"github.com/status-im/status-go/services/wallet/bigint"
|
||||
w_common "github.com/status-im/status-go/services/wallet/common"
|
||||
"github.com/status-im/status-go/sqlite"
|
||||
)
|
||||
|
||||
|
@ -31,3 +45,420 @@ func Test_GetDBFilename(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
require.Equal(t, "", fn)
|
||||
}
|
||||
|
||||
const (
|
||||
erc20ReceiptTestDataTemplate = `{"type":"0x2","root":"0x","status":"0x%d","cumulativeGasUsed":"0x10f8d2c","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000001008000000000000000000000000000000000000002000000000020000000000000000000800000000000000000000000010000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000800000000000000000000","logs":[{"address":"0x98339d8c260052b7ad81c28c16c0b98420f2b46a","topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000000000000000000000000000000000000000000000","0x000000000000000000000000e2d622c817878da5143bbe06866ca8e35273ba8a"],"data":"0x0000000000000000000000000000000000000000000000000000000000989680","blockNumber":"0x825527","transactionHash":"0xdcaa0fc7fe2e0d1f1343d1f36807344bb4fd26cda62ad8f9d8700e2c458cc79a","transactionIndex":"0x6c","blockHash":"0x69e0f829a557052c134cd7e21c220507d91bc35c316d3c47217e9bd362270274","logIndex":"0xcd","removed":false}],"transactionHash":"0xdcaa0fc7fe2e0d1f1343d1f36807344bb4fd26cda62ad8f9d8700e2c458cc79a","contractAddress":"0x0000000000000000000000000000000000000000","gasUsed":"0x8623","blockHash":"0x69e0f829a557052c134cd7e21c220507d91bc35c316d3c47217e9bd362270274","blockNumber":"0x825527","transactionIndex":"0x6c"}`
|
||||
erc20TxTestData = `{"type":"0x2","nonce":"0x3d","gasPrice":"0x0","maxPriorityFeePerGas":"0x8c347c90","maxFeePerGas":"0x45964d43a4","gas":"0x8623","value":"0x0","input":"0x40c10f19000000000000000000000000e2d622c817878da5143bbe06866ca8e35273ba8a0000000000000000000000000000000000000000000000000000000000989680","v":"0x0","r":"0xbcac4bb290d48b467bb18ac67e98050b5f316d2c66b2f75dcc1d63a45c905d21","s":"0x10c15517ea9cabd7fe134b270daabf5d2e8335e935d3e021f54a4efaffb37cd2","to":"0x98339d8c260052b7ad81c28c16c0b98420f2b46a","chainId":"0x5","accessList":[],"hash":"0xdcaa0fc7fe2e0d1f1343d1f36807344bb4fd26cda62ad8f9d8700e2c458cc79a"}`
|
||||
|
||||
erc20LogTestData = `{"address":"0x98339d8c260052b7ad81c28c16c0b98420f2b46a","topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000000000000000000000000000000000000000000000","0x000000000000000000000000e2d622c817878da5143bbe06866ca8e35273ba8a"],"data":"0x0000000000000000000000000000000000000000000000000000000000989680","blockNumber":"0x825527","transactionHash":"0xdcaa0fc7fe2e0d1f1343d1f36807344bb4fd26cda62ad8f9d8700e2c458cc79a","transactionIndex":"0x6c","blockHash":"0x69e0f829a557052c134cd7e21c220507d91bc35c316d3c47217e9bd362270274","logIndex":"0xcd","removed":false}`
|
||||
ethReceiptTestData = `{
|
||||
"type": "0x2",
|
||||
"root": "0x",
|
||||
"status": "0x1",
|
||||
"cumulativeGasUsed": "0x2b461",
|
||||
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"logs": [],
|
||||
"transactionHash": "0x4ac700ee2a1702f82b3cfdc88fd4d91f767b87fea9b929bd6223c6471a5e05b4",
|
||||
"contractAddress": "0x0000000000000000000000000000000000000000",
|
||||
"gasUsed": "0x5208",
|
||||
"blockHash": "0x25fe164361c1cb4ed1b46996f7b5236d3118144529b31fca037fcda1d8ee684d",
|
||||
"blockNumber": "0x5e3294",
|
||||
"transactionIndex": "0x3"
|
||||
}`
|
||||
ethTxTestData = `{
|
||||
"type": "0x2",
|
||||
"nonce": "0x1",
|
||||
"gasPrice": "0x0",
|
||||
"maxPriorityFeePerGas": "0x33",
|
||||
"maxFeePerGas": "0x3b9aca00",
|
||||
"gas": "0x55f0",
|
||||
"value": "0x%s",
|
||||
"input": "0x",
|
||||
"v": "0x0",
|
||||
"r": "0xacc277ce156382d6f333cc8d75a56250778b17f1c6d1676af63cf68d53713986",
|
||||
"s": "0x32417261484e9796390abb8db13f993965d917836be5cd96df25b9b581de91ec",
|
||||
"to": "0xbd54a96c0ae19a220c8e1234f54c940dfab34639",
|
||||
"chainId": "0x1a4",
|
||||
"accessList": [],
|
||||
"hash": "0x4ac700ee2a1702f82b3cfdc88fd4d91f767b87fea9b929bd6223c6471a5e05b4"
|
||||
}`
|
||||
|
||||
erc721TxTestData = `{"type":"0x2","nonce":"0x2f","gasPrice":"0x0","maxPriorityFeePerGas":"0x3b9aca00","maxFeePerGas":"0x2f691e609","gas":"0x1abc3","value":"0x0","input":"0x42842e0e000000000000000000000000165eeecc32dcb623f51fc6c1ddd9e2aea1575c630000000000000000000000001c9751e0fbf5081849b56b522d50fb7f163b8080000000000000000000000000000000000000000000000000000000003ba7b95e360c6ebe","v":"0x1","r":"0xead469c32ffda3aa933f9aed814df411fb07893153c775b50596660036bbb5da","s":"0x73edadd4e4a7f0895f686b68e16101d195c0bb1b5f248f16b21557800b95bdf8","to":"0x85f0e02cb992aa1f9f47112f815f519ef1a59e2d","chainId":"0x1","accessList":[],"hash":"0x1dd936499e35ece8747bc481e476ac43eb4555a3a82e8cb93b7e429219bdd371"}`
|
||||
erc721ReceiptTestData = `{"type":"0x2","root":"0x","status":"0x1","cumulativeGasUsed":"0x54cadb","logsBloom":"0x00000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200200000000000000000000000000008000000000000080000000000000000000000002000200000020000000200000000000800000000000000000000000010000000000000000000000040000000000000000000000000000000000000000000000000020000000000000000000040010000000000000000000000000000000800000000000002020000000000000000000000000000000000000000000000000020000010000000000000000000004000000000000000000000000000000000000000","logs":[{"address":"0x85f0e02cb992aa1f9f47112f815f519ef1a59e2d","topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x000000000000000000000000165eeecc32dcb623f51fc6c1ddd9e2aea1575c63","0x0000000000000000000000000000000000000000000000000000000000000000","0x000000000000000000000000000000000000000000000000000000003ba7b95e"],"data":"0x","blockNumber":"0xf57974","transactionHash":"0x1dd936499e35ece8747bc481e476ac43eb4555a3a82e8cb93b7e429219bdd371","transactionIndex":"0x44","blockHash":"0x9228724ff5c19f9b1586e19b13102f94798d1ee32b5f14d5cbcdf74cc32eb732","logIndex":"0x86","removed":false},{"address":"0x85f0e02cb992aa1f9f47112f815f519ef1a59e2d","topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000165eeecc32dcb623f51fc6c1ddd9e2aea1575c63","0x0000000000000000000000001c9751e0fbf5081849b56b522d50fb7f163b8080","0x000000000000000000000000000000000000000000000000000000003ba7b95e"],"data":"0x","blockNumber":"0xf57974","transactionHash":"0x1dd936499e35ece8747bc481e476ac43eb4555a3a82e8cb93b7e429219bdd371","transactionIndex":"0x44","blockHash":"0x9228724ff5c19f9b1586e19b13102f94798d1ee32b5f14d5cbcdf74cc32eb732","logIndex":"0x87","removed":false}],"transactionHash":"0x1dd936499e35ece8747bc481e476ac43eb4555a3a82e8cb93b7e429219bdd371","contractAddress":"0x0000000000000000000000000000000000000000","gasUsed":"0x18643","blockHash":"0x9228724ff5c19f9b1586e19b13102f94798d1ee32b5f14d5cbcdf74cc32eb732","blockNumber":"0xf57974","transactionIndex":"0x44"}`
|
||||
erc721LogTestData = `{"address":"0x85f0e02cb992aa1f9f47112f815f519ef1a59e2d","topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000165eeecc32dcb623f51fc6c1ddd9e2aea1575c63","0x0000000000000000000000001c9751e0fbf5081849b56b522d50fb7f163b8080","0x000000000000000000000000000000000000000000000000000000003ba7b95e"],"data":"0x","blockNumber":"0xf57974","transactionHash":"0x1dd936499e35ece8747bc481e476ac43eb4555a3a82e8cb93b7e429219bdd371","transactionIndex":"0x44","blockHash":"0x9228724ff5c19f9b1586e19b13102f94798d1ee32b5f14d5cbcdf74cc32eb732","logIndex":"0x87","removed":false}`
|
||||
|
||||
uniswapV2TxTestData = `{"type":"0x2","nonce":"0x42","gasPrice":"0x0","maxPriorityFeePerGas":"0x3b9aca00","maxFeePerGas":"0x13c6f691f2","gas":"0x2ed0d","value":"0xa688906bd8b0000","input":"0x3593564c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000006440875700000000000000000000000000000000000000000000000000000000000000020b080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000a688906bd8b0000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000a688906bd8b000000000000000000000000000000000000000000001188be846e642b0ae4ae055e00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000006982508145454ce325ddbe47a25d4ec3d2311933","v":"0x1","r":"0xeb7b527c2bfd3d26ea8e21951f537f4603867a11532081ba77fde9465696c20a","s":"0x5c120e64973a3b83a80d8b045a2228b9d1421065c1d480d2c1e322dad3b76c0f","to":"0xef1c6e67703c7bd7107eed8303fbe6ec2554bf6b","chainId":"0x1","accessList":[],"hash":"0x6d70a0b14e2fe1ba28d6cb910ffc4aa787264dff6c273e20509136461ac587aa"}`
|
||||
uniswapV2ReceiptTestData = `{"type":"0x2","root":"0x","status":"0x1","cumulativeGasUsed":"0x1ba15e","logsBloom":"0x00200000000000000000000080400000000000000000000000000000000000000000000000000000000000000000000002000000080000000000000200000000000000080000000000000008000000200000000000000000000000008000000000000000000000000000000000000000000000000000000000000010000000000000000000008000000000000000040000000001000000080000004200000000000800000000000000000000008000000000000000000000000000000800000001000012000000000000000000000000400000000000001000000000000000000000200001000000020000000000000000000000000000400000000080000000","logs":[{"address":"0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2","topics":["0xe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c","0x000000000000000000000000ef1c6e67703c7bd7107eed8303fbe6ec2554bf6b"],"data":"0x0000000000000000000000000000000000000000000000000a688906bd8b0000","blockNumber":"0x104ae90","transactionHash":"0x6d70a0b14e2fe1ba28d6cb910ffc4aa787264dff6c273e20509136461ac587aa","transactionIndex":"0x4","blockHash":"0x49e3ef5a17eb5563b327fffdf315dd9269c5a5676eec1f5c15897c4ef61623df","logIndex":"0x2b","removed":false},{"address":"0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2","topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000ef1c6e67703c7bd7107eed8303fbe6ec2554bf6b","0x000000000000000000000000ef1c6e67703c7bd7107eed8303fbe6ec2554bf6b"],"data":"0x0000000000000000000000000000000000000000000000000a688906bd8b0000","blockNumber":"0x104ae90","transactionHash":"0x6d70a0b14e2fe1ba28d6cb910ffc4aa787264dff6c273e20509136461ac587aa","transactionIndex":"0x4","blockHash":"0x49e3ef5a17eb5563b327fffdf315dd9269c5a5676eec1f5c15897c4ef61623df","logIndex":"0x2c","removed":false},{"address":"0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2","topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000ef1c6e67703c7bd7107eed8303fbe6ec2554bf6b","0x000000000000000000000000a43fe16908251ee70ef74718545e4fe6c5ccec9f"],"data":"0x0000000000000000000000000000000000000000000000000a688906bd8b0000","blockNumber":"0x104ae90","transactionHash":"0x6d70a0b14e2fe1ba28d6cb910ffc4aa787264dff6c273e20509136461ac587aa","transactionIndex":"0x4","blockHash":"0x49e3ef5a17eb5563b327fffdf315dd9269c5a5676eec1f5c15897c4ef61623df","logIndex":"0x2d","removed":false},{"address":"0x6982508145454ce325ddbe47a25d4ec3d2311933","topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000a43fe16908251ee70ef74718545e4fe6c5ccec9f","0x000000000000000000000000165eeecc32dcb623f51fc6c1ddd9e2aea1575c63"],"data":"0x000000000000000000000000000000000000000011b2e784030a3a65a3559087","blockNumber":"0x104ae90","transactionHash":"0x6d70a0b14e2fe1ba28d6cb910ffc4aa787264dff6c273e20509136461ac587aa","transactionIndex":"0x4","blockHash":"0x49e3ef5a17eb5563b327fffdf315dd9269c5a5676eec1f5c15897c4ef61623df","logIndex":"0x2e","removed":false},{"address":"0xa43fe16908251ee70ef74718545e4fe6c5ccec9f","topics":["0x1c411e9a96e071241c2f21f7726b17ae89e3cab4c78be50e062b03a9fffbbad1"],"data":"0x000000000000000000000000000000000000003bdd991fe0c766723fa956e323000000000000000000000000000000000000000000000023240d303bb8bbb575","blockNumber":"0x104ae90","transactionHash":"0x6d70a0b14e2fe1ba28d6cb910ffc4aa787264dff6c273e20509136461ac587aa","transactionIndex":"0x4","blockHash":"0x49e3ef5a17eb5563b327fffdf315dd9269c5a5676eec1f5c15897c4ef61623df","logIndex":"0x2f","removed":false},{"address":"0xa43fe16908251ee70ef74718545e4fe6c5ccec9f","topics":["0xd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d822","0x000000000000000000000000ef1c6e67703c7bd7107eed8303fbe6ec2554bf6b","0x000000000000000000000000165eeecc32dcb623f51fc6c1ddd9e2aea1575c63"],"data":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a688906bd8b0000000000000000000000000000000000000000000011b2e784030a3a65a35590870000000000000000000000000000000000000000000000000000000000000000","blockNumber":"0x104ae90","transactionHash":"0x6d70a0b14e2fe1ba28d6cb910ffc4aa787264dff6c273e20509136461ac587aa","transactionIndex":"0x4","blockHash":"0x49e3ef5a17eb5563b327fffdf315dd9269c5a5676eec1f5c15897c4ef61623df","logIndex":"0x30","removed":false}],"transactionHash":"0x6d70a0b14e2fe1ba28d6cb910ffc4aa787264dff6c273e20509136461ac587aa","contractAddress":"0x0000000000000000000000000000000000000000","gasUsed":"0x1ec85","blockHash":"0x49e3ef5a17eb5563b327fffdf315dd9269c5a5676eec1f5c15897c4ef61623df","blockNumber":"0x104ae90","transactionIndex":"0x4"}`
|
||||
uniswapV2LogTestData = `{"address":"0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2","topics":["0xe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c","0x000000000000000000000000ef1c6e67703c7bd7107eed8303fbe6ec2554bf6b"],"data":"0x0000000000000000000000000000000000000000000000000a688906bd8b0000","blockNumber":"0x104ae90","transactionHash":"0x6d70a0b14e2fe1ba28d6cb910ffc4aa787264dff6c273e20509136461ac587aa","transactionIndex":"0x4","blockHash":"0x49e3ef5a17eb5563b327fffdf315dd9269c5a5676eec1f5c15897c4ef61623df","logIndex":"0x2b","removed":false}`
|
||||
|
||||
uniswapV3TxTestData = `{"type":"0x2","nonce":"0x41","gasPrice":"0x0","maxPriorityFeePerGas":"0x3b9aca00","maxFeePerGas":"0x92abb2610","gas":"0x34389","value":"0x1f161421c8e0000","input":"0x3593564c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000643e278300000000000000000000000000000000000000000000000000000000000000020b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000001f161421c8e00000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000001f161421c8e000000000000000000000000000000000000000000000002488dd50cfbb0a2a15abb00000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc20027105026f006b85729a8b14553fae6af249ad16c9aab000000000000000000000000000000000000000000","v":"0x1","r":"0x4fca68a439e7f841bdbe6d108bebd3d4c405f739cae203e61422152c4a0a057c","s":"0x597bd6d3848d31357207df1f92df77580310b7ad31f178575f0dae7f36934b39","to":"0xef1c6e67703c7bd7107eed8303fbe6ec2554bf6b","chainId":"0x1","accessList":[],"hash":"0x5c5bca1291d1f09c07a9b66e56e78cc23da41b3e69e330dcd46a71ef6176df8b"}`
|
||||
uniswapV3ReceiptTestData = `{"type":"0x2","root":"0x","status":"0x1","cumulativeGasUsed":"0x6c1b8a","logsBloom":"0x00000000000000000000000000400000000000000000000200000000000000000000000000000000000000000000000002000000080020000000000200000000000004000000000800000028000000000000000000000000240000008000000000000000000000800000000000000000000000000000000000000010000800000000000000000000000000080000000000000001000000000000000000000000000800000000000000000000000000000000000000000000000000000800002000000002000000000000000000000000400000000000000000000000000000000000200000000000000000000000000000000400000000400000000080000000","logs":[{"address":"0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2","topics":["0xe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c","0x000000000000000000000000ef1c6e67703c7bd7107eed8303fbe6ec2554bf6b"],"data":"0x00000000000000000000000000000000000000000000000001f161421c8e0000","blockNumber":"0x1047cc4","transactionHash":"0x5c5bca1291d1f09c07a9b66e56e78cc23da41b3e69e330dcd46a71ef6176df8b","transactionIndex":"0x4a","blockHash":"0x95c685d5165471e878aea2aaaa719bf4357cdbcd22722df4338e3e54f4e6c5d5","logIndex":"0xd8","removed":false},{"address":"0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2","topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000ef1c6e67703c7bd7107eed8303fbe6ec2554bf6b","0x000000000000000000000000ef1c6e67703c7bd7107eed8303fbe6ec2554bf6b"],"data":"0x00000000000000000000000000000000000000000000000001f161421c8e0000","blockNumber":"0x1047cc4","transactionHash":"0x5c5bca1291d1f09c07a9b66e56e78cc23da41b3e69e330dcd46a71ef6176df8b","transactionIndex":"0x4a","blockHash":"0x95c685d5165471e878aea2aaaa719bf4357cdbcd22722df4338e3e54f4e6c5d5","logIndex":"0xd9","removed":false},{"address":"0x5026f006b85729a8b14553fae6af249ad16c9aab","topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000007316f8dd242974f0fd7b16dbcc68920b96bc4db1","0x000000000000000000000000165eeecc32dcb623f51fc6c1ddd9e2aea1575c63"],"data":"0x000000000000000000000000000000000000000000024cc783fc216d1e77f90d","blockNumber":"0x1047cc4","transactionHash":"0x5c5bca1291d1f09c07a9b66e56e78cc23da41b3e69e330dcd46a71ef6176df8b","transactionIndex":"0x4a","blockHash":"0x95c685d5165471e878aea2aaaa719bf4357cdbcd22722df4338e3e54f4e6c5d5","logIndex":"0xda","removed":false},{"address":"0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2","topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000ef1c6e67703c7bd7107eed8303fbe6ec2554bf6b","0x0000000000000000000000007316f8dd242974f0fd7b16dbcc68920b96bc4db1"],"data":"0x00000000000000000000000000000000000000000000000001f161421c8e0000","blockNumber":"0x1047cc4","transactionHash":"0x5c5bca1291d1f09c07a9b66e56e78cc23da41b3e69e330dcd46a71ef6176df8b","transactionIndex":"0x4a","blockHash":"0x95c685d5165471e878aea2aaaa719bf4357cdbcd22722df4338e3e54f4e6c5d5","logIndex":"0xdb","removed":false},{"address":"0x7316f8dd242974f0fd7b16dbcc68920b96bc4db1","topics":["0xc42079f94a6350d7e6235f29174924f928cc2ac818eb64fed8004e115fbcca67","0x000000000000000000000000ef1c6e67703c7bd7107eed8303fbe6ec2554bf6b","0x000000000000000000000000165eeecc32dcb623f51fc6c1ddd9e2aea1575c63"],"data":"0xfffffffffffffffffffffffffffffffffffffffffffdb3387c03de92e18806f300000000000000000000000000000000000000000000000001f161421c8e00000000000000000000000000000000000000000000000ea9ed3658a1ccb7e6d1cc000000000000000000000000000000000000000000001e5ab304463cab4cd155fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd6f54","blockNumber":"0x1047cc4","transactionHash":"0x5c5bca1291d1f09c07a9b66e56e78cc23da41b3e69e330dcd46a71ef6176df8b","transactionIndex":"0x4a","blockHash":"0x95c685d5165471e878aea2aaaa719bf4357cdbcd22722df4338e3e54f4e6c5d5","logIndex":"0xdc","removed":false}],"transactionHash":"0x5c5bca1291d1f09c07a9b66e56e78cc23da41b3e69e330dcd46a71ef6176df8b","contractAddress":"0x0000000000000000000000000000000000000000","gasUsed":"0x22478","blockHash":"0x95c685d5165471e878aea2aaaa719bf4357cdbcd22722df4338e3e54f4e6c5d5","blockNumber":"0x1047cc4","transactionIndex":"0x4a"}`
|
||||
uniswapV3LogTestData = `{"address":"0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2","topics":["0xe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c","0x000000000000000000000000ef1c6e67703c7bd7107eed8303fbe6ec2554bf6b"],"data":"0x00000000000000000000000000000000000000000000000001f161421c8e0000","blockNumber":"0x1047cc4","transactionHash":"0x5c5bca1291d1f09c07a9b66e56e78cc23da41b3e69e330dcd46a71ef6176df8b","transactionIndex":"0x4a","blockHash":"0x95c685d5165471e878aea2aaaa719bf4357cdbcd22722df4338e3e54f4e6c5d5","logIndex":"0xd8","removed":false}`
|
||||
)
|
||||
|
||||
func TestMigrateWalletJsonBlobs(t *testing.T) {
|
||||
openDB := func() (*sql.DB, error) {
|
||||
return sqlite.OpenDB(sqlite.InMemoryPath, "1234567890", sqlite.ReducedKDFIterationsNumber)
|
||||
}
|
||||
db, err := openDB()
|
||||
require.NoError(t, err)
|
||||
|
||||
// Execute the old migrations
|
||||
err = migrationsprevnodecfg.Migrate(db)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = nodecfg.MigrateNodeConfig(db)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Migrate until 1682393575_sync_ens_name.up
|
||||
err = migrations.MigrateTo(db, customSteps, 1682393575)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Validate that transfers table has no status column
|
||||
exists, err := ColumnExists(db, "transfers", "status")
|
||||
require.NoError(t, err)
|
||||
require.False(t, exists)
|
||||
|
||||
exists, err = ColumnExists(db, "transfers", "status")
|
||||
require.NoError(t, err)
|
||||
require.False(t, exists)
|
||||
|
||||
insertTestTransaction := func(index int, txBlob string, receiptBlob string, logBlob string, ethType bool) error {
|
||||
indexStr := strconv.Itoa(index)
|
||||
var txValue *string
|
||||
if txBlob != "" {
|
||||
txValue = &txBlob
|
||||
}
|
||||
var receiptValue *string
|
||||
if receiptBlob != "" {
|
||||
receiptValue = &receiptBlob
|
||||
}
|
||||
var logValue *string
|
||||
if logBlob != "" {
|
||||
logValue = &logBlob
|
||||
}
|
||||
entryType := "eth"
|
||||
if !ethType {
|
||||
entryType = "erc20"
|
||||
}
|
||||
_, err = db.Exec(`INSERT OR IGNORE INTO blocks(network_id, address, blk_number, blk_hash) VALUES (?, ?, ?, ?);
|
||||
INSERT INTO transfers (hash, address, network_id, tx, receipt, log, blk_hash, type, blk_number, timestamp) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
index, common.HexToAddress(indexStr), index, common.HexToHash(indexStr),
|
||||
common.HexToHash(indexStr), common.HexToAddress(indexStr), index, txValue, receiptValue, logValue, common.HexToHash(indexStr), entryType, index, index)
|
||||
return err
|
||||
}
|
||||
|
||||
// Empty transaction, found the usecase in the test DB
|
||||
err = insertTestTransaction(1, "", "", "", true)
|
||||
require.NoError(t, err)
|
||||
|
||||
erc20FailReceiptJSON := fmt.Sprintf(erc20ReceiptTestDataTemplate, 0)
|
||||
erc20SuccessReceiptJSON := fmt.Sprintf(erc20ReceiptTestDataTemplate, 1)
|
||||
err = insertTestTransaction(2, erc20TxTestData, erc20FailReceiptJSON, erc20LogTestData, false)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = insertTestTransaction(3, erc20TxTestData, erc20SuccessReceiptJSON, erc20LogTestData, false)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = insertTestTransaction(4, erc721TxTestData, erc721ReceiptTestData, erc721LogTestData, false)
|
||||
require.NoError(t, err)
|
||||
|
||||
ethZeroValueTxTestData := fmt.Sprintf(ethTxTestData, "0")
|
||||
ethVeryBigValueTxTestData := fmt.Sprintf(ethTxTestData, "12345678901234567890")
|
||||
ethOriginalTxTestData := fmt.Sprintf(ethTxTestData, "2386f26fc10000")
|
||||
|
||||
err = insertTestTransaction(5, ethZeroValueTxTestData, ethReceiptTestData, "", true)
|
||||
require.NoError(t, err)
|
||||
err = insertTestTransaction(6, ethVeryBigValueTxTestData, "", "", true)
|
||||
require.NoError(t, err)
|
||||
err = insertTestTransaction(7, ethOriginalTxTestData, ethReceiptTestData, "", true)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = insertTestTransaction(8, uniswapV2TxTestData, uniswapV2ReceiptTestData, uniswapV2LogTestData, false)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = insertTestTransaction(9, uniswapV3TxTestData, uniswapV3ReceiptTestData, uniswapV3LogTestData, false)
|
||||
require.NoError(t, err)
|
||||
|
||||
failMigrationSteps := []sqlite.PostStep{
|
||||
{
|
||||
Version: customSteps[1].Version,
|
||||
CustomMigration: func(sqlTx *sql.Tx) error {
|
||||
return errors.New("failed to run custom migration")
|
||||
},
|
||||
RollBackVersion: customSteps[1].RollBackVersion,
|
||||
},
|
||||
}
|
||||
|
||||
// Attempt to run test migration 1686048341 and fail in custom step
|
||||
err = migrations.MigrateTo(db, failMigrationSteps, customSteps[1].Version)
|
||||
require.Error(t, err)
|
||||
|
||||
exists, err = ColumnExists(db, "transfers", "status")
|
||||
require.NoError(t, err)
|
||||
require.False(t, exists)
|
||||
|
||||
// Run test migration 1686048341_transfers_receipt_json_blob_out.<up/down>.sql
|
||||
err = migrations.MigrateTo(db, customSteps, customSteps[1].Version)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Validate that the migration was run and transfers table has now status column
|
||||
exists, err = ColumnExists(db, "transfers", "status")
|
||||
require.NoError(t, err)
|
||||
require.True(t, exists)
|
||||
|
||||
var (
|
||||
status, receiptType, cumulativeGasUsed, gasUsed, txIndex sql.NullInt64
|
||||
gasLimit, gasPriceClamped64, gasTipCapClamped64 sql.NullInt64
|
||||
gasFeeCapClamped64, accountNonce, size, logIndex, txType sql.NullInt64
|
||||
|
||||
protected sql.NullBool
|
||||
dbContractAddress, amount128Hex sql.NullString
|
||||
contractAddress, tokenAddress common.Address
|
||||
txHash, blockHash []byte
|
||||
entryType string
|
||||
isTokenIDNull bool
|
||||
)
|
||||
dbTokenAddress := sqlite.JSONBlob{Data: &tokenAddress}
|
||||
tokenID := new(big.Int)
|
||||
rows, err := db.Query(`SELECT status, receipt_type, tx_hash, log_index, block_hash, cumulative_gas_used, contract_address, gas_used, tx_index,
|
||||
tx_type, protected, gas_limit, gas_price_clamped64, gas_tip_cap_clamped64, gas_fee_cap_clamped64, amount_padded128hex, account_nonce, size, token_address, token_id, type,
|
||||
|
||||
CASE
|
||||
WHEN token_id IS NULL THEN 1
|
||||
ELSE 0
|
||||
END as token_id_status
|
||||
|
||||
FROM transfers ORDER BY timestamp ASC`)
|
||||
require.NoError(t, err)
|
||||
|
||||
scanNextData := func() error {
|
||||
rows.Next()
|
||||
if rows.Err() != nil {
|
||||
return rows.Err()
|
||||
}
|
||||
err := rows.Scan(&status, &receiptType, &txHash, &logIndex, &blockHash, &cumulativeGasUsed, &dbContractAddress, &gasUsed, &txIndex,
|
||||
&txType, &protected, &gasLimit, &gasPriceClamped64, &gasTipCapClamped64, &gasFeeCapClamped64, &amount128Hex, &accountNonce, &size, &dbTokenAddress, (*bigint.SQLBigIntBytes)(tokenID), &entryType, &isTokenIDNull)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if dbContractAddress.Valid {
|
||||
contractAddress = common.HexToAddress(dbContractAddress.String)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
validateTransaction := func(tt *types.Transaction, expectedEntryType w_common.Type, tl *types.Log) {
|
||||
if tt == nil {
|
||||
require.False(t, txType.Valid)
|
||||
require.False(t, protected.Valid)
|
||||
require.False(t, gasLimit.Valid)
|
||||
require.False(t, gasPriceClamped64.Valid)
|
||||
require.False(t, gasTipCapClamped64.Valid)
|
||||
require.False(t, gasFeeCapClamped64.Valid)
|
||||
require.False(t, amount128Hex.Valid)
|
||||
require.False(t, accountNonce.Valid)
|
||||
require.False(t, size.Valid)
|
||||
require.Equal(t, common.Address{}, tokenAddress)
|
||||
require.True(t, isTokenIDNull)
|
||||
require.Equal(t, string(w_common.EthTransfer), entryType)
|
||||
} else {
|
||||
require.True(t, txType.Valid)
|
||||
require.Equal(t, tt.Type(), uint8(txType.Int64))
|
||||
require.True(t, protected.Valid)
|
||||
require.Equal(t, tt.Protected(), protected.Bool)
|
||||
require.True(t, gasLimit.Valid)
|
||||
require.Equal(t, tt.Gas(), uint64(gasLimit.Int64))
|
||||
require.True(t, gasPriceClamped64.Valid)
|
||||
require.Equal(t, *sqlite.BigIntToClampedInt64(tt.GasPrice()), gasPriceClamped64.Int64)
|
||||
require.True(t, gasTipCapClamped64.Valid)
|
||||
require.Equal(t, *sqlite.BigIntToClampedInt64(tt.GasTipCap()), gasTipCapClamped64.Int64)
|
||||
require.True(t, gasFeeCapClamped64.Valid)
|
||||
require.Equal(t, *sqlite.BigIntToClampedInt64(tt.GasFeeCap()), gasFeeCapClamped64.Int64)
|
||||
require.True(t, accountNonce.Valid)
|
||||
require.Equal(t, tt.Nonce(), uint64(accountNonce.Int64))
|
||||
require.True(t, size.Valid)
|
||||
require.Equal(t, int64(tt.Size()), size.Int64)
|
||||
|
||||
if expectedEntryType == w_common.EthTransfer {
|
||||
require.True(t, amount128Hex.Valid)
|
||||
require.Equal(t, *sqlite.BigIntToPadded128BitsStr(tt.Value()), amount128Hex.String)
|
||||
require.False(t, dbTokenAddress.Valid)
|
||||
require.True(t, isTokenIDNull)
|
||||
} else {
|
||||
actualEntryType, expectedTokenAddress, expectedTokenID, expectedValue := w_common.ExtractTokenIdentity(expectedEntryType, tl, tt)
|
||||
if actualEntryType == w_common.Erc20Transfer {
|
||||
require.True(t, amount128Hex.Valid)
|
||||
require.Equal(t, *sqlite.BigIntToPadded128BitsStr(expectedValue), amount128Hex.String)
|
||||
require.True(t, isTokenIDNull)
|
||||
require.True(t, dbTokenAddress.Valid)
|
||||
require.Equal(t, *expectedTokenAddress, tokenAddress)
|
||||
} else if actualEntryType == w_common.Erc721Transfer {
|
||||
require.False(t, amount128Hex.Valid)
|
||||
require.False(t, isTokenIDNull)
|
||||
require.Equal(t, expectedTokenID, expectedTokenID)
|
||||
require.True(t, dbTokenAddress.Valid)
|
||||
require.Equal(t, *expectedTokenAddress, tokenAddress)
|
||||
} else {
|
||||
require.False(t, amount128Hex.Valid)
|
||||
require.True(t, isTokenIDNull)
|
||||
require.False(t, dbTokenAddress.Valid)
|
||||
}
|
||||
|
||||
require.Equal(t, expectedEntryType, actualEntryType)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
validateReceipt := func(tr *types.Receipt, tl *types.Log) {
|
||||
if tr == nil {
|
||||
require.False(t, status.Valid)
|
||||
require.False(t, receiptType.Valid)
|
||||
require.Equal(t, []byte(nil), txHash)
|
||||
require.Equal(t, []byte(nil), blockHash)
|
||||
require.False(t, cumulativeGasUsed.Valid)
|
||||
require.Equal(t, common.Address{}, contractAddress)
|
||||
require.False(t, gasUsed.Valid)
|
||||
require.False(t, txIndex.Valid)
|
||||
} else {
|
||||
require.True(t, status.Valid)
|
||||
require.Equal(t, tr.Status, uint64(status.Int64))
|
||||
require.True(t, receiptType.Valid)
|
||||
require.Equal(t, int64(tr.Type), receiptType.Int64)
|
||||
require.Equal(t, tr.TxHash, common.BytesToHash(txHash))
|
||||
require.Equal(t, tr.BlockHash, common.BytesToHash(blockHash))
|
||||
require.True(t, cumulativeGasUsed.Valid)
|
||||
require.Equal(t, int64(tr.CumulativeGasUsed), cumulativeGasUsed.Int64)
|
||||
require.Equal(t, tr.ContractAddress, contractAddress)
|
||||
require.True(t, gasUsed.Valid)
|
||||
require.Equal(t, int64(tr.GasUsed), gasUsed.Int64)
|
||||
require.True(t, txIndex.Valid)
|
||||
require.Equal(t, int64(tr.TransactionIndex), txIndex.Int64)
|
||||
}
|
||||
if tl == nil {
|
||||
require.False(t, logIndex.Valid)
|
||||
} else {
|
||||
require.True(t, logIndex.Valid)
|
||||
require.Equal(t, uint(logIndex.Int64), tl.Index)
|
||||
}
|
||||
}
|
||||
|
||||
err = scanNextData()
|
||||
require.NoError(t, err)
|
||||
validateTransaction(nil, w_common.EthTransfer, nil)
|
||||
validateReceipt(nil, nil)
|
||||
|
||||
var successReceipt types.Receipt
|
||||
err = json.Unmarshal([]byte(erc20SuccessReceiptJSON), &successReceipt)
|
||||
require.NoError(t, err)
|
||||
|
||||
var failReceipt types.Receipt
|
||||
err = json.Unmarshal([]byte(erc20FailReceiptJSON), &failReceipt)
|
||||
require.NoError(t, err)
|
||||
|
||||
var erc20Log types.Log
|
||||
err = json.Unmarshal([]byte(erc20LogTestData), &erc20Log)
|
||||
require.NoError(t, err)
|
||||
|
||||
var erc20Tx types.Transaction
|
||||
err = json.Unmarshal([]byte(erc20TxTestData), &erc20Tx)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = scanNextData()
|
||||
require.NoError(t, err)
|
||||
validateTransaction(&erc20Tx, w_common.Erc20Transfer, &erc20Log)
|
||||
validateReceipt(&failReceipt, &erc20Log)
|
||||
|
||||
err = scanNextData()
|
||||
require.NoError(t, err)
|
||||
validateTransaction(&erc20Tx, w_common.Erc20Transfer, &erc20Log)
|
||||
validateReceipt(&successReceipt, &erc20Log)
|
||||
|
||||
var erc721Receipt types.Receipt
|
||||
err = json.Unmarshal([]byte(erc721ReceiptTestData), &erc721Receipt)
|
||||
require.NoError(t, err)
|
||||
|
||||
var erc721Log types.Log
|
||||
err = json.Unmarshal([]byte(erc721LogTestData), &erc721Log)
|
||||
require.NoError(t, err)
|
||||
|
||||
var erc721Tx types.Transaction
|
||||
err = json.Unmarshal([]byte(erc721TxTestData), &erc721Tx)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = scanNextData()
|
||||
require.NoError(t, err)
|
||||
validateTransaction(&erc721Tx, w_common.Erc721Transfer, &erc721Log)
|
||||
validateReceipt(&erc721Receipt, &erc721Log)
|
||||
|
||||
var zeroTestTx types.Transaction
|
||||
err = json.Unmarshal([]byte(ethZeroValueTxTestData), &zeroTestTx)
|
||||
require.NoError(t, err)
|
||||
|
||||
var ethReceipt types.Receipt
|
||||
err = json.Unmarshal([]byte(ethReceiptTestData), ðReceipt)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = scanNextData()
|
||||
require.NoError(t, err)
|
||||
validateTransaction(&zeroTestTx, w_common.EthTransfer, nil)
|
||||
validateReceipt(ðReceipt, nil)
|
||||
|
||||
var bigTestTx types.Transaction
|
||||
err = json.Unmarshal([]byte(ethVeryBigValueTxTestData), &bigTestTx)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = scanNextData()
|
||||
require.NoError(t, err)
|
||||
validateTransaction(&bigTestTx, w_common.EthTransfer, nil)
|
||||
validateReceipt(nil, nil)
|
||||
|
||||
var ethOriginalTestTx types.Transaction
|
||||
err = json.Unmarshal([]byte(ethOriginalTxTestData), ðOriginalTestTx)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = scanNextData()
|
||||
require.NoError(t, err)
|
||||
validateTransaction(ðOriginalTestTx, w_common.EthTransfer, nil)
|
||||
validateReceipt(ðReceipt, nil)
|
||||
|
||||
var uniswapV2Receipt types.Receipt
|
||||
err = json.Unmarshal([]byte(uniswapV2ReceiptTestData), &uniswapV2Receipt)
|
||||
require.NoError(t, err)
|
||||
|
||||
var uniswapV2Log types.Log
|
||||
err = json.Unmarshal([]byte(uniswapV2LogTestData), &uniswapV2Log)
|
||||
require.NoError(t, err)
|
||||
|
||||
var uniswapV2Tx types.Transaction
|
||||
err = json.Unmarshal([]byte(uniswapV2TxTestData), &uniswapV2Tx)
|
||||
require.NoError(t, err)
|
||||
|
||||
var uniswapV3Receipt types.Receipt
|
||||
err = json.Unmarshal([]byte(uniswapV3ReceiptTestData), &uniswapV3Receipt)
|
||||
require.NoError(t, err)
|
||||
|
||||
var uniswapV3Log types.Log
|
||||
err = json.Unmarshal([]byte(uniswapV3LogTestData), &uniswapV3Log)
|
||||
require.NoError(t, err)
|
||||
|
||||
var uniswapV3Tx types.Transaction
|
||||
err = json.Unmarshal([]byte(uniswapV3TxTestData), &uniswapV3Tx)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = scanNextData()
|
||||
require.NoError(t, err)
|
||||
validateTransaction(&uniswapV2Tx, w_common.UniswapV2Swap, &uniswapV2Log)
|
||||
validateReceipt(&uniswapV2Receipt, &uniswapV2Log)
|
||||
|
||||
err = scanNextData()
|
||||
require.NoError(t, err)
|
||||
validateTransaction(&uniswapV3Tx, w_common.UniswapV3Swap, &uniswapV3Log)
|
||||
validateReceipt(&uniswapV3Receipt, &uniswapV3Log)
|
||||
|
||||
err = scanNextData()
|
||||
// Validate that we processed all data (no more rows expected)
|
||||
require.Error(t, err)
|
||||
|
||||
db.Close()
|
||||
}
|
||||
|
|
|
@ -67,6 +67,8 @@
|
|||
// 1685463947_add_to_asset_to_multitransaction.up.sql (61B)
|
||||
// 1685880973_add_profile_links_settings_table.up.sql (1.656kB)
|
||||
// 1686041510_add_idx_transfers_blkno_loaded.up.sql (71B)
|
||||
// 1686048341_transfers_receipt_json_blob_out.up.sql.down.sql (104B)
|
||||
// 1686048341_transfers_receipt_json_blob_out.up.sql.up.sql (1.5kB)
|
||||
// doc.go (74B)
|
||||
|
||||
package migrations
|
||||
|
@ -151,7 +153,7 @@ func _1640111208_dummyUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1640111208_dummy.up.sql", size: 258, mode: os.FileMode(0644), modTime: time.Unix(1685543739, 0)}
|
||||
info := bindataFileInfo{name: "1640111208_dummy.up.sql", size: 258, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x3e, 0xf0, 0xae, 0x20, 0x6e, 0x75, 0xd1, 0x36, 0x14, 0xf2, 0x40, 0xe5, 0xd6, 0x7a, 0xc4, 0xa5, 0x72, 0xaa, 0xb5, 0x4d, 0x71, 0x97, 0xb8, 0xe8, 0x95, 0x22, 0x95, 0xa2, 0xac, 0xaf, 0x48, 0x58}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -171,7 +173,7 @@ func _1642666031_add_removed_clock_to_bookmarksUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1642666031_add_removed_clock_to_bookmarks.up.sql", size: 117, mode: os.FileMode(0644), modTime: time.Unix(1685543739, 0)}
|
||||
info := bindataFileInfo{name: "1642666031_add_removed_clock_to_bookmarks.up.sql", size: 117, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x84, 0x4e, 0x38, 0x99, 0x7a, 0xc, 0x90, 0x13, 0xec, 0xfe, 0x2f, 0x55, 0xff, 0xb7, 0xb6, 0xaa, 0x96, 0xc6, 0x92, 0x79, 0xcc, 0xee, 0x4e, 0x99, 0x53, 0xfe, 0x1c, 0xbb, 0x32, 0x2, 0xa4, 0x27}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -191,7 +193,7 @@ func _1643644541_gif_api_key_settingUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1643644541_gif_api_key_setting.up.sql", size: 108, mode: os.FileMode(0644), modTime: time.Unix(1685543739, 0)}
|
||||
info := bindataFileInfo{name: "1643644541_gif_api_key_setting.up.sql", size: 108, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x1b, 0x94, 0x28, 0xfb, 0x66, 0xd1, 0x7c, 0xb8, 0x89, 0xe2, 0xb4, 0x71, 0x65, 0x24, 0x57, 0x22, 0x95, 0x38, 0x97, 0x3, 0x9b, 0xc6, 0xa4, 0x41, 0x7b, 0xba, 0xf7, 0xdb, 0x70, 0xf7, 0x20, 0x3a}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -211,7 +213,7 @@ func _1644188994_recent_stickersUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1644188994_recent_stickers.up.sql", size: 79, mode: os.FileMode(0644), modTime: time.Unix(1685543739, 0)}
|
||||
info := bindataFileInfo{name: "1644188994_recent_stickers.up.sql", size: 79, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x1e, 0xad, 0xaa, 0x30, 0xbf, 0x4, 0x7, 0xf8, 0xc3, 0x3, 0xb8, 0x97, 0x23, 0x2b, 0xbd, 0x1c, 0x60, 0x69, 0xb0, 0x42, 0x5e, 0x6b, 0xd, 0xa7, 0xa3, 0x6b, 0x2e, 0xdc, 0x70, 0x13, 0x72, 0x7}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -231,7 +233,7 @@ func _1646659233_add_address_to_dapp_permisssionUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1646659233_add_address_to_dapp_permisssion.up.sql", size: 700, mode: os.FileMode(0644), modTime: time.Unix(1685543739, 0)}
|
||||
info := bindataFileInfo{name: "1646659233_add_address_to_dapp_permisssion.up.sql", size: 700, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xed, 0xb0, 0x35, 0xcc, 0x2e, 0x16, 0xe6, 0x15, 0x86, 0x2c, 0x37, 0x80, 0xae, 0xa3, 0xc5, 0x31, 0x78, 0x5, 0x9d, 0xcd, 0x7b, 0xeb, 0x5f, 0xf2, 0xb3, 0x74, 0x72, 0xdf, 0xcf, 0x88, 0xb, 0x40}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -251,7 +253,7 @@ func _1646841105_add_emoji_accountUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1646841105_add_emoji_account.up.sql", size: 96, mode: os.FileMode(0644), modTime: time.Unix(1685543739, 0)}
|
||||
info := bindataFileInfo{name: "1646841105_add_emoji_account.up.sql", size: 96, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xe6, 0x77, 0x29, 0x95, 0x18, 0x64, 0x82, 0x63, 0xe7, 0xaf, 0x6c, 0xa9, 0x15, 0x7d, 0x46, 0xa6, 0xbc, 0xdf, 0xa7, 0xd, 0x2b, 0xd2, 0x2d, 0x97, 0x4d, 0xa, 0x6b, 0xd, 0x6e, 0x90, 0x42, 0x5c}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -271,7 +273,7 @@ func _1647278782_display_nameUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1647278782_display_name.up.sql", size: 110, mode: os.FileMode(0644), modTime: time.Unix(1685543739, 0)}
|
||||
info := bindataFileInfo{name: "1647278782_display_name.up.sql", size: 110, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xf4, 0xa1, 0x1f, 0x3e, 0x61, 0x65, 0x8d, 0xff, 0xee, 0xde, 0xc5, 0x91, 0xd9, 0x5c, 0xb5, 0xe2, 0xf0, 0xb7, 0xe7, 0x5c, 0x5c, 0x16, 0x25, 0x89, 0xee, 0x78, 0x12, 0xea, 0x3e, 0x48, 0x41, 0xa6}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -291,7 +293,7 @@ func _1647862838_reset_last_backupUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1647862838_reset_last_backup.up.sql", size: 37, mode: os.FileMode(0644), modTime: time.Unix(1685543739, 0)}
|
||||
info := bindataFileInfo{name: "1647862838_reset_last_backup.up.sql", size: 37, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x21, 0xe3, 0xd5, 0xf6, 0x5f, 0xfe, 0x65, 0xfa, 0x1d, 0x88, 0xf8, 0x5f, 0x24, 0x71, 0x34, 0x68, 0x96, 0x2a, 0x60, 0x87, 0x15, 0x82, 0x4d, 0x8a, 0x59, 0x3d, 0x1f, 0xd8, 0x56, 0xd4, 0xfb, 0xda}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -311,7 +313,7 @@ func _1647871652_add_settings_sync_clock_tableUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1647871652_add_settings_sync_clock_table.up.sql", size: 1044, mode: os.FileMode(0644), modTime: time.Unix(1685543739, 0)}
|
||||
info := bindataFileInfo{name: "1647871652_add_settings_sync_clock_table.up.sql", size: 1044, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xd8, 0x58, 0xec, 0x85, 0x90, 0xfa, 0x30, 0x98, 0x98, 0x9a, 0xa6, 0xa8, 0x96, 0x2b, 0x38, 0x93, 0xf3, 0xae, 0x46, 0x74, 0xa4, 0x41, 0x62, 0x9b, 0x2, 0x86, 0xbf, 0xe5, 0x2a, 0xce, 0xe2, 0xc0}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -331,7 +333,7 @@ func _1647880168_add_torrent_configUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1647880168_add_torrent_config.up.sql", size: 211, mode: os.FileMode(0644), modTime: time.Unix(1685543739, 0)}
|
||||
info := bindataFileInfo{name: "1647880168_add_torrent_config.up.sql", size: 211, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x1, 0x92, 0x22, 0x37, 0x96, 0xf3, 0xb5, 0x5b, 0x27, 0xd0, 0x7d, 0x43, 0x5, 0x4e, 0x9d, 0xe2, 0x49, 0xbe, 0x86, 0x31, 0xa1, 0x89, 0xff, 0xd6, 0x51, 0xe0, 0x9c, 0xb, 0xda, 0xfc, 0xf2, 0x93}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -351,7 +353,7 @@ func _1647882837_add_communities_settings_tableUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1647882837_add_communities_settings_table.up.sql", size: 206, mode: os.FileMode(0644), modTime: time.Unix(1685543739, 0)}
|
||||
info := bindataFileInfo{name: "1647882837_add_communities_settings_table.up.sql", size: 206, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xbd, 0x87, 0x78, 0x99, 0xd9, 0x5d, 0xbd, 0xf7, 0x57, 0x9c, 0xca, 0x97, 0xbd, 0xb3, 0xe9, 0xb5, 0x89, 0x31, 0x3f, 0xf6, 0x5c, 0x13, 0xb, 0xc3, 0x54, 0x93, 0x18, 0x40, 0x7, 0x82, 0xfe, 0x7e}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -371,7 +373,7 @@ func _1647956635_add_waku_messages_tableUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1647956635_add_waku_messages_table.up.sql", size: 266, mode: os.FileMode(0644), modTime: time.Unix(1685543739, 0)}
|
||||
info := bindataFileInfo{name: "1647956635_add_waku_messages_table.up.sql", size: 266, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xd1, 0xe, 0xe1, 0xdc, 0xda, 0x2e, 0x89, 0x8d, 0xdc, 0x2a, 0x1c, 0x13, 0xa1, 0xfc, 0xfe, 0xf, 0xb2, 0xb9, 0x85, 0xc8, 0x45, 0xd6, 0xd1, 0x7, 0x5c, 0xa3, 0x8, 0x47, 0x44, 0x6d, 0x96, 0xe0}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -391,7 +393,7 @@ func _1648554928_network_testUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1648554928_network_test.up.sql", size: 132, mode: os.FileMode(0644), modTime: time.Unix(1685543739, 0)}
|
||||
info := bindataFileInfo{name: "1648554928_network_test.up.sql", size: 132, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x9a, 0xc5, 0x7f, 0x87, 0xf3, 0x2c, 0xf7, 0xbb, 0xd3, 0x3a, 0x4e, 0x76, 0x88, 0xca, 0xaf, 0x73, 0xce, 0x8f, 0xa1, 0xf6, 0x3d, 0x4d, 0xed, 0x6f, 0x49, 0xf2, 0xfe, 0x56, 0x2a, 0x60, 0x68, 0xca}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -411,7 +413,7 @@ func _1649174829_add_visitble_tokenUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1649174829_add_visitble_token.up.sql", size: 84, mode: os.FileMode(0644), modTime: time.Unix(1685543739, 0)}
|
||||
info := bindataFileInfo{name: "1649174829_add_visitble_token.up.sql", size: 84, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xa3, 0x22, 0xc0, 0x2b, 0x3f, 0x4f, 0x3d, 0x5e, 0x4c, 0x68, 0x7c, 0xd0, 0x15, 0x36, 0x9f, 0xec, 0xa1, 0x2a, 0x7b, 0xb4, 0xe3, 0xc6, 0xc9, 0xb4, 0x81, 0x50, 0x4a, 0x11, 0x3b, 0x35, 0x7, 0xcf}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -431,7 +433,7 @@ func _1649882262_add_derived_from_accountsUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1649882262_add_derived_from_accounts.up.sql", size: 110, mode: os.FileMode(0644), modTime: time.Unix(1685543739, 0)}
|
||||
info := bindataFileInfo{name: "1649882262_add_derived_from_accounts.up.sql", size: 110, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x11, 0xb9, 0x44, 0x4d, 0x85, 0x8d, 0x7f, 0xb4, 0xae, 0x4f, 0x5c, 0x66, 0x64, 0xb6, 0xe2, 0xe, 0x3d, 0xad, 0x9d, 0x8, 0x4f, 0xab, 0x6e, 0xa8, 0x7d, 0x76, 0x3, 0xad, 0x96, 0x1, 0xee, 0x5c}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -451,7 +453,7 @@ func _1650612625_add_community_message_archive_hashes_tableUpSql() (*asset, erro
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1650612625_add_community_message_archive_hashes_table.up.sql", size: 130, mode: os.FileMode(0644), modTime: time.Unix(1685543739, 0)}
|
||||
info := bindataFileInfo{name: "1650612625_add_community_message_archive_hashes_table.up.sql", size: 130, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x48, 0x31, 0xb3, 0x75, 0x23, 0xe2, 0x45, 0xe, 0x47, 0x1b, 0x35, 0xa5, 0x6e, 0x83, 0x4e, 0x64, 0x7d, 0xd7, 0xa2, 0xda, 0xe9, 0x53, 0xf1, 0x16, 0x86, 0x2c, 0x57, 0xad, 0xfa, 0xca, 0x39, 0xde}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -471,7 +473,7 @@ func _1650616788_add_communities_archives_info_tableUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1650616788_add_communities_archives_info_table.up.sql", size: 208, mode: os.FileMode(0644), modTime: time.Unix(1685543739, 0)}
|
||||
info := bindataFileInfo{name: "1650616788_add_communities_archives_info_table.up.sql", size: 208, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xd1, 0x4f, 0x80, 0x45, 0xb9, 0xd9, 0x15, 0xe2, 0x78, 0xd0, 0xcb, 0x71, 0xc1, 0x1b, 0xb7, 0x1b, 0x1b, 0x97, 0xfe, 0x47, 0x53, 0x3c, 0x62, 0xbc, 0xdd, 0x3a, 0x94, 0x1a, 0xc, 0x48, 0x76, 0xe}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -491,7 +493,7 @@ func _1652715604_add_clock_accountsUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1652715604_add_clock_accounts.up.sql", size: 62, mode: os.FileMode(0644), modTime: time.Unix(1685543739, 0)}
|
||||
info := bindataFileInfo{name: "1652715604_add_clock_accounts.up.sql", size: 62, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xb6, 0xd9, 0x8d, 0x73, 0xc9, 0xef, 0xfa, 0xb1, 0x4b, 0xa5, 0xf3, 0x5, 0x19, 0x26, 0x46, 0xf8, 0x47, 0x93, 0xdb, 0xac, 0x2, 0xef, 0xf9, 0x71, 0x56, 0x83, 0xe6, 0x2d, 0xb0, 0xd7, 0x83, 0x5c}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -511,7 +513,7 @@ func _1653037334_add_notifications_settings_tableUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1653037334_add_notifications_settings_table.up.sql", size: 1276, mode: os.FileMode(0644), modTime: time.Unix(1685543739, 0)}
|
||||
info := bindataFileInfo{name: "1653037334_add_notifications_settings_table.up.sql", size: 1276, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x4b, 0xc4, 0x65, 0xac, 0xa, 0xf2, 0xef, 0xb6, 0x39, 0x3c, 0xc5, 0xb1, 0xb2, 0x9c, 0x86, 0x58, 0xe0, 0x38, 0xcb, 0x57, 0x3c, 0x76, 0x73, 0x87, 0x79, 0x4e, 0xf6, 0xed, 0xb0, 0x8e, 0x9e, 0xa}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -531,7 +533,7 @@ func _1654702119_add_mutual_contact_settingsUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1654702119_add_mutual_contact_settings.up.sql", size: 78, mode: os.FileMode(0644), modTime: time.Unix(1685543739, 0)}
|
||||
info := bindataFileInfo{name: "1654702119_add_mutual_contact_settings.up.sql", size: 78, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x26, 0x66, 0x67, 0x50, 0xfe, 0xd7, 0xe3, 0x29, 0x8b, 0xff, 0x9d, 0x5a, 0x87, 0xa7, 0x99, 0x6e, 0xd6, 0xcd, 0x2e, 0xbb, 0x17, 0xdf, 0x7f, 0xf7, 0xa3, 0xfa, 0x32, 0x7c, 0x2d, 0x92, 0xc8, 0x74}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -551,7 +553,7 @@ func _1655375270_add_clock_field_to_communities_settings_tableUpSql() (*asset, e
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1655375270_add_clock_field_to_communities_settings_table.up.sql", size: 74, mode: os.FileMode(0644), modTime: time.Unix(1685543739, 0)}
|
||||
info := bindataFileInfo{name: "1655375270_add_clock_field_to_communities_settings_table.up.sql", size: 74, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x19, 0xc5, 0xc0, 0xf9, 0x84, 0x53, 0xdf, 0x83, 0xcf, 0xb6, 0x40, 0x6d, 0xf5, 0xdc, 0x77, 0x37, 0xb7, 0xe3, 0xa, 0x75, 0xe7, 0x6, 0x11, 0xca, 0x2b, 0x51, 0x92, 0xdd, 0x7d, 0xdb, 0xc3, 0xf5}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -571,7 +573,7 @@ func _1655385721_drop_networks_configUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1655385721_drop_networks_config.up.sql", size: 27, mode: os.FileMode(0644), modTime: time.Unix(1685543739, 0)}
|
||||
info := bindataFileInfo{name: "1655385721_drop_networks_config.up.sql", size: 27, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xfc, 0xa7, 0x20, 0xbb, 0x67, 0x21, 0xe, 0xc6, 0xc8, 0x21, 0x74, 0xe0, 0xce, 0xc8, 0xe2, 0x2, 0xb4, 0xea, 0xf0, 0xe5, 0xc4, 0x4d, 0xdd, 0xd4, 0x52, 0x31, 0xa9, 0x3d, 0xcd, 0xd8, 0x9b, 0xab}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -591,7 +593,7 @@ func _1655385724_networks_chaincolor_shortnameUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1655385724_networks_chainColor_shortName.up.sql", size: 220, mode: os.FileMode(0644), modTime: time.Unix(1685543739, 0)}
|
||||
info := bindataFileInfo{name: "1655385724_networks_chainColor_shortName.up.sql", size: 220, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xd9, 0xe7, 0x84, 0xbb, 0x5f, 0xd2, 0x2c, 0x42, 0x88, 0x62, 0x52, 0xb6, 0x58, 0x31, 0xac, 0xc, 0x96, 0x2b, 0x1b, 0xe5, 0x4e, 0x9a, 0x3a, 0xf6, 0xf6, 0xfc, 0xa9, 0x1a, 0x35, 0x62, 0x28, 0x88}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -611,7 +613,7 @@ func _1655456688_add_deleted_at_field_to_bookmarks_tableUpSql() (*asset, error)
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1655456688_add_deleted_at_field_to_bookmarks_table.up.sql", size: 69, mode: os.FileMode(0644), modTime: time.Unix(1685543739, 0)}
|
||||
info := bindataFileInfo{name: "1655456688_add_deleted_at_field_to_bookmarks_table.up.sql", size: 69, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xe7, 0x9a, 0xbd, 0x9a, 0xc9, 0xf, 0xdf, 0x90, 0x0, 0x5d, 0xea, 0x6e, 0x7d, 0x51, 0x95, 0xcd, 0x90, 0xd3, 0x1a, 0x36, 0x6c, 0xf4, 0xbd, 0xa7, 0x6b, 0xbf, 0xe5, 0xdb, 0xa3, 0x88, 0xe3, 0x50}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -631,7 +633,7 @@ func _1655462032_create_bookmarks_deleted_at_indexUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1655462032_create_bookmarks_deleted_at_index.up.sql", size: 81, mode: os.FileMode(0644), modTime: time.Unix(1685543739, 0)}
|
||||
info := bindataFileInfo{name: "1655462032_create_bookmarks_deleted_at_index.up.sql", size: 81, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xf, 0x8e, 0x20, 0x6b, 0x14, 0x9e, 0xcd, 0x97, 0xd3, 0xfe, 0x62, 0x3, 0x26, 0x59, 0x1, 0x6c, 0x99, 0xef, 0x6d, 0x21, 0xd4, 0xb5, 0xa3, 0xf4, 0x39, 0x40, 0x54, 0x6, 0xd, 0x60, 0x13, 0x38}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -651,7 +653,7 @@ func _1657617291_add_multi_transactions_tableUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1657617291_add_multi_transactions_table.up.sql", size: 412, mode: os.FileMode(0644), modTime: time.Unix(1685543739, 0)}
|
||||
info := bindataFileInfo{name: "1657617291_add_multi_transactions_table.up.sql", size: 412, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x86, 0xb0, 0x4e, 0x8c, 0x4, 0x82, 0xb4, 0x43, 0xaa, 0xd0, 0x16, 0xdd, 0xcb, 0x88, 0x81, 0xac, 0x4, 0x34, 0x1a, 0x8f, 0x2e, 0xc5, 0x69, 0xb, 0xf0, 0x17, 0xf7, 0xe3, 0x9, 0xe, 0x54, 0xe0}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -671,7 +673,7 @@ func _1660134042_add_social_links_settings_tableUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1660134042_add_social_links_settings_table.up.sql", size: 334, mode: os.FileMode(0644), modTime: time.Unix(1685543739, 0)}
|
||||
info := bindataFileInfo{name: "1660134042_add_social_links_settings_table.up.sql", size: 334, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x84, 0x73, 0xb6, 0xe7, 0x3f, 0xaa, 0x39, 0x9a, 0x56, 0x56, 0x31, 0xf1, 0x8e, 0x26, 0x23, 0x1, 0xe4, 0xfa, 0x98, 0xfe, 0x78, 0x87, 0x20, 0xcb, 0x52, 0xf4, 0x38, 0x7f, 0xc4, 0x1c, 0x4, 0x22}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -691,7 +693,7 @@ func _1660134060_settings_bioUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1660134060_settings_bio.up.sql", size: 91, mode: os.FileMode(0644), modTime: time.Unix(1685543739, 0)}
|
||||
info := bindataFileInfo{name: "1660134060_settings_bio.up.sql", size: 91, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x46, 0x25, 0xa0, 0xa6, 0x47, 0xff, 0xbc, 0x2a, 0x0, 0xff, 0x59, 0x4b, 0xb0, 0xc9, 0x4e, 0x15, 0xe4, 0xd9, 0xda, 0xeb, 0xfe, 0x55, 0x98, 0xc3, 0x9d, 0x96, 0xe7, 0xf, 0xd1, 0x5c, 0x93, 0x73}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -711,7 +713,7 @@ func _1660134070_add_wakuv2_storeUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1660134070_add_wakuv2_store.up.sql", size: 269, mode: os.FileMode(0644), modTime: time.Unix(1685543739, 0)}
|
||||
info := bindataFileInfo{name: "1660134070_add_wakuv2_store.up.sql", size: 269, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x1d, 0xe6, 0xc3, 0x9, 0xef, 0xdc, 0xae, 0x49, 0x30, 0x78, 0x54, 0xd6, 0xdb, 0xbf, 0xc0, 0x8e, 0x25, 0x8f, 0xfc, 0x67, 0x80, 0x39, 0x37, 0xd4, 0x86, 0xc1, 0x85, 0xc8, 0x99, 0xc4, 0x59, 0xd4}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -731,7 +733,7 @@ func _1660134072_waku2_store_messagesUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1660134072_waku2_store_messages.up.sql", size: 497, mode: os.FileMode(0644), modTime: time.Unix(1685543739, 0)}
|
||||
info := bindataFileInfo{name: "1660134072_waku2_store_messages.up.sql", size: 497, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x3e, 0xeb, 0xb4, 0xa0, 0xa1, 0x2b, 0xcb, 0x4c, 0x3c, 0xc6, 0xd0, 0xe8, 0x96, 0xe3, 0x96, 0xf1, 0x4f, 0x1f, 0xe0, 0xe7, 0x1f, 0x85, 0xa3, 0xe, 0xf7, 0x52, 0x56, 0x63, 0x2b, 0xb0, 0x87, 0x7b}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -751,7 +753,7 @@ func _1662365868_add_key_uid_accountsUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1662365868_add_key_uid_accounts.up.sql", size: 68, mode: os.FileMode(0644), modTime: time.Unix(1685543739, 0)}
|
||||
info := bindataFileInfo{name: "1662365868_add_key_uid_accounts.up.sql", size: 68, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xc6, 0xd8, 0x2f, 0x2f, 0x3b, 0xa8, 0xbd, 0x6d, 0xf6, 0x87, 0x7e, 0xd2, 0xf1, 0xa2, 0xf7, 0x81, 0x6a, 0x23, 0x10, 0xbc, 0xbf, 0x5b, 0xe7, 0x2b, 0x9c, 0xa9, 0x8a, 0x18, 0xbb, 0xd0, 0x86, 0x91}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -771,7 +773,7 @@ func _1662447680_add_keypairs_tableUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1662447680_add_keypairs_table.up.sql", size: 218, mode: os.FileMode(0644), modTime: time.Unix(1685543739, 0)}
|
||||
info := bindataFileInfo{name: "1662447680_add_keypairs_table.up.sql", size: 218, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xdc, 0x25, 0xa9, 0xc7, 0x63, 0x27, 0x97, 0x35, 0x5f, 0x6b, 0xab, 0x26, 0xcb, 0xf9, 0xbd, 0x5e, 0xac, 0x3, 0xa0, 0x5e, 0xb9, 0x71, 0xa3, 0x1f, 0xb3, 0x4f, 0x7f, 0x79, 0x28, 0x48, 0xbe, 0xc}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -791,7 +793,7 @@ func _1662460056_move_favourites_to_saved_addressesUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1662460056_move_favourites_to_saved_addresses.up.sql", size: 233, mode: os.FileMode(0644), modTime: time.Unix(1685543739, 0)}
|
||||
info := bindataFileInfo{name: "1662460056_move_favourites_to_saved_addresses.up.sql", size: 233, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x10, 0xa2, 0x8c, 0xa3, 0xec, 0xad, 0xdf, 0xc3, 0x48, 0x5, 0x9b, 0x50, 0x25, 0x59, 0xae, 0x7d, 0xee, 0x58, 0xd2, 0x41, 0x27, 0xf2, 0x22, 0x2e, 0x9a, 0xb9, 0x4a, 0xcc, 0x38, 0x6e, 0x3a, 0xb2}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -811,7 +813,7 @@ func _1662738097_add_base_fee_transactionUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1662738097_add_base_fee_transaction.up.sql", size: 112, mode: os.FileMode(0644), modTime: time.Unix(1685543739, 0)}
|
||||
info := bindataFileInfo{name: "1662738097_add_base_fee_transaction.up.sql", size: 112, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x6b, 0xfb, 0x10, 0xae, 0xfc, 0x77, 0x70, 0x98, 0x6f, 0xec, 0xaa, 0xcd, 0x7, 0xc7, 0x74, 0x23, 0xc, 0xd5, 0x1e, 0x82, 0xdd, 0xfe, 0xff, 0x3b, 0xd2, 0x49, 0x10, 0x5b, 0x30, 0xc, 0x2d, 0xb0}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -831,7 +833,7 @@ func _1662972194_add_keypairs_tableUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1662972194_add_keypairs_table.up.sql", size: 345, mode: os.FileMode(0644), modTime: time.Unix(1685543739, 0)}
|
||||
info := bindataFileInfo{name: "1662972194_add_keypairs_table.up.sql", size: 345, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xab, 0x76, 0xf2, 0x86, 0xe1, 0x7e, 0xe9, 0x47, 0x32, 0x48, 0xd5, 0x6b, 0xe5, 0xd, 0xab, 0xb7, 0xf1, 0xd4, 0xf1, 0xad, 0x38, 0xa6, 0x11, 0xe7, 0xce, 0x5c, 0x11, 0x11, 0xf, 0x47, 0xb2, 0x4}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -851,7 +853,7 @@ func _1664392661_add_third_party_id_to_waku_messagesUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1664392661_add_third_party_id_to_waku_messages.up.sql", size: 70, mode: os.FileMode(0644), modTime: time.Unix(1685543739, 0)}
|
||||
info := bindataFileInfo{name: "1664392661_add_third_party_id_to_waku_messages.up.sql", size: 70, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xfd, 0x67, 0x66, 0x9e, 0x66, 0x74, 0xce, 0x1c, 0xb, 0x1b, 0x9d, 0xd5, 0xfc, 0x65, 0xe, 0x83, 0x90, 0x4c, 0x61, 0x4e, 0x6b, 0xe7, 0x86, 0xbe, 0x36, 0x4f, 0x91, 0x36, 0x4, 0x47, 0x7b, 0x82}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -871,7 +873,7 @@ func _1664783660_add_sync_info_to_saved_addressesUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1664783660_add_sync_info_to_saved_addresses.up.sql", size: 388, mode: os.FileMode(0644), modTime: time.Unix(1685543739, 0)}
|
||||
info := bindataFileInfo{name: "1664783660_add_sync_info_to_saved_addresses.up.sql", size: 388, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x67, 0x7c, 0x3a, 0x95, 0x4e, 0x55, 0xb2, 0xbd, 0xb4, 0x18, 0x93, 0xc1, 0xcf, 0x9f, 0x12, 0xbb, 0x49, 0x8a, 0x2a, 0x6a, 0x2a, 0x7f, 0xad, 0x44, 0xc3, 0xf, 0x3a, 0x79, 0x18, 0xb9, 0x4c, 0x64}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -891,7 +893,7 @@ func _1668109917_wakunodesUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1668109917_wakunodes.up.sql", size: 99, mode: os.FileMode(0644), modTime: time.Unix(1685543739, 0)}
|
||||
info := bindataFileInfo{name: "1668109917_wakunodes.up.sql", size: 99, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x29, 0xaa, 0x9e, 0x2, 0x66, 0x85, 0x69, 0xa8, 0xd9, 0xe2, 0x4b, 0x8d, 0x2a, 0x9c, 0xdf, 0xd2, 0xef, 0x64, 0x58, 0xe3, 0xa6, 0xe7, 0xc1, 0xd1, 0xc8, 0x9c, 0xc0, 0x2c, 0x1, 0xa8, 0x7b, 0x81}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -911,7 +913,7 @@ func _1670249678_display_name_to_settings_sync_clock_tableUpSql() (*asset, error
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1670249678_display_name_to_settings_sync_clock_table.up.sql", size: 83, mode: os.FileMode(0644), modTime: time.Unix(1685543739, 0)}
|
||||
info := bindataFileInfo{name: "1670249678_display_name_to_settings_sync_clock_table.up.sql", size: 83, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x39, 0x18, 0xdc, 0xc4, 0x1f, 0x79, 0x22, 0x16, 0x4d, 0xdf, 0x6c, 0x66, 0xd5, 0xa4, 0x88, 0x5d, 0x5, 0x37, 0xa7, 0x41, 0x5, 0x50, 0xae, 0x12, 0xfa, 0x7e, 0x89, 0x24, 0x5c, 0xae, 0x30, 0xfc}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -931,7 +933,7 @@ func _1670836810_add_imported_flag_to_community_archive_hashesUpSql() (*asset, e
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1670836810_add_imported_flag_to_community_archive_hashes.up.sql", size: 144, mode: os.FileMode(0644), modTime: time.Unix(1685543739, 0)}
|
||||
info := bindataFileInfo{name: "1670836810_add_imported_flag_to_community_archive_hashes.up.sql", size: 144, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x6f, 0xf, 0xf0, 0xbd, 0xfe, 0x63, 0x25, 0x8f, 0x5e, 0x46, 0x4b, 0x45, 0x31, 0x8b, 0x3e, 0xd8, 0x6b, 0x5d, 0x9d, 0x6d, 0x10, 0x9a, 0x87, 0x4b, 0x18, 0xc6, 0x39, 0x81, 0x6e, 0xe4, 0x75, 0xfb}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -951,7 +953,7 @@ func _1671438731_add_magnetlink_uri_to_communities_archive_infoUpSql() (*asset,
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1671438731_add_magnetlink_uri_to_communities_archive_info.up.sql", size: 86, mode: os.FileMode(0644), modTime: time.Unix(1685543739, 0)}
|
||||
info := bindataFileInfo{name: "1671438731_add_magnetlink_uri_to_communities_archive_info.up.sql", size: 86, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xda, 0x8b, 0x4b, 0xd6, 0xd8, 0xe2, 0x3d, 0xf7, 0x6b, 0xcd, 0x1e, 0x70, 0x9, 0x2e, 0x35, 0x4, 0x61, 0xc3, 0xb5, 0x9d, 0xc5, 0x27, 0x21, 0xa, 0x5a, 0xd6, 0x3e, 0xa6, 0x24, 0xa2, 0x12, 0xdf}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -971,7 +973,7 @@ func _1672933930_switcher_cardUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1672933930_switcher_card.up.sql", size: 162, mode: os.FileMode(0644), modTime: time.Unix(1685543739, 0)}
|
||||
info := bindataFileInfo{name: "1672933930_switcher_card.up.sql", size: 162, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x39, 0xba, 0xdc, 0xbb, 0x40, 0x4, 0xf2, 0x10, 0xdf, 0xb4, 0xd2, 0x80, 0x8a, 0x74, 0x4d, 0xf6, 0xbc, 0x50, 0x7, 0xd, 0x22, 0x7f, 0xc4, 0xaf, 0xaa, 0xde, 0xdc, 0x71, 0xe9, 0x42, 0x98, 0x36}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -991,7 +993,7 @@ func _1674056187_add_price_cacheUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1674056187_add_price_cache.up.sql", size: 255, mode: os.FileMode(0644), modTime: time.Unix(1685543739, 0)}
|
||||
info := bindataFileInfo{name: "1674056187_add_price_cache.up.sql", size: 255, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xb7, 0x79, 0x6a, 0x9b, 0x28, 0xd1, 0x22, 0xf0, 0x84, 0x76, 0x40, 0x39, 0x49, 0x15, 0x5d, 0xaa, 0xfd, 0x11, 0xff, 0x13, 0x27, 0x42, 0x12, 0xfa, 0x82, 0xe6, 0x7a, 0xf0, 0x5e, 0x1f, 0xe3, 0xba}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -1011,7 +1013,7 @@ func _1674136690_ens_usernamesUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1674136690_ens_usernames.up.sql", size: 98, mode: os.FileMode(0644), modTime: time.Unix(1685543739, 0)}
|
||||
info := bindataFileInfo{name: "1674136690_ens_usernames.up.sql", size: 98, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x81, 0x7a, 0xf3, 0xa8, 0x88, 0x99, 0xd6, 0x9c, 0x69, 0x48, 0x3c, 0x10, 0xda, 0x72, 0xdc, 0x14, 0xd, 0x6e, 0x8c, 0x82, 0x92, 0x2d, 0x2c, 0xee, 0x4c, 0x70, 0xa4, 0xdc, 0x5c, 0x5, 0x2, 0xc3}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -1031,7 +1033,7 @@ func _1674232431_add_balance_historyUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1674232431_add_balance_history.up.sql", size: 698, mode: os.FileMode(0644), modTime: time.Unix(1685543739, 0)}
|
||||
info := bindataFileInfo{name: "1674232431_add_balance_history.up.sql", size: 698, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xf7, 0xb5, 0x18, 0xca, 0x4a, 0x93, 0xbb, 0x6f, 0xa4, 0xee, 0xe4, 0x3e, 0xff, 0x6a, 0x4b, 0xe2, 0xe1, 0x61, 0x28, 0xee, 0xc5, 0x26, 0x57, 0x61, 0x5e, 0x6d, 0x44, 0x1e, 0x85, 0x43, 0x70, 0xa2}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -1051,7 +1053,7 @@ func _1676368933_keypairs_to_keycardsUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1676368933_keypairs_to_keycards.up.sql", size: 639, mode: os.FileMode(0644), modTime: time.Unix(1685543739, 0)}
|
||||
info := bindataFileInfo{name: "1676368933_keypairs_to_keycards.up.sql", size: 639, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x81, 0x93, 0x27, 0x2, 0xf0, 0x37, 0x81, 0x65, 0xa4, 0xb3, 0x5b, 0x60, 0x36, 0x95, 0xfc, 0x81, 0xf0, 0x3b, 0x7c, 0xc3, 0x2c, 0x85, 0xbd, 0x38, 0x46, 0xa4, 0x95, 0x4a, 0x6, 0x3e, 0x74, 0xd5}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -1071,7 +1073,7 @@ func _1676951398_add_currency_format_cacheUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1676951398_add_currency_format_cache.up.sql", size: 291, mode: os.FileMode(0644), modTime: time.Unix(1685543739, 0)}
|
||||
info := bindataFileInfo{name: "1676951398_add_currency_format_cache.up.sql", size: 291, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xf9, 0xa3, 0x76, 0x35, 0xca, 0xf, 0xe8, 0xdf, 0xd9, 0x61, 0xf9, 0xed, 0xfc, 0x6d, 0xf5, 0xe, 0x11, 0x88, 0xbd, 0x14, 0x92, 0xc6, 0x57, 0x53, 0xe, 0xcd, 0x52, 0xf4, 0xa9, 0xb1, 0xdd, 0xfd}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -1091,7 +1093,7 @@ func _1676968196_keycards_add_clock_columnUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1676968196_keycards_add_clock_column.up.sql", size: 73, mode: os.FileMode(0644), modTime: time.Unix(1685543739, 0)}
|
||||
info := bindataFileInfo{name: "1676968196_keycards_add_clock_column.up.sql", size: 73, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x4c, 0xf, 0x1c, 0x28, 0x41, 0x57, 0x57, 0x6c, 0xe, 0x75, 0x6b, 0x75, 0x12, 0x0, 0x18, 0x1e, 0x88, 0x1e, 0x45, 0xe0, 0x32, 0xb9, 0xd4, 0xd9, 0x2e, 0xc8, 0xb, 0x80, 0x6, 0x51, 0x3d, 0x28}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -1111,7 +1113,7 @@ func _1676968197_add_fallback_rpc_to_networksUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1676968197_add_fallback_rpc_to_networks.up.sql", size: 112, mode: os.FileMode(0644), modTime: time.Unix(1685543739, 0)}
|
||||
info := bindataFileInfo{name: "1676968197_add_fallback_rpc_to_networks.up.sql", size: 112, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x77, 0x6a, 0xc6, 0x45, 0xfa, 0x62, 0x84, 0x74, 0x6d, 0x7c, 0xd7, 0x1d, 0x79, 0xb6, 0x38, 0x43, 0xa8, 0x8, 0x6b, 0x75, 0x3d, 0x9, 0x2, 0xc5, 0x9f, 0xbb, 0x45, 0x56, 0x4c, 0x4e, 0x17, 0x89}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -1131,7 +1133,7 @@ func _1677674090_add_chains_ens_istest_to_saved_addressesUpSql() (*asset, error)
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1677674090_add_chains_ens_istest_to_saved_addresses.up.sql", size: 638, mode: os.FileMode(0644), modTime: time.Unix(1685543739, 0)}
|
||||
info := bindataFileInfo{name: "1677674090_add_chains_ens_istest_to_saved_addresses.up.sql", size: 638, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xa8, 0x2d, 0xa4, 0x1b, 0xf6, 0x6a, 0x13, 0x7b, 0xe, 0x59, 0xcd, 0xe2, 0x4e, 0x81, 0x99, 0xc4, 0x33, 0x84, 0xde, 0x66, 0xca, 0xac, 0x2f, 0x5, 0x90, 0xac, 0xfd, 0x4e, 0xfc, 0x55, 0x44, 0xe5}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -1151,7 +1153,7 @@ func _1677681143_accounts_table_type_column_updateUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1677681143_accounts_table_type_column_update.up.sql", size: 135, mode: os.FileMode(0644), modTime: time.Unix(1685543739, 0)}
|
||||
info := bindataFileInfo{name: "1677681143_accounts_table_type_column_update.up.sql", size: 135, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xd2, 0xc4, 0x6, 0x42, 0x50, 0x1d, 0xf4, 0x48, 0x55, 0xbc, 0xa2, 0x19, 0xdd, 0xad, 0xc8, 0xc, 0xa7, 0x30, 0xb6, 0xaf, 0xe, 0x2b, 0xaa, 0x2a, 0xa4, 0xe1, 0xb9, 0x41, 0x23, 0x66, 0xd3, 0x3}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -1171,7 +1173,7 @@ func _1678264207_accounts_table_new_columns_addedUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1678264207_accounts_table_new_columns_added.up.sql", size: 130, mode: os.FileMode(0644), modTime: time.Unix(1685543739, 0)}
|
||||
info := bindataFileInfo{name: "1678264207_accounts_table_new_columns_added.up.sql", size: 130, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xf4, 0xd4, 0xf3, 0x35, 0xef, 0x5c, 0x19, 0x3c, 0x15, 0x90, 0x60, 0xbd, 0x1f, 0x81, 0xf0, 0x86, 0x73, 0x89, 0xa0, 0x70, 0xf2, 0x46, 0xae, 0xea, 0xd0, 0xc6, 0x9e, 0x55, 0x4a, 0x54, 0x62, 0xbb}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -1191,7 +1193,7 @@ func _1680770368_add_bio_to_settings_sync_clock_tableUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1680770368_add_bio_to_settings_sync_clock_table.up.sql", size: 75, mode: os.FileMode(0644), modTime: time.Unix(1685543739, 0)}
|
||||
info := bindataFileInfo{name: "1680770368_add_bio_to_settings_sync_clock_table.up.sql", size: 75, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x4a, 0x52, 0xf6, 0x3f, 0xaa, 0xd, 0xa0, 0xee, 0xe8, 0xe6, 0x16, 0x21, 0x80, 0x61, 0xe4, 0x7a, 0x4e, 0x37, 0x8d, 0x30, 0x51, 0x20, 0x4d, 0x15, 0x47, 0xfb, 0x6, 0xa1, 0xce, 0xc8, 0x27, 0x5a}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -1211,7 +1213,7 @@ func _1681110436_add_mnemonic_to_settings_sync_clock_tableUpSql() (*asset, error
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1681110436_add_mnemonic_to_settings_sync_clock_table.up.sql", size: 311, mode: os.FileMode(0644), modTime: time.Unix(1685543739, 0)}
|
||||
info := bindataFileInfo{name: "1681110436_add_mnemonic_to_settings_sync_clock_table.up.sql", size: 311, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x3d, 0x74, 0x81, 0x7d, 0x9e, 0x77, 0xb6, 0xfe, 0xe3, 0xcb, 0x48, 0xe5, 0x5f, 0x39, 0x23, 0xa1, 0x7d, 0x53, 0x22, 0xe8, 0x96, 0x15, 0x8a, 0x1e, 0x8e, 0xbc, 0xe2, 0x1d, 0xc4, 0xc2, 0x56, 0x34}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -1231,7 +1233,7 @@ func _1681392602_9d_sync_periodUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1681392602_9d_sync_period.up.sql", size: 60, mode: os.FileMode(0644), modTime: time.Unix(1685543739, 0)}
|
||||
info := bindataFileInfo{name: "1681392602_9d_sync_period.up.sql", size: 60, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xc9, 0xa, 0x90, 0x29, 0x7f, 0x76, 0x98, 0xa7, 0x71, 0x80, 0x5a, 0x2f, 0xbe, 0x23, 0x9a, 0xd4, 0xf4, 0x39, 0x19, 0xd3, 0xa5, 0x34, 0x6e, 0x67, 0x6a, 0xbe, 0x8a, 0xad, 0x21, 0xc7, 0xba, 0x88}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -1251,7 +1253,7 @@ func _1681762078_default_sync_period_9dUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1681762078_default_sync_period_9d.up.sql", size: 3002, mode: os.FileMode(0644), modTime: time.Unix(1685543739, 0)}
|
||||
info := bindataFileInfo{name: "1681762078_default_sync_period_9d.up.sql", size: 3002, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x3e, 0xd9, 0x26, 0xfc, 0xa9, 0x45, 0xc1, 0x81, 0xa8, 0xe2, 0x2c, 0xe9, 0x3c, 0xea, 0x1d, 0x37, 0x11, 0x45, 0x8c, 0x6c, 0xbc, 0xc2, 0x6, 0x69, 0x2, 0x75, 0x29, 0x40, 0x9f, 0xc5, 0xbb, 0x36}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -1271,7 +1273,7 @@ func _1681780680_add_clock_to_social_links_settingsUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1681780680_add_clock_to_social_links_settings.up.sql", size: 137, mode: os.FileMode(0644), modTime: time.Unix(1685543739, 0)}
|
||||
info := bindataFileInfo{name: "1681780680_add_clock_to_social_links_settings.up.sql", size: 137, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x63, 0x11, 0xf5, 0x41, 0xe5, 0x5a, 0xf4, 0xe3, 0xf3, 0x14, 0x87, 0x28, 0xd8, 0xf0, 0x52, 0x31, 0x8, 0xd5, 0xbb, 0xf4, 0xff, 0x55, 0x5f, 0x42, 0x90, 0xcb, 0xf7, 0x46, 0x2, 0x6, 0xbe, 0x42}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -1291,7 +1293,7 @@ func _1682073779_settings_table_remove_latest_derived_path_columnUpSql() (*asset
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1682073779_settings_table_remove_latest_derived_path_column.up.sql", size: 4470, mode: os.FileMode(0644), modTime: time.Unix(1685543739, 0)}
|
||||
info := bindataFileInfo{name: "1682073779_settings_table_remove_latest_derived_path_column.up.sql", size: 4470, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x7a, 0x36, 0x2, 0x41, 0xd, 0x5c, 0xd1, 0x92, 0x85, 0x6d, 0x84, 0xff, 0x67, 0xa7, 0x4c, 0x67, 0xa4, 0xef, 0x52, 0x69, 0x1f, 0x22, 0x25, 0x92, 0xc, 0xb3, 0x89, 0x50, 0x91, 0xc, 0x49, 0xf9}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -1311,7 +1313,7 @@ func _1682146075_add_created_at_to_saved_addressesUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1682146075_add_created_at_to_saved_addresses.up.sql", size: 107, mode: os.FileMode(0644), modTime: time.Unix(1685543739, 0)}
|
||||
info := bindataFileInfo{name: "1682146075_add_created_at_to_saved_addresses.up.sql", size: 107, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x88, 0xfe, 0x35, 0x9c, 0x6b, 0xdf, 0x67, 0x18, 0x16, 0xe4, 0xc9, 0xd4, 0x77, 0x7c, 0x4, 0xe2, 0x6c, 0x41, 0xd9, 0x53, 0x97, 0xfe, 0x5, 0xa3, 0x23, 0xce, 0x82, 0xad, 0x92, 0x5e, 0xd7, 0x7d}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -1331,7 +1333,7 @@ func _1682393575_sync_ens_nameUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1682393575_sync_ens_name.up.sql", size: 713, mode: os.FileMode(0644), modTime: time.Unix(1685543739, 0)}
|
||||
info := bindataFileInfo{name: "1682393575_sync_ens_name.up.sql", size: 713, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xfb, 0xea, 0xcb, 0x4d, 0x71, 0x5a, 0x49, 0x19, 0x8b, 0xef, 0x66, 0x27, 0x33, 0x89, 0xb0, 0xe, 0x37, 0x1b, 0x41, 0x8, 0x12, 0xcc, 0x56, 0xd8, 0x1b, 0xf, 0xf8, 0x50, 0x4b, 0x93, 0xf1, 0x29}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -1351,7 +1353,7 @@ func _1683457503_add_blocks_ranges_sequential_tableUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1683457503_add_blocks_ranges_sequential_table.up.sql", size: 263, mode: os.FileMode(0644), modTime: time.Unix(1685543739, 0)}
|
||||
info := bindataFileInfo{name: "1683457503_add_blocks_ranges_sequential_table.up.sql", size: 263, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xfe, 0x57, 0x2e, 0x0, 0x6a, 0x6e, 0xd7, 0xeb, 0xe6, 0x66, 0x79, 0x32, 0x22, 0x82, 0x92, 0xf4, 0xc9, 0xf1, 0x58, 0x1a, 0x45, 0x60, 0x77, 0x50, 0xe7, 0x54, 0x4a, 0xc0, 0x42, 0x3a, 0x4f, 0x35}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -1371,7 +1373,7 @@ func _1683627613_accounts_and_keycards_improvementsUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1683627613_accounts_and_keycards_improvements.up.sql", size: 3640, mode: os.FileMode(0644), modTime: time.Unix(1685543739, 0)}
|
||||
info := bindataFileInfo{name: "1683627613_accounts_and_keycards_improvements.up.sql", size: 3640, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x8e, 0xbe, 0x62, 0xf5, 0x9, 0x42, 0x8c, 0x8f, 0xa8, 0x45, 0xe7, 0x36, 0xc9, 0xde, 0xf4, 0xe2, 0xfd, 0xc4, 0x8, 0xd0, 0xa3, 0x8, 0x64, 0xe2, 0x56, 0xcc, 0xa7, 0x6d, 0xc5, 0xcc, 0x82, 0x2c}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -1391,7 +1393,7 @@ func _1685041348_settings_table_add_latest_derived_path_columnUpSql() (*asset, e
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1685041348_settings_table_add_latest_derived_path_column.up.sql", size: 115, mode: os.FileMode(0644), modTime: time.Unix(1685543739, 0)}
|
||||
info := bindataFileInfo{name: "1685041348_settings_table_add_latest_derived_path_column.up.sql", size: 115, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x21, 0xd4, 0x1b, 0xbf, 0x8, 0xf9, 0xd4, 0xb0, 0xa0, 0x6, 0x5b, 0xfb, 0x7e, 0xff, 0xfa, 0xbf, 0xcc, 0x64, 0x47, 0x81, 0x8b, 0x5e, 0x17, 0x6a, 0xa7, 0xa4, 0x35, 0x8f, 0x30, 0x4f, 0xd9, 0xd}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -1411,7 +1413,7 @@ func _1685440989_update_color_id_accountsUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1685440989_update_color_id_accounts.up.sql", size: 918, mode: os.FileMode(0644), modTime: time.Unix(1686041617, 0)}
|
||||
info := bindataFileInfo{name: "1685440989_update_color_id_accounts.up.sql", size: 918, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x10, 0x2e, 0x51, 0x1d, 0x2d, 0x16, 0x84, 0xd6, 0xe8, 0xbc, 0x20, 0x53, 0x47, 0xb8, 0x40, 0x21, 0x52, 0x5c, 0xd9, 0xbb, 0xea, 0xe2, 0xa5, 0x77, 0xc8, 0x35, 0x4c, 0xe0, 0x9d, 0x42, 0x44, 0x50}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -1431,7 +1433,7 @@ func _1685463947_add_to_asset_to_multitransactionUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1685463947_add_to_asset_to_multitransaction.up.sql", size: 61, mode: os.FileMode(0644), modTime: time.Unix(1686041617, 0)}
|
||||
info := bindataFileInfo{name: "1685463947_add_to_asset_to_multitransaction.up.sql", size: 61, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xd3, 0x66, 0x15, 0x10, 0xfa, 0x66, 0x81, 0x68, 0xd9, 0xb4, 0x93, 0x9e, 0x11, 0xed, 0x1d, 0x16, 0x9d, 0x5a, 0xf8, 0xd7, 0x8, 0xea, 0x7a, 0xaf, 0xe4, 0xb3, 0x22, 0x19, 0xca, 0xff, 0x75, 0x7c}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -1451,7 +1453,7 @@ func _1685880973_add_profile_links_settings_tableUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1685880973_add_profile_links_settings_table.up.sql", size: 1656, mode: os.FileMode(0644), modTime: time.Unix(1686041617, 0)}
|
||||
info := bindataFileInfo{name: "1685880973_add_profile_links_settings_table.up.sql", size: 1656, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x13, 0x23, 0x7b, 0x1e, 0x82, 0x61, 0xcc, 0x76, 0xd6, 0xc7, 0x42, 0x6e, 0x69, 0x21, 0x1b, 0xfd, 0x7d, 0xda, 0xd7, 0xb7, 0xc7, 0xd3, 0x22, 0x63, 0xfe, 0xc6, 0xd3, 0xdf, 0xc8, 0x5f, 0x50, 0xcc}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -1471,11 +1473,51 @@ func _1686041510_add_idx_transfers_blkno_loadedUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1686041510_add_idx_transfers_blkno_loaded.up.sql", size: 71, mode: os.FileMode(0644), modTime: time.Unix(1686041617, 0)}
|
||||
info := bindataFileInfo{name: "1686041510_add_idx_transfers_blkno_loaded.up.sql", size: 71, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xe2, 0x5d, 0x7e, 0x43, 0x14, 0x3c, 0x50, 0x44, 0x25, 0xd0, 0xe1, 0x75, 0xba, 0x61, 0x7b, 0x68, 0x2e, 0x43, 0x74, 0x1d, 0x10, 0x61, 0x8e, 0x45, 0xe6, 0x25, 0x78, 0x81, 0x68, 0x6, 0x24, 0x5b}}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var __1686048341_transfers_receipt_json_blob_outUpSqlDownSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x44\xcb\xc1\x0d\xc2\x30\x0c\x46\xe1\x55\xfe\x05\xc2\x1a\x88\x13\x17\x16\x30\xc1\x21\x16\xc1\xae\x6c\x37\x52\xb7\xaf\x72\xea\xed\x49\x4f\x5f\x29\x78\x75\x09\xfc\xe5\xeb\x94\x62\x0a\x09\x88\xe2\xfe\x44\xb5\x0f\xdf\xf0\x68\xab\xaf\xdd\x48\x46\x20\x97\x61\x4d\x3f\x10\xec\x93\x03\x14\x70\x1b\xe3\x4d\xf5\x87\x34\x64\x67\x6c\xce\x53\x6c\x0f\x98\xf2\x19\x00\x00\xff\xff\x4e\x62\x72\x83\x68\x00\x00\x00")
|
||||
|
||||
func _1686048341_transfers_receipt_json_blob_outUpSqlDownSqlBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
__1686048341_transfers_receipt_json_blob_outUpSqlDownSql,
|
||||
"1686048341_transfers_receipt_json_blob_out.up.sql.down.sql",
|
||||
)
|
||||
}
|
||||
|
||||
func _1686048341_transfers_receipt_json_blob_outUpSqlDownSql() (*asset, error) {
|
||||
bytes, err := _1686048341_transfers_receipt_json_blob_outUpSqlDownSqlBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1686048341_transfers_receipt_json_blob_out.up.sql.down.sql", size: 104, mode: os.FileMode(0644), modTime: time.Unix(1686147405, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x9f, 0x6c, 0xd9, 0x76, 0x83, 0x64, 0xf0, 0xf2, 0x74, 0x97, 0xca, 0xd7, 0xaa, 0x4, 0x74, 0x7c, 0x34, 0x56, 0x88, 0x10, 0xa9, 0x4d, 0x1d, 0x8e, 0x85, 0xc3, 0x66, 0x1, 0x2b, 0x30, 0x90, 0xf4}}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var __1686048341_transfers_receipt_json_blob_outUpSqlUpSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x9c\x94\x41\x6f\x9b\x4e\x10\xc5\xef\xf9\x14\x73\x4c\xa4\x24\x7f\xfd\xd3\xaa\xaa\x9a\x13\x8e\x51\xea\xca\x05\xc9\x25\x6a\x6e\x74\xbc\x3b\x98\xad\x97\x1d\xb4\x33\x24\xa4\x9f\xbe\x32\xb6\x53\xb7\x27\xc8\x0d\x2d\xf3\x7b\x6f\x61\xf7\xbd\xab\x2b\x28\x6a\x27\xd0\xb8\x4d\x44\x75\x1c\xc0\x09\x58\x0e\x04\x2e\xc0\x7d\x0e\x86\x2d\x01\x0a\x20\x98\x4e\x94\x1b\x10\xa5\xf6\xfa\xec\x88\x55\xce\x13\x08\xc5\x27\x92\x61\x2a\x00\x06\x53\x73\x84\x8a\x23\x68\x4d\x27\xba\xf2\x22\x4a\xcd\x8e\xbc\xab\xc9\x6c\x0f\x6f\xe8\x3b\x7a\x4f\xfa\x45\x38\xcc\x3c\xaf\x05\xaa\xc8\x0d\x60\xdb\x5a\x54\x5c\xa3\xd0\x7f\xc7\x87\xeb\x0d\x9f\xed\x7d\x09\x2a\xf6\x9e\x9f\x5d\xd8\x0c\xdb\x11\xc0\x48\xff\x6e\xfa\xd3\x30\x9c\x2c\x8b\x74\x05\x45\x32\x5b\xa6\xa0\x11\x83\x54\x14\x05\x92\xf9\x1c\xee\xf2\xe5\xc3\xd7\x0c\x44\x51\x3b\x81\x45\x56\xdc\x8e\x9a\x8f\x64\xc8\xb5\x5a\xea\x4b\x4b\xe3\x29\xed\xcb\x1a\xa5\x86\xd9\x32\x9f\x8d\x23\x3c\x6f\x4a\x17\x2c\xf5\xe3\x4d\xd6\x9e\xcd\x76\xaa\x8f\xe9\x9a\xce\xa3\xba\x27\x2a\x37\x28\x65\x27\x64\xc7\x3b\x1a\x0e\x1a\xd1\x68\x89\xd6\x46\x12\x81\x22\x7d\x1c\x89\x4e\x37\xd3\xfe\xf4\x87\x8c\x45\xa6\x9d\x53\x1b\x59\xc9\x28\x59\x98\xe5\xf9\x32\x4d\xb2\xf1\x1f\xe3\x5d\xe3\x14\x1e\xb2\x6f\x8b\xfb\x2c\x9d\x8f\xb7\xdc\xb1\x6d\x74\x86\x4a\xe3\xb1\x69\xc9\x7e\x78\x3f\x0d\x56\xd7\x96\x06\xdb\xb7\xe2\x15\xd1\x5b\x71\x6c\xb8\x0b\x5a\xb6\x68\x2d\xd9\xff\x6f\x3e\xd6\xd4\xc3\xdd\xe7\x64\x75\xfe\xee\xe6\x62\xa4\x82\x31\x83\x44\xe0\x60\x26\x1c\x93\xb8\x5f\x53\xc2\xc7\x5b\x0a\xaf\x57\x74\x7c\x34\xf6\x9c\xb3\x07\x64\x68\xae\x55\x9a\x14\x29\x2c\xb2\x79\xfa\xf8\x07\x2a\x2b\xe7\x95\x22\xe4\xd9\x89\xd0\xf9\xbe\x59\x2e\xff\xb6\xbf\x7c\x55\xbd\xb8\xfd\x31\x48\xa6\xfd\x10\x21\xd0\x1e\x30\xd8\x63\xbf\xc0\xae\xf5\xf6\x5d\xb8\x6b\xd1\x9f\xc2\x61\x97\xef\xf5\x30\x83\xd6\x0e\xab\x2e\x54\x1c\x9b\x43\x6b\x07\xe5\x61\x31\xd0\x33\x18\xf6\x5d\x13\xe4\x77\x00\x00\x00\xff\xff\x39\x7c\x13\x6d\xdc\x05\x00\x00")
|
||||
|
||||
func _1686048341_transfers_receipt_json_blob_outUpSqlUpSqlBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
__1686048341_transfers_receipt_json_blob_outUpSqlUpSql,
|
||||
"1686048341_transfers_receipt_json_blob_out.up.sql.up.sql",
|
||||
)
|
||||
}
|
||||
|
||||
func _1686048341_transfers_receipt_json_blob_outUpSqlUpSql() (*asset, error) {
|
||||
bytes, err := _1686048341_transfers_receipt_json_blob_outUpSqlUpSqlBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1686048341_transfers_receipt_json_blob_out.up.sql.up.sql", size: 1500, mode: os.FileMode(0644), modTime: time.Unix(1686147405, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x49, 0xcd, 0xe3, 0xa6, 0x8c, 0x53, 0x51, 0xe6, 0x3c, 0x64, 0xcb, 0x3, 0x3, 0xb, 0x4d, 0x52, 0xa5, 0x1c, 0xcc, 0xe1, 0x23, 0x94, 0x14, 0x79, 0xd7, 0x56, 0x58, 0xef, 0xcc, 0x1a, 0x6, 0xa4}}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var _docGo = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x2c\xc9\xb1\x0d\xc4\x20\x0c\x05\xd0\x9e\x29\xfe\x02\xd8\xfd\x6d\xe3\x4b\xac\x2f\x44\x82\x09\x78\x7f\xa5\x49\xfd\xa6\x1d\xdd\xe8\xd8\xcf\x55\x8a\x2a\xe3\x47\x1f\xbe\x2c\x1d\x8c\xfa\x6f\xe3\xb4\x34\xd4\xd9\x89\xbb\x71\x59\xb6\x18\x1b\x35\x20\xa2\x9f\x0a\x03\xa2\xe5\x0d\x00\x00\xff\xff\x60\xcd\x06\xbe\x4a\x00\x00\x00")
|
||||
|
||||
func docGoBytes() ([]byte, error) {
|
||||
|
@ -1491,7 +1533,7 @@ func docGo() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "doc.go", size: 74, mode: os.FileMode(0644), modTime: time.Unix(1685543739, 0)}
|
||||
info := bindataFileInfo{name: "doc.go", size: 74, mode: os.FileMode(0644), modTime: time.Unix(1686145633, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xde, 0x7c, 0x28, 0xcd, 0x47, 0xf2, 0xfa, 0x7c, 0x51, 0x2d, 0xd8, 0x38, 0xb, 0xb0, 0x34, 0x9d, 0x4c, 0x62, 0xa, 0x9e, 0x28, 0xc3, 0x31, 0x23, 0xd9, 0xbb, 0x89, 0x9f, 0xa0, 0x89, 0x1f, 0xe8}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -1721,6 +1763,10 @@ var _bindata = map[string]func() (*asset, error){
|
|||
|
||||
"1686041510_add_idx_transfers_blkno_loaded.up.sql": _1686041510_add_idx_transfers_blkno_loadedUpSql,
|
||||
|
||||
"1686048341_transfers_receipt_json_blob_out.up.sql.down.sql": _1686048341_transfers_receipt_json_blob_outUpSqlDownSql,
|
||||
|
||||
"1686048341_transfers_receipt_json_blob_out.up.sql.up.sql": _1686048341_transfers_receipt_json_blob_outUpSqlUpSql,
|
||||
|
||||
"doc.go": docGo,
|
||||
}
|
||||
|
||||
|
@ -1832,6 +1878,8 @@ var _bintree = &bintree{nil, map[string]*bintree{
|
|||
"1685463947_add_to_asset_to_multitransaction.up.sql": &bintree{_1685463947_add_to_asset_to_multitransactionUpSql, map[string]*bintree{}},
|
||||
"1685880973_add_profile_links_settings_table.up.sql": &bintree{_1685880973_add_profile_links_settings_tableUpSql, map[string]*bintree{}},
|
||||
"1686041510_add_idx_transfers_blkno_loaded.up.sql": &bintree{_1686041510_add_idx_transfers_blkno_loadedUpSql, map[string]*bintree{}},
|
||||
"1686048341_transfers_receipt_json_blob_out.up.sql.down.sql": &bintree{_1686048341_transfers_receipt_json_blob_outUpSqlDownSql, map[string]*bintree{}},
|
||||
"1686048341_transfers_receipt_json_blob_out.up.sql.up.sql": &bintree{_1686048341_transfers_receipt_json_blob_outUpSqlUpSql, map[string]*bintree{}},
|
||||
"doc.go": &bintree{docGo, map[string]*bintree{}},
|
||||
}}
|
||||
|
||||
|
|
|
@ -9,11 +9,22 @@ import (
|
|||
)
|
||||
|
||||
// Migrate applies migrations.
|
||||
func Migrate(db *sql.DB) error {
|
||||
// see Migrate in vendor/status-go/sqlite/migrate.go
|
||||
func Migrate(db *sql.DB, customSteps []sqlite.PostStep) error {
|
||||
return sqlite.Migrate(db, bindata.Resource(
|
||||
AssetNames(),
|
||||
func(name string) ([]byte, error) {
|
||||
return Asset(name)
|
||||
},
|
||||
))
|
||||
), customSteps, nil)
|
||||
}
|
||||
|
||||
// MigrateTo is used for testing purposes
|
||||
func MigrateTo(db *sql.DB, customSteps []sqlite.PostStep, untilVersion uint) error {
|
||||
return sqlite.Migrate(db, bindata.Resource(
|
||||
AssetNames(),
|
||||
func(name string) ([]byte, error) {
|
||||
return Asset(name)
|
||||
},
|
||||
), customSteps, &untilVersion)
|
||||
}
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
-- This migration is in GO code. If GO migration fails this entry serves as rollback to the previous one
|
|
@ -0,0 +1,31 @@
|
|||
-- This migration is done in GO code as a custom step.
|
||||
-- This file serves as an anchor for the migration system
|
||||
-- Check migrateWalletJsonBlobs from appdatabase/database.go
|
||||
|
||||
-- The following steps are done in GO code:
|
||||
|
||||
-- ALTER TABLE transfers ADD COLUMN status INT;
|
||||
-- ALTER TABLE transfers ADD COLUMN receipt_type INT;
|
||||
-- ALTER TABLE transfers ADD COLUMN tx_hash BLOB;
|
||||
-- ALTER TABLE transfers ADD COLUMN log_index INT;
|
||||
-- ALTER TABLE transfers ADD COLUMN block_hash BLOB;
|
||||
-- ALTER TABLE transfers ADD COLUMN cumulative_gas_used INT;
|
||||
-- ALTER TABLE transfers ADD COLUMN contract_address TEXT;
|
||||
-- ALTER TABLE transfers ADD COLUMN gas_used INT;
|
||||
-- ALTER TABLE transfers ADD COLUMN tx_index INT;
|
||||
|
||||
-- ALTER TABLE transfers ADD COLUMN tx_type INT;
|
||||
-- ALTER TABLE transfers ADD COLUMN protected BOOLEAN;
|
||||
-- ALTER TABLE transfers ADD COLUMN gas_limit UNSIGNED INT;
|
||||
-- ALTER TABLE transfers ADD COLUMN gas_price_clamped64 INT;
|
||||
-- ALTER TABLE transfers ADD COLUMN gas_tip_cap_clamped64 INT;
|
||||
-- ALTER TABLE transfers ADD COLUMN gas_fee_cap_clamped64 INT;
|
||||
-- ALTER TABLE transfers ADD COLUMN amount_padded128hex CHAR(32);
|
||||
-- ALTER TABLE transfers ADD COLUMN account_nonce INT;
|
||||
-- ALTER TABLE transfers ADD COLUMN size INT;
|
||||
-- ALTER TABLE transfers ADD COLUMN token_address BLOB;
|
||||
-- ALTER TABLE transfers ADD COLUMN token_id BLOB;
|
||||
|
||||
-- CREATE INDEX transfers_filter ON transfers (status, token_address, token_id);`
|
||||
|
||||
-- Extract tx and receipt data from the json blob and add the information into the new columns
|
|
@ -15,5 +15,5 @@ func Migrate(db *sql.DB) error {
|
|||
func(name string) ([]byte, error) {
|
||||
return Asset(name)
|
||||
},
|
||||
))
|
||||
), nil, nil)
|
||||
}
|
||||
|
|
|
@ -38,3 +38,34 @@ func SetupTestMemorySQLDB(prefix string) (*sql.DB, error) {
|
|||
|
||||
return db, nil
|
||||
}
|
||||
|
||||
func ColumnExists(db *sql.DB, tableName string, columnName string) (bool, error) {
|
||||
rows, err := db.Query("PRAGMA table_info(" + tableName + ")")
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var cid int
|
||||
var name string
|
||||
var dataType string
|
||||
var notNull bool
|
||||
var dFLTValue sql.NullString
|
||||
var pk int
|
||||
|
||||
for rows.Next() {
|
||||
err := rows.Scan(&cid, &name, &dataType, ¬Null, &dFLTValue, &pk)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if name == columnName {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
|
||||
if rows.Err() != nil {
|
||||
return false, rows.Err()
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
|
|
@ -102,7 +102,7 @@ func InitializeDB(path string) (*Database, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = migrations.Migrate(db)
|
||||
err = migrations.Migrate(db, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -9,11 +9,12 @@ import (
|
|||
)
|
||||
|
||||
// Migrate applies migrations.
|
||||
func Migrate(db *sql.DB) error {
|
||||
// see Migrate in vendor/status-go/sqlite/migrate.go
|
||||
func Migrate(db *sql.DB, customSteps []sqlite.PostStep) error {
|
||||
return sqlite.Migrate(db, bindata.Resource(
|
||||
AssetNames(),
|
||||
func(name string) ([]byte, error) {
|
||||
return Asset(name)
|
||||
},
|
||||
))
|
||||
), customSteps, nil)
|
||||
}
|
||||
|
|
|
@ -152,7 +152,7 @@ func WithDatabase(db *sql.DB) Option {
|
|||
func WithToplevelDatabaseMigrations() Option {
|
||||
return func(c *config) error {
|
||||
c.afterDbCreatedHooks = append(c.afterDbCreatedHooks, func(c *config) error {
|
||||
return migrations.Migrate(c.db)
|
||||
return migrations.Migrate(c.db, nil)
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -48,8 +48,8 @@ import (
|
|||
localnotifications "github.com/status-im/status-go/services/local-notifications"
|
||||
mailserversDB "github.com/status-im/status-go/services/mailservers"
|
||||
"github.com/status-im/status-go/services/wallet"
|
||||
w_common "github.com/status-im/status-go/services/wallet/common"
|
||||
"github.com/status-im/status-go/services/wallet/thirdparty"
|
||||
"github.com/status-im/status-go/services/wallet/transfer"
|
||||
)
|
||||
|
||||
// EnvelopeEventsHandler used for two different event types.
|
||||
|
@ -296,7 +296,7 @@ func (c *verifyTransactionClient) TransactionByHash(ctx context.Context, hash ty
|
|||
|
||||
// Token transfer, check the logs
|
||||
if len(coremessage.Data()) != 0 {
|
||||
if transfer.IsTokenTransfer(receipt.Logs) {
|
||||
if w_common.IsTokenTransfer(receipt.Logs) {
|
||||
return coremessage, coretypes.TransactionStatus(receipt.Status), nil
|
||||
}
|
||||
return coremessage, coretypes.TransactionStatusFailed, nil
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
w_common "github.com/status-im/status-go/services/wallet/common"
|
||||
"github.com/status-im/status-go/services/wallet/transfer"
|
||||
"github.com/status-im/status-go/services/wallet/walletevent"
|
||||
"github.com/status-im/status-go/signal"
|
||||
|
@ -99,7 +100,7 @@ func TestTransactionNotification(t *testing.T) {
|
|||
transfers := []transfer.Transfer{
|
||||
{
|
||||
ID: common.Hash{1},
|
||||
Type: transfer.Type("eth"),
|
||||
Type: w_common.Type("eth"),
|
||||
BlockHash: header.Hash,
|
||||
BlockNumber: header.Number,
|
||||
Transaction: tx,
|
||||
|
|
|
@ -0,0 +1,157 @@
|
|||
# DB extension and refactoring for activity
|
||||
|
||||
## Work in progress
|
||||
|
||||
| | Buy | Swap | Bridge | Send/Receive |
|
||||
| ------------- | -------------- | -------------- | ------------- | ------------- |
|
||||
| Activity data | ~~API~~ ~~DB~~ | ~~API~~ ~~DB~~ | _API_ _DB_ | _API_ _DB_ |
|
||||
| Raw data | ~~API~~ ~~DB~~ | ~~API~~ ~~DB~~ | _API_ _DB_ | _API_ _DB_ |
|
||||
| Pending data | ~~API~~ ~~DB~~ | ~~API~~ ~~DB~~ | _API_ _DB_ | _API_ _DB_ |
|
||||
|
||||
Legend:
|
||||
|
||||
- ~~API~~ - not much or at all provided
|
||||
- _API_ - partially provided
|
||||
- API - complete
|
||||
|
||||
### Summary
|
||||
|
||||
Improve on the identified limitations
|
||||
|
||||
- [ ] Missing filtering data
|
||||
- [x] Missing cached (not extracted as a column)
|
||||
- Extracting the data from the raw data is expensive but might be negligible given that usually we should not expect more than 20 entries per second in the worst case scenario.
|
||||
- [x] Table extensions
|
||||
- ~~Activity specific info in activity data store (multi_transaction table)~~
|
||||
- Activity specific info in in the transactions data store (transfers table)
|
||||
|
||||
### Missing data
|
||||
|
||||
Filter requirements
|
||||
|
||||
- [ ] Activity operation status
|
||||
- [ ] `pending`: have to aggregate for `Buy`, `Swap`, `Bridge`
|
||||
- already there for `Send`, `Receive`
|
||||
- [ ] `complete`: only extract and check for `status` in the `receipt` for `Send`, `Receive`
|
||||
- For complex operations aggregate the `complete` status `Buy`, `Swap`, `Bridge`
|
||||
- [ ] `finalized`: similar to `complete` for `Send`, `Receive`
|
||||
- all sub-transactions are `complete` for `Buy`, `Swap`, `Bridge`
|
||||
- [ ] `failed`: extract from `status` for all sub-transactions
|
||||
- [ ] `chainID`: aggregate data for activity entries `Bridge`, `Buy`, `Swap`
|
||||
- [ ] `tokenCode` for activity entries `Send`, `Receive`
|
||||
- For `Bridge` its already there and `Buy`, `Swap` is coming soon
|
||||
- [ ] `collectibles`: require adding collectible attributes to activity data (probably `token_address` and `tokenId`)
|
||||
|
||||
UX requirements
|
||||
|
||||
- [ ] `status`: for status icon and label
|
||||
- [ ] `chainIDs`: for chain icons
|
||||
- Missing for `Bridge`, `Buy`, `Swap`
|
||||
- [ ] `amount`s: add to the activity.Entry
|
||||
- already in DB
|
||||
- [ ] `tokenCode`s: add to the activity.Entry
|
||||
- already in DB
|
||||
- [ ] `to`/`from`/`owner`: add to the activity.Entry
|
||||
- already in DB, coming soon
|
||||
- [ ] `tokenIdentity`: collectible is missing (`chainId`, `address`, `tokenId`)
|
||||
- `tokenCode` should be covering fungible operations
|
||||
- [x] `identity`: for all the sources
|
||||
- [x] `type`: for the main icon and label
|
||||
- [x] `time`: timestamp
|
||||
|
||||
### Refactoring
|
||||
|
||||
## Current state
|
||||
|
||||
### Transfers Table
|
||||
|
||||
The `transfers` transactions raw data
|
||||
|
||||
- Transaction identity: `network_id`, `hash`, `address`
|
||||
- Implementation by `sqlite_autoindex_transfers_1` unique index
|
||||
- `multi_transaction_id`: `multi_transaction` entries to `transfers` entries mapping (one to many)
|
||||
- Raw data:
|
||||
- `tx` transaction
|
||||
- `receipt`: transfer receipt
|
||||
|
||||
### Multi-Transaction Table
|
||||
|
||||
Represented by `multi_transaction`
|
||||
|
||||
Responsibilities
|
||||
|
||||
- UX metadata for transactions originating from our APP.
|
||||
- `from_address`, `to_address`
|
||||
- `from_asset`, `to_asset`
|
||||
- `from_amount`, `to_amount` (token codes)
|
||||
- `type` identifies the type (initially only Send and Bridge)
|
||||
- `timestamp` the timestamp of the execution
|
||||
- Multi-transaction to sub-transaction mapping
|
||||
- The `multi_transaction_id` in the `transfers` and `pending_transaction` table corresponds to the `ROWID` in the `multi_transactions`.
|
||||
|
||||
### Pending Transactions Table
|
||||
|
||||
The `pending_transactions` table represents transactions initiated from the app
|
||||
|
||||
- Transaction identity
|
||||
- `network_id`, `hash`
|
||||
- implemented by the `sqlite_autoindex_pending_transactions_1` index
|
||||
- Note how this is different from the `transfers` table, where the `address` is also part of the identity.
|
||||
- `timestamp`: The timestamp of the pending transaction.
|
||||
- `multi_transaction_id`: `multi_transaction` entries to `pending_transactions` entries mapping (one to many)
|
||||
|
||||
### Schema
|
||||
|
||||
Relationships between the tables
|
||||
|
||||
```mermaid
|
||||
erDiagram
|
||||
multi_transaction ||--o{ transfers : has
|
||||
multi_transaction ||--o{ pending_transactions : has
|
||||
transfers {
|
||||
network_id BIGINT
|
||||
hash VARCHAR
|
||||
timestamp BIGINT
|
||||
multi_transaction_id INT
|
||||
tx BLOB
|
||||
receipt BLOB
|
||||
log BLOB
|
||||
}
|
||||
multi_transaction {
|
||||
ROWID INT
|
||||
type VARCHAR
|
||||
}
|
||||
pending_transactions {
|
||||
network_id BIGINT
|
||||
hash VARCHAR
|
||||
timestamp INT
|
||||
multi_transaction_id INT
|
||||
}
|
||||
```
|
||||
|
||||
### Dropped tasks
|
||||
|
||||
Dropped the DB refactoring and improvements after further discussion and concerns
|
||||
|
||||
- [x] Terminology proposal
|
||||
- [x] using `transactions` instead of `transfers` for the raw data
|
||||
- [x] using `activity` instead of `multi-transaction` to better match the new requirements
|
||||
- [x] Convert JSON blobs into structured data
|
||||
|
||||
Dropped benchmark performance and move on using theoretical knowledge by adding indexes for what we know only
|
||||
Will leave the performance concerns for the next milestone
|
||||
|
||||
- [ ] Joining DBs
|
||||
- [ ] One activity DB for all require metadata
|
||||
- Pros:
|
||||
- Faster to query (don't know the numbers)
|
||||
- Simpler query will decrease maintenance
|
||||
- Cons:
|
||||
- have to migrate all data, extract and fill the activity on every download of updates for all activities
|
||||
- [ ] Keep only filter specific metadata in the Activity DB
|
||||
- Pros:
|
||||
- Less changes to migrate existing data. Still have to maintain activity filtering specific data
|
||||
- Cons:
|
||||
- Slower to query (don't know how much yet)
|
||||
- Complex query increases maintenance
|
||||
|
|
@ -19,9 +19,7 @@ import (
|
|||
|
||||
type PayloadType = int
|
||||
|
||||
// Beware if adding/removing please check if affected and update the functions below
|
||||
// - NewActivityEntryWithTransaction
|
||||
// - multiTransactionTypeToActivityType
|
||||
// Beware: pleas update multiTransactionTypeToActivityType if changing this enum
|
||||
const (
|
||||
MultiTransactionPT PayloadType = iota + 1
|
||||
SimpleTransactionPT
|
||||
|
@ -75,9 +73,18 @@ func (e *Entry) UnmarshalJSON(data []byte) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func NewActivityEntryWithTransaction(payloadType PayloadType, transaction *transfer.TransactionIdentity, timestamp int64, activityType Type, activityStatus Status) Entry {
|
||||
if payloadType != SimpleTransactionPT && payloadType != PendingTransactionPT {
|
||||
panic("invalid transaction type")
|
||||
func newActivityEntryWithPendingTransaction(transaction *transfer.TransactionIdentity, timestamp int64, activityType Type, activityStatus Status) Entry {
|
||||
return newActivityEntryWithTransaction(true, transaction, timestamp, activityType, activityStatus)
|
||||
}
|
||||
|
||||
func newActivityEntryWithSimpleTransaction(transaction *transfer.TransactionIdentity, timestamp int64, activityType Type, activityStatus Status) Entry {
|
||||
return newActivityEntryWithTransaction(false, transaction, timestamp, activityType, activityStatus)
|
||||
}
|
||||
|
||||
func newActivityEntryWithTransaction(pending bool, transaction *transfer.TransactionIdentity, timestamp int64, activityType Type, activityStatus Status) Entry {
|
||||
payloadType := SimpleTransactionPT
|
||||
if pending {
|
||||
payloadType = PendingTransactionPT
|
||||
}
|
||||
|
||||
return Entry{
|
||||
|
@ -442,14 +449,13 @@ func GetActivityEntries(db *sql.DB, addresses []eth.Address, chainIDs []common.C
|
|||
// TODO: extend DB with status in order to filter by status. The status has to be extracted from the receipt upon downloading
|
||||
activityStatus := FinalizedAS
|
||||
activityType, filteredAddress := getActivityType(dbTrType)
|
||||
entry = NewActivityEntryWithTransaction(SimpleTransactionPT,
|
||||
entry = newActivityEntryWithSimpleTransaction(
|
||||
&transfer.TransactionIdentity{ChainID: common.ChainID(chainID.Int64), Hash: eth.BytesToHash(transferHash), Address: filteredAddress},
|
||||
timestamp, activityType, activityStatus)
|
||||
} else if pendingHash != nil && chainID.Valid {
|
||||
activityStatus := PendingAS
|
||||
activityType, _ := getActivityType(dbTrType)
|
||||
entry = NewActivityEntryWithTransaction(PendingTransactionPT,
|
||||
&transfer.TransactionIdentity{ChainID: common.ChainID(chainID.Int64), Hash: eth.BytesToHash(pendingHash)},
|
||||
entry = newActivityEntryWithPendingTransaction(&transfer.TransactionIdentity{ChainID: common.ChainID(chainID.Int64), Hash: eth.BytesToHash(pendingHash)},
|
||||
timestamp, activityType, activityStatus)
|
||||
} else if multiTxID.Valid {
|
||||
activityType := multiTransactionTypeToActivityType(transfer.MultiTransactionType(dbMtType.Byte))
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
package transfer
|
||||
// Moved here because transactions package depends on accounts package which
|
||||
// depends on appdatabase where this functionality is needed
|
||||
package common
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
@ -6,6 +8,7 @@ import (
|
|||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
)
|
||||
|
||||
|
@ -17,21 +20,21 @@ type EventType string
|
|||
|
||||
const (
|
||||
// Transaction types
|
||||
ethTransfer Type = "eth"
|
||||
erc20Transfer Type = "erc20"
|
||||
erc721Transfer Type = "erc721"
|
||||
uniswapV2Swap Type = "uniswapV2Swap"
|
||||
uniswapV3Swap Type = "uniswapV3Swap"
|
||||
EthTransfer Type = "eth"
|
||||
Erc20Transfer Type = "erc20"
|
||||
Erc721Transfer Type = "erc721"
|
||||
UniswapV2Swap Type = "uniswapV2Swap"
|
||||
UniswapV3Swap Type = "uniswapV3Swap"
|
||||
unknownTransaction Type = "unknown"
|
||||
|
||||
// Event types
|
||||
erc20TransferEventType EventType = "erc20Event"
|
||||
erc721TransferEventType EventType = "erc721Event"
|
||||
uniswapV2SwapEventType EventType = "uniswapV2SwapEvent"
|
||||
uniswapV3SwapEventType EventType = "uniswapV3SwapEvent"
|
||||
unknownEventType EventType = "unknownEvent"
|
||||
Erc20TransferEventType EventType = "erc20Event"
|
||||
Erc721TransferEventType EventType = "erc721Event"
|
||||
UniswapV2SwapEventType EventType = "uniswapV2SwapEvent"
|
||||
UniswapV3SwapEventType EventType = "uniswapV3SwapEvent"
|
||||
UnknownEventType EventType = "unknownEvent"
|
||||
|
||||
erc20_721TransferEventSignature = "Transfer(address,address,uint256)"
|
||||
Erc20_721TransferEventSignature = "Transfer(address,address,uint256)"
|
||||
|
||||
erc20TransferEventIndexedParameters = 3 // signature, from, to
|
||||
erc721TransferEventIndexedParameters = 4 // signature, from, to, tokenId
|
||||
|
@ -47,39 +50,39 @@ var (
|
|||
|
||||
// Detect event type for a cetain item from the Events Log
|
||||
func GetEventType(log *types.Log) EventType {
|
||||
erc20_721TransferEventSignatureHash := getEventSignatureHash(erc20_721TransferEventSignature)
|
||||
uniswapV2SwapEventSignatureHash := getEventSignatureHash(uniswapV2SwapEventSignature)
|
||||
uniswapV3SwapEventSignatureHash := getEventSignatureHash(uniswapV3SwapEventSignature)
|
||||
erc20_721TransferEventSignatureHash := GetEventSignatureHash(Erc20_721TransferEventSignature)
|
||||
uniswapV2SwapEventSignatureHash := GetEventSignatureHash(uniswapV2SwapEventSignature)
|
||||
uniswapV3SwapEventSignatureHash := GetEventSignatureHash(uniswapV3SwapEventSignature)
|
||||
|
||||
if len(log.Topics) > 0 {
|
||||
switch log.Topics[0] {
|
||||
case erc20_721TransferEventSignatureHash:
|
||||
switch len(log.Topics) {
|
||||
case erc20TransferEventIndexedParameters:
|
||||
return erc20TransferEventType
|
||||
return Erc20TransferEventType
|
||||
case erc721TransferEventIndexedParameters:
|
||||
return erc721TransferEventType
|
||||
return Erc721TransferEventType
|
||||
}
|
||||
case uniswapV2SwapEventSignatureHash:
|
||||
return uniswapV2SwapEventType
|
||||
return UniswapV2SwapEventType
|
||||
case uniswapV3SwapEventSignatureHash:
|
||||
return uniswapV3SwapEventType
|
||||
return UniswapV3SwapEventType
|
||||
}
|
||||
}
|
||||
|
||||
return unknownEventType
|
||||
return UnknownEventType
|
||||
}
|
||||
|
||||
func EventTypeToSubtransactionType(eventType EventType) Type {
|
||||
switch eventType {
|
||||
case erc20TransferEventType:
|
||||
return erc20Transfer
|
||||
case erc721TransferEventType:
|
||||
return erc721Transfer
|
||||
case uniswapV2SwapEventType:
|
||||
return uniswapV2Swap
|
||||
case uniswapV3SwapEventType:
|
||||
return uniswapV3Swap
|
||||
case Erc20TransferEventType:
|
||||
return Erc20Transfer
|
||||
case Erc721TransferEventType:
|
||||
return Erc721Transfer
|
||||
case UniswapV2SwapEventType:
|
||||
return UniswapV2Swap
|
||||
case UniswapV3SwapEventType:
|
||||
return UniswapV3Swap
|
||||
}
|
||||
|
||||
return unknownTransaction
|
||||
|
@ -88,20 +91,20 @@ func EventTypeToSubtransactionType(eventType EventType) Type {
|
|||
func GetFirstEvent(logs []*types.Log) (EventType, *types.Log) {
|
||||
for _, log := range logs {
|
||||
eventType := GetEventType(log)
|
||||
if eventType != unknownEventType {
|
||||
if eventType != UnknownEventType {
|
||||
return eventType, log
|
||||
}
|
||||
}
|
||||
|
||||
return unknownEventType, nil
|
||||
return UnknownEventType, nil
|
||||
}
|
||||
|
||||
func IsTokenTransfer(logs []*types.Log) bool {
|
||||
eventType, _ := GetFirstEvent(logs)
|
||||
return eventType == erc20TransferEventType
|
||||
return eventType == Erc20TransferEventType
|
||||
}
|
||||
|
||||
func parseErc20TransferLog(ethlog *types.Log) (from, to common.Address, amount *big.Int) {
|
||||
func ParseErc20TransferLog(ethlog *types.Log) (from, to common.Address, amount *big.Int) {
|
||||
amount = new(big.Int)
|
||||
if len(ethlog.Topics) < 3 {
|
||||
log.Warn("not enough topics for erc20 transfer", "topics", ethlog.Topics)
|
||||
|
@ -126,7 +129,7 @@ func parseErc20TransferLog(ethlog *types.Log) (from, to common.Address, amount *
|
|||
return
|
||||
}
|
||||
|
||||
func parseErc721TransferLog(ethlog *types.Log) (from, to common.Address, tokenID *big.Int) {
|
||||
func ParseErc721TransferLog(ethlog *types.Log) (from, to common.Address, tokenID *big.Int) {
|
||||
tokenID = new(big.Int)
|
||||
if len(ethlog.Topics) < 4 {
|
||||
log.Warn("not enough topics for erc721 transfer", "topics", ethlog.Topics)
|
||||
|
@ -151,7 +154,7 @@ func parseErc721TransferLog(ethlog *types.Log) (from, to common.Address, tokenID
|
|||
return
|
||||
}
|
||||
|
||||
func parseUniswapV2Log(ethlog *types.Log) (pairAddress common.Address, from common.Address, to common.Address, amount0In *big.Int, amount1In *big.Int, amount0Out *big.Int, amount1Out *big.Int, err error) {
|
||||
func ParseUniswapV2Log(ethlog *types.Log) (pairAddress common.Address, from common.Address, to common.Address, amount0In *big.Int, amount1In *big.Int, amount0Out *big.Int, amount1Out *big.Int, err error) {
|
||||
amount0In = new(big.Int)
|
||||
amount1In = new(big.Int)
|
||||
amount0Out = new(big.Int)
|
||||
|
@ -199,7 +202,7 @@ func readInt256(b []byte) *big.Int {
|
|||
return ret
|
||||
}
|
||||
|
||||
func parseUniswapV3Log(ethlog *types.Log) (poolAddress common.Address, sender common.Address, recipient common.Address, amount0 *big.Int, amount1 *big.Int, err error) {
|
||||
func ParseUniswapV3Log(ethlog *types.Log) (poolAddress common.Address, sender common.Address, recipient common.Address, amount0 *big.Int, amount1 *big.Int, err error) {
|
||||
amount0 = new(big.Int)
|
||||
amount1 = new(big.Int)
|
||||
|
||||
|
@ -229,3 +232,35 @@ func parseUniswapV3Log(ethlog *types.Log) (poolAddress common.Address, sender co
|
|||
|
||||
return
|
||||
}
|
||||
|
||||
func GetEventSignatureHash(signature string) common.Hash {
|
||||
return crypto.Keccak256Hash([]byte(signature))
|
||||
}
|
||||
|
||||
func ExtractTokenIdentity(dbEntryType Type, log *types.Log, tx *types.Transaction) (correctType Type, tokenAddress *common.Address, tokenID *big.Int, value *big.Int) {
|
||||
// erc721 transfers share signature with erc20 ones, so they both used to be categorized as erc20
|
||||
// by the Downloader. We fix this here since they might be mis-categorized in the db.
|
||||
if dbEntryType == Erc20Transfer {
|
||||
eventType := GetEventType(log)
|
||||
correctType = EventTypeToSubtransactionType(eventType)
|
||||
} else {
|
||||
correctType = dbEntryType
|
||||
}
|
||||
|
||||
switch correctType {
|
||||
case EthTransfer:
|
||||
if tx != nil {
|
||||
value = new(big.Int).Set(tx.Value())
|
||||
}
|
||||
case Erc20Transfer:
|
||||
tokenAddress = new(common.Address)
|
||||
*tokenAddress = log.Address
|
||||
_, _, value = ParseErc20TransferLog(log)
|
||||
case Erc721Transfer:
|
||||
tokenAddress = new(common.Address)
|
||||
*tokenAddress = log.Address
|
||||
_, _, tokenID = ParseErc721TransferLog(log)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
|
@ -11,8 +11,10 @@ import (
|
|||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/event"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
|
||||
"github.com/status-im/status-go/rpc/chain"
|
||||
"github.com/status-im/status-go/services/wallet/async"
|
||||
w_common "github.com/status-im/status-go/services/wallet/common"
|
||||
"github.com/status-im/status-go/services/wallet/token"
|
||||
"github.com/status-im/status-go/services/wallet/walletevent"
|
||||
)
|
||||
|
@ -450,7 +452,7 @@ func (c *transfersCommand) checkAndProcessPendingMultiTx(subTx *Transfer) (Multi
|
|||
func (c *transfersCommand) checkAndProcessSwapMultiTx(ctx context.Context, subTx *Transfer) (MultiTransactionIDType, error) {
|
||||
switch subTx.Type {
|
||||
// If the Tx contains any uniswapV2Swap/uniswapV3Swap subTx, generate a Swap multiTx
|
||||
case uniswapV2Swap, uniswapV3Swap:
|
||||
case w_common.UniswapV2Swap, w_common.UniswapV3Swap:
|
||||
multiTransaction, err := buildUniswapSwapMultitransaction(ctx, c.chainClient, c.tokenManager, subTx)
|
||||
if err != nil {
|
||||
return NoMultiTransactionID, err
|
||||
|
|
|
@ -12,7 +12,10 @@ import (
|
|||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
|
||||
"github.com/status-im/status-go/services/wallet/bigint"
|
||||
w_common "github.com/status-im/status-go/services/wallet/common"
|
||||
"github.com/status-im/status-go/sqlite"
|
||||
)
|
||||
|
||||
// DBHeader fields from header that are stored in database.
|
||||
|
@ -25,7 +28,7 @@ type DBHeader struct {
|
|||
Address common.Address
|
||||
// Head is true if the block was a head at the time it was pulled from chain.
|
||||
Head bool
|
||||
// Loaded is true if trasfers from this block has been already fetched
|
||||
// Loaded is true if transfers from this block have been already fetched
|
||||
Loaded bool
|
||||
}
|
||||
|
||||
|
@ -364,15 +367,15 @@ func insertBlocksWithTransactions(chainID uint64, creator statementCreator, acco
|
|||
return err
|
||||
}
|
||||
updateTx, err := creator.Prepare(`UPDATE transfers
|
||||
SET log = ?
|
||||
SET log = ?, log_index = ?
|
||||
WHERE network_id = ? AND address = ? AND hash = ?`)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
insertTx, err := creator.Prepare(`INSERT OR IGNORE
|
||||
INTO transfers (network_id, address, sender, hash, blk_number, blk_hash, type, timestamp, log, loaded)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, 0, ?, 0)`)
|
||||
INTO transfers (network_id, address, sender, hash, blk_number, blk_hash, type, timestamp, log, loaded, log_index)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, 0, ?, 0, ?)`)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -383,7 +386,12 @@ func insertBlocksWithTransactions(chainID uint64, creator statementCreator, acco
|
|||
return err
|
||||
}
|
||||
for _, transaction := range header.PreloadedTransactions {
|
||||
res, err := updateTx.Exec(&JSONBlob{transaction.Log}, chainID, account, transaction.ID)
|
||||
var logIndex *uint
|
||||
if transaction.Log != nil {
|
||||
logIndex = new(uint)
|
||||
*logIndex = transaction.Log.Index
|
||||
}
|
||||
res, err := updateTx.Exec(&JSONBlob{transaction.Log}, logIndex, chainID, account, transaction.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -395,9 +403,9 @@ func insertBlocksWithTransactions(chainID uint64, creator statementCreator, acco
|
|||
continue
|
||||
}
|
||||
|
||||
_, err = insertTx.Exec(chainID, account, account, transaction.ID, (*bigint.SQLBigInt)(header.Number), header.Hash, erc20Transfer, &JSONBlob{transaction.Log})
|
||||
_, err = insertTx.Exec(chainID, account, account, transaction.ID, (*bigint.SQLBigInt)(header.Number), header.Hash, w_common.Erc20Transfer, &JSONBlob{transaction.Log}, logIndex)
|
||||
if err != nil {
|
||||
log.Error("error saving erc20transfer", "err", err)
|
||||
log.Error("error saving Erc20transfer", "err", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
@ -407,14 +415,70 @@ func insertBlocksWithTransactions(chainID uint64, creator statementCreator, acco
|
|||
|
||||
func updateOrInsertTransfers(chainID uint64, creator statementCreator, transfers []Transfer) error {
|
||||
insert, err := creator.Prepare(`INSERT OR REPLACE INTO transfers
|
||||
(network_id, hash, blk_hash, blk_number, timestamp, address, tx, sender, receipt, log, type, loaded, base_gas_fee, multi_transaction_id)
|
||||
(network_id, hash, blk_hash, blk_number, timestamp, address, tx, sender, receipt, log, type, loaded, base_gas_fee, multi_transaction_id,
|
||||
status, receipt_type, tx_hash, log_index, block_hash, cumulative_gas_used, contract_address, gas_used, tx_index,
|
||||
tx_type, protected, gas_limit, gas_price_clamped64, gas_tip_cap_clamped64, gas_fee_cap_clamped64, amount_padded128hex, account_nonce, size, token_address, token_id)
|
||||
VALUES
|
||||
(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 1, ?, ?)`)
|
||||
(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 1, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, t := range transfers {
|
||||
_, err = insert.Exec(chainID, t.ID, t.BlockHash, (*bigint.SQLBigInt)(t.BlockNumber), t.Timestamp, t.Address, &JSONBlob{t.Transaction}, t.From, &JSONBlob{t.Receipt}, &JSONBlob{t.Log}, t.Type, t.BaseGasFees, t.MultiTransactionID)
|
||||
var receiptType *uint8
|
||||
var txHash, blockHash *common.Hash
|
||||
var receiptStatus, cumulativeGasUsed, gasUsed *uint64
|
||||
var contractAddress *common.Address
|
||||
var transactionIndex, logIndex *uint
|
||||
|
||||
if t.Receipt != nil {
|
||||
receiptType = &t.Receipt.Type
|
||||
receiptStatus = &t.Receipt.Status
|
||||
txHash = &t.Receipt.TxHash
|
||||
if t.Log != nil {
|
||||
logIndex = new(uint)
|
||||
*logIndex = t.Log.Index
|
||||
}
|
||||
blockHash = &t.Receipt.BlockHash
|
||||
cumulativeGasUsed = &t.Receipt.CumulativeGasUsed
|
||||
contractAddress = &t.Receipt.ContractAddress
|
||||
gasUsed = &t.Receipt.GasUsed
|
||||
transactionIndex = &t.Receipt.TransactionIndex
|
||||
}
|
||||
|
||||
var txProtected *bool
|
||||
var txGas, txNonce, txSize *uint64
|
||||
var txGasPrice, txGasTipCap, txGasFeeCap *int64
|
||||
var txType *uint8
|
||||
var txValue *string
|
||||
var tokenAddress *common.Address
|
||||
var tokenID *big.Int
|
||||
if t.Transaction != nil {
|
||||
var value *big.Int
|
||||
if t.Log != nil {
|
||||
_, tokenAddress, tokenID, value = w_common.ExtractTokenIdentity(t.Type, t.Log, t.Transaction)
|
||||
} else {
|
||||
value = new(big.Int).Set(t.Transaction.Value())
|
||||
}
|
||||
|
||||
txType = new(uint8)
|
||||
*txType = t.Transaction.Type()
|
||||
txProtected = new(bool)
|
||||
*txProtected = t.Transaction.Protected()
|
||||
txGas = new(uint64)
|
||||
*txGas = t.Transaction.Gas()
|
||||
txGasPrice = sqlite.BigIntToClampedInt64(t.Transaction.GasPrice())
|
||||
txGasTipCap = sqlite.BigIntToClampedInt64(t.Transaction.GasTipCap())
|
||||
txGasFeeCap = sqlite.BigIntToClampedInt64(t.Transaction.GasFeeCap())
|
||||
txValue = sqlite.BigIntToPadded128BitsStr(value)
|
||||
txNonce = new(uint64)
|
||||
*txNonce = t.Transaction.Nonce()
|
||||
txSize = new(uint64)
|
||||
*txSize = uint64(t.Transaction.Size())
|
||||
}
|
||||
|
||||
_, err = insert.Exec(chainID, t.ID, t.BlockHash, (*bigint.SQLBigInt)(t.BlockNumber), t.Timestamp, t.Address, &JSONBlob{t.Transaction}, t.From, &JSONBlob{t.Receipt}, &JSONBlob{t.Log}, t.Type, t.BaseGasFees, t.MultiTransactionID,
|
||||
receiptStatus, receiptType, txHash, logIndex, blockHash, cumulativeGasUsed, contractAddress, gasUsed, transactionIndex,
|
||||
txType, txProtected, txGas, txGasPrice, txGasTipCap, txGasFeeCap, txValue, txNonce, txSize, &sqlite.JSONBlob{Data: tokenAddress}, (*bigint.SQLBigIntBytes)(tokenID))
|
||||
if err != nil {
|
||||
log.Error("can't save transfer", "b-hash", t.BlockHash, "b-n", t.BlockNumber, "a", t.Address, "h", t.ID)
|
||||
return err
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/core/types"
|
||||
|
||||
"github.com/status-im/status-go/appdatabase"
|
||||
w_common "github.com/status-im/status-go/services/wallet/common"
|
||||
)
|
||||
|
||||
func setupTestDB(t *testing.T) (*Database, *BlockDAO, func()) {
|
||||
|
@ -28,11 +29,11 @@ func TestDBProcessBlocks(t *testing.T) {
|
|||
from := big.NewInt(0)
|
||||
to := big.NewInt(10)
|
||||
blocks := []*DBHeader{
|
||||
&DBHeader{
|
||||
{
|
||||
Number: big.NewInt(1),
|
||||
Hash: common.Hash{1},
|
||||
},
|
||||
&DBHeader{
|
||||
{
|
||||
Number: big.NewInt(2),
|
||||
Hash: common.Hash{2},
|
||||
}}
|
||||
|
@ -48,7 +49,7 @@ func TestDBProcessBlocks(t *testing.T) {
|
|||
transfers := []Transfer{
|
||||
{
|
||||
ID: common.Hash{1},
|
||||
Type: ethTransfer,
|
||||
Type: w_common.EthTransfer,
|
||||
BlockHash: common.Hash{2},
|
||||
BlockNumber: big.NewInt(1),
|
||||
Address: common.Address{1},
|
||||
|
@ -71,7 +72,7 @@ func TestDBProcessTransfer(t *testing.T) {
|
|||
transfers := []Transfer{
|
||||
{
|
||||
ID: common.Hash{1},
|
||||
Type: ethTransfer,
|
||||
Type: w_common.EthTransfer,
|
||||
BlockHash: header.Hash,
|
||||
BlockNumber: header.Number,
|
||||
Transaction: tx,
|
||||
|
@ -115,7 +116,7 @@ func TestDBReorgTransfers(t *testing.T) {
|
|||
}
|
||||
require.NoError(t, db.ProcessBlocks(777, original.Address, original.Number, lastBlock, []*DBHeader{original}))
|
||||
require.NoError(t, db.ProcessTransfers(777, []Transfer{
|
||||
{ethTransfer, common.Hash{1}, *originalTX.To(), original.Number, original.Hash, 100, originalTX, true, 1777, common.Address{1}, rcpt, nil, "2100", NoMultiTransactionID},
|
||||
{w_common.EthTransfer, common.Hash{1}, *originalTX.To(), original.Number, original.Hash, 100, originalTX, true, 1777, common.Address{1}, rcpt, nil, "2100", NoMultiTransactionID},
|
||||
}, []*DBHeader{}))
|
||||
nonce = int64(0)
|
||||
lastBlock = &Block{
|
||||
|
@ -125,7 +126,7 @@ func TestDBReorgTransfers(t *testing.T) {
|
|||
}
|
||||
require.NoError(t, db.ProcessBlocks(777, replaced.Address, replaced.Number, lastBlock, []*DBHeader{replaced}))
|
||||
require.NoError(t, db.ProcessTransfers(777, []Transfer{
|
||||
{ethTransfer, common.Hash{2}, *replacedTX.To(), replaced.Number, replaced.Hash, 100, replacedTX, true, 1777, common.Address{1}, rcpt, nil, "2100", NoMultiTransactionID},
|
||||
{w_common.EthTransfer, common.Hash{2}, *replacedTX.To(), replaced.Number, replaced.Hash, 100, replacedTX, true, 1777, common.Address{1}, rcpt, nil, "2100", NoMultiTransactionID},
|
||||
}, []*DBHeader{original}))
|
||||
|
||||
all, err := db.GetTransfers(777, big.NewInt(0), nil)
|
||||
|
@ -151,7 +152,7 @@ func TestDBGetTransfersFromBlock(t *testing.T) {
|
|||
receipt.Logs = []*types.Log{}
|
||||
transfer := Transfer{
|
||||
ID: tx.Hash(),
|
||||
Type: ethTransfer,
|
||||
Type: w_common.EthTransfer,
|
||||
BlockNumber: header.Number,
|
||||
BlockHash: header.Hash,
|
||||
Transaction: tx,
|
||||
|
|
|
@ -13,7 +13,9 @@ import (
|
|||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
|
||||
"github.com/status-im/status-go/rpc/chain"
|
||||
w_common "github.com/status-im/status-go/services/wallet/common"
|
||||
)
|
||||
|
||||
type MultiTransactionIDType int64
|
||||
|
@ -22,10 +24,6 @@ const (
|
|||
NoMultiTransactionID = MultiTransactionIDType(0)
|
||||
)
|
||||
|
||||
func getEventSignatureHash(signature string) common.Hash {
|
||||
return crypto.Keccak256Hash([]byte(signature))
|
||||
}
|
||||
|
||||
func getLogSubTxID(log types.Log) common.Hash {
|
||||
// Get unique ID by using TxHash and log index
|
||||
index := [4]byte{}
|
||||
|
@ -45,7 +43,7 @@ var (
|
|||
// To be converted into one or many Transfer objects post-indexing.
|
||||
type PreloadedTransaction struct {
|
||||
NetworkID uint64
|
||||
Type Type `json:"type"`
|
||||
Type w_common.Type `json:"type"`
|
||||
ID common.Hash `json:"-"`
|
||||
Address common.Address `json:"address"`
|
||||
BlockNumber *big.Int `json:"blockNumber"`
|
||||
|
@ -61,7 +59,7 @@ type PreloadedTransaction struct {
|
|||
// Transfer stores information about transfer.
|
||||
// A Transfer represents a plain ETH transfer or some token activity inside a Transaction
|
||||
type Transfer struct {
|
||||
Type Type `json:"type"`
|
||||
Type w_common.Type `json:"type"`
|
||||
ID common.Hash `json:"-"`
|
||||
Address common.Address `json:"address"`
|
||||
BlockNumber *big.Int `json:"blockNumber"`
|
||||
|
@ -114,8 +112,8 @@ func getTransferByHash(ctx context.Context, client *chain.ClientWithFallback, si
|
|||
return nil, err
|
||||
}
|
||||
|
||||
eventType, transactionLog := GetFirstEvent(receipt.Logs)
|
||||
transactionType := EventTypeToSubtransactionType(eventType)
|
||||
eventType, transactionLog := w_common.GetFirstEvent(receipt.Logs)
|
||||
transactionType := w_common.EventTypeToSubtransactionType(eventType)
|
||||
|
||||
from, err := types.Sender(signer, transaction)
|
||||
|
||||
|
@ -184,7 +182,7 @@ func (d *ETHDownloader) getTransfersInBlock(ctx context.Context, blk *types.Bloc
|
|||
return nil, err
|
||||
}
|
||||
|
||||
eventType, _ := GetFirstEvent(receipt.Logs)
|
||||
eventType, _ := w_common.GetFirstEvent(receipt.Logs)
|
||||
|
||||
baseGasFee, err := d.chainClient.GetBaseFeeFromBlock(blk.Number())
|
||||
if err != nil {
|
||||
|
@ -193,9 +191,9 @@ func (d *ETHDownloader) getTransfersInBlock(ctx context.Context, blk *types.Bloc
|
|||
|
||||
// If the transaction is not already some known transfer type, add it
|
||||
// to the list as a plain eth transfer
|
||||
if eventType == unknownEventType {
|
||||
if eventType == w_common.UnknownEventType {
|
||||
rst = append(rst, Transfer{
|
||||
Type: ethTransfer,
|
||||
Type: w_common.EthTransfer,
|
||||
ID: tx.Hash(),
|
||||
Address: address,
|
||||
BlockNumber: blk.Number(),
|
||||
|
@ -218,7 +216,7 @@ func (d *ETHDownloader) getTransfersInBlock(ctx context.Context, blk *types.Bloc
|
|||
|
||||
// NewERC20TransfersDownloader returns new instance.
|
||||
func NewERC20TransfersDownloader(client *chain.ClientWithFallback, accounts []common.Address, signer types.Signer) *ERC20TransfersDownloader {
|
||||
signature := getEventSignatureHash(erc20_721TransferEventSignature)
|
||||
signature := w_common.GetEventSignatureHash(w_common.Erc20_721TransferEventSignature)
|
||||
|
||||
return &ERC20TransfersDownloader{
|
||||
client: client,
|
||||
|
@ -230,7 +228,7 @@ func NewERC20TransfersDownloader(client *chain.ClientWithFallback, accounts []co
|
|||
|
||||
// ERC20TransfersDownloader is a downloader for erc20 and erc721 tokens transfers.
|
||||
// Since both transaction types share the same signature, both will be assigned
|
||||
// type erc20Transfer. Until the downloader gets refactored and a migration of the
|
||||
// type Erc20Transfer. Until the downloader gets refactored and a migration of the
|
||||
// database gets implemented, differentiation between erc20 and erc721 will handled
|
||||
// in the controller.
|
||||
type ERC20TransfersDownloader struct {
|
||||
|
@ -291,28 +289,28 @@ func (d *ETHDownloader) subTransactionsFromTransactionHash(parent context.Contex
|
|||
rst := make([]Transfer, 0, len(receipt.Logs))
|
||||
|
||||
for _, log := range receipt.Logs {
|
||||
eventType := GetEventType(log)
|
||||
eventType := w_common.GetEventType(log)
|
||||
// Only add ERC20/ERC721 transfers from/to the given account
|
||||
// Other types of events get always added
|
||||
mustAppend := false
|
||||
switch eventType {
|
||||
case erc20TransferEventType:
|
||||
from, to, _ := parseErc20TransferLog(log)
|
||||
case w_common.Erc20TransferEventType:
|
||||
from, to, _ := w_common.ParseErc20TransferLog(log)
|
||||
if from == address || to == address {
|
||||
mustAppend = true
|
||||
}
|
||||
case erc721TransferEventType:
|
||||
from, to, _ := parseErc721TransferLog(log)
|
||||
case w_common.Erc721TransferEventType:
|
||||
from, to, _ := w_common.ParseErc721TransferLog(log)
|
||||
if from == address || to == address {
|
||||
mustAppend = true
|
||||
}
|
||||
case uniswapV2SwapEventType, uniswapV3SwapEventType:
|
||||
case w_common.UniswapV2SwapEventType, w_common.UniswapV3SwapEventType:
|
||||
mustAppend = true
|
||||
}
|
||||
|
||||
if mustAppend {
|
||||
transfer := Transfer{
|
||||
Type: EventTypeToSubtransactionType(eventType),
|
||||
Type: w_common.EventTypeToSubtransactionType(eventType),
|
||||
ID: getLogSubTxID(*log),
|
||||
Address: address,
|
||||
BlockNumber: new(big.Int).SetUint64(log.BlockNumber),
|
||||
|
@ -359,7 +357,7 @@ func (d *ERC20TransfersDownloader) blocksFromLogs(parent context.Context, logs [
|
|||
ID: id,
|
||||
From: address,
|
||||
Loaded: false,
|
||||
Type: erc20Transfer,
|
||||
Type: w_common.Erc20Transfer,
|
||||
Log: &l,
|
||||
BaseGasFees: baseGasFee,
|
||||
}},
|
||||
|
|
|
@ -53,7 +53,7 @@ func (q *transfersQuery) addWhereSeparator(separator SeparatorType) {
|
|||
|
||||
type SeparatorType int
|
||||
|
||||
// Beware if changing this enum please update addWhereSeparator as well
|
||||
// Beware: please update addWhereSeparator if changing this enum
|
||||
const (
|
||||
NoSeparator SeparatorType = iota + 1
|
||||
OrSeparator
|
||||
|
|
|
@ -9,9 +9,11 @@ import (
|
|||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
|
||||
uniswapv2 "github.com/status-im/status-go/contracts/uniswapV2"
|
||||
uniswapv3 "github.com/status-im/status-go/contracts/uniswapV3"
|
||||
"github.com/status-im/status-go/rpc/chain"
|
||||
w_common "github.com/status-im/status-go/services/wallet/common"
|
||||
"github.com/status-im/status-go/services/wallet/token"
|
||||
)
|
||||
|
||||
|
@ -86,7 +88,7 @@ func identifyUniswapV2Asset(tokenManager *token.Manager, chainID uint64, amount0
|
|||
}
|
||||
|
||||
func fetchUniswapV2Info(ctx context.Context, client *chain.ClientWithFallback, tokenManager *token.Manager, log *types.Log) (fromAsset string, fromAmount *hexutil.Big, toAsset string, toAmount *hexutil.Big, err error) {
|
||||
pairAddress, _, _, amount0In, amount1In, amount0Out, amount1Out, err := parseUniswapV2Log(log)
|
||||
pairAddress, _, _, amount0In, amount1In, amount0Out, amount1Out, err := w_common.ParseUniswapV2Log(log)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -155,7 +157,7 @@ func identifyUniswapV3Assets(tokenManager *token.Manager, chainID uint64, amount
|
|||
}
|
||||
|
||||
func fetchUniswapV3Info(ctx context.Context, client *chain.ClientWithFallback, tokenManager *token.Manager, log *types.Log) (fromAsset string, fromAmount *hexutil.Big, toAsset string, toAmount *hexutil.Big, err error) {
|
||||
poolAddress, _, _, amount0, amount1, err := parseUniswapV3Log(log)
|
||||
poolAddress, _, _, amount0, amount1, err := w_common.ParseUniswapV3Log(log)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -183,11 +185,11 @@ func fetchUniswapV3Info(ctx context.Context, client *chain.ClientWithFallback, t
|
|||
return
|
||||
}
|
||||
|
||||
func fetchUniswapInfo(ctx context.Context, client *chain.ClientWithFallback, tokenManager *token.Manager, log *types.Log, logType EventType) (fromAsset string, fromAmount *hexutil.Big, toAsset string, toAmount *hexutil.Big, err error) {
|
||||
func fetchUniswapInfo(ctx context.Context, client *chain.ClientWithFallback, tokenManager *token.Manager, log *types.Log, logType w_common.EventType) (fromAsset string, fromAmount *hexutil.Big, toAsset string, toAmount *hexutil.Big, err error) {
|
||||
switch logType {
|
||||
case uniswapV2SwapEventType:
|
||||
case w_common.UniswapV2SwapEventType:
|
||||
return fetchUniswapV2Info(ctx, client, tokenManager, log)
|
||||
case uniswapV3SwapEventType:
|
||||
case w_common.UniswapV3SwapEventType:
|
||||
return fetchUniswapV3Info(ctx, client, tokenManager, log)
|
||||
}
|
||||
err = fmt.Errorf("wrong log type %s", logType)
|
||||
|
@ -204,12 +206,12 @@ func buildUniswapSwapMultitransaction(ctx context.Context, client *chain.ClientW
|
|||
}
|
||||
|
||||
var firstSwapLog, lastSwapLog *types.Log
|
||||
var firstSwapLogType, lastSwapLogType EventType
|
||||
var firstSwapLogType, lastSwapLogType w_common.EventType
|
||||
|
||||
for _, ethlog := range transfer.Receipt.Logs {
|
||||
logType := GetEventType(ethlog)
|
||||
logType := w_common.GetEventType(ethlog)
|
||||
switch logType {
|
||||
case uniswapV2SwapEventType, uniswapV3SwapEventType:
|
||||
case w_common.UniswapV2SwapEventType, w_common.UniswapV3SwapEventType:
|
||||
if firstSwapLog == nil {
|
||||
firstSwapLog = ethlog
|
||||
firstSwapLogType = logType
|
||||
|
|
|
@ -5,13 +5,14 @@ import (
|
|||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
w_common "github.com/status-im/status-go/services/wallet/common"
|
||||
)
|
||||
|
||||
// View stores only fields used by a client and ensures that all relevant fields are
|
||||
// encoded in hex.
|
||||
type View struct {
|
||||
ID common.Hash `json:"id"`
|
||||
Type Type `json:"type"`
|
||||
Type w_common.Type `json:"type"`
|
||||
Address common.Address `json:"address"`
|
||||
BlockNumber *hexutil.Big `json:"blockNumber"`
|
||||
BlockHash common.Hash `json:"blockhash"`
|
||||
|
@ -27,8 +28,8 @@ type View struct {
|
|||
TxStatus hexutil.Uint64 `json:"txStatus"`
|
||||
Input hexutil.Bytes `json:"input"`
|
||||
TxHash common.Hash `json:"txHash"`
|
||||
Value *hexutil.Big `json:"value"` // Only used for Type ethTransfer and erc20Transfer
|
||||
TokenID *hexutil.Big `json:"tokenId"` // Only used for Type erc721Transfer
|
||||
Value *hexutil.Big `json:"value"` // Only used for Type EthTransfer and Erc20Transfer
|
||||
TokenID *hexutil.Big `json:"tokenId"` // Only used for Type Erc721Transfer
|
||||
From common.Address `json:"from"`
|
||||
To common.Address `json:"to"`
|
||||
Contract common.Address `json:"contract"`
|
||||
|
@ -41,7 +42,7 @@ func castToTransferViews(transfers []Transfer) []View {
|
|||
views := make([]View, 0, len(transfers))
|
||||
for _, tx := range transfers {
|
||||
switch tx.Type {
|
||||
case ethTransfer, erc20Transfer, erc721Transfer:
|
||||
case w_common.EthTransfer, w_common.Erc20Transfer, w_common.Erc721Transfer:
|
||||
view := CastToTransferView(tx)
|
||||
views = append(views, view)
|
||||
}
|
||||
|
@ -82,20 +83,20 @@ func CastToTransferView(t Transfer) View {
|
|||
tokenID := new(hexutil.Big)
|
||||
|
||||
switch view.Type {
|
||||
case ethTransfer:
|
||||
case w_common.EthTransfer:
|
||||
view.From = t.From
|
||||
if t.Transaction.To() != nil {
|
||||
view.To = *t.Transaction.To()
|
||||
}
|
||||
value = (*hexutil.Big)(t.Transaction.Value())
|
||||
view.Contract = t.Receipt.ContractAddress
|
||||
case erc20Transfer:
|
||||
case w_common.Erc20Transfer:
|
||||
view.Contract = t.Log.Address
|
||||
from, to, valueInt := parseErc20TransferLog(t.Log)
|
||||
from, to, valueInt := w_common.ParseErc20TransferLog(t.Log)
|
||||
view.From, view.To, value = from, to, (*hexutil.Big)(valueInt)
|
||||
case erc721Transfer:
|
||||
case w_common.Erc721Transfer:
|
||||
view.Contract = t.Log.Address
|
||||
from, to, tokenIDInt := parseErc721TransferLog(t.Log)
|
||||
from, to, tokenIDInt := w_common.ParseErc721TransferLog(t.Log)
|
||||
view.From, view.To, tokenID = from, to, (*hexutil.Big)(tokenIDInt)
|
||||
}
|
||||
|
||||
|
@ -106,12 +107,12 @@ func CastToTransferView(t Transfer) View {
|
|||
return view
|
||||
}
|
||||
|
||||
func getFixedTransferType(tx Transfer) Type {
|
||||
func getFixedTransferType(tx Transfer) w_common.Type {
|
||||
// erc721 transfers share signature with erc20 ones, so they both used to be categorized as erc20
|
||||
// by the Downloader. We fix this here since they might be mis-categorized in the db.
|
||||
if tx.Type == erc20Transfer {
|
||||
eventType := GetEventType(tx.Log)
|
||||
return EventTypeToSubtransactionType(eventType)
|
||||
if tx.Type == w_common.Erc20Transfer {
|
||||
eventType := w_common.GetEventType(tx.Log)
|
||||
return w_common.EventTypeToSubtransactionType(eventType)
|
||||
}
|
||||
return tx.Type
|
||||
}
|
||||
|
|
|
@ -4,28 +4,44 @@ import (
|
|||
"database/sql/driver"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"math/big"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// JSONBlob type for marshaling/unmarshaling inner type to json.
|
||||
type JSONBlob struct {
|
||||
Data interface{}
|
||||
Valid bool
|
||||
}
|
||||
|
||||
// Scan implements interface.
|
||||
func (blob *JSONBlob) Scan(value interface{}) error {
|
||||
dataVal := reflect.ValueOf(blob.Data)
|
||||
blob.Valid = false
|
||||
if value == nil || dataVal.Kind() == reflect.Ptr && dataVal.IsNil() {
|
||||
return nil
|
||||
}
|
||||
bytes, ok := value.([]byte)
|
||||
|
||||
var bytes []byte
|
||||
ok := true
|
||||
switch v := value.(type) {
|
||||
case []byte:
|
||||
bytes, ok = value.([]byte)
|
||||
case string:
|
||||
bytes = []byte(v)
|
||||
default:
|
||||
ok = false
|
||||
}
|
||||
if !ok {
|
||||
return errors.New("not a byte slice")
|
||||
return errors.New("not a byte slice or string")
|
||||
}
|
||||
if len(bytes) == 0 {
|
||||
return nil
|
||||
}
|
||||
err := json.Unmarshal(bytes, blob.Data)
|
||||
blob.Valid = err == nil
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -45,3 +61,29 @@ func (blob *JSONBlob) Value() (driver.Value, error) {
|
|||
|
||||
return json.Marshal(blob.Data)
|
||||
}
|
||||
|
||||
func BigIntToClampedInt64(val *big.Int) *int64 {
|
||||
if val == nil {
|
||||
return nil
|
||||
}
|
||||
var v int64
|
||||
if val.IsInt64() {
|
||||
v = val.Int64()
|
||||
} else {
|
||||
v = math.MaxInt64
|
||||
}
|
||||
return &v
|
||||
}
|
||||
|
||||
// BigIntToPadded128BitsStr converts a big.Int to a string, padding it with 0 to account for 128 bits size
|
||||
// Returns nil if input val is nil
|
||||
// This should work to sort and compare big.Ints values in SQLite
|
||||
func BigIntToPadded128BitsStr(val *big.Int) *string {
|
||||
if val == nil {
|
||||
return nil
|
||||
}
|
||||
hexStr := val.Text(16)
|
||||
res := new(string)
|
||||
*res = fmt.Sprintf("%032s", hexStr)
|
||||
return res
|
||||
}
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
package sqlite
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func strToPtr(s string) *string {
|
||||
res := new(string)
|
||||
*res = s
|
||||
return res
|
||||
}
|
||||
|
||||
func TestBigIntToPadded128BitsStr(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
input *big.Int
|
||||
expected *string
|
||||
}{
|
||||
{
|
||||
name: "case small",
|
||||
input: big.NewInt(123456),
|
||||
expected: strToPtr("0000000000000000000000000001e240"),
|
||||
},
|
||||
{
|
||||
name: "case zero",
|
||||
input: big.NewInt(0),
|
||||
expected: strToPtr("00000000000000000000000000000000"),
|
||||
},
|
||||
{
|
||||
name: "case very large",
|
||||
input: new(big.Int).Exp(big.NewInt(10), big.NewInt(26), nil),
|
||||
expected: strToPtr("000000000052b7d2dcc80cd2e4000000"),
|
||||
},
|
||||
{
|
||||
name: "case max",
|
||||
input: new(big.Int).Sub(new(big.Int).Lsh(big.NewInt(1), 128), big.NewInt(1)),
|
||||
expected: strToPtr("ffffffffffffffffffffffffffffffff"),
|
||||
},
|
||||
{
|
||||
name: "case 3",
|
||||
input: nil,
|
||||
expected: nil,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
result := BigIntToPadded128BitsStr(tc.input)
|
||||
if result != nil && tc.expected != nil {
|
||||
if *result != *tc.expected {
|
||||
t.Errorf("expected %s, got %s", *tc.expected, *result)
|
||||
}
|
||||
} else if result != nil || tc.expected != nil {
|
||||
t.Errorf("expected %v, got %v", tc.expected, result)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -2,37 +2,178 @@ package sqlite
|
|||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"sort"
|
||||
|
||||
"github.com/status-im/migrate/v4"
|
||||
"github.com/status-im/migrate/v4/database/sqlcipher"
|
||||
bindata "github.com/status-im/migrate/v4/source/go_bindata"
|
||||
)
|
||||
|
||||
// Migrate database using provided resources.
|
||||
func Migrate(db *sql.DB, resources *bindata.AssetSource) error {
|
||||
type PostStep struct {
|
||||
Version uint
|
||||
CustomMigration func(tx *sql.Tx) error
|
||||
RollBackVersion uint
|
||||
}
|
||||
|
||||
var migrationTable = "status_go_" + sqlcipher.DefaultMigrationsTable
|
||||
|
||||
// Migrate database with option to augment the migration steps with additional processing using the customSteps
|
||||
// parameter. For each PostStep entry in customSteps the CustomMigration will be called after the migration step
|
||||
// with the matching Version number has been executed. If the CustomMigration returns an error, the migration process
|
||||
// is aborted. In case the custom step failures the migrations are run down to RollBackVersion if > 0.
|
||||
//
|
||||
// The recommended way to create a custom migration is by providing empty and versioned run/down sql files as markers.
|
||||
// Then running all the SQL code inside the same transaction to transform and commit provides the possibility
|
||||
// to completely rollback the migration in case of failure, avoiding to leave the DB in an inconsistent state.
|
||||
//
|
||||
// Marker migrations can be created by using PostStep structs with specific Version numbers and a callback function,
|
||||
// even when no accompanying SQL migration is needed. This can be used to trigger Go code at specific points
|
||||
// during the migration process.
|
||||
//
|
||||
// Caution: This mechanism should be used as a last resort. Prefer data migration using SQL migration files
|
||||
// whenever possible to ensure consistency and compatibility with standard migration tools.
|
||||
//
|
||||
// untilVersion, for testing purposes optional parameter, can be used to limit the migration to a specific version.
|
||||
// Pass nil to migrate to the latest available version.
|
||||
func Migrate(db *sql.DB, resources *bindata.AssetSource, customSteps []PostStep, untilVersion *uint) error {
|
||||
source, err := bindata.WithInstance(resources)
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("failed to create bindata migration source: %w", err)
|
||||
}
|
||||
|
||||
driver, err := sqlcipher.WithInstance(db, &sqlcipher.Config{
|
||||
MigrationsTable: "status_go_" + sqlcipher.DefaultMigrationsTable,
|
||||
MigrationsTable: migrationTable,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("failed to create sqlcipher driver: %w", err)
|
||||
}
|
||||
|
||||
m, err := migrate.NewWithInstance(
|
||||
"go-bindata",
|
||||
source,
|
||||
"sqlcipher",
|
||||
driver)
|
||||
m, err := migrate.NewWithInstance("go-bindata", source, "sqlcipher", driver)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create migration instance: %w", err)
|
||||
}
|
||||
|
||||
if len(customSteps) == 0 {
|
||||
return runRemainingMigrations(m, untilVersion)
|
||||
}
|
||||
|
||||
sort.Slice(customSteps, func(i, j int) bool {
|
||||
return customSteps[i].Version < customSteps[j].Version
|
||||
})
|
||||
|
||||
lastVersion, err := getCurrentVersion(m, db)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = m.Up(); err != migrate.ErrNoChange {
|
||||
customIndex := 0
|
||||
// ignore processed versions
|
||||
for customIndex < len(customSteps) && customSteps[customIndex].Version <= lastVersion {
|
||||
customIndex++
|
||||
}
|
||||
|
||||
if err := runCustomMigrations(m, db, customSteps, customIndex, untilVersion); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return runRemainingMigrations(m, untilVersion)
|
||||
}
|
||||
|
||||
// runCustomMigrations performs source migrations from current to each custom steps, then runs custom migration callback
|
||||
// until it executes all custom migrations or an error occurs and it tries to rollback to RollBackVersion if > 0.
|
||||
func runCustomMigrations(m *migrate.Migrate, db *sql.DB, customSteps []PostStep, customIndex int, untilVersion *uint) error {
|
||||
for customIndex < len(customSteps) && (untilVersion == nil || customSteps[customIndex].Version <= *untilVersion) {
|
||||
customStep := customSteps[customIndex]
|
||||
|
||||
if err := m.Migrate(customStep.Version); err != nil && err != migrate.ErrNoChange {
|
||||
return fmt.Errorf("failed to migrate to version %d: %w", customStep.Version, err)
|
||||
}
|
||||
|
||||
if err := runCustomMigrationStep(db, customStep, m); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
customIndex++
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func runCustomMigrationStep(db *sql.DB, customStep PostStep, m *migrate.Migrate) error {
|
||||
sqlTx, err := db.Begin()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to begin transaction: %w", err)
|
||||
}
|
||||
|
||||
if err := customStep.CustomMigration(sqlTx); err != nil {
|
||||
_ = sqlTx.Rollback()
|
||||
return rollbackCustomMigration(m, customStep, err)
|
||||
}
|
||||
|
||||
if err := sqlTx.Commit(); err != nil {
|
||||
return fmt.Errorf("failed to commit transaction: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func rollbackCustomMigration(m *migrate.Migrate, customStep PostStep, customErr error) error {
|
||||
if customStep.RollBackVersion > 0 {
|
||||
err := m.Migrate(customStep.RollBackVersion)
|
||||
newV, _, _ := m.Version()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to rollback migration to version %d: %w", customStep.RollBackVersion, err)
|
||||
}
|
||||
return fmt.Errorf("custom migration step failed for version %d. Successfully rolled back migration to version %d: %w", customStep.Version, newV, customErr)
|
||||
}
|
||||
return fmt.Errorf("custom migration step failed for version %d: %w", customStep.Version, customErr)
|
||||
}
|
||||
|
||||
func runRemainingMigrations(m *migrate.Migrate, untilVersion *uint) error {
|
||||
if untilVersion != nil {
|
||||
if err := m.Migrate(*untilVersion); err != nil && err != migrate.ErrNoChange {
|
||||
return fmt.Errorf("failed to migrate to version %d: %w", *untilVersion, err)
|
||||
}
|
||||
} else {
|
||||
if err := m.Up(); err != nil && err != migrate.ErrNoChange {
|
||||
return fmt.Errorf("failed to migrate up: %w", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func getCurrentVersion(m *migrate.Migrate, db *sql.DB) (uint, error) {
|
||||
lastVersion, dirty, err := m.Version()
|
||||
if err != nil && err != migrate.ErrNilVersion {
|
||||
return 0, fmt.Errorf("failed to get migration version: %w", err)
|
||||
}
|
||||
if dirty {
|
||||
return 0, fmt.Errorf("DB is dirty after migration version %d", lastVersion)
|
||||
}
|
||||
if err == migrate.ErrNilVersion {
|
||||
lastVersion, _, err = GetLastMigrationVersion(db)
|
||||
return lastVersion, err
|
||||
}
|
||||
return lastVersion, nil
|
||||
}
|
||||
|
||||
// GetLastMigrationVersion returns the last migration version stored in the migration table.
|
||||
// Returns 0 for version in case migrationTableExists is true
|
||||
func GetLastMigrationVersion(db *sql.DB) (version uint, migrationTableExists bool, err error) {
|
||||
// Check if the migration table exists
|
||||
row := db.QueryRow("SELECT exists(SELECT name FROM sqlite_master WHERE type='table' AND name=?)", migrationTable)
|
||||
migrationTableExists = false
|
||||
err = row.Scan(&migrationTableExists)
|
||||
if err != nil && err != sql.ErrNoRows {
|
||||
return 0, false, err
|
||||
}
|
||||
|
||||
var lastMigration uint64 = 0
|
||||
if migrationTableExists {
|
||||
row = db.QueryRow("SELECT version FROM status_go_schema_migrations")
|
||||
err = row.Scan(&lastMigration)
|
||||
if err != nil && err != sql.ErrNoRows {
|
||||
return 0, true, err
|
||||
}
|
||||
}
|
||||
return uint(lastMigration), migrationTableExists, nil
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue