Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions reality-experience/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

settings/Mainnet.toml
settings/Testnet.toml
history.txt
4 changes: 4 additions & 0 deletions reality-experience/.vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

{
"deno.enable": true,
}
18 changes: 18 additions & 0 deletions reality-experience/.vscode/tasks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@

{
"version": "2.0.0",
"tasks": [
{
"label": "check contracts",
"group": "test",
"type": "shell",
"command": "clarinet check"
},
{
"label": "test contracts",
"group": "test",
"type": "shell",
"command": "clarinet test"
}
]
}
11 changes: 11 additions & 0 deletions reality-experience/Clarinet.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[project]
name = "reality-experience"
authors = []
description = ""
telemetry = true
requirements = []
analysis = ["check_checker"]
costs_version = 2
[contracts.augmented]
path = "contracts/augmented.clar"
depends_on = []
339 changes: 339 additions & 0 deletions reality-experience/contracts/augmented.clar
Original file line number Diff line number Diff line change
@@ -0,0 +1,339 @@
;; Augmented Reality Experiences Smart Contract
;; A comprehensive contract for managing AR experiences on Stacks blockchain

;; Constants
(define-constant contract-owner tx-sender)
(define-constant err-owner-only (err u100))
(define-constant err-not-found (err u101))
(define-constant err-unauthorized (err u102))
(define-constant err-already-exists (err u103))
(define-constant err-insufficient-payment (err u104))
(define-constant err-invalid-rating (err u105))
(define-constant err-invalid-input (err u106))

;; Data Variables
(define-data-var next-experience-id uint u1)
(define-data-var platform-fee-percentage uint u5) ;; 5% platform fee

;; Data Maps
(define-map ar-experiences
{ experience-id: uint }
{
creator: principal,
title: (string-ascii 100),
description: (string-ascii 500),
category: (string-ascii 50),
price: uint,
metadata-uri: (string-ascii 200),
created-at: uint,
is-active: bool,
total-downloads: uint,
average-rating: uint,
rating-count: uint
}
)

(define-map user-purchases
{ user: principal, experience-id: uint }
{ purchased-at: uint, access-granted: bool }
)

(define-map experience-ratings
{ user: principal, experience-id: uint }
{ rating: uint, review: (string-ascii 300), rated-at: uint }
)

(define-map creator-profiles
{ creator: principal }
{
display-name: (string-ascii 50),
bio: (string-ascii 200),
total-experiences: uint,
total-earnings: uint,
verified: bool
}
)

;; Private Functions
(define-private (is-contract-owner)
(is-eq tx-sender contract-owner)
)

(define-private (calculate-platform-fee (amount uint))
(/ (* amount (var-get platform-fee-percentage)) u100)
)

(define-private (update-experience-rating (experience-id uint) (new-rating uint))
(let (
(experience (unwrap! (map-get? ar-experiences { experience-id: experience-id }) (err err-not-found)))
(current-total (* (get average-rating experience) (get rating-count experience)))
(new-count (+ (get rating-count experience) u1))
(new-average (if (> new-count u0) (/ (+ current-total new-rating) new-count) u0))
)
(map-set ar-experiences
{ experience-id: experience-id }
(merge experience {
average-rating: new-average,
rating-count: new-count
})
)
(ok true)
)
)

;; Public Functions

;; Create AR Experience
(define-public (create-ar-experience
(title (string-ascii 100))
(description (string-ascii 500))
(category (string-ascii 50))
(price uint)
(metadata-uri (string-ascii 200))
)
(let (
(experience-id (var-get next-experience-id))
)
;; Input validation to fix warnings
(asserts! (> (len title) u0) (err err-invalid-input))
(asserts! (> (len description) u0) (err err-invalid-input))
(asserts! (> (len category) u0) (err err-invalid-input))
(asserts! (<= price u1000000000000) (err err-invalid-input)) ;; Max price limit
(asserts! (> (len metadata-uri) u0) (err err-invalid-input))

(map-set ar-experiences
{ experience-id: experience-id }
{
creator: tx-sender,
title: title,
description: description,
category: category,
price: price,
metadata-uri: metadata-uri,
created-at: block-height,
is-active: true,
total-downloads: u0,
average-rating: u0,
rating-count: u0
}
)

;; Update creator profile
(match (map-get? creator-profiles { creator: tx-sender })
existing-profile (map-set creator-profiles
{ creator: tx-sender }
(merge existing-profile { total-experiences: (+ (get total-experiences existing-profile) u1) })
)
(map-set creator-profiles
{ creator: tx-sender }
{
display-name: "",
bio: "",
total-experiences: u1,
total-earnings: u0,
verified: false
}
)
)

(var-set next-experience-id (+ experience-id u1))
(ok experience-id)
)
)

