Source Code

;; Advanced Order Types Contract
;; Supports stop-loss, take-profit, and TWAP orders
;; Uses Clarity 4 features: block timestamps for time-based logic

;; Constants
(define-constant contract-owner tx-sender)
(define-constant err-owner-only (err u200))
(define-constant err-not-authorized (err u201))
(define-constant err-order-not-found (err u202))
(define-constant err-invalid-params (err u203))
(define-constant err-too-early (err u204))
(define-constant err-condition-not-met (err u205))
(define-constant err-already-triggered (err u206))

;; Advanced order types
(define-constant type-stop-loss u1)
(define-constant type-take-profit u2)
(define-constant type-twap u3)

;; Advanced order status
(define-constant adv-status-pending u1)
(define-constant adv-status-triggered u2)
(define-constant adv-status-executing u3)
(define-constant adv-status-completed u4)
(define-constant adv-status-cancelled u5)

;; Data Variables
(define-data-var next-advanced-order-id uint u1)
(define-data-var current-market-price uint u1000000)  ;; Price oracle (simplified)

;; Stop-loss / Take-profit orders
(define-map conditional-orders
  { order-id: uint }
  {
    trader: principal,
    order-type: uint,  ;; 1 = stop-loss, 2 = take-profit
    trigger-price: uint,
    amount: uint,
    status: uint,
    created-at: uint,
    triggered-at: (optional uint)
  }
)

;; TWAP orders - Time-Weighted Average Price
(define-map twap-orders
  { order-id: uint }
  {
    trader: principal,
    total-amount: uint,
    executed-amount: uint,
    num-chunks: uint,
    executed-chunks: uint,
    interval-seconds: uint,  ;; Time between chunks
    start-time: uint,
    last-execution: uint,
    status: uint
  }
)

;; User's advanced orders
(define-map user-advanced-orders
  { user: principal }
  { order-ids: (list 100 uint) }
)

;; Private helper functions

;; Check if stop-loss condition is met
(define-private (is-stop-loss-triggered (trigger-price uint))
  (let (
    (market-price (var-get current-market-price))
  )
    (<= market-price trigger-price)
  )
)

;; Check if take-profit condition is met
(define-private (is-take-profit-triggered (trigger-price uint))
  (let (
    (market-price (var-get current-market-price))
  )
    (>= market-price trigger-price)
  )
)

;; Calculate TWAP chunk size
(define-private (calculate-twap-chunk (total-amount uint) (num-chunks uint))
  (/ total-amount num-chunks)
)

;; Check if enough time has passed for next TWAP execution
(define-private (can-execute-next-twap-chunk 
                 (last-execution uint) 
                 (interval-seconds uint))
  (let (
    (current-time stacks-block-height)  ;; Clarity 4 feature
    (time-since-last (- current-time last-execution))
  )
    (>= time-since-last interval-seconds)
  )
)

;; Add order to user's advanced order list
(define-private (add-advanced-order-to-user (user principal) (order-id uint))
  (let (
    (current-orders (default-to (list) 
                      (get order-ids (map-get? user-advanced-orders { user: user }))))
    (new-orders (unwrap-panic (as-max-len? (append current-orders order-id) u100)))
  )
    (map-set user-advanced-orders { user: user } { order-ids: new-orders })
  )
)

;; Public functions

;; Create a stop-loss order
(define-public (create-stop-loss-order 
                 (trigger-price uint) 
                 (amount uint))
  (let (
    (order-id (var-get next-advanced-order-id))
    (timestamp stacks-block-height)
  )
    ;; Validations
    (asserts! (> trigger-price u0) err-invalid-params)
    (asserts! (> amount u0) err-invalid-params)
    
    ;; Create order
    (map-set conditional-orders
      { order-id: order-id }
      {
        trader: tx-sender,
        order-type: type-stop-loss,
        trigger-price: trigger-price,
        amount: amount,
        status: adv-status-pending,
        created-at: timestamp,
        triggered-at: none
      }
    )
    
    ;; Add to user orders
    (add-advanced-order-to-user tx-sender order-id)
    
    ;; Increment order ID
    (var-set next-advanced-order-id (+ order-id u1))
    
    ;; Print event
    (print {
      event: "stop-loss-created",
      order-id: order-id,
      trader: tx-sender,
      trigger-price: trigger-price,
      amount: amount,
      timestamp: timestamp
    })
    
    (ok order-id)
  )
)

