Source Code

;; title: weather-oracle
;; version:
;; summary:
;; description:

;; Error codes
(define-constant ERROR-UNAUTHORIZED-ACCESS (err u100))
(define-constant ERROR-INVALID-COMMODITY-PRICE (err u101))
(define-constant ERROR-INSUFFICIENT-ESCROW-BALANCE (err u102))
(define-constant ERROR-TRADING-DISABLED (err u103))
(define-constant ERROR-INVALID-TRADE-QUANTITY (err u104))
(define-constant ERROR-ESCROW-TRANSACTION-FAILED (err u105))
(define-constant ERROR-INVALID-INPUT (err u106))

;; Data Variables
(define-data-var contract-administrator principal tx-sender)
(define-data-var commodity-price-oracle principal tx-sender)
(define-data-var market-trading-status bool true)
(define-data-var minimum-trade-quantity uint u100)

;; Data Maps
(define-map available-commodities-inventory
    { commodity-identifier: uint }
    { 
        available-quantity: uint,
        current-market-price: uint,
        commodity-owner: principal
    }
)

(define-map active-trading-positions
    { trader-address: principal, trade-position-id: uint }
    {
        commodity-identifier: uint,
        traded-quantity: uint,
        position-entry-price: uint,
        position-creation-timestamp: uint
    }
)

(define-map trader-escrow-accounts
    { trader-address: principal }
    { escrow-balance: uint }
)

;; Read-only functions
(define-read-only (get-commodity-market-data (commodity-identifier uint))
    (match (map-get? available-commodities-inventory { commodity-identifier: commodity-identifier })
        commodity-market-data (ok commodity-market-data)
        (err u404)
    )
)

(define-read-only (get-trader-position-details (trader-address principal) (trade-position-id uint))
    (match (map-get? active-trading-positions { trader-address: trader-address, trade-position-id: trade-position-id })
        trader-position-data (ok trader-position-data)
        (err u404)
    )
)

(define-read-only (get-trader-escrow-balance (trader-address principal))
    (match (map-get? trader-escrow-accounts { trader-address: trader-address })
        escrow-account-data (ok (get escrow-balance escrow-account-data))
        (err u404)
    )
)

;; Private functions
(define-private (verify-administrator-access (caller-address principal))
    (if (is-eq caller-address (var-get contract-administrator))
        (ok true)
        ERROR-UNAUTHORIZED-ACCESS
    )
)

(define-private (validate-trade-parameters (trade-quantity uint) (trade-price uint))
    (if (and 
            (>= trade-quantity (var-get minimum-trade-quantity))
            (> trade-price u0)
        )
        (ok true)
        ERROR-INVALID-TRADE-QUANTITY
    )
)

(define-private (validate-uint (value uint))
    (> value u0)
)

;; Public functions
(define-public (update-price-oracle-address (new-oracle-address principal))
    (begin
        (try! (verify-administrator-access tx-sender))
        (asserts! (is-some (some new-oracle-address)) ERROR-INVALID-INPUT)
        (ok (var-set commodity-price-oracle new-oracle-address))
    )
)

(define-public (toggle-market-trading-status)
    (begin
        (try! (verify-administrator-access tx-sender))
        (ok (var-set market-trading-status (not (var-get market-trading-status))))
    )
)

(define-public (register-new-commodity (commodity-identifier uint) (initial-available-quantity uint) (initial-market-price uint))
    (begin
        (try! (verify-administrator-access tx-sender))
        (asserts! (validate-uint commodity-identifier) ERROR-INVALID-INPUT)
        (asserts! (validate-uint initial-available-quantity) ERROR-INVALID-INPUT)
        (asserts! (validate-uint initial-market-price) ERROR-INVALID-INPUT)
        (try! (validate-trade-parameters initial-available-quantity initial-market-price))
        (map-set available-commodities-inventory
            { commodity-identifier: commodity-identifier }
            {
                available-quantity: initial-available-quantity,
                current-market-price: initial-market-price,
                commodity-owner: tx-sender
            }
        )
        (ok true)
    )
)



