(define-constant O tx-sender)
(define-constant E1 (err u950))
(define-constant E2 (err u951))
(define-constant E3 (err u952))
(define-data-var ec uint u0)
(define-map escrows uint
{sender: principal, receiver: principal, amount: uint, released: bool, refunded: bool})
(define-public (create-escrow (receiver principal) (amt uint))
(let ((id (var-get ec)))
(asserts! (> amt u0) E2)
(try! (stx-transfer? amt tx-sender (as-contract tx-sender)))
(var-set ec (+ id u1))
(ok (map-set escrows id
{sender: tx-sender, receiver: receiver, amount: amt,
released: false, refunded: false}))))
(define-public (release-escrow (eid uint))
(let ((e (unwrap! (map-get? escrows eid) E3)))
(asserts! (is-eq tx-sender (get sender e)) E1)
(asserts! (not (get released e)) E2)
(asserts! (not (get refunded e)) E2)
(try! (as-contract (stx-transfer? (get amount e) tx-sender (get receiver e))))
(ok (map-set escrows eid (merge e {released: true})))))
(define-public (refund-escrow (eid uint))
(let ((e (unwrap! (map-get? escrows eid) E3)))
(asserts! (or (is-eq tx-sender O) (is-eq tx-sender (get sender e))) E1)
(asserts! (not (get released e)) E2)
(asserts! (not (get refunded e)) E2)
(try! (as-contract (stx-transfer? (get amount e) tx-sender (get sender e))))
(ok (map-set escrows eid (merge e {refunded: true})))))
(define-read-only (get-escrow (eid uint)) (map-get? escrows eid))
(define-read-only (get-escrow-count) (var-get ec))