;; Create a take-profit order
(define-public (create-take-profit-order 
                 (trigger-price uint) 
                 (amount uint))
  (let (
    (order-id (var-get next-advanced-order-id))
    (timestamp stacks-block-height)
  )
    ;; Validations
    (asserts! (> trigger-price u0) err-invalid-params)
    (asserts! (> amount u0) err-invalid-params)
    
    ;; Create order
    (map-set conditional-orders
      { order-id: order-id }
      {
        trader: tx-sender,
        order-type: type-take-profit,
        trigger-price: trigger-price,
        amount: amount,
        status: adv-status-pending,
        created-at: timestamp,
        triggered-at: none
      }
    )
    
    ;; Add to user orders
    (add-advanced-order-to-user tx-sender order-id)
    
    ;; Increment order ID
    (var-set next-advanced-order-id (+ order-id u1))
    
    ;; Print event
    (print {
      event: "take-profit-created",
      order-id: order-id,
      trader: tx-sender,
      trigger-price: trigger-price,
      amount: amount,
      timestamp: timestamp
    })
    
    (ok order-id)
  )
)

;; Create a TWAP order
(define-public (create-twap-order 
                 (total-amount uint) 
                 (num-chunks uint) 
                 (interval-seconds uint))
  (let (
    (order-id (var-get next-advanced-order-id))
    (timestamp stacks-block-height)
  )
    ;; Validations
    (asserts! (> total-amount u0) err-invalid-params)
    (asserts! (> num-chunks u0) err-invalid-params)
    (asserts! (> interval-seconds u0) err-invalid-params)
    (asserts! (<= num-chunks u100) err-invalid-params)  ;; Max 100 chunks
    
    ;; Create TWAP order
    (map-set twap-orders
      { order-id: order-id }
      {
        trader: tx-sender,
        total-amount: total-amount,
        executed-amount: u0,
        num-chunks: num-chunks,
        executed-chunks: u0,
        interval-seconds: interval-seconds,
        start-time: timestamp,
        last-execution: timestamp,
        status: adv-status-pending
      }
    )
    
    ;; Add to user orders
    (add-advanced-order-to-user tx-sender order-id)
    
    ;; Increment order ID
    (var-set next-advanced-order-id (+ order-id u1))
    
    ;; Print event
    (print {
      event: "twap-order-created",
      order-id: order-id,
      trader: tx-sender,
      total-amount: total-amount,
      num-chunks: num-chunks,
      interval-seconds: interval-seconds,
      timestamp: timestamp
    })
    
    (ok order-id)
  )
)

;; Try to trigger a conditional order (stop-loss or take-profit)
(define-public (try-trigger-conditional-order (order-id uint))
  (let (
    (order (unwrap! (map-get? conditional-orders { order-id: order-id }) 
                    err-order-not-found))
    (is-stop-loss (is-eq (get order-type order) type-stop-loss))
    (is-triggered (if is-stop-loss
                     (is-stop-loss-triggered (get trigger-price order))
                     (is-take-profit-triggered (get trigger-price order))))
  )
    ;; Check if order is pending
    (asserts! (is-eq (get status order) adv-status-pending) err-already-triggered)
    
    ;; Check if condition is met
    (asserts! is-triggered err-condition-not-met)
    
    ;; Update order status
    (map-set conditional-orders
      { order-id: order-id }
      (merge order { 
        status: adv-status-triggered,
        triggered-at: (some stacks-block-height)
      })
    )
    
    ;; In a full implementation, this would call the order book to place a market order
    ;; For now, we just mark it as triggered
    
    ;; Print event
    (print {
      event: "conditional-order-triggered",
      order-id: order-id,
      order-type: (get order-type order),
      trigger-price: (get trigger-price order),
      market-price: (var-get current-market-price),
      timestamp: stacks-block-height
    })
    
    (ok true)
  )
)

