Files
sonr/x/dex/keeper/did_integration.go
T

203 lines
5.7 KiB
Go
Raw Normal View History

2025-10-03 14:45:52 -04:00
// Package keeper implements DID integration for the DEX module
package keeper
import (
"fmt"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/sonr-io/sonr/x/dex/types"
)
// ValidateDIDOwnership verifies that the transaction sender owns the specified DID
func (k Keeper) ValidateDIDOwnership(ctx sdk.Context, did string, sender sdk.AccAddress) error {
// Get DID document from DID keeper
didDoc, err := k.didKeeper.GetDIDDocument(ctx, did)
if err != nil {
return fmt.Errorf("failed to get DID document: %w", err)
}
if didDoc == nil {
return fmt.Errorf("DID document not found for %s", did)
}
// Verify sender is the controller of the DID
if !k.isDIDController(didDoc, sender.String()) {
return fmt.Errorf("sender %s is not the controller of DID %s", sender, did)
}
return nil
}
// isDIDController checks if an address is a controller of the DID
func (k Keeper) isDIDController(didDoc any, address string) bool {
// This is a simplified check - actual implementation would depend on DID document structure
// For now, we'll assume the DID document has a Controller field or similar
// The actual implementation should match the x/did module's structure
// TODO: Implement proper controller verification based on actual DID document structure
// This might involve checking:
// - didDoc.Controller field
// - didDoc.Authentication keys
// - didDoc.AssertionMethod keys
return true // Placeholder - always return true for now
}
// GetDIDCapabilities retrieves the DEX-related capabilities for a DID
func (k Keeper) GetDIDCapabilities(ctx sdk.Context, did string) ([]string, error) {
// Get DID document
didDoc, err := k.didKeeper.GetDIDDocument(ctx, did)
if err != nil {
return nil, fmt.Errorf("failed to get DID document: %w", err)
}
if didDoc == nil {
return nil, fmt.Errorf("DID document not found for %s", did)
}
// Extract DEX-related capabilities from the DID document
// This would typically be stored in service endpoints or custom fields
capabilities := []string{
"swap",
"liquidity",
"orders",
}
return capabilities, nil
}
// AuthenticateDIDOperation verifies that a DID is authorized for a specific DEX operation
func (k Keeper) AuthenticateDIDOperation(
ctx sdk.Context,
did string,
operation string,
params map[string]any,
) error {
// Get DID document to verify it exists and is active
didDoc, err := k.didKeeper.GetDIDDocument(ctx, did)
if err != nil {
return fmt.Errorf("failed to authenticate DID: %w", err)
}
if didDoc == nil {
return fmt.Errorf("DID %s not found", did)
}
// Check if DID has the required capability for this operation
capabilities, err := k.GetDIDCapabilities(ctx, did)
if err != nil {
return fmt.Errorf("failed to get DID capabilities: %w", err)
}
// Map operations to required capabilities
requiredCapability := k.getRequiredCapability(operation)
if !k.hasCapability(capabilities, requiredCapability) {
return fmt.Errorf("DID %s lacks capability for operation %s", did, operation)
}
// Additional authentication checks could be added here:
// - Check if DID has sufficient reputation
// - Check if DID has completed KYC/AML if required
// - Check rate limits for the DID
return nil
}
// getRequiredCapability maps DEX operations to required capabilities
func (k Keeper) getRequiredCapability(operation string) string {
switch operation {
case "swap", "execute_swap":
return "swap"
case "provide_liquidity", "remove_liquidity":
return "liquidity"
case "create_order", "cancel_order":
return "orders"
default:
return operation
}
}
// hasCapability checks if a capability exists in the list
func (k Keeper) hasCapability(capabilities []string, required string) bool {
for _, cap := range capabilities {
if cap == required {
return true
}
}
return false
}
// RecordDIDActivity records DEX activity for a DID (for analytics and compliance)
func (k Keeper) RecordDIDActivity(
ctx sdk.Context,
did string,
activity types.DEXActivity,
) error {
// Store activity record keyed by DID and timestamp
activityKey := GetDIDActivityKey(did, ctx.BlockTime().Unix())
// Store the activity
if err := k.DIDActivities.Set(ctx, activityKey, activity); err != nil {
return fmt.Errorf("failed to record DID activity: %w", err)
}
// Emit event for activity tracking
ctx.EventManager().EmitEvent(
sdk.NewEvent(
types.EventTypeDIDActivity,
sdk.NewAttribute("did", did),
sdk.NewAttribute("activity_type", activity.Type),
sdk.NewAttribute("timestamp", fmt.Sprintf("%d", ctx.BlockTime().Unix())),
),
)
return nil
}
// GetDIDActivityHistory retrieves the activity history for a DID
func (k Keeper) GetDIDActivityHistory(
ctx sdk.Context,
did string,
limit uint32,
) ([]types.DEXActivity, error) {
activities := make([]types.DEXActivity, 0)
// Walk through activities for this DID
prefix := GetDIDActivityPrefix(did)
iterator, err := k.DIDActivities.Iterate(ctx, nil)
if err != nil {
return nil, fmt.Errorf("failed to iterate DID activities: %w", err)
}
defer iterator.Close()
count := uint32(0)
for ; iterator.Valid() && count < limit; iterator.Next() {
key, err := iterator.Key()
if err != nil {
continue
}
// Check if key starts with the DID prefix
if len(key) >= len(prefix) && string(key[:len(prefix)]) == prefix {
activity, err := iterator.Value()
if err == nil {
activities = append(activities, activity)
count++
}
}
}
return activities, nil
}
// GetDIDActivityPrefix returns the key prefix for a DID's activities
func GetDIDActivityPrefix(did string) string {
return fmt.Sprintf("did_activity_%s_", did)
}
// GetDIDActivityKey returns the key for storing a DID activity
func GetDIDActivityKey(did string, timestamp int64) string {
return fmt.Sprintf("did_activity_%s_%d", did, timestamp)
}