Files
sonr/x/did/keeper/assertion_queries.go
T
Prad NukalaandGitHub 13e6c3e84d Master (#1262)
* clear

* feat: Add everything

* fix: Commenht
2025-10-03 14:45:52 -04:00

207 lines
5.1 KiB
Go

package keeper
import (
"context"
"fmt"
sdk "github.com/cosmos/cosmos-sdk/types"
apiv1 "github.com/sonr-io/sonr/api/did/v1"
"github.com/sonr-io/sonr/x/did/types"
)
// GetAssertionByControllerAndSubject retrieves an assertion by controller and subject
// This uses the unique index for optimal performance
func (k Keeper) GetAssertionByControllerAndSubject(
ctx context.Context,
controller string,
subject string,
) (*apiv1.Assertion, error) {
// Use the unique index on (controller, subject)
return k.OrmDB.AssertionTable().GetByControllerSubject(ctx, controller, subject)
}
// GetAssertionsByController retrieves all assertions for a controller
func (k Keeper) GetAssertionsByController(
ctx context.Context,
controller string,
) ([]*apiv1.Assertion, error) {
var assertions []*apiv1.Assertion
// Use the index on controller
indexKey := apiv1.AssertionControllerSubjectIndexKey{}.WithController(controller)
iter, err := k.OrmDB.AssertionTable().List(ctx, indexKey)
if err != nil {
return nil, fmt.Errorf("failed to query assertions: %w", err)
}
defer iter.Close()
for iter.Next() {
assertion, err := iter.Value()
if err != nil {
return nil, fmt.Errorf("failed to get assertion value: %w", err)
}
assertions = append(assertions, assertion)
}
return assertions, nil
}
// HasAssertion checks if an assertion exists for a given DID
func (k Keeper) HasAssertion(ctx context.Context, did string) bool {
_, err := k.OrmDB.AssertionTable().Get(ctx, did)
return err == nil
}
// ValidateAssertionUniqueness validates that a controller+subject combination is unique
func (k Keeper) ValidateAssertionUniqueness(
ctx context.Context,
controller string,
subject string,
) error {
existing, err := k.GetAssertionByControllerAndSubject(ctx, controller, subject)
if err == nil && existing != nil {
return fmt.Errorf("assertion already exists for controller=%s, subject=%s", controller, subject)
}
return nil
}
// CreateAssertion creates a new assertion with uniqueness validation
func (k Keeper) CreateAssertion(
ctx context.Context,
did string,
controller string,
subject string,
publicKeyBase64 string,
didKind string,
) error {
sdkCtx := sdk.UnwrapSDKContext(ctx)
// Validate uniqueness
if err := k.ValidateAssertionUniqueness(ctx, controller, subject); err != nil {
return err
}
// Create assertion
assertion := &apiv1.Assertion{
Did: did,
Controller: controller,
Subject: subject,
PublicKeyBase64: publicKeyBase64,
DidKind: didKind,
CreationBlock: sdkCtx.BlockHeight(),
}
// Insert into ORM
if err := k.OrmDB.AssertionTable().Insert(ctx, assertion); err != nil {
return fmt.Errorf("failed to store assertion: %w", err)
}
// Emit event
sdkCtx.EventManager().EmitEvent(
sdk.NewEvent(
"assertion_created",
sdk.NewAttribute("did", did),
sdk.NewAttribute("controller", controller),
sdk.NewAttribute("subject", subject),
sdk.NewAttribute("kind", didKind),
),
)
return nil
}
// UpdateAssertion updates an existing assertion
func (k Keeper) UpdateAssertion(
ctx context.Context,
did string,
publicKeyBase64 string,
) error {
// Get existing assertion
existing, err := k.OrmDB.AssertionTable().Get(ctx, did)
if err != nil {
return fmt.Errorf("assertion not found: %s", did)
}
// Update fields
existing.PublicKeyBase64 = publicKeyBase64
// Update in ORM
if err := k.OrmDB.AssertionTable().Update(ctx, existing); err != nil {
return fmt.Errorf("failed to update assertion: %w", err)
}
return nil
}
// DeleteAssertion removes an assertion
func (k Keeper) DeleteAssertion(ctx context.Context, did string) error {
// Check if assertion exists
existing, err := k.OrmDB.AssertionTable().Get(ctx, did)
if err != nil {
return fmt.Errorf("assertion not found: %s", did)
}
// Delete from ORM
if err := k.OrmDB.AssertionTable().Delete(ctx, existing); err != nil {
return fmt.Errorf("failed to delete assertion: %w", err)
}
sdkCtx := sdk.UnwrapSDKContext(ctx)
sdkCtx.EventManager().EmitEvent(
sdk.NewEvent(
"assertion_deleted",
sdk.NewAttribute("did", did),
sdk.NewAttribute("controller", existing.Controller),
sdk.NewAttribute("subject", existing.Subject),
),
)
return nil
}
// GetAssertionStats returns statistics about assertions
func (k Keeper) GetAssertionStats(ctx context.Context) (*types.AssertionStats, error) {
stats := &types.AssertionStats{
TotalAssertions: 0,
EmailAssertions: 0,
TelAssertions: 0,
SonrAssertions: 0,
WebAuthnAssertions: 0,
OtherAssertions: 0,
}
// Iterate through all assertions
iter, err := k.OrmDB.AssertionTable().List(ctx, apiv1.AssertionPrimaryKey{})
if err != nil {
return nil, fmt.Errorf("failed to list assertions: %w", err)
}
defer iter.Close()
for iter.Next() {
assertion, err := iter.Value()
if err != nil {
continue
}
stats.TotalAssertions++
// Categorize by kind
switch assertion.DidKind {
case "email":
stats.EmailAssertions++
case "tel":
stats.TelAssertions++
case "sonr":
stats.SonrAssertions++
case "webauthn":
stats.WebAuthnAssertions++
default:
stats.OtherAssertions++
}
}
return stats, nil
}