(define-public (execute-trade (commodity-identifier uint) (trade-quantity uint) (trade-position-id uint))
    (let (
        (commodity-data (unwrap! (get-commodity-market-data commodity-identifier) ERROR-INVALID-COMMODITY-PRICE))
        (current-market-price (get current-market-price commodity-data))
        (total-trade-cost (* trade-quantity current-market-price))
    )
        (begin
            (asserts! (var-get market-trading-status) ERROR-TRADING-DISABLED)
            (asserts! (validate-uint commodity-identifier) ERROR-INVALID-INPUT)
            (asserts! (validate-uint trade-quantity) ERROR-INVALID-INPUT)
            (asserts! (validate-uint trade-position-id) ERROR-INVALID-INPUT)
            (try! (validate-trade-parameters trade-quantity current-market-price))
            
            ;; Check escrow balance
            (match (map-get? trader-escrow-accounts { trader-address: tx-sender })
                escrow-account-data
                    (if (>= (get escrow-balance escrow-account-data) total-trade-cost)
                        (begin
                            ;; Update escrow balance
                            (map-set trader-escrow-accounts
                                { trader-address: tx-sender }
                                { escrow-balance: (- (get escrow-balance escrow-account-data) total-trade-cost) }
                            )
                            
                            ;; Record trading position
                            (map-set active-trading-positions
                                { trader-address: tx-sender, trade-position-id: trade-position-id }
                                {
                                    commodity-identifier: commodity-identifier,
                                    traded-quantity: trade-quantity,
                                    position-entry-price: current-market-price,
                                    position-creation-timestamp: stacks-block-height
                                }
                            )
                            (ok true)
                        )
                        ERROR-INSUFFICIENT-ESCROW-BALANCE
                    )
                ERROR-INSUFFICIENT-ESCROW-BALANCE
            )
        )
    )
)

(define-public (close-trading-position (trade-position-id uint))
    (let (
        (position-data (unwrap! (get-trader-position-details tx-sender trade-position-id) ERROR-INVALID-TRADE-QUANTITY))
        (commodity-data (unwrap! (get-commodity-market-data (get commodity-identifier position-data)) ERROR-INVALID-COMMODITY-PRICE))
        (current-market-price (get current-market-price commodity-data))
        (position-settlement-amount (* (get traded-quantity position-data) current-market-price))
    )
        (begin
            (asserts! (validate-uint trade-position-id) ERROR-INVALID-INPUT)
            ;; Return funds to escrow account
            (match (map-get? trader-escrow-accounts { trader-address: tx-sender })
                escrow-account-data
                    (map-set trader-escrow-accounts
                        { trader-address: tx-sender }
                        { escrow-balance: (+ (get escrow-balance escrow-account-data) position-settlement-amount) }
                    )
                (map-set trader-escrow-accounts
                    { trader-address: tx-sender }
                    { escrow-balance: position-settlement-amount }
                )
            )
            
            ;; Delete the position
            (map-delete active-trading-positions { trader-address: tx-sender, trade-position-id: trade-position-id })
            (ok true)
        )
    )
)

;; Contract initialization
(define-public (initialize-contract (administrator-address principal))
    (begin
        (asserts! (is-some (some administrator-address)) ERROR-INVALID-INPUT)
        (var-set contract-administrator administrator-address)
        (var-set commodity-price-oracle administrator-address)
        (ok true)
    )
)

Functions (12)

FunctionAccessArgs
get-commodity-market-dataread-onlycommodity-identifier: uint
get-trader-position-detailsread-onlytrader-address: principal, trade-position-id: uint
get-trader-escrow-balanceread-onlytrader-address: principal
verify-administrator-accessprivatecaller-address: principal
validate-trade-parametersprivatetrade-quantity: uint, trade-price: uint
validate-uintprivatevalue: uint
update-price-oracle-addresspublicnew-oracle-address: principal
toggle-market-trading-statuspublic
register-new-commoditypubliccommodity-identifier: uint, initial-available-quantity: uint, initial-market-price: uint
execute-tradepubliccommodity-identifier: uint, trade-quantity: uint, trade-position-id: uint
close-trading-positionpublictrade-position-id: uint
initialize-contractpublicadministrator-address: principal