;; Purchase AR Experience
(define-public (purchase-experience (experience-id uint))
(let (
(experience (unwrap! (map-get? ar-experiences { experience-id: experience-id }) (err err-not-found)))
(price (get price experience))
(creator (get creator experience))
(platform-fee (calculate-platform-fee price))
(creator-payment (- price platform-fee))
)
;; Input validation
(asserts! (> experience-id u0) (err err-invalid-input))
(asserts! (< experience-id (var-get next-experience-id)) (err err-not-found))
(asserts! (get is-active experience) (err err-unauthorized))
(asserts! (is-none (map-get? user-purchases { user: tx-sender, experience-id: experience-id }))
(err err-already-exists))

;; Handle payment transfers
(if (> price u0)
(begin
(unwrap! (stx-transfer? creator-payment tx-sender creator) (err err-insufficient-payment))
(unwrap! (stx-transfer? platform-fee tx-sender contract-owner) (err err-insufficient-payment))
)
true
)

;; Record purchase
(map-set user-purchases
{ user: tx-sender, experience-id: experience-id }
{ purchased-at: block-height, access-granted: true }
)

;; Update experience stats
(map-set ar-experiences
{ experience-id: experience-id }
(merge experience { total-downloads: (+ (get total-downloads experience) u1) })
)

;; Update creator earnings
(match (map-get? creator-profiles { creator: creator })
existing-profile (map-set creator-profiles
{ creator: creator }
(merge existing-profile { total-earnings: (+ (get total-earnings existing-profile) creator-payment) })
)
true
)

(ok true)
)
)

;; Rate AR Experience
(define-public (rate-experience
(experience-id uint)
(rating uint)
(review (string-ascii 300))
)
(begin
;; Input validation
(asserts! (> experience-id u0) (err err-invalid-input))
(asserts! (< experience-id (var-get next-experience-id)) (err err-not-found))
(asserts! (and (>= rating u1) (<= rating u5)) (err err-invalid-rating))
(asserts! (<= (len review) u300) (err err-invalid-input))
(asserts! (is-some (map-get? ar-experiences { experience-id: experience-id })) (err err-not-found))
(asserts! (is-some (map-get? user-purchases { user: tx-sender, experience-id: experience-id }))
(err err-unauthorized))

(map-set experience-ratings
{ user: tx-sender, experience-id: experience-id }
{ rating: rating, review: review, rated-at: block-height }
)

(try! (update-experience-rating experience-id rating))
(ok true)
)
)

;; Update Creator Profile
(define-public (update-creator-profile
(display-name (string-ascii 50))
(bio (string-ascii 200))
)
(begin
;; Input validation
(asserts! (<= (len display-name) u50) (err err-invalid-input))
(asserts! (<= (len bio) u200) (err err-invalid-input))

(match (map-get? creator-profiles { creator: tx-sender })
existing-profile (map-set creator-profiles
{ creator: tx-sender }
(merge existing-profile { display-name: display-name, bio: bio })
)
(map-set creator-profiles
{ creator: tx-sender }
{
display-name: display-name,
bio: bio,
total-experiences: u0,
total-earnings: u0,
verified: false
}
)
)
(ok true)
)
)

;; Toggle Experience Status (Creator only)
(define-public (toggle-experience-status (experience-id uint))
(let (
(experience (unwrap! (map-get? ar-experiences { experience-id: experience-id }) (err err-not-found)))
)
;; Input validation
(asserts! (> experience-id u0) (err err-invalid-input))
(asserts! (< experience-id (var-get next-experience-id)) (err err-not-found))
(asserts! (is-eq tx-sender (get creator experience)) (err err-unauthorized))

(map-set ar-experiences
{ experience-id: experience-id }
(merge experience { is-active: (not (get is-active experience)) })
)
(ok true)
)
)

;; Admin Functions
(define-public (verify-creator (creator principal))
(begin
(asserts! (is-contract-owner) (err err-owner-only))
;; Input validation - ensure creator is not contract owner
(asserts! (not (is-eq creator contract-owner)) (err err-invalid-input))

(match (map-get? creator-profiles { creator: creator })
existing-profile (begin
(map-set creator-profiles
{ creator: creator }
(merge existing-profile { verified: true })
)
(ok true)
)
(err err-not-found)
)
)
)

(define-public (set-platform-fee (new-fee uint))
(begin
(asserts! (is-contract-owner) (err err-owner-only))
(asserts! (<= new-fee u20) (err err-invalid-input))
(var-set platform-fee-percentage new-fee)
(ok true)
)
)

;; Read-only Functions
(define-read-only (get-experience (experience-id uint))
(map-get? ar-experiences { experience-id: experience-id })
)

(define-read-only (get-user-purchase (user principal) (experience-id uint))
(map-get? user-purchases { user: user, experience-id: experience-id })
)

(define-read-only (get-experience-rating (user principal) (experience-id uint))
(map-get? experience-ratings { user: user, experience-id: experience-id })
)

(define-read-only (get-creator-profile (creator principal))
(map-get? creator-profiles { creator: creator })
)

(define-read-only (has-access (user principal) (experience-id uint))
(match (map-get? user-purchases { user: user, experience-id: experience-id })
purchase (get access-granted purchase)
false
)
)

(define-read-only (get-next-experience-id)
(var-get next-experience-id)
)

(define-read-only (get-platform-fee)
(var-get platform-fee-percentage)
)

(define-read-only (get-experience-stats (experience-id uint))
(match (map-get? ar-experiences { experience-id: experience-id })
experience (ok {
downloads: (get total-downloads experience),
rating: (get average-rating experience),
rating-count: (get rating-count experience),
is-active: (get is-active experience)
})
(err err-not-found)
)
)
Loading