From df9393194aec20eb7176d25e23ddffea5b5a0cf5 Mon Sep 17 00:00:00 2001 From: Roman D Date: Thu, 16 Jan 2025 13:17:24 +0300 Subject: [PATCH] feat: PostgreSQL support (#922) * feat: enable Postgres connections * feat: implement migration templates * feat: convert sqlite-specific migrations to migration templates; adjust SQL syntax * fix: add migration to fix postgres incompatibilities in the DB schema * fix: correct SQL syntax for comparisons in the transactions service * feat: database migration tool * chore: update tests for testing with Postgres * fix: update test * fix: explicitly store mock timestamps in UTC * chore: add txdb to go.mod and run tidy * fix: serialize concurrent transactions when running tests with txdb * chore: update README to mention postgres * fix: use timestamptz in Postgres * test: add Github action for testing the backend with Postgres * chore: fix migration name and add comments * docs: add db migration notes to README * fix: address PR feedback * fix: rename the cmd/migrate tool to cmd/db_migrate * feat: add schema check in the DB migration tool * test: use testdb instead of txdb for testing with Postgresql * fix: fix tests after merge * chore: comment out unused VACUUM in migrations * fix: reset Postgres sequences after migrating data * docs: update migrate command in readme * fix: do not allow backup for migration when postgres is enabled * chore: add debug logs for db backend type * chore: use Logrus instead of slog for db_migrate * fix: initialize logger in the keys tests * test: add db_migrate test * fix: use transaction object in db_migrate function * fix: txlock in db migration test --------- Co-authored-by: Roland Bewick --- .github/workflows/test-postgres.yml | 45 ++++ README.md | 16 +- alby/alby_oauth_service_test.go | 15 +- api/backup.go | 4 + cmd/db_migrate/main.go | 242 ++++++++++++++++++ cmd/db_migrate/migrate_test.go | 179 +++++++++++++ db/db.go | 92 ++++++- .../202401191539_initial_migration.go | 7 +- .../202401191539_initial_migration.sql | 16 -- .../202401191539_initial_migration.sql.tmpl | 16 ++ .../202404021909_nullable_expires_at.go | 2 +- .../202405302121_store_decrypted_request.go | 6 +- db/migrations/202406061259_delete_content.go | 10 +- db/migrations/202406071726_vacuum.go | 10 +- db/migrations/202407012100_transactions.go | 38 +-- db/migrations/202407151352_autoincrement.go | 65 +++-- .../202407262257_remove_invalid_scopes.go | 6 +- ...2408061737_add_boostagrams_and_use_json.go | 2 +- ...202408191242_transaction_failure_reason.go | 2 +- db/migrations/202412212345_fix_types.go | 37 +++ db/migrations/migrate.go | 43 ++++ db/queries/get_isolated_balance_test.go | 13 +- go.mod | 3 + go.sum | 24 +- lnclient/ldk/ldk_test.go | 11 +- .../get_balance_controller_test.go | 12 +- .../controllers/get_budget_controller_test.go | 20 +- nip47/controllers/get_info_controller_test.go | 12 +- .../list_transactions_controller_test.go | 20 +- .../lookup_invoice_controller_test.go | 4 +- .../make_invoice_controller_test.go | 4 +- .../multi_pay_invoice_controller_test.go | 20 +- .../multi_pay_keysend_controller_test.go | 8 +- .../pay_invoice_controller_test.go | 16 +- .../pay_keysend_controller_test.go | 8 +- ...event_handler_shared_wallet_pubkey_test.go | 43 ++-- nip47/event_handler_test.go | 63 ++--- nip47/notifications/nip47_notifier_test.go | 44 ++-- nip47/permissions/permissions_test.go | 35 +-- service/keys/keys_test.go | 17 +- tests/db/test_db.go | 73 ++++++ tests/test_service.go | 38 +-- transactions/app_payments_test.go | 29 ++- .../check_unsettled_transaction_test.go | 13 +- transactions/isolated_app_payments_test.go | 33 +-- transactions/keysend_test.go | 49 ++-- transactions/list_transactions_test.go | 41 +-- transactions/lookup_transaction_test.go | 13 +- transactions/make_invoice_test.go | 17 +- transactions/notifications_test.go | 29 ++- transactions/payments_test.go | 51 ++-- transactions/receive_keysend_test.go | 13 +- transactions/self_payments_test.go | 33 +-- transactions/transactions_service.go | 31 +-- 54 files changed, 1234 insertions(+), 459 deletions(-) create mode 100644 .github/workflows/test-postgres.yml create mode 100644 cmd/db_migrate/main.go create mode 100644 cmd/db_migrate/migrate_test.go delete mode 100644 db/migrations/202401191539_initial_migration.sql create mode 100644 db/migrations/202401191539_initial_migration.sql.tmpl create mode 100644 db/migrations/202412212345_fix_types.go create mode 100644 tests/db/test_db.go diff --git a/.github/workflows/test-postgres.yml b/.github/workflows/test-postgres.yml new file mode 100644 index 000000000..33dc63384 --- /dev/null +++ b/.github/workflows/test-postgres.yml @@ -0,0 +1,45 @@ +name: Backend testing with Postgres + +on: + push: + branches: + - master + pull_request: + types: [opened, synchronize] + +jobs: + test-postgres: + runs-on: ubuntu-latest + + services: + postgres: + image: postgres:17.2 + ports: + - 5432:5432 + env: + POSTGRES_DB: albyhub + POSTGRES_USER: alby + POSTGRES_PASSWORD: albytest123 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + + steps: + - uses: actions/checkout@v4 + name: Check out code + + - name: Setup GoLang + uses: actions/setup-go@v5 + with: + go-version-file: "./go.mod" + + - name: Get dependencies + run: go get -v -t -d ./... + + - name: Run tests + env: + TEST_DATABASE_URI: "postgresql://alby:albytest123@localhost:5432/albyhub" + TEST_DB_MIGRATE_POSTGRES_URI: "postgresql://alby:albytest123@localhost:5432/albyhub" + run: mkdir frontend/dist && touch frontend/dist/tmp && go test ./... diff --git a/README.md b/README.md index 8fe9bd82e..71922f055 100644 --- a/README.md +++ b/README.md @@ -138,12 +138,24 @@ The following configuration options can be set as environment variables or in a - `RELAY`: default: "wss://relay.getalby.com/v1" - `JWT_SECRET`: a randomly generated secret string. (only needed in http mode) -- `DATABASE_URI`: a sqlite filename. Default: $XDG_DATA_HOME/albyhub/nwc.db +- `DATABASE_URI`: a sqlite filename or postgres URL. Default is SQLite DB `nwc.db` without a path, which will be put in the user home directory: $XDG_DATA_HOME/albyhub/nwc.db - `PORT`: the port on which the app should listen on (default: 8080) - `WORK_DIR`: directory to store NWC data files. Default: $XDG_DATA_HOME/albyhub - `LOG_LEVEL`: log level for the application. Higher is more verbose. Default: 4 (info) - `AUTO_UNLOCK_PASSWORD`: provide unlock password to auto-unlock Alby Hub on startup (e.g. after a machine restart). Unlock password still be required to access the interface. +### Migrating the database (Sqlite <-> Postgres) + +Migration of the database is currently experimental. Please make a backup before continuing. + +#### Migration from Sqlite to Postgres + +1. Stop the running hub +2. Update the `DATABASE_URI` to your destination e.g. `postgresql://myuser:mypass@localhost:5432/nwc` +3. Run the migration: + + go run cmd/db_migrate/main.go -from .data/nwc.db -to postgresql://myuser:mypass@localhost:5432/nwc + ## Node-specific backend parameters - `ENABLE_ADVANCED_SETUP`: set to `false` to force a specific backend type (combined with backend parameters below) @@ -434,7 +446,7 @@ LDK logs: ### Docker -Alby provides container images for each release. Please make sure to use a persistent volume. The lightning state and application state is persisted to disk. +Alby provides container images for each release. Please make sure to use a persistent volume. The lightning state and application state is persisted to disk. #### From Alby's Container Registry diff --git a/alby/alby_oauth_service_test.go b/alby/alby_oauth_service_test.go index 3b6179648..0c0c5337f 100644 --- a/alby/alby_oauth_service_test.go +++ b/alby/alby_oauth_service_test.go @@ -3,19 +3,20 @@ package alby import ( "testing" - "github.com/getAlby/hub/config" - "github.com/getAlby/hub/events" - "github.com/getAlby/hub/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/tyler-smith/go-bip32" "github.com/tyler-smith/go-bip39" + + "github.com/getAlby/hub/config" + "github.com/getAlby/hub/events" + "github.com/getAlby/hub/tests" ) func TestExistingEncryptedBackup(t *testing.T) { - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() mnemonic := "limit reward expect search tissue call visa fit thank cream brave jump" unlockPassword := "123" @@ -40,11 +41,11 @@ func TestExistingEncryptedBackup(t *testing.T) { } func TestEncryptedBackup(t *testing.T) { - defer tests.RemoveTestService() mnemonic := "limit reward expect search tissue call visa fit thank cream brave jump" unlockPassword := "123" - svc, err := tests.CreateTestServiceWithMnemonic(mnemonic, unlockPassword) + svc, err := tests.CreateTestServiceWithMnemonic(t, mnemonic, unlockPassword) require.NoError(t, err) + defer svc.Remove() albyOAuthSvc := NewAlbyOAuthService(svc.DB, svc.Cfg, svc.Keys, svc.EventPublisher) encryptedBackup, err := albyOAuthSvc.createEncryptedChannelBackup(&events.StaticChannelsBackupEvent{ diff --git a/api/backup.go b/api/backup.go index f4adc04cb..d51da850f 100644 --- a/api/backup.go +++ b/api/backup.go @@ -38,6 +38,10 @@ func (api *api) CreateBackup(unlockPassword string, w io.Writer) error { return errors.New("Please disable auto-unlock before using this feature") } + if api.db.Dialector.Name() != "sqlite" { + return errors.New("Migration with non-sqlite backend is currently not supported") + } + workDir, err := filepath.Abs(api.cfg.GetEnv().Workdir) if err != nil { return fmt.Errorf("failed to get absolute workdir: %w", err) diff --git a/cmd/db_migrate/main.go b/cmd/db_migrate/main.go new file mode 100644 index 000000000..df3680619 --- /dev/null +++ b/cmd/db_migrate/main.go @@ -0,0 +1,242 @@ +package main + +import ( + "flag" + "fmt" + "os" + "slices" + "strconv" + + "github.com/sirupsen/logrus" + "gorm.io/gorm" + + "github.com/getAlby/hub/db" + "github.com/getAlby/hub/logger" +) + +var expectedTables = []string{ + "apps", + "app_permissions", + "request_events", + "response_events", + "transactions", + "user_configs", + "migrations", +} + +func main() { + var fromDSN, toDSN string + + logger.Init(strconv.Itoa(int(logrus.DebugLevel))) + + flag.StringVar(&fromDSN, "from", "", "source DSN") + flag.StringVar(&toDSN, "to", "", "destination DSN") + + flag.Parse() + + if fromDSN == "" || toDSN == "" { + flag.Usage() + logger.Logger.Error("missing DSN") + os.Exit(1) + } + + stopDB := func(d *gorm.DB) { + if err := db.Stop(d); err != nil { + logger.Logger.WithError(err).Error("failed to close database") + } + } + + logger.Logger.Info("opening source DB...") + fromDB, err := db.NewDB(fromDSN, false) + if err != nil { + logger.Logger.WithError(err).Error("failed to open source database") + os.Exit(1) + } + defer stopDB(fromDB) + + logger.Logger.Info("opening destination DB...") + toDB, err := db.NewDB(toDSN, false) + if err != nil { + logger.Logger.WithError(err).Error("failed to open destination database") + os.Exit(1) + } + defer stopDB(toDB) + + // Migrations are applied to both the source and the target DB, so + // schemas should be equal at this point. + err = checkSchema(fromDB) + if err != nil { + logger.Logger.WithError(err).Error("database schema check failed; the migration tool may be outdated") + os.Exit(1) + } + + logger.Logger.Info("migrating...") + err = migrateDB(fromDB, toDB) + if err != nil { + logger.Logger.WithError(err).Error("failed to migrate database") + os.Exit(1) + } + + logger.Logger.Info("migration complete") +} + +func migrateDB(from, to *gorm.DB) error { + tx := to.Begin() + defer tx.Rollback() + + if err := tx.Error; err != nil { + return fmt.Errorf("failed to start transaction: %w", err) + } + + // Table migration order matters: referenced tables must be migrated + // before referencing tables. + + logger.Logger.Info("migrating apps...") + if err := migrateTable[db.App](from, tx); err != nil { + return fmt.Errorf("failed to migrate apps: %w", err) + } + + logger.Logger.Info("migrating app_permissions...") + if err := migrateTable[db.AppPermission](from, tx); err != nil { + return fmt.Errorf("failed to migrate app_permissions: %w", err) + } + + logger.Logger.Info("migrating request_events...") + if err := migrateTable[db.RequestEvent](from, tx); err != nil { + return fmt.Errorf("failed to migrate request_events: %w", err) + } + + logger.Logger.Info("migrating response_events...") + if err := migrateTable[db.ResponseEvent](from, tx); err != nil { + return fmt.Errorf("failed to migrate response_events: %w", err) + } + + logger.Logger.Info("migrating transactions...") + if err := migrateTable[db.Transaction](from, tx); err != nil { + return fmt.Errorf("failed to migrate transactions: %w", err) + } + + logger.Logger.Info("migrating user_configs...") + if err := migrateTable[db.UserConfig](from, tx); err != nil { + return fmt.Errorf("failed to migrate user_configs: %w", err) + } + + if to.Dialector.Name() == "postgres" { + logger.Logger.Info("resetting sequences...") + if err := resetSequences(to); err != nil { + return fmt.Errorf("failed to reset sequences: %w", err) + } + } + + tx.Commit() + if err := tx.Error; err != nil { + return fmt.Errorf("failed to commit transaction: %w", err) + } + + return nil +} + +func migrateTable[T any](from, to *gorm.DB) error { + var data []T + if err := from.Find(&data).Error; err != nil { + return fmt.Errorf("failed to fetch data: %w", err) + } + + if len(data) == 0 { + return nil + } + + if err := to.Create(data).Error; err != nil { + return fmt.Errorf("failed to insert data: %w", err) + } + + return nil +} + +func checkSchema(db *gorm.DB) error { + tables, err := listTables(db) + if err != nil { + return fmt.Errorf("failed to list database tables: %w", err) + } + + for _, table := range expectedTables { + if !slices.Contains(tables, table) { + return fmt.Errorf("table missing from the database: %q", table) + } + } + + for _, table := range tables { + if !slices.Contains(expectedTables, table) { + return fmt.Errorf("unexpected table found in the database: %q", table) + } + } + + return nil +} + +func listTables(db *gorm.DB) ([]string, error) { + var query string + + switch db.Dialector.Name() { + case "sqlite": + query = "SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%';" + case "postgres": + query = "SELECT tablename FROM pg_tables WHERE schemaname = 'public';" + default: + return nil, fmt.Errorf("unsupported database: %q", db.Dialector.Name()) + } + + rows, err := db.Raw(query).Rows() + if err != nil { + return nil, fmt.Errorf("failed to query table names: %w", err) + } + defer func() { + if err := rows.Close(); err != nil { + logger.Logger.WithError(err).Error("failed to close rows") + } + }() + + var tables []string + for rows.Next() { + var table string + if err := rows.Scan(&table); err != nil { + return nil, fmt.Errorf("failed to scan table name: %w", err) + } + tables = append(tables, table) + } + + return tables, nil +} + +func resetSequences(db *gorm.DB) error { + type resetReq struct { + table string + seq string + } + + resetReqs := []resetReq{ + {"apps", "apps_2_id_seq"}, + {"app_permissions", "app_permissions_2_id_seq"}, + {"request_events", "request_events_id_seq"}, + {"response_events", "response_events_id_seq"}, + {"transactions", "transactions_id_seq"}, + {"user_configs", "user_configs_id_seq"}, + } + + for _, req := range resetReqs { + if err := resetPostgresSequence(db, req.table, req.seq); err != nil { + return fmt.Errorf("failed to reset sequence %q for %q: %w", req.seq, req.table, err) + } + } + + return nil +} + +func resetPostgresSequence(db *gorm.DB, table string, seq string) error { + query := fmt.Sprintf("SELECT setval('%s', (SELECT MAX(id) FROM %s));", seq, table) + if err := db.Exec(query).Error; err != nil { + return fmt.Errorf("failed to execute setval(): %w", err) + } + + return nil +} diff --git a/cmd/db_migrate/migrate_test.go b/cmd/db_migrate/migrate_test.go new file mode 100644 index 000000000..cce55a27e --- /dev/null +++ b/cmd/db_migrate/migrate_test.go @@ -0,0 +1,179 @@ +package main + +import ( + "fmt" + "os" + "strconv" + "testing" + "time" + + "github.com/sirupsen/logrus" + "github.com/stretchr/testify/require" + "gorm.io/datatypes" + "gorm.io/gorm" + + "github.com/getAlby/hub/db" + "github.com/getAlby/hub/logger" + test_db "github.com/getAlby/hub/tests/db" +) + +type testEnvironment struct { + source *gorm.DB + dest *gorm.DB +} + +func (e *testEnvironment) cleanup(t *testing.T) { + err := db.Stop(e.source) + require.NoError(t, err) + + err = db.Stop(e.dest) + require.NoError(t, err) +} + +func TestMigrate(t *testing.T) { + type testCase struct { + name string + sourceURI string + destURI string + } + + // Test migration between sqlite instances for basic sanity checking. + tc := []testCase{ + { + name: "sqlite to sqlite", + sourceURI: getTestSqliteURI(0), + destURI: getTestSqliteURI(1), + }, + } + + // Only run Postgres tests if Postgres is configured and its URI is set. + if getTestPostgresURI() != "" { + tcPg := []testCase{ + { + name: "sqlite to postgres", + sourceURI: getTestSqliteURI(0), + destURI: getTestPostgresURI(), + }, + { + name: "postgres to sqlite", + sourceURI: getTestPostgresURI(), + destURI: getTestSqliteURI(0), + }, + } + + tc = append(tc, tcPg...) + } + + for _, tt := range tc { + t.Run(tt.name, func(t *testing.T) { + env, err := setupTest(t, tt.sourceURI, tt.destURI) + require.NoError(t, err) + defer env.cleanup(t) + + err = migrateDB(env.source, env.dest) + require.NoError(t, err) + }) + } +} + +func getTestSqliteURI(dbIndex int) string { + if uri := os.Getenv("TEST_DB_MIGRATE_SQLITE_URI"); uri != "" { + return uri + } + + return fmt.Sprintf("file:testmemdb%d?mode=memory&cache=shared&_txlock=immediate", dbIndex) +} + +func getTestPostgresURI() string { + return os.Getenv("TEST_DB_MIGRATE_POSTGRES_URI") +} + +func setupTest(t *testing.T, sourceURI string, destURI string) (*testEnvironment, error) { + logger.Init(strconv.Itoa(int(logrus.DebugLevel))) + + source, err := test_db.NewDBWithURI(t, sourceURI) + if err != nil { + t.Fatalf("failed to open source database: %v", err) + } + + dest, err := test_db.NewDBWithURI(t, destURI) + if err != nil { + t.Fatalf("failed to open destination database: %v", err) + } + + insertMockData(t, source) + + return &testEnvironment{ + source: source, + dest: dest, + }, nil +} + +func insertMockData(t *testing.T, tx *gorm.DB) { + baseTime := time.Date(2025, 01, 15, 8, 0, 0, 0, time.UTC) + + userCfg1 := &db.UserConfig{ + Key: "Relay", + Value: "wss://relay.getalby.com/v1", + Encrypted: false, + CreatedAt: baseTime, + UpdatedAt: baseTime, + } + create(t, tx, userCfg1) + + app1 := &db.App{ + Name: "test1", + Description: "test1 description", + AppPubkey: "2b7dea2866958f17c568cf024e113db7a3baa9c253a9016889196b8d0b11c7ae", + WalletPubkey: ptr("f766024546ddbdc45db6016714047e34117d5e0d68e51fae06ffca9687783995"), + CreatedAt: baseTime, + UpdatedAt: baseTime, + Isolated: false, + Metadata: datatypes.JSON("{}"), + } + create(t, tx, app1) + + app1Perm := &db.AppPermission{ + App: *app1, + Scope: "pay_invoice", + MaxAmountSat: 0, + BudgetRenewal: "monthly", + ExpiresAt: nil, + CreatedAt: baseTime, + UpdatedAt: baseTime, + } + create(t, tx, app1Perm) + + app2 := &db.App{ + Name: "test2", + Description: "test2 description", + AppPubkey: "560f31e764f7af64719aba1dfdc0bcb3e681d48bb76265ca939622e1a719fe2a", + WalletPubkey: ptr("b44c5b3e9c3105b9347cce9f4bbfc899df13c591976fe0f706c1aacd4358020b"), + CreatedAt: baseTime, + UpdatedAt: baseTime, + Isolated: false, + Metadata: datatypes.JSON("{}"), + } + create(t, tx, app2) + + app2Perm := &db.AppPermission{ + App: *app2, + Scope: "get_info", + MaxAmountSat: 0, + BudgetRenewal: "monthly", + ExpiresAt: nil, + CreatedAt: baseTime, + UpdatedAt: baseTime, + } + create(t, tx, app2Perm) +} + +func create[T any](t *testing.T, tx *gorm.DB, v T) *gorm.DB { + tx.Create(v) + require.NoError(t, tx.Error) + return tx +} + +func ptr[T any](v T) *T { + return &v +} diff --git a/db/db.go b/db/db.go index 364bb8433..f1934be53 100644 --- a/db/db.go +++ b/db/db.go @@ -2,25 +2,81 @@ package db import ( "fmt" + "strings" - "github.com/getAlby/hub/db/migrations" - "github.com/getAlby/hub/logger" + "gorm.io/driver/postgres" "gorm.io/driver/sqlite" "gorm.io/gorm" gorm_logger "gorm.io/gorm/logger" + + "github.com/getAlby/hub/db/migrations" + "github.com/getAlby/hub/logger" ) +type Config struct { + URI string + LogQueries bool + DriverName string +} + func NewDB(uri string, logDBQueries bool) (*gorm.DB, error) { + return NewDBWithConfig(&Config{ + URI: uri, + LogQueries: logDBQueries, + DriverName: "", + }) +} - config := &gorm.Config{ +func NewDBWithConfig(cfg *Config) (*gorm.DB, error) { + gormConfig := &gorm.Config{ TranslateError: true, } - if logDBQueries { - config.Logger = gorm_logger.Default.LogMode(gorm_logger.Info) + if cfg.LogQueries { + gormConfig.Logger = gorm_logger.Default.LogMode(gorm_logger.Info) + } + + var ret *gorm.DB + + if IsPostgresURI(cfg.URI) { + pgConfig := postgres.Config{ + DriverName: cfg.DriverName, + DSN: cfg.URI, + } + var err error + ret, err = newPostgresDB(pgConfig, gormConfig) + if err != nil { + return nil, err + } + } else { + sqliteURI := cfg.URI + // avoid SQLITE_BUSY errors with _txlock=IMMEDIATE + if !strings.Contains(sqliteURI, "_txlock=") { + sqliteURI = sqliteURI + "?_txlock=IMMEDIATE" + } + sqliteConfig := sqlite.Config{ + DriverName: cfg.DriverName, + DSN: sqliteURI, + } + var err error + ret, err = newSqliteDB(sqliteConfig, gormConfig) + if err != nil { + return nil, err + } } - // avoid SQLITE_BUSY errors with _txlock=IMMEDIATE - gormDB, err := gorm.Open(sqlite.Open(uri+"?_txlock=IMMEDIATE"), config) + logger.Logger.WithField("db_backend", ret.Dialector.Name()).Debug("loaded database") + + err := migrations.Migrate(ret) + if err != nil { + logger.Logger.WithError(err).Error("Failed to migrate") + return nil, err + } + + return ret, nil +} + +func newSqliteDB(sqliteConfig sqlite.Config, gormConfig *gorm.Config) (*gorm.DB, error) { + gormDB, err := gorm.Open(sqlite.New(sqliteConfig), gormConfig) if err != nil { return nil, err } @@ -65,9 +121,12 @@ func NewDB(uri string, logDBQueries bool) (*gorm.DB, error) { return nil, err } - err = migrations.Migrate(gormDB) + return gormDB, nil +} + +func newPostgresDB(pgConfig postgres.Config, gormConfig *gorm.Config) (*gorm.DB, error) { + gormDB, err := gorm.Open(postgres.New(pgConfig), gormConfig) if err != nil { - logger.Logger.WithError(err).Error("Failed to migrate") return nil, err } @@ -80,9 +139,13 @@ func Stop(db *gorm.DB) error { return fmt.Errorf("failed to get database connection: %w", err) } - err = db.Exec("PRAGMA wal_checkpoint(FULL)", nil).Error - if err != nil { - logger.Logger.WithError(err).Error("Failed to execute wal endpoint") + dbBackend := db.Dialector.Name() + logger.Logger.WithField("db_backend", dbBackend).Debug("shutting down database") + if dbBackend == "sqlite" { + err = db.Exec("PRAGMA wal_checkpoint(FULL)", nil).Error + if err != nil { + logger.Logger.WithError(err).Error("Failed to execute wal endpoint") + } } err = sqlDB.Close() @@ -91,3 +154,8 @@ func Stop(db *gorm.DB) error { } return nil } + +func IsPostgresURI(uri string) bool { + return strings.HasPrefix(uri, "postgresql://") || + strings.HasPrefix(uri, "postgres://") // Schema used by the "testdb" package. +} diff --git a/db/migrations/202401191539_initial_migration.go b/db/migrations/202401191539_initial_migration.go index 125d4c9bd..856d396f0 100644 --- a/db/migrations/202401191539_initial_migration.go +++ b/db/migrations/202401191539_initial_migration.go @@ -2,19 +2,22 @@ package migrations import ( _ "embed" + "text/template" "github.com/go-gormigrate/gormigrate/v2" "gorm.io/gorm" ) -//go:embed 202401191539_initial_migration.sql +//go:embed 202401191539_initial_migration.sql.tmpl var initialMigration string +var initialMigrationTmpl = template.Must(template.New("initial_migration").Parse(initialMigration)) + // Initial migration var _202401191539_initial_migration = &gormigrate.Migration{ ID: "202401191539_initial_migration", Migrate: func(tx *gorm.DB) error { - return tx.Exec(initialMigration).Error + return exec(tx, initialMigrationTmpl) }, Rollback: func(tx *gorm.DB) error { return nil diff --git a/db/migrations/202401191539_initial_migration.sql b/db/migrations/202401191539_initial_migration.sql deleted file mode 100644 index abf44c7be..000000000 --- a/db/migrations/202401191539_initial_migration.sql +++ /dev/null @@ -1,16 +0,0 @@ -CREATE TABLE `apps` (`id` integer,`name` text,`description` text,`nostr_pubkey` text UNIQUE,`created_at` datetime,`updated_at` datetime,PRIMARY KEY (`id`)); -CREATE TABLE `app_permissions` (`id` integer,`app_id` integer,`request_method` text,`max_amount` integer,`budget_renewal` text,`expires_at` datetime,`created_at` datetime,`updated_at` datetime,PRIMARY KEY (`id`),CONSTRAINT `fk_app_permissions_app` FOREIGN KEY (`app_id`) REFERENCES `apps`(`id`) ON DELETE CASCADE); -CREATE INDEX `idx_app_permissions_request_method` ON `app_permissions`(`request_method`); -CREATE INDEX `idx_app_permissions_app_id` ON `app_permissions`(`app_id`); -CREATE TABLE `payments` (`id` integer,`app_id` integer,`request_event_id` integer,`amount` integer,`payment_request` text,`preimage` text,`created_at` datetime,`updated_at` datetime,PRIMARY KEY (`id`),CONSTRAINT `fk_payments_app` FOREIGN KEY (`app_id`) REFERENCES `apps`(`id`) ON DELETE CASCADE,CONSTRAINT `fk_payments_request_event` FOREIGN KEY (`request_event_id`) REFERENCES `request_events`(`id`)); -CREATE INDEX `idx_payments_request_event_id` ON `payments`(`request_event_id`); -CREATE INDEX `idx_payments_app_id` ON `payments`(`app_id`); -CREATE TABLE "request_events" (`id` integer,`app_id` integer null,`nostr_id` text UNIQUE,`content` text,`state` text,`created_at` datetime,`updated_at` datetime,PRIMARY KEY (`id`),CONSTRAINT `fk_request_events_app` FOREIGN KEY (`app_id`) REFERENCES `apps`(`id`) ON DELETE CASCADE); -CREATE UNIQUE INDEX `idx_request_events_nostr_id` ON `request_events`(`nostr_id`); -CREATE INDEX `idx_request_events_app_id` ON `request_events`(`app_id`); -CREATE INDEX idx_payment_sum ON payments (app_id, preimage, created_at); -CREATE INDEX idx_request_events_app_id_and_id ON request_events(app_id, id); -CREATE TABLE "response_events" (`id` integer,`nostr_id` text UNIQUE,`request_id` integer,`content` text,`state` text,`replied_at` datetime,`created_at` datetime,`updated_at` datetime,PRIMARY KEY (`id`),CONSTRAINT `fk_response_events_request_event` FOREIGN KEY (`request_id`) REFERENCES `request_events`(`id`) ON DELETE CASCADE); -CREATE UNIQUE INDEX `idx_response_events_nostr_id` ON `response_events`(`nostr_id`); -CREATE TABLE "user_configs" ("id" integer, "key" text NOT NULL UNIQUE, "value" text, "encrypted" numeric, `created_at` datetime,`updated_at` datetime, PRIMARY KEY("id")); -CREATE UNIQUE INDEX "idx_user_configs_key" ON "user_configs" ("key"); diff --git a/db/migrations/202401191539_initial_migration.sql.tmpl b/db/migrations/202401191539_initial_migration.sql.tmpl new file mode 100644 index 000000000..675d1d585 --- /dev/null +++ b/db/migrations/202401191539_initial_migration.sql.tmpl @@ -0,0 +1,16 @@ +CREATE TABLE "apps" ("id" integer,"name" text,"description" text,"nostr_pubkey" text UNIQUE,"created_at" {{ .Timestamp }},"updated_at" {{ .Timestamp }},PRIMARY KEY ("id")); +CREATE TABLE "app_permissions" ("id" integer,"app_id" integer,"request_method" text,"max_amount" integer,"budget_renewal" text,"expires_at" {{ .Timestamp }},"created_at" {{ .Timestamp }},"updated_at" {{ .Timestamp }},PRIMARY KEY ("id"),CONSTRAINT "fk_app_permissions_app" FOREIGN KEY ("app_id") REFERENCES "apps"("id") ON DELETE CASCADE); +CREATE INDEX "idx_app_permissions_request_method" ON "app_permissions"("request_method"); +CREATE INDEX "idx_app_permissions_app_id" ON "app_permissions"("app_id"); +CREATE TABLE "request_events" ("id" integer,"app_id" integer null,"nostr_id" text UNIQUE,"content" text,"state" text,"created_at" {{ .Timestamp }},"updated_at" {{ .Timestamp }},PRIMARY KEY ("id"),CONSTRAINT "fk_request_events_app" FOREIGN KEY ("app_id") REFERENCES "apps"("id") ON DELETE CASCADE); +CREATE UNIQUE INDEX "idx_request_events_nostr_id" ON "request_events"("nostr_id"); +CREATE INDEX "idx_request_events_app_id" ON "request_events"("app_id"); +CREATE TABLE "payments" ("id" integer,"app_id" integer,"request_event_id" integer,"amount" integer,"payment_request" text,"preimage" text,"created_at" {{ .Timestamp }},"updated_at" {{ .Timestamp }},PRIMARY KEY ("id"),CONSTRAINT "fk_payments_app" FOREIGN KEY ("app_id") REFERENCES "apps"("id") ON DELETE CASCADE,CONSTRAINT "fk_payments_request_event" FOREIGN KEY ("request_event_id") REFERENCES "request_events"("id")); +CREATE INDEX "idx_payments_request_event_id" ON "payments"("request_event_id"); +CREATE INDEX "idx_payments_app_id" ON "payments"("app_id"); +CREATE INDEX idx_payment_sum ON payments (app_id, preimage, created_at); +CREATE INDEX idx_request_events_app_id_and_id ON request_events(app_id, id); +CREATE TABLE "response_events" ("id" integer,"nostr_id" text UNIQUE,"request_id" integer,"content" text,"state" text,"replied_at" {{ .Timestamp }},"created_at" {{ .Timestamp }},"updated_at" {{ .Timestamp }},PRIMARY KEY ("id"),CONSTRAINT "fk_response_events_request_event" FOREIGN KEY ("request_id") REFERENCES "request_events"("id") ON DELETE CASCADE); +CREATE UNIQUE INDEX "idx_response_events_nostr_id" ON "response_events"("nostr_id"); +CREATE TABLE "user_configs" ("id" integer, "key" text NOT NULL UNIQUE, "value" text, "encrypted" numeric, "created_at" {{ .Timestamp }},"updated_at" {{ .Timestamp }}, PRIMARY KEY("id")); +CREATE UNIQUE INDEX "idx_user_configs_key" ON "user_configs" ("key"); diff --git a/db/migrations/202404021909_nullable_expires_at.go b/db/migrations/202404021909_nullable_expires_at.go index 525b49508..bebd311c2 100644 --- a/db/migrations/202404021909_nullable_expires_at.go +++ b/db/migrations/202404021909_nullable_expires_at.go @@ -13,7 +13,7 @@ var _202404021909_nullable_expires_at = &gormigrate.Migration{ ID: "202404021909_nullable_expires_at", Migrate: func(tx *gorm.DB) error { - err := tx.Exec(`update app_permissions set expires_at = NULL where expires_at = "0001-01-01 00:00:00+00:00"`).Error + err := tx.Exec(`update app_permissions set expires_at = NULL where expires_at = '0001-01-01 00:00:00+00:00'`).Error return err }, diff --git a/db/migrations/202405302121_store_decrypted_request.go b/db/migrations/202405302121_store_decrypted_request.go index e5bb5ad09..7c445bd4d 100644 --- a/db/migrations/202405302121_store_decrypted_request.go +++ b/db/migrations/202405302121_store_decrypted_request.go @@ -11,17 +11,17 @@ var _202405302121_store_decrypted_request = &gormigrate.Migration{ ID: "_202405302121_store_decrypted_request", Migrate: func(tx *gorm.DB) error { - err := tx.Exec("ALTER TABLE request_events ADD COLUMN method TEXT;").Error + err := tx.Exec(`ALTER TABLE request_events ADD COLUMN method TEXT;`).Error if err != nil { return err } - err = tx.Exec("CREATE INDEX `idx_request_events_method` ON `request_events`(`method`);").Error + err = tx.Exec(`CREATE INDEX "idx_request_events_method" ON "request_events"("method");`).Error if err != nil { return err } - err = tx.Exec("ALTER TABLE request_events ADD COLUMN content_data TEXT").Error + err = tx.Exec(`ALTER TABLE request_events ADD COLUMN content_data TEXT`).Error return err }, Rollback: func(tx *gorm.DB) error { diff --git a/db/migrations/202406061259_delete_content.go b/db/migrations/202406061259_delete_content.go index 1d9850e17..f267f9ddb 100644 --- a/db/migrations/202406061259_delete_content.go +++ b/db/migrations/202406061259_delete_content.go @@ -19,9 +19,13 @@ var _202406061259_delete_content = &gormigrate.Migration{ return err } - if err := tx.Exec("VACUUM").Error; err != nil { - return err - } + // Disabled for now: not used. + // Cannot run when testing with txdb: VACUUM must be run outside of transaction. + // if !testing.Testing() { + // if err := tx.Exec("VACUUM").Error; err != nil { + // return err + // } + // } return nil }, diff --git a/db/migrations/202406071726_vacuum.go b/db/migrations/202406071726_vacuum.go index d405cbfdc..dc8c1646f 100644 --- a/db/migrations/202406071726_vacuum.go +++ b/db/migrations/202406071726_vacuum.go @@ -15,9 +15,13 @@ import ( var _202406071726_vacuum = &gormigrate.Migration{ ID: "202406071726_vacuum", Migrate: func(tx *gorm.DB) error { - if err := tx.Exec("VACUUM").Error; err != nil { - return err - } + // Disabled for now: not used. + // Cannot run when testing with txdb: VACUUM must be run outside of transaction. + // if !testing.Testing() { + // if err := tx.Exec("VACUUM").Error; err != nil { + // return err + // } + // } return nil }, diff --git a/db/migrations/202407012100_transactions.go b/db/migrations/202407012100_transactions.go index 7c978202f..6fe2feb16 100644 --- a/db/migrations/202407012100_transactions.go +++ b/db/migrations/202407012100_transactions.go @@ -2,24 +2,15 @@ package migrations import ( _ "embed" + "text/template" "github.com/go-gormigrate/gormigrate/v2" "gorm.io/gorm" ) -// This migration -// - Replaces the old payments table with a new transactions table -// - Adds new properties to apps -// - isolated boolean -// -// - Renames max amount on app permissions to be clear its in sats -var _202407012100_transactions = &gormigrate.Migration{ - ID: "202407012100_transactions", - Migrate: func(tx *gorm.DB) error { - - if err := tx.Exec(` +const transactionsMigration = ` CREATE TABLE transactions( - id integer PRIMARY KEY AUTOINCREMENT, + id {{ .AutoincrementPrimaryKey }}, app_id integer, request_event_id integer, type text, @@ -32,10 +23,10 @@ CREATE TABLE transactions( amount_msat integer, fee_msat integer, fee_reserve_msat integer, - created_at datetime, - updated_at datetime, - expires_at datetime, - settled_at datetime, + created_at {{ .Timestamp }}, + updated_at {{ .Timestamp }}, + expires_at {{ .Timestamp }}, + settled_at {{ .Timestamp }}, metadata text, self_payment boolean ); @@ -46,8 +37,21 @@ ALTER TABLE apps ADD isolated boolean; UPDATE apps set isolated = false; ALTER TABLE app_permissions RENAME COLUMN max_amount TO max_amount_sat; +` + +var transactionsMigrationTmpl = template.Must(template.New("transactionsMigration").Parse(transactionsMigration)) + +// This migration +// - Replaces the old payments table with a new transactions table +// - Adds new properties to apps +// - isolated boolean +// +// - Renames max amount on app permissions to be clear its in sats +var _202407012100_transactions = &gormigrate.Migration{ + ID: "202407012100_transactions", + Migrate: func(tx *gorm.DB) error { -`).Error; err != nil { + if err := exec(tx, transactionsMigrationTmpl); err != nil { return err } diff --git a/db/migrations/202407151352_autoincrement.go b/db/migrations/202407151352_autoincrement.go index 48ecb7f8e..fbc28c3f3 100644 --- a/db/migrations/202407151352_autoincrement.go +++ b/db/migrations/202407151352_autoincrement.go @@ -2,11 +2,47 @@ package migrations import ( _ "embed" + "text/template" "github.com/go-gormigrate/gormigrate/v2" "gorm.io/gorm" ) +const dropMigration = ` +DROP TABLE request_events {{ .DropTableCascade }}; +DROP TABLE response_events; +` + +var dropMigrationTmpl = template.Must(template.New("dropMigration").Parse(dropMigration)) + +const appsMigration = ` +DELETE FROM app_permissions WHERE app_id NOT IN (SELECT id FROM apps); +CREATE TABLE apps_2 (id {{ .AutoincrementPrimaryKey }},name text,description text,nostr_pubkey text UNIQUE,created_at {{ .Timestamp }},updated_at {{ .Timestamp }}, isolated boolean); +INSERT INTO apps_2 (id, name, description, nostr_pubkey, created_at, updated_at, isolated) SELECT id, name text, description, nostr_pubkey, created_at, updated_at, isolated FROM apps; +CREATE TABLE app_permissions_2 (id {{ .AutoincrementPrimaryKey }},app_id integer,"scope" text,"max_amount_sat" integer,budget_renewal text,expires_at {{ .Timestamp }},created_at {{ .Timestamp }},updated_at {{ .Timestamp }},CONSTRAINT fk_app_permissions_app FOREIGN KEY (app_id) REFERENCES apps_2(id) ON DELETE CASCADE); +INSERT INTO app_permissions_2 (id, app_id, scope, max_amount_sat, budget_renewal, expires_at, created_at, updated_at) SELECT id, app_id, scope, max_amount_sat, budget_renewal, expires_at, created_at, updated_at FROM app_permissions; + +DROP TABLE apps {{ .DropTableCascade }}; +ALTER TABLE apps_2 RENAME TO apps; +DROP TABLE app_permissions; +ALTER TABLE app_permissions_2 RENAME TO app_permissions; + +CREATE INDEX idx_app_permissions_scope ON app_permissions("scope"); +CREATE INDEX idx_app_permissions_app_id ON app_permissions(app_id); +` + +var appsMigrationTmpl = template.Must(template.New("appsMigration").Parse(appsMigration)) + +const reqRespMigration = ` +CREATE TABLE "request_events" (id {{ .AutoincrementPrimaryKey }},app_id integer,nostr_id text UNIQUE,state text,created_at {{ .Timestamp }},updated_at {{ .Timestamp }}, method TEXT, content_data TEXT,CONSTRAINT fk_request_events_app FOREIGN KEY (app_id) REFERENCES apps(id) ON DELETE CASCADE); +CREATE INDEX idx_request_events_app_id ON request_events(app_id); +CREATE INDEX idx_request_events_app_id_and_id ON request_events(app_id, id); +CREATE INDEX idx_request_events_method ON request_events(method); +CREATE TABLE "response_events" (id {{ .AutoincrementPrimaryKey }},nostr_id text UNIQUE,request_id integer,state text,replied_at {{ .Timestamp }},created_at {{ .Timestamp }},updated_at {{ .Timestamp }},CONSTRAINT fk_response_events_request_event FOREIGN KEY (request_id) REFERENCES request_events(id) ON DELETE CASCADE); +` + +var reqRespMigrationTmpl = template.Must(template.New("reqRespMigration").Parse(reqRespMigration)) + // This migration (inside a DB transaction), // - Adds AUTOINCREMENT to the primary key of: // - apps, app_permissions, request_events, response_events @@ -22,42 +58,19 @@ var _202407151352_autoincrement = &gormigrate.Migration{ if err := db.Transaction(func(tx *gorm.DB) error { // drop old request and response event tables - if err := tx.Exec(` -DROP TABLE request_events; -DROP TABLE response_events; -`).Error; err != nil { + if err := exec(tx, dropMigrationTmpl); err != nil { return err } // Apps & app permissions (interdependent) // create new tables, copy old values, delete old tables, rename new tables, create new indexes // also deletes broken app permissions no longer linked to apps (from reused app IDs) - if err := tx.Exec(` -DELETE FROM app_permissions WHERE app_id NOT IN (SELECT id FROM apps); -CREATE TABLE apps_2 (id integer PRIMARY KEY AUTOINCREMENT,name text,description text,nostr_pubkey text UNIQUE,created_at datetime,updated_at datetime, isolated boolean); -INSERT INTO apps_2 (id, name, description, nostr_pubkey, created_at, updated_at, isolated) SELECT id, name text, description, nostr_pubkey, created_at, updated_at, isolated FROM apps; -CREATE TABLE app_permissions_2 (id integer PRIMARY KEY AUTOINCREMENT,app_id integer,"scope" text,"max_amount_sat" integer,budget_renewal text,expires_at datetime,created_at datetime,updated_at datetime,CONSTRAINT fk_app_permissions_app FOREIGN KEY (app_id) REFERENCES apps_2(id) ON DELETE CASCADE); -INSERT INTO app_permissions_2 (id, app_id, scope, max_amount_sat, budget_renewal, expires_at, created_at, updated_at) SELECT id, app_id, scope, max_amount_sat, budget_renewal, expires_at, created_at, updated_at FROM app_permissions; - -DROP TABLE apps; -ALTER TABLE apps_2 RENAME TO apps; -DROP TABLE app_permissions; -ALTER TABLE app_permissions_2 RENAME TO app_permissions; - -CREATE INDEX idx_app_permissions_scope ON app_permissions("scope"); -CREATE INDEX idx_app_permissions_app_id ON app_permissions(app_id); -`).Error; err != nil { + if err := exec(tx, appsMigrationTmpl); err != nil { return err } // create fresh request and response event tables - if err := tx.Exec(` -CREATE TABLE "request_events" (id integer PRIMARY KEY AUTOINCREMENT,app_id integer,nostr_id text UNIQUE,state text,created_at datetime,updated_at datetime, method TEXT, content_data TEXT,CONSTRAINT fk_request_events_app FOREIGN KEY (app_id) REFERENCES apps(id) ON DELETE CASCADE); -CREATE INDEX idx_request_events_app_id ON request_events(app_id); -CREATE INDEX idx_request_events_app_id_and_id ON request_events(app_id, id); -CREATE INDEX idx_request_events_method ON request_events(method); -CREATE TABLE "response_events" (id integer PRIMARY KEY AUTOINCREMENT,nostr_id text UNIQUE,request_id integer,state text,replied_at datetime,created_at datetime,updated_at datetime,CONSTRAINT fk_response_events_request_event FOREIGN KEY (request_id) REFERENCES request_events(id) ON DELETE CASCADE); -`).Error; err != nil { + if err := exec(tx, reqRespMigrationTmpl); err != nil { return err } diff --git a/db/migrations/202407262257_remove_invalid_scopes.go b/db/migrations/202407262257_remove_invalid_scopes.go index 903c396c0..0d0da5aee 100644 --- a/db/migrations/202407262257_remove_invalid_scopes.go +++ b/db/migrations/202407262257_remove_invalid_scopes.go @@ -13,9 +13,9 @@ var _202407262257_remove_invalid_scopes = &gormigrate.Migration{ Migrate: func(tx *gorm.DB) error { if err := tx.Exec(` -delete from app_permissions where scope = "pay_keysend"; -delete from app_permissions where scope = "multi_pay_keysend"; -delete from app_permissions where scope = "multi_pay_invoice"; +delete from app_permissions where scope = 'pay_keysend'; +delete from app_permissions where scope = 'multi_pay_keysend'; +delete from app_permissions where scope = 'multi_pay_invoice'; `).Error; err != nil { return err } diff --git a/db/migrations/202408061737_add_boostagrams_and_use_json.go b/db/migrations/202408061737_add_boostagrams_and_use_json.go index ab7f48c7f..ba6d4d4db 100644 --- a/db/migrations/202408061737_add_boostagrams_and_use_json.go +++ b/db/migrations/202408061737_add_boostagrams_and_use_json.go @@ -15,7 +15,7 @@ var _202408061737_add_boostagrams_and_use_json = &gormigrate.Migration{ return tx.Exec(` ALTER TABLE transactions ADD COLUMN boostagram JSON; ALTER TABLE transactions ADD COLUMN metadata_temp JSON; - UPDATE transactions SET metadata_temp = json(metadata) where metadata != ""; + UPDATE transactions SET metadata_temp = json(metadata) where metadata != ''; ALTER TABLE transactions DROP COLUMN metadata; ALTER TABLE transactions RENAME COLUMN metadata_temp TO metadata; `).Error diff --git a/db/migrations/202408191242_transaction_failure_reason.go b/db/migrations/202408191242_transaction_failure_reason.go index ab1af2452..214e5e304 100644 --- a/db/migrations/202408191242_transaction_failure_reason.go +++ b/db/migrations/202408191242_transaction_failure_reason.go @@ -13,7 +13,7 @@ var _202408191242_transaction_failure_reason = &gormigrate.Migration{ Migrate: func(tx *gorm.DB) error { if err := tx.Exec(` - ALTER TABLE transactions ADD failure_reason string; + ALTER TABLE transactions ADD failure_reason text; `).Error; err != nil { return err } diff --git a/db/migrations/202412212345_fix_types.go b/db/migrations/202412212345_fix_types.go new file mode 100644 index 000000000..7a5d3e2df --- /dev/null +++ b/db/migrations/202412212345_fix_types.go @@ -0,0 +1,37 @@ +package migrations + +import ( + "github.com/go-gormigrate/gormigrate/v2" + "gorm.io/gorm" +) + +// This migration fixes column types for Postgres compatibility. +// +// First, an autoincrement sequence is created for user_configs.id (this works +// in sqlite, because an integer primary key becomes "autoincrement" +// automatically). +// +// Second, user_configs.encrypted is converted into a boolean; otherwise, +// it fails to de/serialize from/to the Go model's `Encrypted bool` field. +// Again, this happens to work in sqlite due to the way booleans are handled +// (they're just an alias for numeric). +var _202412212345_fix_types = &gormigrate.Migration{ + ID: "20241221234500_fix_types", + Migrate: func(tx *gorm.DB) error { + if tx.Dialector.Name() == "postgres" { + err := tx.Exec(` +CREATE SEQUENCE user_configs_id_seq; +ALTER TABLE user_configs ALTER COLUMN id SET DEFAULT nextval('user_configs_id_seq'); +ALTER SEQUENCE user_configs_id_seq OWNED BY user_configs.id; +ALTER TABLE user_configs ALTER COLUMN encrypted SET DATA TYPE BOOLEAN USING encrypted::integer::boolean; +`).Error + if err != nil { + return err + } + } + return nil + }, + Rollback: func(tx *gorm.DB) error { + return nil + }, +} diff --git a/db/migrations/migrate.go b/db/migrations/migrate.go index fe2ff05a4..fc0f4bbea 100644 --- a/db/migrations/migrate.go +++ b/db/migrations/migrate.go @@ -1,6 +1,10 @@ package migrations import ( + "fmt" + "strings" + "text/template" + "github.com/go-gormigrate/gormigrate/v2" "gorm.io/gorm" ) @@ -23,7 +27,46 @@ func Migrate(gormDB *gorm.DB) error { _202408191242_transaction_failure_reason, _202408291715_app_metadata, _202410141503_add_wallet_pubkey, + _202412212345_fix_types, }) return m.Migrate() } + +type sqlDialectDef struct { + Timestamp string + AutoincrementPrimaryKey string + DropTableCascade string +} + +var sqlDialectSqlite = sqlDialectDef{ + Timestamp: "datetime", + AutoincrementPrimaryKey: "INTEGER PRIMARY KEY AUTOINCREMENT", + DropTableCascade: "", +} + +var sqlDialectPostgres = sqlDialectDef{ + Timestamp: "timestamptz", + AutoincrementPrimaryKey: "SERIAL PRIMARY KEY", + DropTableCascade: "CASCADE", +} + +func getDialect(tx *gorm.DB) *sqlDialectDef { + switch tx.Dialector.Name() { + case "postgres": + return &sqlDialectPostgres + default: + return &sqlDialectSqlite + } +} + +func exec(tx *gorm.DB, templ *template.Template) error { + dialect := getDialect(tx) + var buf strings.Builder + err := templ.Execute(&buf, dialect) + if err != nil { + panic(fmt.Sprintf("failed to render SQL template: %v", err)) + } + + return tx.Exec(buf.String()).Error +} diff --git a/db/queries/get_isolated_balance_test.go b/db/queries/get_isolated_balance_test.go index 773e5e0da..0a3cff60b 100644 --- a/db/queries/get_isolated_balance_test.go +++ b/db/queries/get_isolated_balance_test.go @@ -3,17 +3,18 @@ package queries import ( "testing" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/getAlby/hub/constants" "github.com/getAlby/hub/db" "github.com/getAlby/hub/tests" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) func TestGetIsolatedBalance_PendingNoOverflow(t *testing.T) { - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() app, _, err := tests.CreateApp(svc) assert.NoError(t, err) @@ -40,9 +41,9 @@ func TestGetIsolatedBalance_PendingNoOverflow(t *testing.T) { } func TestGetIsolatedBalance_SettledNoOverflow(t *testing.T) { - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() app, _, err := tests.CreateApp(svc) assert.NoError(t, err) diff --git a/go.mod b/go.mod index 05942382e..73e35611e 100644 --- a/go.mod +++ b/go.mod @@ -15,6 +15,7 @@ require ( github.com/nbd-wtf/go-nostr v0.46.0 github.com/nbd-wtf/ln-decodepay v1.13.0 github.com/orandin/lumberjackrus v1.0.1 + github.com/peterldowns/pgtestdb v0.1.1 github.com/stretchr/testify v1.10.0 github.com/tyler-smith/go-bip39 v1.1.0 github.com/wailsapp/wails/v2 v2.9.2 @@ -23,6 +24,7 @@ require ( google.golang.org/grpc v1.68.0 gopkg.in/DataDog/dd-trace-go.v1 v1.70.3 gopkg.in/macaroon.v2 v2.1.0 + gorm.io/driver/postgres v1.5.0 gorm.io/driver/sqlite v1.5.7 gorm.io/gorm v1.25.12 ) @@ -170,6 +172,7 @@ require ( github.com/spf13/pflag v1.0.5 // indirect github.com/stretchr/objx v0.5.2 // indirect github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect + github.com/testcontainers/testcontainers-go v0.32.0 // indirect github.com/tidwall/gjson v1.18.0 // indirect github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.1 // indirect diff --git a/go.sum b/go.sum index a878c43e2..d4a811fa9 100644 --- a/go.sum +++ b/go.sum @@ -47,8 +47,8 @@ github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0 github.com/Microsoft/go-winio v0.5.0/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= -github.com/Microsoft/hcsshim v0.11.4 h1:68vKo2VN8DE9AdN4tnkWnmdhqdbpUFM8OF3Airm7fz8= -github.com/Microsoft/hcsshim v0.11.4/go.mod h1:smjE4dvqPX9Zldna+t5FG3rnoHhaB7QYxPRqGcpAD9w= +github.com/Microsoft/hcsshim v0.11.5 h1:haEcLNpj9Ka1gd3B3tAEs9CpE0c+1IhoL59w/exYU38= +github.com/Microsoft/hcsshim v0.11.5/go.mod h1:MV8xMfmECjl5HdO7U/3/hFVnkmSBjAjmA09d4bExKcU= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= github.com/adrg/xdg v0.5.3 h1:xRnxJXne7+oWDatRhR1JLnvuccuIeCoBu2rtuLqQB78= @@ -131,10 +131,12 @@ github.com/cockroachdb/datadriven v1.0.2 h1:H9MtNqVoVhvd9nCBwOyDjUEdZCREqbIdCJD9 github.com/cockroachdb/datadriven v1.0.2/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= github.com/coder/websocket v1.8.12 h1:5bUXkEPPIbewrnkU8LTCLVaxi4N4J8ahufH2vlo4NAo= github.com/coder/websocket v1.8.12/go.mod h1:LNVeNrXQZfe5qhS9ALED3uA+l5pPqvwXg3CKoDBB2gs= -github.com/containerd/containerd v1.7.15 h1:afEHXdil9iAm03BmhjzKyXnnEBtjaLJefdU7DV0IFes= -github.com/containerd/containerd v1.7.15/go.mod h1:ISzRRTMF8EXNpJlTzyr2XMhN+j9K302C21/+cr3kUnY= +github.com/containerd/containerd v1.7.18 h1:jqjZTQNfXGoEaZdW1WwPU0RqSn1Bm2Ay/KJPUuO8nao= +github.com/containerd/containerd v1.7.18/go.mod h1:IYEk9/IO6wAPUz2bCMVUbsfXjzw5UNP5fLz4PsUygQ4= github.com/containerd/continuity v0.4.3 h1:6HVkalIp+2u1ZLH1J/pYX2oBVXlJZvh1X1A7bEZ9Su8= github.com/containerd/continuity v0.4.3/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ= +github.com/containerd/errdefs v0.1.0 h1:m0wCRBiu1WJT/Fr+iOoQHMQS/eP5myQ8lCv4Dz5ZURM= +github.com/containerd/errdefs v0.1.0/go.mod h1:YgWiiHtLmSeBrvpw+UfPijzbLaB77mEG1WwJTDETIV0= github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4= @@ -362,12 +364,14 @@ github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgS github.com/jackc/pgx/v4 v4.18.2/go.mod h1:Ey4Oru5tH5sB6tV7hDmfWFahwF15Eb7DNXlRKx2CkVw= github.com/jackc/pgx/v4 v4.18.3 h1:dE2/TrEsGX3RBprb3qryqSV9Y60iZN1C6i8IrmW9/BA= github.com/jackc/pgx/v4 v4.18.3/go.mod h1:Ey4Oru5tH5sB6tV7hDmfWFahwF15Eb7DNXlRKx2CkVw= +github.com/jackc/pgx/v5 v5.3.0/go.mod h1:t3JDKnCBlYIc0ewLF0Q7B8MXmoIaBOZj/ic7iHozM/8= github.com/jackc/pgx/v5 v5.7.1 h1:x7SYsPBYDkHDksogeSmZZ5xzThcTgRz++I5E+ePFUcs= github.com/jackc/pgx/v5 v5.7.1/go.mod h1:e7O26IywZZ+naJtWWos6i6fvWK+29etgITqrqHLfoZA= github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.3.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackc/puddle/v2 v2.2.0/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo= github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e h1:Q3+PugElBCf4PFpxhErSzU3/PY5sFL5Z6rfv4AbGAck= @@ -412,6 +416,7 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxv github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= @@ -564,6 +569,10 @@ github.com/ory/dockertest/v3 v3.11.0 h1:OiHcxKAvSDUwsEVh2BjxQQc/5EHz9n0va9awCtNG github.com/ory/dockertest/v3 v3.11.0/go.mod h1:VIPxS1gwT9NpPOrfD3rACs8Y9Z7yhzO4SB194iUDnUI= github.com/outcaste-io/ristretto v0.2.3 h1:AK4zt/fJ76kjlYObOeNwh4T3asEuaCmp26pOvUOL9w0= github.com/outcaste-io/ristretto v0.2.3/go.mod h1:W8HywhmtlopSB1jeMg3JtdIhf+DYkLAr0VN/s4+MHac= +github.com/peterldowns/pgtestdb v0.1.1 h1:+hBCD1DcbKeg5Sfg0G+5WNIy/Cm0ORgwMkF4ygihrmU= +github.com/peterldowns/pgtestdb v0.1.1/go.mod h1:yVWInWV0dxvmLdL2ao3nXDzWZ9+G6EhJ4gRwvI1Ozeg= +github.com/peterldowns/testy v0.0.1 h1:9a6LzvnKcL52Crzud1z7jbsAojTntCh89ho6mgsr4KU= +github.com/peterldowns/testy v0.0.1/go.mod h1:J4sm75UEzbfBIcq0zbrshWWjsJQiJ5RrhTPYKVY2Ww8= github.com/philhofer/fwd v1.1.3-0.20240612014219-fbbf4953d986 h1:jYi87L8j62qkXzaYHAQAhEapgukhenIMZRBKTNRLHJ4= github.com/philhofer/fwd v1.1.3-0.20240612014219-fbbf4953d986/go.mod h1:RqIHx9QI14HlwKwm98g9Re5prTQ6LdeRQn+gXJFxsJM= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= @@ -598,6 +607,7 @@ github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6So github.com/rogpeppe/fastuuid v1.2.0 h1:Ppwyp6VYCF1nvBTXL3trRso7mXMlRrw9ooo375wvi2s= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= @@ -652,8 +662,8 @@ github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d h1:vfofYNRScrDdvS342BElfbETmL1Aiz3i2t0zfRj16Hs= github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= -github.com/testcontainers/testcontainers-go v0.31.0 h1:W0VwIhcEVhRflwL9as3dhY6jXjVCA27AkmbnZ+UTh3U= -github.com/testcontainers/testcontainers-go v0.31.0/go.mod h1:D2lAoA0zUFiSY+eAflqK5mcUx/A5hrrORaEQrd0SefI= +github.com/testcontainers/testcontainers-go v0.32.0 h1:ug1aK08L3gCHdhknlTTwWjPHPS+/alvLJU/DRxTD/ME= +github.com/testcontainers/testcontainers-go v0.32.0/go.mod h1:CRHrzHLQhlXUsa5gXjTOfqIEJcrK5+xMDmBr/WMI88E= github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY= github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= @@ -784,6 +794,7 @@ golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWP golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.20.0/go.mod h1:Xwo95rrVNIoSMx9wa1JroENMToLWn3RNVrTBpLHgZPQ= golang.org/x/crypto v0.30.0 h1:RwoQn3GkWiMkzlX562cLB7OxWvjH1L8xutO2WoJcRoY= @@ -1012,6 +1023,7 @@ gorm.io/driver/sqlite v1.5.7 h1:8NvsrhP0ifM7LX9G4zPB97NwovUakUxc+2V2uuf3Z1I= gorm.io/driver/sqlite v1.5.7/go.mod h1:U+J8craQU6Fzkcvu8oLeAQmi50TkwPEhHDEjQZXDah4= gorm.io/driver/sqlserver v1.5.4 h1:xA+Y1KDNspv79q43bPyjDMUgHoYHLhXYmdFcYPobg8g= gorm.io/driver/sqlserver v1.5.4/go.mod h1:+frZ/qYmuna11zHPlh5oc2O6ZA/lS88Keb0XSH1Zh/g= +gorm.io/gorm v1.24.7-0.20230306060331-85eaf9eeda11/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8= gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ= diff --git a/lnclient/ldk/ldk_test.go b/lnclient/ldk/ldk_test.go index 0edf141b0..f993e8aa5 100644 --- a/lnclient/ldk/ldk_test.go +++ b/lnclient/ldk/ldk_test.go @@ -3,18 +3,19 @@ package ldk import ( "testing" - "github.com/getAlby/hub/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/getAlby/hub/tests" ) func TestGetVssNodeIdentifier(t *testing.T) { mnemonic := "thought turkey ask pottery head say catalog desk pledge elbow naive mimic" expectedVssNodeIdentifier := "751636" - defer tests.RemoveTestService() - svc, err := tests.CreateTestServiceWithMnemonic(mnemonic, "123") + svc, err := tests.CreateTestServiceWithMnemonic(t, mnemonic, "123") require.NoError(t, err) + defer svc.Remove() vssNodeIdentifier, err := GetVssNodeIdentifier(svc.Keys) require.NoError(t, err) @@ -25,9 +26,9 @@ func TestGetVssNodeIdentifier2(t *testing.T) { mnemonic := "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about" expectedVssNodeIdentifier := "770256" - defer tests.RemoveTestService() - svc, err := tests.CreateTestServiceWithMnemonic(mnemonic, "123") + svc, err := tests.CreateTestServiceWithMnemonic(t, mnemonic, "123") require.NoError(t, err) + defer svc.Remove() vssNodeIdentifier, err := GetVssNodeIdentifier(svc.Keys) require.NoError(t, err) diff --git a/nip47/controllers/get_balance_controller_test.go b/nip47/controllers/get_balance_controller_test.go index 551211376..b19310244 100644 --- a/nip47/controllers/get_balance_controller_test.go +++ b/nip47/controllers/get_balance_controller_test.go @@ -25,9 +25,9 @@ const nip47GetBalanceJson = ` func TestHandleGetBalanceEvent(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() nip47Request := &models.Request{} err = json.Unmarshal([]byte(nip47GetBalanceJson), nip47Request) @@ -57,9 +57,9 @@ func TestHandleGetBalanceEvent(t *testing.T) { func TestHandleGetBalanceEvent_IsolatedApp_NoTransactions(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() nip47Request := &models.Request{} err = json.Unmarshal([]byte(nip47GetBalanceJson), nip47Request) @@ -90,9 +90,9 @@ func TestHandleGetBalanceEvent_IsolatedApp_NoTransactions(t *testing.T) { } func TestHandleGetBalanceEvent_IsolatedApp_Transactions(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() nip47Request := &models.Request{} err = json.Unmarshal([]byte(nip47GetBalanceJson), nip47Request) diff --git a/nip47/controllers/get_budget_controller_test.go b/nip47/controllers/get_budget_controller_test.go index 64df460de..93b1c8424 100644 --- a/nip47/controllers/get_budget_controller_test.go +++ b/nip47/controllers/get_budget_controller_test.go @@ -26,9 +26,9 @@ const nip47GetBudgetJson = ` func TestHandleGetBudgetEvent_NoRenewal(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() nip47Request := &models.Request{} err = json.Unmarshal([]byte(nip47GetBudgetJson), nip47Request) @@ -71,9 +71,9 @@ func TestHandleGetBudgetEvent_NoRenewal(t *testing.T) { func TestHandleGetBudgetEvent_NoneUsed(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() nip47Request := &models.Request{} err = json.Unmarshal([]byte(nip47GetBudgetJson), nip47Request) @@ -118,9 +118,9 @@ func TestHandleGetBudgetEvent_NoneUsed(t *testing.T) { func TestHandleGetBudgetEvent_HalfUsed(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() nip47Request := &models.Request{} err = json.Unmarshal([]byte(nip47GetBudgetJson), nip47Request) @@ -172,9 +172,9 @@ func TestHandleGetBudgetEvent_HalfUsed(t *testing.T) { func TestHandleGetBudgetEvent_NoBudget(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() nip47Request := &models.Request{} err = json.Unmarshal([]byte(nip47GetBudgetJson), nip47Request) @@ -219,9 +219,9 @@ func TestHandleGetBudgetEvent_NoBudget(t *testing.T) { func TestHandleGetBudgetEvent_NoPayInvoicePermission(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() nip47Request := &models.Request{} err = json.Unmarshal([]byte(nip47GetBudgetJson), nip47Request) diff --git a/nip47/controllers/get_info_controller_test.go b/nip47/controllers/get_info_controller_test.go index 0ec97f4a7..d63536ca9 100644 --- a/nip47/controllers/get_info_controller_test.go +++ b/nip47/controllers/get_info_controller_test.go @@ -25,9 +25,9 @@ const nip47GetInfoJson = ` func TestHandleGetInfoEvent_NoPermission(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() app, _, err := tests.CreateApp(svc) assert.NoError(t, err) @@ -74,9 +74,9 @@ func TestHandleGetInfoEvent_NoPermission(t *testing.T) { func TestHandleGetInfoEvent_WithPermission(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() app, _, err := tests.CreateApp(svc) assert.NoError(t, err) @@ -122,9 +122,9 @@ func TestHandleGetInfoEvent_WithPermission(t *testing.T) { func TestHandleGetInfoEvent_WithNotifications(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() app, _, err := tests.CreateApp(svc) assert.NoError(t, err) diff --git a/nip47/controllers/list_transactions_controller_test.go b/nip47/controllers/list_transactions_controller_test.go index 4f5321aa6..5dbd86ee1 100644 --- a/nip47/controllers/list_transactions_controller_test.go +++ b/nip47/controllers/list_transactions_controller_test.go @@ -20,9 +20,9 @@ import ( func TestHandleListTransactionsEvent(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() const nip47ListTransactionsJson = ` { @@ -98,9 +98,9 @@ func TestHandleListTransactionsEvent(t *testing.T) { func TestHandleListTransactionsEvent_UnpaidOutgoingOnly(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() const nip47ListTransactionsJson = ` { @@ -160,9 +160,9 @@ func TestHandleListTransactionsEvent_UnpaidOutgoingOnly(t *testing.T) { func TestHandleListTransactionsEvent_UnpaidIncomingOnly(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() const nip47ListTransactionsJson = ` { @@ -222,9 +222,9 @@ func TestHandleListTransactionsEvent_UnpaidIncomingOnly(t *testing.T) { func TestHandleListTransactionsEvent_Unpaid(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() const nip47ListTransactionsJson = ` { @@ -282,9 +282,9 @@ func TestHandleListTransactionsEvent_Unpaid(t *testing.T) { func TestHandleListTransactionsEvent_Paid(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() const nip47ListTransactionsJson = ` { diff --git a/nip47/controllers/lookup_invoice_controller_test.go b/nip47/controllers/lookup_invoice_controller_test.go index 8cc61d649..ac9980164 100644 --- a/nip47/controllers/lookup_invoice_controller_test.go +++ b/nip47/controllers/lookup_invoice_controller_test.go @@ -28,9 +28,9 @@ var nip47LookupInvoiceJson = ` func TestHandleLookupInvoiceEvent(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() nip47Request := &models.Request{} err = json.Unmarshal([]byte(nip47LookupInvoiceJson), nip47Request) diff --git a/nip47/controllers/make_invoice_controller_test.go b/nip47/controllers/make_invoice_controller_test.go index 980cba3b8..6fc862629 100644 --- a/nip47/controllers/make_invoice_controller_test.go +++ b/nip47/controllers/make_invoice_controller_test.go @@ -41,9 +41,9 @@ const nip47MakeInvoiceJson = ` func TestHandleMakeInvoiceEvent(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() nip47Request := &models.Request{} err = json.Unmarshal([]byte(nip47MakeInvoiceJson), nip47Request) diff --git a/nip47/controllers/multi_pay_invoice_controller_test.go b/nip47/controllers/multi_pay_invoice_controller_test.go index 26981f040..26334eb81 100644 --- a/nip47/controllers/multi_pay_invoice_controller_test.go +++ b/nip47/controllers/multi_pay_invoice_controller_test.go @@ -73,9 +73,9 @@ const MockExpiredPaymentHash = "320c2c5a1492ccfd5bc7aa4ad9b657d6aaec3cfcc0d1d984 func TestHandleMultiPayInvoiceEvent_Success(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() var preimages = []string{"123preimage", "123preimage2"} @@ -151,9 +151,9 @@ func TestHandleMultiPayInvoiceEvent_Success(t *testing.T) { func TestHandleMultiPayInvoiceEvent_OneMalformedInvoice(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() app, _, err := tests.CreateApp(svc) assert.NoError(t, err) @@ -212,9 +212,9 @@ func TestHandleMultiPayInvoiceEvent_OneMalformedInvoice(t *testing.T) { func TestHandleMultiPayInvoiceEvent_OneExpiredInvoice(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() app, _, err := tests.CreateApp(svc) assert.NoError(t, err) @@ -274,9 +274,9 @@ func TestHandleMultiPayInvoiceEvent_OneExpiredInvoice(t *testing.T) { func TestHandleMultiPayInvoiceEvent_IsolatedApp_OneBudgetExceeded(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() app, _, err := tests.CreateApp(svc) assert.NoError(t, err) @@ -356,9 +356,9 @@ func TestHandleMultiPayInvoiceEvent_LNClient_OnePaymentFailed(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() svc.LNClient.(*tests.MockLn).PayInvoiceResponses = []*lnclient.PayInvoiceResponse{{ Preimage: "123preimage", }, nil} diff --git a/nip47/controllers/multi_pay_keysend_controller_test.go b/nip47/controllers/multi_pay_keysend_controller_test.go index 9fdbbb1c0..5c0a6d96d 100644 --- a/nip47/controllers/multi_pay_keysend_controller_test.go +++ b/nip47/controllers/multi_pay_keysend_controller_test.go @@ -71,9 +71,9 @@ const nip47MultiPayKeysendOneOverflowingBudgetJson = ` func TestHandleMultiPayKeysendEvent_Success(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() app, _, err := tests.CreateApp(svc) assert.NoError(t, err) @@ -122,9 +122,9 @@ func TestHandleMultiPayKeysendEvent_Success(t *testing.T) { func TestHandleMultiPayKeysendEvent_OneBudgetExceeded(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() app, _, err := tests.CreateApp(svc) assert.NoError(t, err) diff --git a/nip47/controllers/pay_invoice_controller_test.go b/nip47/controllers/pay_invoice_controller_test.go index e2074be11..4ead93483 100644 --- a/nip47/controllers/pay_invoice_controller_test.go +++ b/nip47/controllers/pay_invoice_controller_test.go @@ -56,9 +56,9 @@ const nip47PayJsonExpiredInvoice = ` func TestHandlePayInvoiceEvent(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() app, _, err := tests.CreateApp(svc) assert.NoError(t, err) @@ -107,9 +107,9 @@ func TestHandlePayInvoiceEvent(t *testing.T) { func TestHandlePayInvoiceEvent_0Amount(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() app, _, err := tests.CreateApp(svc) assert.NoError(t, err) @@ -152,9 +152,9 @@ func TestHandlePayInvoiceEvent_0Amount(t *testing.T) { func TestHandlePayInvoiceEvent_MalformedInvoice(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() app, _, err := tests.CreateApp(svc) assert.NoError(t, err) @@ -193,9 +193,9 @@ func TestHandlePayInvoiceEvent_MalformedInvoice(t *testing.T) { func TestHandlePayInvoiceEvent_ExpiredInvoice(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() app, _, err := tests.CreateApp(svc) assert.NoError(t, err) diff --git a/nip47/controllers/pay_keysend_controller_test.go b/nip47/controllers/pay_keysend_controller_test.go index a5e2c4768..3b06202d7 100644 --- a/nip47/controllers/pay_keysend_controller_test.go +++ b/nip47/controllers/pay_keysend_controller_test.go @@ -48,9 +48,9 @@ const nip47KeysendJsonWithPreimage = ` func TestHandlePayKeysendEvent(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() app, _, err := tests.CreateApp(svc) assert.NoError(t, err) @@ -89,9 +89,9 @@ func TestHandlePayKeysendEvent(t *testing.T) { } func TestHandlePayKeysendEvent_WithPreimage(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() app, _, err := tests.CreateApp(svc) assert.NoError(t, err) diff --git a/nip47/event_handler_shared_wallet_pubkey_test.go b/nip47/event_handler_shared_wallet_pubkey_test.go index ddb15f5fb..5fbe7c98e 100644 --- a/nip47/event_handler_shared_wallet_pubkey_test.go +++ b/nip47/event_handler_shared_wallet_pubkey_test.go @@ -3,86 +3,87 @@ package nip47 import ( "testing" - "github.com/getAlby/hub/tests" "github.com/stretchr/testify/require" + + "github.com/getAlby/hub/tests" ) func TestHandleResponse_SharedWalletPubkey_Nip04_WithPermission(t *testing.T) { - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() doTestHandleResponse_WithPermission(t, svc, tests.CreateAppWithSharedWalletPubkey, "0.0") } func TestHandleResponse_SharedWalletPubkey_Nip44_WithPermission(t *testing.T) { - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() doTestHandleResponse_WithPermission(t, svc, tests.CreateAppWithSharedWalletPubkey, "1.0") } func TestHandleResponse_SharedWalletPubkey_Nip04_DuplicateRequest(t *testing.T) { - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() doTestHandleResponse_DuplicateRequest(t, svc, tests.CreateAppWithSharedWalletPubkey, "0.0") } func TestHandleResponse_SharedWalletPubkey_Nip44_DuplicateRequest(t *testing.T) { - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() doTestHandleResponse_DuplicateRequest(t, svc, tests.CreateAppWithSharedWalletPubkey, "1.0") } func TestHandleResponse_SharedWalletPubkey_Nip04_NoPermission(t *testing.T) { - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() doTestHandleResponse_NoPermission(t, svc, tests.CreateAppWithSharedWalletPubkey, "0.0") } func TestHandleResponse_SharedWalletPubkey_Nip44_NoPermission(t *testing.T) { - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() doTestHandleResponse_NoPermission(t, svc, tests.CreateAppWithSharedWalletPubkey, "1.0") } func TestHandleResponse_SharedWalletPubkey_Nip04_IncorrectPubkey(t *testing.T) { - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() doTestHandleResponse_IncorrectPubkey(t, svc, tests.CreateAppWithSharedWalletPubkey, "0.0") } func TestHandleResponse_SharedWalletPubkey_Nip44_IncorrectPubkey(t *testing.T) { - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() doTestHandleResponse_IncorrectPubkey(t, svc, tests.CreateAppWithSharedWalletPubkey, "1.0") } func TestHandleResponse_SharedWalletPubkey_Nip04_OldRequestForPayment(t *testing.T) { - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() doTestHandleResponse_OldRequestForPayment(t, svc, tests.CreateAppWithSharedWalletPubkey, "0.0") } func TestHandleResponse_SharedWalletPubkey_Nip44_OldRequestForPayment(t *testing.T) { - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() doTestHandleResponse_OldRequestForPayment(t, svc, tests.CreateAppWithSharedWalletPubkey, "1.0") } diff --git a/nip47/event_handler_test.go b/nip47/event_handler_test.go index 84f7adeb3..9eead0e31 100644 --- a/nip47/event_handler_test.go +++ b/nip47/event_handler_test.go @@ -7,15 +7,16 @@ import ( "testing" "time" + "github.com/nbd-wtf/go-nostr" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/getAlby/hub/constants" "github.com/getAlby/hub/db" "github.com/getAlby/hub/nip47/cipher" "github.com/getAlby/hub/nip47/models" "github.com/getAlby/hub/nip47/permissions" "github.com/getAlby/hub/tests" - "github.com/nbd-wtf/go-nostr" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) // TODO: test HandleEvent @@ -23,17 +24,17 @@ import ( // TODO: test if an app doesn't exist it returns the right error code func TestCreateResponse_Nip04(t *testing.T) { - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() doTestCreateResponse(t, svc, "0.0") } func TestCreateResponse_Nip44(t *testing.T) { - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() doTestCreateResponse(t, svc, "1.0") } @@ -87,17 +88,17 @@ func doTestCreateResponse(t *testing.T, svc *tests.TestService, nip47Version str } func TestHandleResponse_Nip04_WithPermission(t *testing.T) { - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() doTestHandleResponse_WithPermission(t, svc, tests.CreateAppWithPrivateKey, "0.0") } func TestHandleResponse_Nip44_WithPermission(t *testing.T) { - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() doTestHandleResponse_WithPermission(t, svc, tests.CreateAppWithPrivateKey, "1.0") } @@ -175,17 +176,17 @@ func doTestHandleResponse_WithPermission(t *testing.T, svc *tests.TestService, c } func TestHandleResponse_Nip04_DuplicateRequest(t *testing.T) { - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() doTestHandleResponse_DuplicateRequest(t, svc, tests.CreateAppWithPrivateKey, "0.0") } func TestHandleResponse_Nip44_DuplicateRequest(t *testing.T) { - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() doTestHandleResponse_DuplicateRequest(t, svc, tests.CreateAppWithPrivateKey, "1.0") } @@ -249,17 +250,17 @@ func doTestHandleResponse_DuplicateRequest(t *testing.T, svc *tests.TestService, } func TestHandleResponse_Nip04_NoPermission(t *testing.T) { - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() doTestHandleResponse_NoPermission(t, svc, tests.CreateAppWithPrivateKey, "0.0") } func TestHandleResponse_Nip44_NoPermission(t *testing.T) { - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() doTestHandleResponse_NoPermission(t, svc, tests.CreateAppWithPrivateKey, "1.0") } @@ -320,17 +321,17 @@ func doTestHandleResponse_NoPermission(t *testing.T, svc *tests.TestService, cre } func TestHandleResponse_Nip04_OldRequestForPayment(t *testing.T) { - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() doTestHandleResponse_OldRequestForPayment(t, svc, tests.CreateAppWithPrivateKey, "0.0") } func TestHandleResponse_Nip44_OldRequestForPayment(t *testing.T) { - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() doTestHandleResponse_OldRequestForPayment(t, svc, tests.CreateAppWithPrivateKey, "1.0") } @@ -395,17 +396,17 @@ func doTestHandleResponse_OldRequestForPayment(t *testing.T, svc *tests.TestServ } func TestHandleResponse_Nip04_IncorrectPubkey(t *testing.T) { - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() doTestHandleResponse_IncorrectPubkey(t, svc, tests.CreateAppWithPrivateKey, "0.0") } func TestHandleResponse_Nip44_IncorrectPubkey(t *testing.T) { - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() doTestHandleResponse_IncorrectPubkey(t, svc, tests.CreateAppWithPrivateKey, "1.0") } @@ -465,9 +466,9 @@ func doTestHandleResponse_IncorrectPubkey(t *testing.T, svc *tests.TestService, } func TestHandleResponse_NoApp(t *testing.T) { - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() nip47svc := NewNip47Service(svc.DB, svc.Cfg, svc.Keys, svc.EventPublisher) reqPrivateKey := nostr.GeneratePrivateKey() @@ -510,9 +511,9 @@ func TestHandleResponse_NoApp(t *testing.T) { } func TestHandleResponse_IncorrectVersions(t *testing.T) { - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() // version specifies what cipher will use. If "1.0" is passed, // cipher must be NIP-44, otherwise cipher MUST be NIP-04 doTestHandleResponse_IncorrectVersion(t, svc, "0.0", "1.0") diff --git a/nip47/notifications/nip47_notifier_test.go b/nip47/notifications/nip47_notifier_test.go index 962edb7db..88c208a9f 100644 --- a/nip47/notifications/nip47_notifier_test.go +++ b/nip47/notifications/nip47_notifier_test.go @@ -7,6 +7,8 @@ import ( "time" "github.com/nbd-wtf/go-nostr" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "github.com/getAlby/hub/constants" "github.com/getAlby/hub/db" @@ -15,8 +17,6 @@ import ( "github.com/getAlby/hub/nip47/permissions" "github.com/getAlby/hub/tests" "github.com/getAlby/hub/transactions" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) type mockConsumer struct { @@ -118,32 +118,32 @@ func doTestSendNotificationPaymentReceived(t *testing.T, svc *tests.TestService, } func TestSendNotification_Nip04_PaymentReceived(t *testing.T) { - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() doTestSendNotificationPaymentReceived(t, svc, tests.CreateAppWithPrivateKey, "0.0") } func TestSendNotification_Nip44_PaymentReceived(t *testing.T) { - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() doTestSendNotificationPaymentReceived(t, svc, tests.CreateAppWithPrivateKey, "1.0") } func TestSendNotification_SharedWalletPubkey_Nip04_PaymentReceived(t *testing.T) { - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) + defer svc.Remove() require.NoError(t, err) doTestSendNotificationPaymentReceived(t, svc, tests.CreateAppWithSharedWalletPubkey, "0.0") } func TestSendNotification_SharedWalletPubkey_Nip44_PaymentReceived(t *testing.T) { - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) + defer svc.Remove() require.NoError(t, err) doTestSendNotificationPaymentReceived(t, svc, tests.CreateAppWithSharedWalletPubkey, "1.0") @@ -233,33 +233,33 @@ func doTestSendNotificationPaymentSent(t *testing.T, svc *tests.TestService, cre } func TestSendNotification_Nip04_PaymentSent(t *testing.T) { - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() doTestSendNotificationPaymentSent(t, svc, tests.CreateAppWithPrivateKey, "0.0") } func TestSendNotification_Nip44_PaymentSent(t *testing.T) { - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() doTestSendNotificationPaymentSent(t, svc, tests.CreateAppWithPrivateKey, "1.0") } func TestSendNotification_SharedWalletPubkey_Nip04_PaymentSent(t *testing.T) { - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() doTestSendNotificationPaymentSent(t, svc, tests.CreateAppWithSharedWalletPubkey, "0.0") } func TestSendNotification_SharedWalletPubkey_Nip44_PaymentSent(t *testing.T) { - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() doTestSendNotificationPaymentSent(t, svc, tests.CreateAppWithSharedWalletPubkey, "1.0") } @@ -298,18 +298,18 @@ func doTestSendNotificationNoPermission(t *testing.T, svc *tests.TestService) { } func TestSendNotification_NoPermission(t *testing.T) { - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() _, _, err = tests.CreateAppWithPrivateKey(svc, nostr.GeneratePrivateKey(), "1.0") assert.NoError(t, err) doTestSendNotificationNoPermission(t, svc) } func TestSendNotification_SharedWalletPubkey_NoPermission(t *testing.T) { - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() _, _, err = tests.CreateAppWithSharedWalletPubkey(svc, nostr.GeneratePrivateKey(), "1.0") assert.NoError(t, err) doTestSendNotificationNoPermission(t, svc) diff --git a/nip47/permissions/permissions_test.go b/nip47/permissions/permissions_test.go index 8424c53eb..1b82593e9 100644 --- a/nip47/permissions/permissions_test.go +++ b/nip47/permissions/permissions_test.go @@ -4,18 +4,19 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/getAlby/hub/constants" "github.com/getAlby/hub/db" "github.com/getAlby/hub/nip47/models" "github.com/getAlby/hub/tests" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) func TestHasPermission_NoPermission(t *testing.T) { - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() app, _, err := tests.CreateApp(svc) assert.NoError(t, err) @@ -28,9 +29,9 @@ func TestHasPermission_NoPermission(t *testing.T) { } func TestHasPermission_Expired(t *testing.T) { - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() app, _, err := tests.CreateApp(svc) assert.NoError(t, err) @@ -58,7 +59,7 @@ func TestHasPermission_Expired(t *testing.T) { // TODO: move to transactions service /*func TestHasPermission_Exceeded(t *testing.T) { defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) app, _, err := tests.CreateApp(svc) @@ -85,9 +86,9 @@ func TestHasPermission_Expired(t *testing.T) { }*/ func TestHasPermission_OK(t *testing.T) { - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() app, _, err := tests.CreateApp(svc) assert.NoError(t, err) @@ -113,9 +114,9 @@ func TestHasPermission_OK(t *testing.T) { } func TestRequestMethodToScope_GetBudget(t *testing.T) { - defer tests.RemoveTestService() - _, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) assert.NoError(t, err) + defer svc.Remove() scope, err := RequestMethodToScope(models.GET_BUDGET_METHOD) assert.NoError(t, err) @@ -123,9 +124,9 @@ func TestRequestMethodToScope_GetBudget(t *testing.T) { } func TestRequestMethodsToScopes_GetBudget(t *testing.T) { - defer tests.RemoveTestService() - _, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) assert.NoError(t, err) + defer svc.Remove() scopes, err := RequestMethodsToScopes([]string{models.GET_BUDGET_METHOD}) assert.NoError(t, err) @@ -145,9 +146,9 @@ func TestRequestMethodsToScopes_GetInfo(t *testing.T) { } func TestGetPermittedMethods_AlwaysGranted(t *testing.T) { - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() app, _, err := tests.CreateApp(svc) assert.NoError(t, err) @@ -158,9 +159,9 @@ func TestGetPermittedMethods_AlwaysGranted(t *testing.T) { } func TestGetPermittedMethods_PayInvoiceScopeGivesAllPaymentMethods(t *testing.T) { - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() app, _, err := tests.CreateApp(svc) assert.NoError(t, err) diff --git a/service/keys/keys_test.go b/service/keys/keys_test.go index 08758740f..65e32864c 100644 --- a/service/keys/keys_test.go +++ b/service/keys/keys_test.go @@ -1,11 +1,16 @@ package keys import ( + "strconv" "strings" "testing" + "github.com/sirupsen/logrus" + "github.com/getAlby/hub/config" - "github.com/getAlby/hub/db" + "github.com/getAlby/hub/logger" + "github.com/getAlby/hub/tests/db" + "github.com/nbd-wtf/go-nostr" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -13,11 +18,11 @@ import ( "github.com/tyler-smith/go-bip39" ) -const testDB = "test.db" - func TestUseExistingMnemonic(t *testing.T) { - gormDb, err := db.NewDB(testDB, true) + logger.Init(strconv.Itoa(int(logrus.DebugLevel))) + gormDb, err := db.NewDB(t) require.NoError(t, err) + defer db.CloseDB(gormDb) mnemonic := "thought turkey ask pottery head say catalog desk pledge elbow naive mimic" unlockPassword := "123" @@ -59,8 +64,10 @@ func TestUseExistingMnemonic(t *testing.T) { } func TestGenerateNewMnemonic(t *testing.T) { - gormDb, err := db.NewDB(testDB, true) + logger.Init(strconv.Itoa(int(logrus.DebugLevel))) + gormDb, err := db.NewDB(t) require.NoError(t, err) + defer db.CloseDB(gormDb) unlockPassword := "123" diff --git a/tests/db/test_db.go b/tests/db/test_db.go new file mode 100644 index 000000000..5239b8bce --- /dev/null +++ b/tests/db/test_db.go @@ -0,0 +1,73 @@ +package db + +import ( + "fmt" + "net/url" + "os" + "strings" + "testing" + + "github.com/peterldowns/pgtestdb" + "gorm.io/gorm" + + "github.com/getAlby/hub/db" +) + +const defaultTestDB = "test.db" + +func GetTestDatabaseURI() string { + ret := os.Getenv("TEST_DATABASE_URI") + if ret == "" { + // TODO: use in-memory DB, or a temporary file + return defaultTestDB + } + + return ret +} + +func NewDB(t *testing.T) (*gorm.DB, error) { + return NewDBWithURI(t, GetTestDatabaseURI()) +} + +func NewDBWithURI(t *testing.T, uri string) (*gorm.DB, error) { + if db.IsPostgresURI(uri) { + parsedURI, err := url.Parse(uri) + if err != nil { + return nil, fmt.Errorf("failed to parse postgres DB URI: %w", err) + } + + var user, password string + if userInfo := parsedURI.User; userInfo != nil { + user = userInfo.Username() + password, _ = userInfo.Password() + } + + dbName := strings.TrimPrefix(parsedURI.Path, "/") + + config := pgtestdb.Custom(t, pgtestdb.Config{ + DriverName: "pgx", + Host: parsedURI.Hostname(), + Port: parsedURI.Port(), + User: user, + Password: password, + Database: dbName, + }, pgtestdb.NoopMigrator{}) + + uri = config.URL() + } + + return db.NewDBWithConfig(&db.Config{ + URI: uri, + LogQueries: true, + }) +} + +func CloseDB(d *gorm.DB) { + if err := db.Stop(d); err != nil { + panic("failed to close database: " + err.Error()) + } + + if GetTestDatabaseURI() == defaultTestDB { + os.Remove(defaultTestDB) + } +} diff --git a/tests/test_service.go b/tests/test_service.go index 8c124ea76..bf5a7ec7b 100644 --- a/tests/test_service.go +++ b/tests/test_service.go @@ -1,29 +1,31 @@ package tests import ( - "os" "strconv" + "testing" + + "github.com/sirupsen/logrus" "github.com/getAlby/hub/apps" + "github.com/getAlby/hub/logger" + "github.com/getAlby/hub/tests/db" + + "gorm.io/gorm" "github.com/getAlby/hub/config" - "github.com/getAlby/hub/db" "github.com/getAlby/hub/events" "github.com/getAlby/hub/lnclient" - "github.com/getAlby/hub/logger" "github.com/getAlby/hub/service/keys" - "github.com/sirupsen/logrus" - "gorm.io/gorm" ) -const testDB = "test.db" - -func CreateTestService() (svc *TestService, err error) { - return CreateTestServiceWithMnemonic("", "") +func CreateTestService(t *testing.T) (svc *TestService, err error) { + return CreateTestServiceWithMnemonic(t, "", "") } -func CreateTestServiceWithMnemonic(mnemonic string, unlockPassword string) (svc *TestService, err error) { - gormDb, err := db.NewDB(testDB, true) +func CreateTestServiceWithMnemonic(t *testing.T, mnemonic string, unlockPassword string) (svc *TestService, err error) { + logger.Init(strconv.Itoa(int(logrus.DebugLevel))) + + gormDb, err := db.NewDB(t) if err != nil { return nil, err } @@ -33,8 +35,6 @@ func CreateTestServiceWithMnemonic(mnemonic string, unlockPassword string) (svc return nil, err } - logger.Init(strconv.Itoa(int(logrus.DebugLevel))) - appConfig := &config.AppConfig{ Workdir: ".test", } @@ -49,10 +49,14 @@ func CreateTestServiceWithMnemonic(mnemonic string, unlockPassword string) (svc keys := keys.NewKeys() if mnemonic != "" { - cfg.SetUpdate("Mnemonic", mnemonic, unlockPassword) + if err = cfg.SetUpdate("Mnemonic", mnemonic, unlockPassword); err != nil { + return nil, err + } } - keys.Init(cfg, unlockPassword) + if err = keys.Init(cfg, unlockPassword); err != nil { + return nil, err + } eventPublisher := events.NewEventPublisher() @@ -77,6 +81,6 @@ type TestService struct { DB *gorm.DB } -func RemoveTestService() { - os.Remove(testDB) +func (s *TestService) Remove() { + db.CloseDB(s.DB) } diff --git a/transactions/app_payments_test.go b/transactions/app_payments_test.go index 7ecfa18b3..7e46c787b 100644 --- a/transactions/app_payments_test.go +++ b/transactions/app_payments_test.go @@ -5,19 +5,20 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/getAlby/hub/constants" "github.com/getAlby/hub/db" "github.com/getAlby/hub/tests" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) func TestSendPaymentSync_App_NoPermission(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() app, _, err := tests.CreateApp(svc) assert.NoError(t, err) @@ -36,9 +37,9 @@ func TestSendPaymentSync_App_NoPermission(t *testing.T) { func TestSendPaymentSync_App_WithPermission(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() app, _, err := tests.CreateApp(svc) assert.NoError(t, err) @@ -69,9 +70,9 @@ func TestSendPaymentSync_App_WithPermission(t *testing.T) { func TestSendPaymentSync_App_BudgetExceeded(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() app, _, err := tests.CreateApp(svc) assert.NoError(t, err) @@ -110,9 +111,9 @@ func TestSendPaymentSync_App_BudgetExceeded(t *testing.T) { func TestSendPaymentSync_App_BudgetExceeded_SettledPayment(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() app, _, err := tests.CreateApp(svc) assert.NoError(t, err) @@ -149,9 +150,9 @@ func TestSendPaymentSync_App_BudgetExceeded_SettledPayment(t *testing.T) { func TestSendPaymentSync_App_BudgetExceeded_UnsettledPayment(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() app, _, err := tests.CreateApp(svc) assert.NoError(t, err) @@ -189,9 +190,9 @@ func TestSendPaymentSync_App_BudgetExceeded_UnsettledPayment(t *testing.T) { func TestSendPaymentSync_App_BudgetNotExceeded_FailedPayment(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() app, _, err := tests.CreateApp(svc) assert.NoError(t, err) diff --git a/transactions/check_unsettled_transaction_test.go b/transactions/check_unsettled_transaction_test.go index db3da93ec..1cdff0e92 100644 --- a/transactions/check_unsettled_transaction_test.go +++ b/transactions/check_unsettled_transaction_test.go @@ -5,18 +5,19 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/getAlby/hub/constants" "github.com/getAlby/hub/db" "github.com/getAlby/hub/lnclient" "github.com/getAlby/hub/tests" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) func TestCheckUnsettledTransaction(t *testing.T) { - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() dbTransaction := db.Transaction{ State: constants.TRANSACTION_STATE_PENDING, @@ -51,9 +52,9 @@ func TestCheckUnsettledTransaction(t *testing.T) { } func TestCheckUnsettledTransactions(t *testing.T) { - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() dbTransaction := db.Transaction{ State: constants.TRANSACTION_STATE_PENDING, diff --git a/transactions/isolated_app_payments_test.go b/transactions/isolated_app_payments_test.go index 6936ce169..8d0a304ab 100644 --- a/transactions/isolated_app_payments_test.go +++ b/transactions/isolated_app_payments_test.go @@ -4,19 +4,20 @@ import ( "context" "testing" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/getAlby/hub/constants" "github.com/getAlby/hub/db" "github.com/getAlby/hub/tests" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) func TestSendPaymentSync_IsolatedApp_NoBalance(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() app, _, err := tests.CreateApp(svc) assert.NoError(t, err) @@ -46,9 +47,9 @@ func TestSendPaymentSync_IsolatedApp_NoBalance(t *testing.T) { func TestSendPaymentSync_IsolatedApp_BalanceInsufficient(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() app, _, err := tests.CreateApp(svc) assert.NoError(t, err) @@ -95,9 +96,9 @@ func TestSendPaymentSync_IsolatedApp_BalanceInsufficient(t *testing.T) { func TestSendPaymentSync_IsolatedApp_BalanceSufficient(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() app, _, err := tests.CreateApp(svc) assert.NoError(t, err) @@ -137,9 +138,9 @@ func TestSendPaymentSync_IsolatedApp_BalanceSufficient(t *testing.T) { func TestSendPaymentSync_IsolatedApp_BalanceInsufficient_OutstandingPayment(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() app, _, err := tests.CreateApp(svc) assert.NoError(t, err) @@ -183,9 +184,9 @@ func TestSendPaymentSync_IsolatedApp_BalanceInsufficient_OutstandingPayment(t *t func TestSendPaymentSync_IsolatedApp_BalanceInsufficient_SettledPayment(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() app, _, err := tests.CreateApp(svc) assert.NoError(t, err) @@ -229,9 +230,9 @@ func TestSendPaymentSync_IsolatedApp_BalanceInsufficient_SettledPayment(t *testi func TestSendPaymentSync_IsolatedApp_BalanceSufficient_UnrelatedPayment(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() app, _, err := tests.CreateApp(svc) assert.NoError(t, err) @@ -277,9 +278,9 @@ func TestSendPaymentSync_IsolatedApp_BalanceSufficient_UnrelatedPayment(t *testi func TestSendPaymentSync_IsolatedApp_BalanceSufficient_FailedPayment(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() app, _, err := tests.CreateApp(svc) assert.NoError(t, err) diff --git a/transactions/keysend_test.go b/transactions/keysend_test.go index e673c3ed8..e49972c4e 100644 --- a/transactions/keysend_test.go +++ b/transactions/keysend_test.go @@ -7,21 +7,22 @@ import ( "strconv" "testing" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/getAlby/hub/constants" "github.com/getAlby/hub/db" "github.com/getAlby/hub/db/queries" "github.com/getAlby/hub/lnclient" "github.com/getAlby/hub/tests" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) func TestSendKeysend(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() mockEventConsumer := tests.NewMockEventConsumer() svc.EventPublisher.RegisterSubscriber(mockEventConsumer) @@ -51,9 +52,9 @@ func TestSendKeysend(t *testing.T) { func TestSendKeysend_CustomPreimage(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() customPreimage := "018465013e2337234a7e5530a21c4a8cf70d84231f4a8ff0b1e2cce3cb2bd03b" transactionsService := NewTransactionsService(svc.DB, svc.EventPublisher) @@ -77,9 +78,9 @@ func TestSendKeysend_CustomPreimage(t *testing.T) { func TestSendKeysend_App_NoPermission(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() app, _, err := tests.CreateApp(svc) assert.NoError(t, err) @@ -99,9 +100,9 @@ func TestSendKeysend_App_NoPermission(t *testing.T) { func TestSendKeysend_App_WithPermission(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() app, _, err := tests.CreateApp(svc) assert.NoError(t, err) @@ -141,9 +142,9 @@ func TestSendKeysend_App_WithPermission(t *testing.T) { func TestSendKeysend_App_BudgetExceeded(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() app, _, err := tests.CreateApp(svc) assert.NoError(t, err) @@ -179,9 +180,9 @@ func TestSendKeysend_App_BudgetExceeded(t *testing.T) { func TestSendKeysend_App_BudgetNotExceeded(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() app, _, err := tests.CreateApp(svc) assert.NoError(t, err) @@ -222,9 +223,9 @@ func TestSendKeysend_App_BudgetNotExceeded(t *testing.T) { func TestSendKeysend_App_BalanceExceeded(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() app, _, err := tests.CreateApp(svc) assert.NoError(t, err) @@ -260,9 +261,9 @@ func TestSendKeysend_App_BalanceExceeded(t *testing.T) { func TestSendKeysend_App_BalanceSufficient(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() app, _, err := tests.CreateApp(svc) assert.NoError(t, err) @@ -311,9 +312,9 @@ func TestSendKeysend_App_BalanceSufficient(t *testing.T) { func TestSendKeysend_TLVs(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() transactionsService := NewTransactionsService(svc.DB, svc.EventPublisher) transaction, err := transactionsService.SendKeysend(ctx, uint64(1000), "fake destination", []lnclient.TLVRecord{ @@ -359,9 +360,9 @@ func TestSendKeysend_TLVs(t *testing.T) { func TestSendKeysend_IsolatedAppToNoApp(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() // setup for self payment svc.LNClient.(*tests.MockLn).Pubkey = "03cbd788f5b22bd56e2714bff756372d2293504c064e03250ed16a4dd80ad70e2c" @@ -424,9 +425,9 @@ func TestSendKeysend_IsolatedAppToNoApp(t *testing.T) { func TestSendKeysend_IsolatedAppToIsolatedApp(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() // setup for self payment svc.LNClient.(*tests.MockLn).Pubkey = "03cbd788f5b22bd56e2714bff756372d2293504c064e03250ed16a4dd80ad70e2c" diff --git a/transactions/list_transactions_test.go b/transactions/list_transactions_test.go index cd0bf142f..40e277b0d 100644 --- a/transactions/list_transactions_test.go +++ b/transactions/list_transactions_test.go @@ -5,19 +5,20 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/getAlby/hub/constants" "github.com/getAlby/hub/db" "github.com/getAlby/hub/tests" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) func TestListTransactions_Paid(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() mockPreimage := tests.MockLNClientTransaction.Preimage svc.DB.Create(&db.Transaction{ @@ -59,9 +60,9 @@ func TestListTransactions_Paid(t *testing.T) { func TestListTransactions_UnpaidIncoming(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() mockPreimage := tests.MockLNClientTransaction.Preimage svc.DB.Create(&db.Transaction{ @@ -126,9 +127,9 @@ func TestListTransactions_UnpaidIncoming(t *testing.T) { func TestListTransactions_UnpaidOutgoing(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() mockPreimage := tests.MockLNClientTransaction.Preimage svc.DB.Create(&db.Transaction{ @@ -193,9 +194,9 @@ func TestListTransactions_UnpaidOutgoing(t *testing.T) { func TestListTransactions_Unpaid(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() mockPreimage := tests.MockLNClientTransaction.Preimage svc.DB.Create(&db.Transaction{ @@ -254,9 +255,9 @@ func TestListTransactions_Unpaid(t *testing.T) { func TestListTransactions_Limit(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() mockPreimage := tests.MockLNClientTransaction.Preimage svc.DB.Create(&db.Transaction{ @@ -290,9 +291,9 @@ func TestListTransactions_Limit(t *testing.T) { func TestListTransactions_Offset(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() mockPreimage := tests.MockLNClientTransaction.Preimage svc.DB.Create(&db.Transaction{ @@ -346,9 +347,9 @@ func TestListTransactions_Offset(t *testing.T) { func TestListTransactions_FromUntil(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() mockPreimage := tests.MockLNClientTransaction.Preimage svc.DB.Create(&db.Transaction{ @@ -396,9 +397,9 @@ func TestListTransactions_FromUntil(t *testing.T) { func TestListTransactions_FromUntilUnpaidOutgoing(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() mockPreimage := tests.MockLNClientTransaction.Preimage svc.DB.Create(&db.Transaction{ @@ -458,9 +459,9 @@ func TestListTransactions_FromUntilUnpaidOutgoing(t *testing.T) { func TestListTransactions_FromUntilUnpaidIncoming(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() mockPreimage := tests.MockLNClientTransaction.Preimage svc.DB.Create(&db.Transaction{ diff --git a/transactions/lookup_transaction_test.go b/transactions/lookup_transaction_test.go index af64507c0..b31e7eb36 100644 --- a/transactions/lookup_transaction_test.go +++ b/transactions/lookup_transaction_test.go @@ -4,19 +4,20 @@ import ( "context" "testing" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/getAlby/hub/constants" "github.com/getAlby/hub/db" "github.com/getAlby/hub/tests" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) func TestLookupTransaction_IncomingPayment(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() mockPreimage := tests.MockLNClientTransaction.Preimage svc.DB.Create(&db.Transaction{ @@ -41,9 +42,9 @@ func TestLookupTransaction_IncomingPayment(t *testing.T) { func TestLookupTransaction_OutgoingPayment(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() mockPreimage := tests.MockLNClientTransaction.Preimage svc.DB.Create(&db.Transaction{ diff --git a/transactions/make_invoice_test.go b/transactions/make_invoice_test.go index 58781c499..da9378561 100644 --- a/transactions/make_invoice_test.go +++ b/transactions/make_invoice_test.go @@ -7,19 +7,20 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/getAlby/hub/constants" "github.com/getAlby/hub/db" "github.com/getAlby/hub/tests" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) func TestMakeInvoice_NoApp(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() txMetadata := make(map[string]interface{}) txMetadata["randomkey"] = strings.Repeat("a", constants.INVOICE_METADATA_MAX_LENGTH-16) // json encoding adds 16 characters - {"randomkey":""} @@ -41,9 +42,9 @@ func TestMakeInvoice_NoApp(t *testing.T) { func TestMakeInvoice_MetadataTooLarge(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() metadata := make(map[string]interface{}) metadata["randomkey"] = strings.Repeat("a", constants.INVOICE_METADATA_MAX_LENGTH-15) // json encoding adds 16 characters @@ -59,9 +60,9 @@ func TestMakeInvoice_MetadataTooLarge(t *testing.T) { func TestMakeInvoice_App(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() app, _, err := tests.CreateApp(svc) assert.NoError(t, err) diff --git a/transactions/notifications_test.go b/transactions/notifications_test.go index fe5c7407a..7b75b8806 100644 --- a/transactions/notifications_test.go +++ b/transactions/notifications_test.go @@ -5,21 +5,22 @@ import ( "encoding/json" "testing" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/getAlby/hub/constants" "github.com/getAlby/hub/db" "github.com/getAlby/hub/events" "github.com/getAlby/hub/lnclient" "github.com/getAlby/hub/tests" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) func TestNotifications_ReceivedKnownPayment(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() mockPreimage := tests.MockLNClientTransaction.Preimage svc.DB.Create(&db.Transaction{ @@ -53,9 +54,9 @@ func TestNotifications_ReceivedKnownPayment(t *testing.T) { func TestNotifications_ReceivedUnknownPayment(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() transactionsService := NewTransactionsService(svc.DB, svc.EventPublisher) @@ -80,9 +81,9 @@ func TestNotifications_ReceivedUnknownPayment(t *testing.T) { func TestNotifications_ReceivedKeysend(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() transactionsService := NewTransactionsService(svc.DB, svc.EventPublisher) @@ -146,9 +147,9 @@ func TestNotifications_ReceivedKeysend(t *testing.T) { func TestNotifications_SentKnownPayment(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() svc.DB.Create(&db.Transaction{ State: constants.TRANSACTION_STATE_PENDING, @@ -182,9 +183,9 @@ func TestNotifications_SentKnownPayment(t *testing.T) { func TestNotifications_SentUnknownPayment(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() transactionsService := NewTransactionsService(svc.DB, svc.EventPublisher) @@ -206,9 +207,9 @@ func TestNotifications_SentUnknownPayment(t *testing.T) { func TestNotifications_FailedKnownPayment(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() svc.DB.Create(&db.Transaction{ State: constants.TRANSACTION_STATE_PENDING, diff --git a/transactions/payments_test.go b/transactions/payments_test.go index 298ecb140..af39e6517 100644 --- a/transactions/payments_test.go +++ b/transactions/payments_test.go @@ -9,21 +9,22 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "gorm.io/gorm" + "github.com/getAlby/hub/constants" "github.com/getAlby/hub/db" "github.com/getAlby/hub/lnclient" "github.com/getAlby/hub/tests" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "gorm.io/gorm" ) func TestSendPaymentSync_NoApp(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() metadata := map[string]interface{}{ "a": 123, @@ -50,9 +51,9 @@ func TestSendPaymentSync_NoApp(t *testing.T) { func TestSendPaymentSync_0Amount(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() metadata := map[string]interface{}{ "a": 123, @@ -72,9 +73,9 @@ func TestSendPaymentSync_0Amount(t *testing.T) { func TestSendPaymentSync_MetadataTooLarge(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() metadata := make(map[string]interface{}) metadata["randomkey"] = strings.Repeat("a", constants.INVOICE_METADATA_MAX_LENGTH-15) // json encoding adds 16 characters @@ -90,9 +91,9 @@ func TestSendPaymentSync_MetadataTooLarge(t *testing.T) { func TestSendPaymentSync_Duplicate(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() svc.DB.Create(&db.Transaction{ State: constants.TRANSACTION_STATE_SETTLED, @@ -110,9 +111,9 @@ func TestSendPaymentSync_Duplicate(t *testing.T) { } func TestMarkSettled_Sent(t *testing.T) { - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() dbTransaction := db.Transaction{ State: constants.TRANSACTION_STATE_PENDING, @@ -139,9 +140,9 @@ func TestMarkSettled_Sent(t *testing.T) { } func TestMarkSettled_Received(t *testing.T) { - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() dbTransaction := db.Transaction{ State: constants.TRANSACTION_STATE_PENDING, @@ -168,9 +169,9 @@ func TestMarkSettled_Received(t *testing.T) { } func TestDoNotMarkSettledTwice(t *testing.T) { - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() settledAt := time.Now().Add(time.Duration(-1) * time.Minute) dbTransaction := db.Transaction{ @@ -195,9 +196,9 @@ func TestDoNotMarkSettledTwice(t *testing.T) { } func TestMarkFailed(t *testing.T) { - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() dbTransaction := db.Transaction{ State: constants.TRANSACTION_STATE_PENDING, @@ -224,9 +225,9 @@ func TestMarkFailed(t *testing.T) { } func TestDoNotMarkFailedTwice(t *testing.T) { - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() updatedAt := time.Now().Add(time.Duration(-1) * time.Minute) dbTransaction := db.Transaction{ @@ -253,9 +254,9 @@ func TestDoNotMarkFailedTwice(t *testing.T) { func TestSendPaymentSync_FailedRemovesFeeReserve(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() svc.LNClient.(*tests.MockLn).PayInvoiceErrors = append(svc.LNClient.(*tests.MockLn).PayInvoiceErrors, errors.New("Some error")) svc.LNClient.(*tests.MockLn).PayInvoiceResponses = append(svc.LNClient.(*tests.MockLn).PayInvoiceResponses, nil) @@ -285,9 +286,9 @@ func TestSendPaymentSync_FailedRemovesFeeReserve(t *testing.T) { func TestSendPaymentSync_PendingHasFeeReserve(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() // timeout will leave the payment as pending svc.LNClient.(*tests.MockLn).PayInvoiceErrors = append(svc.LNClient.(*tests.MockLn).PayInvoiceErrors, lnclient.NewTimeoutError()) diff --git a/transactions/receive_keysend_test.go b/transactions/receive_keysend_test.go index 3c07cb9ee..242d3bfaa 100644 --- a/transactions/receive_keysend_test.go +++ b/transactions/receive_keysend_test.go @@ -6,19 +6,20 @@ import ( "strconv" "testing" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/getAlby/hub/events" "github.com/getAlby/hub/lnclient" "github.com/getAlby/hub/tests" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) func TestReceiveKeysendWithCustomKey(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() transactionsService := NewTransactionsService(svc.DB, svc.EventPublisher) app, _, err := tests.CreateApp(svc) @@ -63,9 +64,9 @@ func TestReceiveKeysendWithCustomKey(t *testing.T) { func TestReceiveKeysend(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() transactionsService := NewTransactionsService(svc.DB, svc.EventPublisher) _, _, err = tests.CreateApp(svc) diff --git a/transactions/self_payments_test.go b/transactions/self_payments_test.go index ba255f9f1..5a631a903 100644 --- a/transactions/self_payments_test.go +++ b/transactions/self_payments_test.go @@ -4,20 +4,21 @@ import ( "context" "testing" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/getAlby/hub/constants" "github.com/getAlby/hub/db" "github.com/getAlby/hub/db/queries" "github.com/getAlby/hub/tests" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) func TestSendPaymentSync_SelfPayment_NoAppToNoApp(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() // pubkey matches mock invoice = self payment svc.LNClient.(*tests.MockLn).Pubkey = "03cbd788f5b22bd56e2714bff756372d2293504c064e03250ed16a4dd80ad70e2c" @@ -57,9 +58,9 @@ func TestSendPaymentSync_SelfPayment_NoAppToNoApp(t *testing.T) { func TestSendPaymentSync_SelfPayment_NoAppToIsolatedApp(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() // pubkey matches mock invoice = self payment svc.LNClient.(*tests.MockLn).Pubkey = "03cbd788f5b22bd56e2714bff756372d2293504c064e03250ed16a4dd80ad70e2c" @@ -112,9 +113,9 @@ func TestSendPaymentSync_SelfPayment_NoAppToIsolatedApp(t *testing.T) { func TestSendPaymentSync_SelfPayment_NoAppToApp(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() // pubkey matches mock invoice = self payment svc.LNClient.(*tests.MockLn).Pubkey = "03cbd788f5b22bd56e2714bff756372d2293504c064e03250ed16a4dd80ad70e2c" @@ -163,9 +164,9 @@ func TestSendPaymentSync_SelfPayment_NoAppToApp(t *testing.T) { func TestSendPaymentSync_SelfPayment_IsolatedAppToNoApp(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() // pubkey matches mock invoice = self payment svc.LNClient.(*tests.MockLn).Pubkey = "03cbd788f5b22bd56e2714bff756372d2293504c064e03250ed16a4dd80ad70e2c" @@ -235,9 +236,9 @@ func TestSendPaymentSync_SelfPayment_IsolatedAppToNoApp(t *testing.T) { func TestSendPaymentSync_SelfPayment_IsolatedAppToApp(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() // pubkey matches mock invoice = self payment svc.LNClient.(*tests.MockLn).Pubkey = "03cbd788f5b22bd56e2714bff756372d2293504c064e03250ed16a4dd80ad70e2c" @@ -311,9 +312,9 @@ func TestSendPaymentSync_SelfPayment_IsolatedAppToApp(t *testing.T) { func TestSendPaymentSync_SelfPayment_IsolatedAppToIsolatedApp(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() // pubkey matches mock invoice = self payment svc.LNClient.(*tests.MockLn).Pubkey = "03cbd788f5b22bd56e2714bff756372d2293504c064e03250ed16a4dd80ad70e2c" @@ -404,9 +405,9 @@ func TestSendPaymentSync_SelfPayment_IsolatedAppToIsolatedApp(t *testing.T) { func TestSendPaymentSync_SelfPayment_IsolatedAppToSelf(t *testing.T) { ctx := context.TODO() - defer tests.RemoveTestService() - svc, err := tests.CreateTestService() + svc, err := tests.CreateTestService(t) require.NoError(t, err) + defer svc.Remove() // pubkey matches mock invoice = self payment svc.LNClient.(*tests.MockLn).Pubkey = "03cbd788f5b22bd56e2714bff756372d2293504c064e03250ed16a4dd80ad70e2c" diff --git a/transactions/transactions_service.go b/transactions/transactions_service.go index 5e783eb37..1c8d5b7c3 100644 --- a/transactions/transactions_service.go +++ b/transactions/transactions_service.go @@ -14,16 +14,17 @@ import ( "strings" "time" + decodepay "github.com/nbd-wtf/ln-decodepay" + "github.com/sirupsen/logrus" + "gorm.io/datatypes" + "gorm.io/gorm" + "github.com/getAlby/hub/constants" "github.com/getAlby/hub/db" "github.com/getAlby/hub/db/queries" "github.com/getAlby/hub/events" "github.com/getAlby/hub/lnclient" "github.com/getAlby/hub/logger" - decodepay "github.com/nbd-wtf/ln-decodepay" - "github.com/sirupsen/logrus" - "gorm.io/datatypes" - "gorm.io/gorm" ) type transactionsService struct { @@ -489,18 +490,18 @@ func (svc *transactionsService) LookupTransaction(ctx context.Context, paymentHa return nil, NewNotFoundError() } if app.Isolated { - tx = tx.Where("app_id == ?", *appId) + tx = tx.Where("app_id = ?", *appId) } } if transactionType != nil { - tx = tx.Where("type == ?", *transactionType) + tx = tx.Where("type = ?", *transactionType) } // order settled first, otherwise by created date, as there can be multiple outgoing payments // for the same payment hash (if you tried to pay an invoice multiple times - e.g. the first time failed) result := tx.Order("settled_at desc, created_at desc").Limit(1).Find(&transaction, &db.Transaction{ - //Type: transactionType, + // Type: transactionType, PaymentHash: paymentHash, }) @@ -530,17 +531,17 @@ func (svc *transactionsService) ListTransactions(ctx context.Context, from, unti tx := svc.db if !unpaidOutgoing && !unpaidIncoming { - tx = tx.Where("state == ?", constants.TRANSACTION_STATE_SETTLED) + tx = tx.Where("state = ?", constants.TRANSACTION_STATE_SETTLED) } else if unpaidOutgoing && !unpaidIncoming { - tx = tx.Where(tx.Where("state == ?", constants.TRANSACTION_STATE_SETTLED). - Or("type == ?", constants.TRANSACTION_TYPE_OUTGOING)) + tx = tx.Where(tx.Where("state = ?", constants.TRANSACTION_STATE_SETTLED). + Or("type = ?", constants.TRANSACTION_TYPE_OUTGOING)) } else if unpaidIncoming && !unpaidOutgoing { - tx = tx.Where(tx.Where("state == ?", constants.TRANSACTION_STATE_SETTLED). - Or("type == ?", constants.TRANSACTION_TYPE_INCOMING)) + tx = tx.Where(tx.Where("state = ?", constants.TRANSACTION_STATE_SETTLED). + Or("type = ?", constants.TRANSACTION_TYPE_INCOMING)) } if transactionType != nil { - tx = tx.Where("type == ?", *transactionType) + tx = tx.Where("type = ?", *transactionType) } if from > 0 { @@ -559,7 +560,7 @@ func (svc *transactionsService) ListTransactions(ctx context.Context, from, unti return nil, NewNotFoundError() } if app.Isolated || forceFilterByAppId { - tx = tx.Where("app_id == ?", *appId) + tx = tx.Where("app_id = ?", *appId) } } @@ -590,7 +591,7 @@ func (svc *transactionsService) checkUnsettledTransactions(ctx context.Context, // check pending payments less than a day old transactions := []Transaction{} - result := svc.db.Where("state == ? AND created_at > ?", constants.TRANSACTION_STATE_PENDING, time.Now().Add(-24*time.Hour)).Find(&transactions) + result := svc.db.Where("state = ? AND created_at > ?", constants.TRANSACTION_STATE_PENDING, time.Now().Add(-24*time.Hour)).Find(&transactions) if result.Error != nil { logger.Logger.WithError(result.Error).Error("Failed to list DB transactions") return