verified-identity-registry-vault

SP3BXJENEWVNCFYGJF75DFS478H1BZJXNZPT84EAD

Source Code

;; identity-registry.clar
;; Advanced identity management and profile system
;; Version: 1.0.0

;; ============================================
;; Error Codes
;; ============================================
(define-constant ERR-not-authorized (err u401))
(define-constant ERR-invalid-params (err u400))
(define-constant ERR-not-found (err u404))
(define-constant ERR-user-exists (err u405))
(define-constant ERR-invalid-role (err u406))
(define-constant ERR-user-inactive (err u407))
(define-constant ERR-invalid-status (err u408))
(define-constant ERR-not-verified (err u409))
(define-constant ERR-verification-expired (err u410))
(define-constant ERR-max-profiles-reached (err u411))
(define-constant ERR-invalid-profile-type (err u412))

;; ============================================
;; Constants
;; ============================================
(define-constant contract-owner tx-sender)
(define-constant max-profiles-per-user u3)
(define-constant verification-duration u1440)  ;; 10 days in blocks
(define-constant PROFILE-TYPE-ADVERTISER "advertiser")
(define-constant PROFILE-TYPE-PUBLISHER "publisher")
(define-constant PROFILE-TYPE-VIEWER "viewer")
(define-constant STATUS-ACTIVE "active")
(define-constant STATUS-INACTIVE "inactive")
(define-constant STATUS-SUSPENDED "suspended")
(define-constant STATUS-BANNED "banned")
(define-constant VERIFICATION-PENDING "pending")
(define-constant VERIFICATION-VERIFIED "verified")
(define-constant VERIFICATION-REJECTED "rejected")

;; ============================================
;; Data Variables
;; ============================================
(define-data-var user-counter uint u0)
(define-data-var total-advertisers uint u0)
(define-data-var total-publishers uint u0)
(define-data-var total-viewers uint u0)

;; ============================================
;; Data Maps
;; ============================================

;; Core User Maps
(define-map users 
    { user-id: principal }
    {
        status: (string-ascii 10),
        roles: (list 3 (string-ascii 20)),
        join-height: uint,
        last-active: uint,
        verification-status: (string-ascii 10),
        verification-expires: uint,
        profiles-count: uint,
        metadata: (optional (string-utf8 500))
    }
)

;; User Profiles
(define-map user-profiles
    { user-id: principal, profile-type: (string-ascii 20) }
    {
        profile-id: uint,
        display-name: (string-ascii 50),
        bio: (string-utf8 500),              ;; This needs to match
        website: (optional (string-ascii 100)), ;; This needs to match
        social-links: (list 3 {              ;; This needs to match
            platform: (string-ascii 20),
            url: (string-ascii 100)
        }),
        created-at: uint,
        updated-at: uint,
        status: (string-ascii 10)
    }
)

;; User Stats
(define-map user-stats
    { user-id: principal }
    {
        total-campaigns: uint,
        total-spent: uint,
        total-earned: uint,
        reputation-score: uint,
        activity-score: uint,
        last-updated: uint
    }
)

;; Verification Records
(define-map verification-records
    { user-id: principal }
    {
        verifier: principal,
        verification-type: (string-ascii 20),
        verification-data: (buff 32),
        verified-at: uint,
        expires-at: uint,
        status: (string-ascii 10)
    }
)

;; Role Permissions
(define-map role-permissions
    { role: (string-ascii 20) }
    {
        can-create-campaigns: bool,
        can-publish-ads: bool,
        can-view-ads: bool,
        can-earn-rewards: bool,
        max-campaigns: uint,
        min-balance: uint
    }
)

;; ============================================
;; Private Functions
;; ============================================

;; Basic Checks
(define-private (is-owner)
    (is-eq tx-sender contract-owner)
)

(define-private (is-user-active (user-id principal))
    (match (map-get? users { user-id: user-id })
        user (is-eq (get status user) STATUS-ACTIVE)
        false
    )
)

