package chainassetsdb import ( ri "github.com/tech/sendico/pkg/db/repository/index" "github.com/tech/sendico/pkg/db/template" "github.com/tech/sendico/pkg/mlogger" "github.com/tech/sendico/pkg/model" "github.com/tech/sendico/pkg/mservice" "go.mongodb.org/mongo-driver/mongo" "go.uber.org/zap" ) type ChainAssetsDB struct { template.DBImp[*model.ChainAssetDescription] } func Create(logger mlogger.Logger, db *mongo.Database) (*ChainAssetsDB, error) { p := &ChainAssetsDB{ DBImp: *template.Create[*model.ChainAssetDescription](logger, mservice.ChainAssets, db), } // 1) Canonical lookup: enforce single (chain, tokenSymbol) if err := p.Repository.CreateIndex(&ri.Definition{ Name: "idx_chain_symbol", Unique: true, Keys: []ri.Key{ {Field: "asset.chain", Sort: ri.Asc}, {Field: "asset.tokenSymbol", Sort: ri.Asc}, }, }); err != nil { p.Logger.Error("failed index (chain, symbol) unique", zap.Error(err)) return nil, err } // 2) Prevent duplicate contracts inside the same chain, but only when contract exists if err := p.Repository.CreateIndex(&ri.Definition{ Name: "idx_chain_contract_unique", Unique: true, Sparse: true, Keys: []ri.Key{ {Field: "asset.chain", Sort: ri.Asc}, {Field: "asset.contractAddress", Sort: ri.Asc}, }, }); err != nil { p.Logger.Error("failed index (chain, contract) unique", zap.Error(err)) return nil, err } // 3) Fast contract lookup, skip docs without contractAddress (native assets) if err := p.Repository.CreateIndex(&ri.Definition{ Name: "idx_contract_lookup", Sparse: true, Keys: []ri.Key{ {Field: "asset.contractAddress", Sort: ri.Asc}, }, }); err != nil { p.Logger.Error("failed index contract lookup", zap.Error(err)) return nil, err } // 4) List assets per chain if err := p.Repository.CreateIndex(&ri.Definition{ Name: "idx_chain_list", Keys: []ri.Key{ {Field: "asset.chain", Sort: ri.Asc}, }, }); err != nil { p.Logger.Error("failed index chain list", zap.Error(err)) return nil, err } return p, nil }