Added ownership reference + wallet creation methods

This commit is contained in:
Stephan D
2026-01-07 13:12:31 +01:00
parent 33647a0f3d
commit 9e747e7251
19 changed files with 400 additions and 85 deletions

View File

@@ -0,0 +1,73 @@
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
}

View File

@@ -0,0 +1,18 @@
package chainassetsdb
import (
"context"
"github.com/tech/sendico/pkg/db/repository"
"github.com/tech/sendico/pkg/model"
)
func (db *ChainAssetsDB) Resolve(ctx context.Context, chainAsset model.ChainAssetKey) (*model.ChainAssetDescription, error) {
var assetDescription model.ChainAssetDescription
assetField := repository.Field("asset")
q := repository.Query().And(
repository.Query().Filter(assetField.Dot("chain"), chainAsset.Chain),
repository.Query().Filter(assetField.Dot("tokenSymbol"), chainAsset.TokenSymbol),
)
return &assetDescription, db.DBImp.FindOne(ctx, q, &assetDescription)
}

View File

@@ -10,8 +10,10 @@ import (
"github.com/mitchellh/mapstructure"
"github.com/tech/sendico/pkg/auth"
"github.com/tech/sendico/pkg/db/account"
"github.com/tech/sendico/pkg/db/chainassets"
"github.com/tech/sendico/pkg/db/confirmation"
"github.com/tech/sendico/pkg/db/internal/mongo/accountdb"
"github.com/tech/sendico/pkg/db/internal/mongo/chainassetsdb"
"github.com/tech/sendico/pkg/db/internal/mongo/confirmationdb"
"github.com/tech/sendico/pkg/db/internal/mongo/invitationdb"
"github.com/tech/sendico/pkg/db/internal/mongo/organizationdb"
@@ -312,6 +314,10 @@ func collectReplicaHosts(configuredHosts []string, replicaSet, defaultPort, host
return hosts
}
func (db *DB) NewChainAsstesDB() (chainassets.DB, error) {
return chainassetsdb.Create(db.logger, db.db())
}
func (db *DB) Permissions() auth.Provider {
return db
}

View File

@@ -44,6 +44,9 @@ func (r *MongoRepository) CreateIndex(def *ri.Definition) error {
if def.PartialFilter != nil {
opts.SetPartialFilterExpression(def.PartialFilter.BuildQuery())
}
if def.Sparse {
opts.SetSparse(def.Sparse)
}
_, err := r.collection.Indexes().CreateOne(
context.Background(),