package chainwalletroutesdb import ( "context" "errors" "github.com/tech/sendico/pkg/db/repository" ri "github.com/tech/sendico/pkg/db/repository/index" "github.com/tech/sendico/pkg/db/template" "github.com/tech/sendico/pkg/merrors" "github.com/tech/sendico/pkg/mlogger" "github.com/tech/sendico/pkg/model" "github.com/tech/sendico/pkg/mservice" "go.mongodb.org/mongo-driver/v2/mongo" "go.uber.org/zap" ) type ChainWalletRoutesDB struct { template.DBImp[*model.ChainWalletRoute] } func Create(logger mlogger.Logger, db *mongo.Database) (*ChainWalletRoutesDB, error) { p := &ChainWalletRoutesDB{ DBImp: *template.Create[*model.ChainWalletRoute](logger, mservice.WalletRoutes, db), } if err := p.Repository.CreateIndex(&ri.Definition{ Name: "idx_org_wallet_unique", Unique: true, Keys: []ri.Key{ {Field: "organizationRef", Sort: ri.Asc}, {Field: "walletRef", Sort: ri.Asc}, }, }); err != nil { p.Logger.Error("Failed to create unique organization/wallet route index", zap.Error(err)) return nil, err } if err := p.Repository.CreateIndex(&ri.Definition{ Name: "idx_wallet_ref", Keys: []ri.Key{ {Field: "walletRef", Sort: ri.Asc}, }, }); err != nil { p.Logger.Error("Failed to create wallet route lookup index", zap.Error(err)) return nil, err } return p, nil } func (db *ChainWalletRoutesDB) Get(ctx context.Context, organizationRef string, walletRef string) (*model.ChainWalletRoute, error) { org := model.ChainWalletRoute{OrganizationRef: organizationRef, WalletRef: walletRef} org.Normalize() if org.OrganizationRef == "" || org.WalletRef == "" { return nil, merrors.InvalidArgument("wallet route requires organizationRef and walletRef") } var route model.ChainWalletRoute query := repository.Query(). Filter(repository.Field("organizationRef"), org.OrganizationRef). Filter(repository.Field("walletRef"), org.WalletRef) return &route, db.FindOne(ctx, query, &route) } func (db *ChainWalletRoutesDB) Upsert(ctx context.Context, route *model.ChainWalletRoute) error { if route == nil { return merrors.InvalidArgument("wallet route is nil") } route.Normalize() if route.OrganizationRef == "" || route.WalletRef == "" { return merrors.InvalidArgument("wallet route requires organizationRef and walletRef") } if route.Network == "" && route.GatewayID == "" { return merrors.InvalidArgument("wallet route requires network or gatewayId") } existing, err := db.Get(ctx, route.OrganizationRef, route.WalletRef) if err != nil { if !errors.Is(err, merrors.ErrNoData) { return err } if createErr := db.Create(ctx, route); createErr != nil { if errors.Is(createErr, merrors.ErrDataConflict) { existing, err = db.Get(ctx, route.OrganizationRef, route.WalletRef) if err != nil { return err } } else { return createErr } } else { return nil } } changed := false if route.Network != "" && existing.Network != route.Network { existing.Network = route.Network changed = true } if route.GatewayID != "" && existing.GatewayID != route.GatewayID { existing.GatewayID = route.GatewayID changed = true } if !changed { return nil } return db.Update(ctx, existing) }