(define-constant OWNER tx-sender)
  
(define-constant ERR_O (err u1000))
(define-constant ERR_L (err u1001))
(define-constant ERR_Q (err u1002))
(define-constant ERR_F (err u1003))
(define-constant ERR_S (err u1004))
(define-constant ERR_X (err u1005))
  
(define-constant ERR_ALEX_A (err u2100))
(define-constant ERR_ALEX_B (err u2101))
(define-constant ERR_DIKO_A (err u2200))
(define-constant ERR_DIKO_B (err u2201))

(define-constant T_STX  "a")
(define-constant T_XUSD "b")
(define-constant T_XBTC "c")
(define-constant T_ALEX "d")
(define-constant T_DIKO "e")
(define-constant T_USDA "f")
(define-constant T_STSW "g")
(define-constant T_LBTC "h")
(define-constant T_MIA2 "i")
(define-constant T_NYC2 "j")
(define-constant T_MIA1 "k")
(define-constant T_NYC1 "l")
        
(define-constant SWAP_DIKO 'SP2C2YFP12AJZB4MABJBAJ55XECVS7E4PMMZ89YZR.arkadiko-swap-v2-1)

(define-constant C_WSTX_diko 'SP2C2YFP12AJZB4MABJBAJ55XECVS7E4PMMZ89YZR.wrapped-stx-token)
(define-constant C_WSTX_stsw 'SP1Z92MPDQEWZXW36VX71Q25HKF5K2EPCJ304F275.wstx-token-v4a)
(define-constant C_XUSD 'SP2TZK01NKDC89J6TA56SA47SDF7RTHYEQ79AAB9A.Wrapped-USD)
(define-constant C_XBTC 'SP3DX3H4FEYZJZ586MFBS25ZW3HZDMEW92260R2PR.Wrapped-Bitcoin)
(define-constant C_ALEX 'SP3K8BC0PPEVCV7NZ6QSRWPQ2JE9E5B6N3PA0KBR9.age000-governance-token)
(define-constant C_DIKO 'SP2C2YFP12AJZB4MABJBAJ55XECVS7E4PMMZ89YZR.arkadiko-token)
(define-constant C_USDA 'SP2C2YFP12AJZB4MABJBAJ55XECVS7E4PMMZ89YZR.usda-token)
(define-constant C_STSW 'SP1Z92MPDQEWZXW36VX71Q25HKF5K2EPCJ304F275.stsw-token-v4a)
(define-constant C_LBTC 'SP1Z92MPDQEWZXW36VX71Q25HKF5K2EPCJ304F275.lbtc-token-v1c)
(define-constant C_MIA2 'SP1H1733V5MZ3SZ9XRW9FKYGEZT0JDGEB8Y634C7R.miamicoin-token-v2)
(define-constant C_NYC2 'SPSCWDV3RKV5ZRN1FQD84YE1NQFEDJ9R1F4DYQ11.newyorkcitycoin-token-v2)
(define-constant C_MIA1 'SP466FNC0P7JWTNM2R9T199QRZN1MYEDTAR0KP27.miamicoin-token)
(define-constant C_NYC1 'SP2H8PY27SEZ03MWRKS5XABZYQN17ETGQS3527SA5.newyorkcitycoin-token)


(define-private (wstx-xusd-a (dx uint))
(let ((r (try! (contract-call? 'SP3K8BC0PPEVCV7NZ6QSRWPQ2JE9E5B6N3PA0KBR9.fixed-weight-pool-v1-01 swap-x-for-y
'SP3K8BC0PPEVCV7NZ6QSRWPQ2JE9E5B6N3PA0KBR9.token-wstx
'SP3K8BC0PPEVCV7NZ6QSRWPQ2JE9E5B6N3PA0KBR9.token-wxusd
u50000000 u50000000 (* dx u100) (some u0)))))
(ok (get dy r))))

(define-private (xusd-wstx-a (dx uint))
(let ((r (try! (contract-call? 'SP3K8BC0PPEVCV7NZ6QSRWPQ2JE9E5B6N3PA0KBR9.fixed-weight-pool-v1-01 swap-y-for-x
'SP3K8BC0PPEVCV7NZ6QSRWPQ2JE9E5B6N3PA0KBR9.token-wstx
'SP3K8BC0PPEVCV7NZ6QSRWPQ2JE9E5B6N3PA0KBR9.token-wxusd
u50000000 u50000000 dx (some u0)))))
(ok (/ (get dx r) u100))))

(define-private (wstx-xbtc-a (dx uint))
(let ((r (try! (contract-call? 'SP3K8BC0PPEVCV7NZ6QSRWPQ2JE9E5B6N3PA0KBR9.fixed-weight-pool-v1-01 swap-x-for-y
'SP3K8BC0PPEVCV7NZ6QSRWPQ2JE9E5B6N3PA0KBR9.token-wstx
'SP3K8BC0PPEVCV7NZ6QSRWPQ2JE9E5B6N3PA0KBR9.token-wbtc
u50000000 u50000000 (* dx u100) (some u0)))))
(ok (get dy r))))

(define-private (xbtc-wstx-a (dx uint))
(let ((r (try! (contract-call? 'SP3K8BC0PPEVCV7NZ6QSRWPQ2JE9E5B6N3PA0KBR9.fixed-weight-pool-v1-01 swap-y-for-x
'SP3K8BC0PPEVCV7NZ6QSRWPQ2JE9E5B6N3PA0KBR9.token-wstx
'SP3K8BC0PPEVCV7NZ6QSRWPQ2JE9E5B6N3PA0KBR9.token-wbtc
u50000000 u50000000 dx (some u0)))))
(ok (/ (get dx r) u100))))

(define-private (wstx-alex-a (dx uint))
(let ((r (try! (contract-call? 'SP3K8BC0PPEVCV7NZ6QSRWPQ2JE9E5B6N3PA0KBR9.fixed-weight-pool-v1-01 swap-x-for-y
'SP3K8BC0PPEVCV7NZ6QSRWPQ2JE9E5B6N3PA0KBR9.token-wstx
'SP3K8BC0PPEVCV7NZ6QSRWPQ2JE9E5B6N3PA0KBR9.age000-governance-token
u50000000 u50000000 (* dx u100) (some u0)))))
(ok (get dy r))))

(define-private (alex-wstx-a (dx uint))
(let ((r (try! (contract-call? 'SP3K8BC0PPEVCV7NZ6QSRWPQ2JE9E5B6N3PA0KBR9.fixed-weight-pool-v1-01 swap-y-for-x
'SP3K8BC0PPEVCV7NZ6QSRWPQ2JE9E5B6N3PA0KBR9.token-wstx
'SP3K8BC0PPEVCV7NZ6QSRWPQ2JE9E5B6N3PA0KBR9.age000-governance-token
u50000000 u50000000 dx (some u0)))))
(ok (/ (get dx r) u100))))

(define-private (xusd-usda-a (dx uint))
(let ((r (try! (contract-call? 'SP3K8BC0PPEVCV7NZ6QSRWPQ2JE9E5B6N3PA0KBR9.amm-swap-pool swap-x-for-y
'SP3K8BC0PPEVCV7NZ6QSRWPQ2JE9E5B6N3PA0KBR9.token-wxusd
'SP3K8BC0PPEVCV7NZ6QSRWPQ2JE9E5B6N3PA0KBR9.token-wusda
u10000 dx (some u0)))))
(ok (/ (get dy r) u100))))

(define-private (usda-xusd-a (dx uint))
(let ((r (try! (contract-call? 'SP3K8BC0PPEVCV7NZ6QSRWPQ2JE9E5B6N3PA0KBR9.amm-swap-pool swap-y-for-x
'SP3K8BC0PPEVCV7NZ6QSRWPQ2JE9E5B6N3PA0KBR9.token-wxusd
'SP3K8BC0PPEVCV7NZ6QSRWPQ2JE9E5B6N3PA0KBR9.token-wusda
u10000 (* dx u100) (some u0)))))
(ok (get dx r))))

(define-private (alex-usda-a (dx uint))
(let ((r (try! (contract-call? 'SP3K8BC0PPEVCV7NZ6QSRWPQ2JE9E5B6N3PA0KBR9.simple-weight-pool-alex swap-x-for-y
'SP3K8BC0PPEVCV7NZ6QSRWPQ2JE9E5B6N3PA0KBR9.age000-governance-token
'SP3K8BC0PPEVCV7NZ6QSRWPQ2JE9E5B6N3PA0KBR9.token-wusda
dx (some u0)))))
(ok (/ (get dy r) u100))))

(define-private (usda-alex-a (dx uint))
(let ((r (try! (contract-call? 'SP3K8BC0PPEVCV7NZ6QSRWPQ2JE9E5B6N3PA0KBR9.simple-weight-pool-alex swap-y-for-x
'SP3K8BC0PPEVCV7NZ6QSRWPQ2JE9E5B6N3PA0KBR9.age000-governance-token
'SP3K8BC0PPEVCV7NZ6QSRWPQ2JE9E5B6N3PA0KBR9.token-wusda
(* dx u100) (some u0)))))
(ok (get dx r))))

(define-public (swap-alex
  (a (string-ascii 1))
  (b (string-ascii 1))
  (x uint)
)
  (if (is-eq a T_STX)
    (if (is-eq b T_XUSD) (wstx-xusd-a x)
    (if (is-eq b T_XBTC) (wstx-xbtc-a x)
    (if (is-eq b T_ALEX) (wstx-alex-a x)
    ERR_ALEX_B)))
  (if (is-eq a T_XUSD)
    (if (is-eq b T_STX)  (xusd-wstx-a x)
    (if (is-eq b T_USDA) (xusd-usda-a x)
    ERR_ALEX_B))
  (if (is-eq a T_XBTC)
    (if (is-eq b T_STX) (xbtc-wstx-a x)
    ERR_ALEX_B)
  (if (is-eq a T_ALEX)
    (if (is-eq b T_STX)  (alex-wstx-a x)
    (if (is-eq b T_USDA) (alex-usda-a x)
    ERR_ALEX_B))
  (if (is-eq a T_USDA)
    (if (is-eq b T_XUSD) (usda-xusd-a x)
    (if (is-eq b T_ALEX) (usda-alex-a x)
    ERR_ALEX_B))
  ERR_ALEX_A)))))
)


(define-private (wstx-xbtc-d (x uint))
(let ((v (try! (contract-call? SWAP_DIKO swap-x-for-y C_WSTX_diko C_XBTC x u0))))
(ok (unwrap-panic (element-at v u1)))))

(define-private (xbtc-wstx-d (x uint))
(let ((v (try! (contract-call? SWAP_DIKO swap-y-for-x C_WSTX_diko C_XBTC x u0))))
(ok (unwrap-panic (element-at v u0)))))

(define-private (wstx-diko-d (x uint))
(let ((v (try! (contract-call? SWAP_DIKO swap-x-for-y C_WSTX_diko C_DIKO x u0))))
(ok (unwrap-panic (element-at v u1)))))

(define-private (diko-wstx-d (x uint))
(let ((v (try! (contract-call? SWAP_DIKO swap-y-for-x C_WSTX_diko C_DIKO x u0))))
(ok (unwrap-panic (element-at v u0)))))

(define-private (wstx-usda-d (x uint))
(let ((v (try! (contract-call? SWAP_DIKO swap-x-for-y C_WSTX_diko C_USDA x u0))))
(ok (unwrap-panic (element-at v u1)))))

(define-private (usda-wstx-d (x uint))
(let ((v (try! (contract-call? SWAP_DIKO swap-y-for-x C_WSTX_diko C_USDA x u0))))
(ok (unwrap-panic (element-at v u0)))))

(define-private (xbtc-usda-d (x uint))
(let ((v (try! (contract-call? SWAP_DIKO swap-x-for-y C_XBTC C_USDA x u0))))
(ok (unwrap-panic (element-at v u1)))))

(define-private (usda-xbtc-d (x uint))
(let ((v (try! (contract-call? SWAP_DIKO swap-y-for-x C_XBTC C_USDA x u0))))
(ok (unwrap-panic (element-at v u0)))))

(define-private (diko-usda-d (x uint))
(let ((v (try! (contract-call? SWAP_DIKO swap-x-for-y C_DIKO C_USDA x u0))))
(ok (unwrap-panic (element-at v u1)))))

(define-private (usda-diko-d (x uint))
(let ((v (try! (contract-call? SWAP_DIKO swap-y-for-x C_DIKO C_USDA x u0))))
(ok (unwrap-panic (element-at v u0)))))

(define-public (swap-diko
  (a (string-ascii 1))
  (b (string-ascii 1))
  (x uint)
)
  (if (is-eq a T_STX) ;; stx
    (if (is-eq b T_XBTC) (wstx-xbtc-d x)
    (if (is-eq b T_ALEX) (wstx-diko-d x)
    (if (is-eq b T_USDA) (wstx-usda-d x)
    ERR_DIKO_B)))
  (if (is-eq a T_XBTC)
    (if (is-eq b T_STX)  (xbtc-wstx-d x)
    (if (is-eq b T_USDA) (xbtc-usda-d x)
    ERR_DIKO_B))
  (if (is-eq a T_DIKO)
    (if (is-eq b T_STX)  (diko-wstx-d x)
    (if (is-eq b T_USDA) (diko-usda-d x)
    ERR_DIKO_B))
  (if (is-eq a T_USDA)
    (if (is-eq b T_STX)  (usda-wstx-d x)
    (if (is-eq b T_XBTC) (usda-xbtc-d x)
    (if (is-eq b T_DIKO) (usda-diko-d x)
    ERR_DIKO_B)))
  ERR_DIKO_A))))
)


(define-private (xfer
  (a (string-ascii 1))
  (amt uint)
  (src principal)
  (dst principal)
)
  (if (is-eq a T_STX) (stx-transfer? amt src dst)
  ERR_X
  )
)

(define-public (swap
  (s (string-ascii 1))
  (a (string-ascii 1))
  (b (string-ascii 1))
  (x uint)
)
  (if (is-eq s "a") (swap-alex a b x)
  (if (is-eq s "b") (swap-diko a b x)
  ERR_S
  ))
)

(define-private (t
  (q (string-ascii 3))
  (v (list 21 (response uint uint)))
)
  (match (unwrap-panic (element-at v (- (len v) u1)))
    x (let
        (
          (s (unwrap-panic (element-at q u0)))
          (a (unwrap-panic (element-at q u1)))
          (b (unwrap-panic (element-at q u2)))
          (y (swap s a b x))
        )
        (unwrap-panic (as-max-len? (append v y) u21))
      )
    x (unwrap-panic (as-max-len? (append v (err x)) u21))
  )
)

(define-private (t2
  (q (response uint uint))
  (v (list 21 uint))
)
  (unwrap-panic (as-max-len? (append v (unwrap-panic q)) u21))
)

(define-public (Z
  (q (list 20 (string-ascii 3)))
  (x uint)
  (Y uint)
)
  (let
    (
      (sender tx-sender)
      (f (unwrap! (element-at q u0) ERR_Q))
      (l (unwrap! (element-at q (- (len q) u1)) ERR_Q))
      (a (unwrap! (element-at f u1) ERR_Q))
      (b (unwrap! (element-at l u2) ERR_Q))
    )
    (asserts! (is-eq tx-sender OWNER) ERR_O)
;;    (try! (xfer a x tx-sender (as-contract tx-sender)))
;;    (as-contract
      (let
        (
          (v (fold t q (list (ok x))))
          (resp (unwrap! (element-at v (- (len v) u1)) ERR_F))
        )
        (match resp
          y (begin
              (asserts! (>= y Y) (err ERR_L))
;;              (try! (xfer b y tx-sender sender))
              (ok (fold t2 v (list)))
            )
          y (err y)
        )
      )
;;    )
  )
)

(define-public (z
  (q (list 20 (string-ascii 3)))
  (x uint)
)
  (Z q x (+ x u1))
)