Source Code

;; interesting-peach-albatross

;; Use DLMM pool trait and SIP 010 trait
(use-trait dlmm-pool-trait .consistent-harlequin-crane.dlmm-pool-trait)
(use-trait sip-010-trait 'SM1793C4R5PZ4NS4VQ4WMP7SKKYVH8JZEWSZ9HCCR.sip-010-trait-ft-standard-v-1-1.sip-010-trait)

;; Error constants
(define-constant ERR_NO_RESULT_DATA (err u2001))
(define-constant ERR_BIN_SLIPPAGE (err u2002))
(define-constant ERR_MINIMUM_RECEIVED (err u2003))
(define-constant ERR_NO_ACTIVE_BIN_DATA (err u2004))
(define-constant ERR_EMPTY_SWAPS_LIST (err u2005))

;; Swap through multiple bins in multiple pools
(define-public (swap-multi
    (swaps (list 350 {pool-trait: <dlmm-pool-trait>, x-token-trait: <sip-010-trait>, y-token-trait: <sip-010-trait>, expected-bin-id: int, amount: uint, x-for-y: bool}))
    (min-received uint) (max-unfavorable-bins uint)
  )
  (let (
    (swap-result (try! (fold fold-swap-multi swaps (ok {received: u0, unfavorable: u0}))))
    (received (get received swap-result))
  )
    (asserts! (> (len swaps) u0) ERR_EMPTY_SWAPS_LIST)
    (asserts! (<= (get unfavorable swap-result) max-unfavorable-bins) ERR_BIN_SLIPPAGE)
    (asserts! (>= received min-received) ERR_MINIMUM_RECEIVED)
    (ok received)
  )
)

;; Fold function to swap through multiple bins in multiple pools
(define-private (fold-swap-multi
    (swap {pool-trait: <dlmm-pool-trait>, x-token-trait: <sip-010-trait>, y-token-trait: <sip-010-trait>, expected-bin-id: int, amount: uint, x-for-y: bool})
    (result (response {received: uint, unfavorable: uint} uint))
  )
  (let (
      (pool-trait (get pool-trait swap))
      (x-token-trait (get x-token-trait swap))
      (y-token-trait (get y-token-trait swap))
      (amount (get amount swap))
      (x-for-y (get x-for-y swap))
      (active-bin-id (unwrap! (contract-call? pool-trait get-active-bin-id) ERR_NO_ACTIVE_BIN_DATA))
      (bin-id-delta (- active-bin-id (get expected-bin-id swap)))
      (is-unfavorable (if x-for-y (> bin-id-delta 0) (< bin-id-delta 0)))
      (swap-result (if x-for-y
                       (try! (contract-call? .working-amaranth-clownfish swap-x-for-y pool-trait x-token-trait y-token-trait active-bin-id amount))
                       (try! (contract-call? .working-amaranth-clownfish swap-y-for-x pool-trait x-token-trait y-token-trait active-bin-id amount))))
      (result-data (unwrap! result ERR_NO_RESULT_DATA))
  )
    (ok {
      received: (+ (get received result-data) swap-result),
      unfavorable: (+ (get unfavorable result-data) (if is-unfavorable (abs-int bin-id-delta) u0))
    })
  )
)

;; Get absolute value of a signed int as uint
(define-private (abs-int (value int))
  (to-uint (if (>= value 0) value (- value)))
)

Functions (3)

FunctionAccessArgs
swap-multipublicswaps: (list 350 {pool-trait: <dlmm-pool-trait>, x-token-trait: <sip-010-trait>, y-token-trait: <sip-010-trait>, expected-bin-id: int, amount: uint, x-for-y: bool}
fold-swap-multiprivateswap: {pool-trait: <dlmm-pool-trait>, x-token-trait: <sip-010-trait>, y-token-trait: <sip-010-trait>, expected-bin-id: int, amount: uint, x-for-y: bool}, result: (response {received: uint, unfavorable: uint} uint
abs-intprivatevalue: int