;; SatGuard Governance Timelock
(define-constant err-owner (err u220))
(define-constant err-nf (err u221))
(define-constant err-early (err u222))
(define-constant err-dup (err u223))
(define-constant TL-PEND u1)
(define-constant TL-EXEC u2)
(define-constant TL-CAN u3)
(define-data-var delay uint u144) ;; ~1 day in blocks
(define-data-var admin principal tx-sender)
(define-data-var t-nonce uint u0)
(define-map timelocks {id: uint} {cr: principal,pid: uint,eta: uint,st: uint})
(define-read-only (get-timelock (id uint)) (map-get? timelocks {id: id}))
(define-read-only (get-delay) (var-get delay))
(define-public (schedule-action (pid uint))
(let ((nid (+ (var-get t-nonce) u1))
(prop (unwrap! (contract-call? .sg-gov-proposals get-proposal pid) err-nf)))
(map-set timelocks {id: nid} {cr: tx-sender,pid: pid,eta: (+ block-height (var-get delay)),st: TL-PEND})
(var-set t-nonce nid)
(print {e: "action-scheduled",id: nid,pid: pid,eta: (+ block-height (var-get delay))})
(ok nid)))
(define-public (execute-action (id uint))
(let ((tl (unwrap! (get-timelock id) err-nf)))
(asserts! (is-eq (get st tl) TL-PEND) err-dup)
(asserts! (>= block-height (get eta tl)) err-early)
(map-set timelocks {id: id} (merge tl {st: TL-EXEC}))
(print {e: "action-executed",id: id})
(ok true)))
(define-public (cancel-action (id uint))
(let ((tl (unwrap! (get-timelock id) err-nf)))
(asserts! (is-eq tx-sender (var-get admin)) err-owner)
(asserts! (is-eq (get st tl) TL-PEND) err-dup)
(map-set timelocks {id: id} (merge tl {st: TL-CAN}))
(print {e: "action-cancelled",id: id})
(ok true)))