(define-private (is-valid-profile-type (profile-type (string-ascii 20)))
    (or 
        (is-eq profile-type PROFILE-TYPE-ADVERTISER)
        (is-eq profile-type PROFILE-TYPE-PUBLISHER)
        (is-eq profile-type PROFILE-TYPE-VIEWER)
    )
)

(define-private (is-valid-status (status (string-ascii 10)))
    (or
        (is-eq status STATUS-ACTIVE)
        (is-eq status STATUS-INACTIVE)
        (is-eq status STATUS-SUSPENDED)
        (is-eq status STATUS-BANNED)
    )
)

;; User Management Helpers
(define-private (generate-profile-id)
    (let ((counter (var-get user-counter)))
        (var-set user-counter (+ counter u1))
        counter
    )
)

(define-private (update-user-stats 
    (user-id principal) 
    (campaigns uint) 
    (spent uint) 
    (earned uint))
    
    (match (map-get? user-stats { user-id: user-id })
        existing-stats 
        (map-set user-stats
            { user-id: user-id }
            (merge existing-stats {
                total-campaigns: (+ (get total-campaigns existing-stats) campaigns),
                total-spent: (+ (get total-spent existing-stats) spent),
                total-earned: (+ (get total-earned existing-stats) earned),
                last-updated: stacks-block-time
            })
        )
        (map-set user-stats
            { user-id: user-id }
            {
                total-campaigns: campaigns,
                total-spent: spent,
                total-earned: earned,
                reputation-score: u100,
                activity-score: u0,
                last-updated: stacks-block-time
            }
        )
    )
)

(define-private (validate-social-links 
    (links (list 3 {platform: (string-ascii 20), url: (string-ascii 100)})))
    (>= u3 (len links))
)

;; ============================================
;; Public Functions
;; ============================================

;; User Registration
(define-public (register-user 
    (profile-type (string-ascii 20)) 
    (display-name (string-ascii 50))
    (metadata (optional (string-utf8 500))))
    
    (let
        ((user tx-sender))
        
        ;; Validations
        (asserts! (is-valid-profile-type profile-type) ERR-invalid-profile-type)
        (asserts! (is-none (map-get? users { user-id: user })) ERR-user-exists)
        
        ;; Create user record
        (map-set users
            { user-id: user }
            {
                status: STATUS-ACTIVE,
                roles: (list profile-type),
                join-height: stacks-block-time,
                last-active: stacks-block-time,
                verification-status: VERIFICATION-PENDING,
                verification-expires: (+ stacks-block-time verification-duration),
                profiles-count: u1,
                metadata: metadata
            }
        )
        
        ;; Create initial profile
        (try! (create-profile profile-type display-name))
        
        ;; Update counters based on profile type using if/else
        (if (is-eq profile-type PROFILE-TYPE-ADVERTISER)
            (var-set total-advertisers (+ (var-get total-advertisers) u1))
            (if (is-eq profile-type PROFILE-TYPE-PUBLISHER)
                (var-set total-publishers (+ (var-get total-publishers) u1))
                (if (is-eq profile-type PROFILE-TYPE-VIEWER)
                    (var-set total-viewers (+ (var-get total-viewers) u1))
                    false
                )
            )
        )
        
        (ok true)
    )
)