;; Execute next chunk of a TWAP order
(define-public (execute-twap-chunk (order-id uint))
  (let (
    (order (unwrap! (map-get? twap-orders { order-id: order-id }) 
                    err-order-not-found))
    (chunk-size (calculate-twap-chunk (get total-amount order) (get num-chunks order)))
  )
    ;; Check authorization
    (asserts! (is-eq (get trader order) tx-sender) err-not-authorized)
    
    ;; Check if all chunks executed
    (asserts! (< (get executed-chunks order) (get num-chunks order)) 
              err-condition-not-met)
    
    ;; Check if enough time has passed
    (asserts! (can-execute-next-twap-chunk 
                (get last-execution order) 
                (get interval-seconds order))
              err-too-early)
    
    ;; Update order
    (map-set twap-orders
      { order-id: order-id }
      (merge order {
        executed-amount: (+ (get executed-amount order) chunk-size),
        executed-chunks: (+ (get executed-chunks order) u1),
        last-execution: stacks-block-height,
        status: (if (is-eq (+ (get executed-chunks order) u1) (get num-chunks order))
                   adv-status-completed
                   adv-status-executing)
      })
    )
    
    ;; In a full implementation, this would call the order book to place a market order
    ;; for the chunk-size amount
    
    ;; Print event
    (print {
      event: "twap-chunk-executed",
      order-id: order-id,
      chunk-size: chunk-size,
      executed-chunks: (+ (get executed-chunks order) u1),
      total-chunks: (get num-chunks order),
      timestamp: stacks-block-height
    })
    
    (ok chunk-size)
  )
)

;; Cancel an advanced order
(define-public (cancel-advanced-order (order-id uint) (is-twap bool))
  (if is-twap
    (let (
      (order (unwrap! (map-get? twap-orders { order-id: order-id }) 
                      err-order-not-found))
    )
      (asserts! (is-eq (get trader order) tx-sender) err-not-authorized)
      (map-set twap-orders
        { order-id: order-id }
        (merge order { status: adv-status-cancelled })
      )
      (ok true)
    )
    (let (
      (order (unwrap! (map-get? conditional-orders { order-id: order-id }) 
                      err-order-not-found))
    )
      (asserts! (is-eq (get trader order) tx-sender) err-not-authorized)
      (map-set conditional-orders
        { order-id: order-id }
        (merge order { status: adv-status-cancelled })
      )
      (ok true)
    )
  )
)

;; Update market price (simplified oracle - in production would use Redstone/Pyth)
(define-public (update-market-price (new-price uint))
  (begin
    (asserts! (is-eq tx-sender contract-owner) err-owner-only)
    (var-set current-market-price new-price)
    (print { event: "price-updated", price: new-price, timestamp: stacks-block-height })
    (ok true)
  )
)

;; Read-only functions

;; Get conditional order
(define-read-only (get-conditional-order (order-id uint))
  (ok (map-get? conditional-orders { order-id: order-id }))
)

;; Get TWAP order
(define-read-only (get-twap-order (order-id uint))
  (ok (map-get? twap-orders { order-id: order-id }))
)

;; Get user's advanced orders
(define-read-only (get-user-advanced-orders (user principal))
  (ok (map-get? user-advanced-orders { user: user }))
)

;; Get current market price
(define-read-only (get-market-price)
  (ok (var-get current-market-price))
)

;; Get next advanced order ID
(define-read-only (get-next-advanced-order-id)
  (ok (var-get next-advanced-order-id))
)

Functions (17)

FunctionAccessArgs
is-stop-loss-triggeredprivatetrigger-price: uint
is-take-profit-triggeredprivatetrigger-price: uint
calculate-twap-chunkprivatetotal-amount: uint, num-chunks: uint
can-execute-next-twap-chunkprivatelast-execution: uint, interval-seconds: uint
add-advanced-order-to-userprivateuser: principal, order-id: uint
create-stop-loss-orderpublictrigger-price: uint, amount: uint
create-take-profit-orderpublictrigger-price: uint, amount: uint
create-twap-orderpublictotal-amount: uint, num-chunks: uint, interval-seconds: uint
try-trigger-conditional-orderpublicorder-id: uint
execute-twap-chunkpublicorder-id: uint
cancel-advanced-orderpublicorder-id: uint, is-twap: bool
update-market-pricepublicnew-price: uint
get-conditional-orderread-onlyorder-id: uint
get-twap-orderread-onlyorder-id: uint
get-user-advanced-ordersread-onlyuser: principal
get-market-priceread-only
get-next-advanced-order-idread-only