(define-constant O tx-sender)
(define-constant E1 (err u850))
(define-constant E2 (err u851))
(define-constant E3 (err u852))
(define-data-var vc uint u0)
(define-map vesting-schedules uint
{beneficiary: principal, total: uint, claimed: uint, start: uint, duration: uint})
(define-public (create-vest (who principal) (total uint) (duration uint))
(begin (asserts! (is-eq tx-sender O) E1)
(let ((id (var-get vc)))
(var-set vc (+ id u1))
(try! (stx-transfer? total tx-sender (as-contract tx-sender)))
(ok (map-set vesting-schedules id
{beneficiary: who, total: total, claimed: u0,
start: stacks-block-height, duration: duration})))))
(define-public (claim-vested (vid uint))
(let ((v (unwrap! (map-get? vesting-schedules vid) E2)))
(asserts! (is-eq tx-sender (get beneficiary v)) E1)
(let ((elapsed (- stacks-block-height (get start v)))
(vested (if (>= elapsed (get duration v))
(get total v)
(/ (* (get total v) elapsed) (get duration v))))
(claimable (- vested (get claimed v))))
(asserts! (> claimable u0) E3)
(try! (as-contract (stx-transfer? claimable tx-sender (get beneficiary v))))
(ok (map-set vesting-schedules vid
(merge v {claimed: (+ (get claimed v) claimable)}))))))
(define-read-only (get-vest (vid uint))
(map-get? vesting-schedules vid))
(define-read-only (get-vest-count) (var-get vc))