;; Profile Management
(define-public (create-profile
    (profile-type (string-ascii 20))
    (display-name (string-ascii 50)))
    
    (let
        ((user tx-sender)
         (user-data (unwrap! (map-get? users { user-id: user }) ERR-not-found)))
        
        ;; Validations
        (asserts! (is-valid-profile-type profile-type) ERR-invalid-profile-type)
        (asserts! (< (get profiles-count user-data) max-profiles-per-user) 
                 ERR-max-profiles-reached)
        
        ;; Create profile with correct types
        (map-set user-profiles
            { user-id: user, profile-type: profile-type }
            {
                profile-id: (generate-profile-id),
                display-name: display-name,
                bio: u"",                     ;; Fixed: empty UTF-8 string
                website: (some ""),           ;; Fixed: optional string
                social-links: (list          ;; Fixed: empty list with correct type
                    {
                        platform: "",
                        url: ""
                    }
                ),
                created-at: stacks-block-time,
                updated-at: stacks-block-time,
                status: STATUS-ACTIVE
            }
        )
        
        ;; Update user record
        (map-set users
            { user-id: user }
            (merge user-data {
                profiles-count: (+ (get profiles-count user-data) u1),
                last-active: stacks-block-time
            })
        )
        
        (ok true)
    )
)

;; ============================================
;; Admin Functions
;; ============================================

;; Update User Status
(define-public (update-user-status 
    (user-id principal) 
    (new-status (string-ascii 10)))
    
    (begin
        (asserts! (is-owner) ERR-not-authorized)
        (asserts! (is-valid-status new-status) ERR-invalid-status)
        
        (match (map-get? users { user-id: user-id })
            user-data
            (ok (map-set users
                { user-id: user-id }
                (merge user-data {
                    status: new-status,
                    last-active: stacks-block-time
                })
            ))
            ERR-not-found
        )
    )
)
;; Verify User
(define-public (verify-user 
    (user-id principal)
    (verification-type (string-ascii 20))
    (verification-data (buff 32)))
    
    (begin
        (asserts! (is-owner) ERR-not-authorized)
        
        ;; Set verification record first
        (map-set verification-records
            { user-id: user-id }
            {
                verifier: tx-sender,
                verification-type: verification-type,
                verification-data: verification-data,
                verified-at: stacks-block-time,
                expires-at: (+ stacks-block-time verification-duration),
                status: VERIFICATION-VERIFIED
            }
        )
        
        ;; Update user verification status
        (match (map-get? users { user-id: user-id })
            user-data
            (ok (begin
                (map-set users
                    { user-id: user-id }
                    (merge user-data {
                        verification-status: VERIFICATION-VERIFIED,
                        verification-expires: (+ stacks-block-time verification-duration)
                    })
                )
                true
            ))
            ERR-not-found
        )
    )
)

;; ============================================
;; Read-Only Functions
;; ============================================

;; Get User Details
(define-read-only (get-user-details (user-id principal))
    (match (map-get? users { user-id: user-id })
        user (ok user)
        ERR-not-found
    )
)

;; Get User Profile
(define-read-only (get-user-profile 
    (user-id principal) 
    (profile-type (string-ascii 20)))
    
    (match (map-get? user-profiles { user-id: user-id, profile-type: profile-type })
        profile (ok profile)
        ERR-not-found
    )
)

;; Get User Stats
(define-read-only (get-user-stats (user-id principal))
    (match (map-get? user-stats { user-id: user-id })
        stats (ok stats)
        ERR-not-found
    )
)

;; Check Verification Status
(define-read-only (get-verification-status (user-id principal))
    (match (map-get? verification-records { user-id: user-id })
        record (ok record)
        ERR-not-found
    )
)

Functions (14)

FunctionAccessArgs
is-ownerprivate
is-user-activeprivateuser-id: principal
is-valid-profile-typeprivateprofile-type: (string-ascii 20
is-valid-statusprivatestatus: (string-ascii 10
generate-profile-idprivate
update-user-statsprivateuser-id: principal, campaigns: uint, spent: uint, earned: uint
register-userpublicprofile-type: (string-ascii 20
create-profilepublicprofile-type: (string-ascii 20
update-user-statuspublicuser-id: principal, new-status: (string-ascii 10
verify-userpublicuser-id: principal, verification-type: (string-ascii 20
get-user-detailsread-onlyuser-id: principal
get-user-profileread-onlyuser-id: principal, profile-type: (string-ascii 20
get-user-statsread-onlyuser-id: principal
get-verification-statusread-onlyuser-id: principal