(mod
  (
    SINGLETON_STRUCT
    ROYALTY_ADDRESS
    TRADE_PRICE_PERCENTAGE
    Current_Owner  ; Truth
    conditions  ; Truth
    solution  ; created from the NFT's inner puzzle - solution is (new_owner trade_prices_list new_did_inner_hash)
  )

  ; This is a transfer program - which must return (new_owner, Optional[new_transfer_program], conditions)

  (include condition_codes.clib)
  (include curry-and-treehash.clib)

  (defconstant TEN_THOUSAND 10000)

  ;; return the full puzzlehash for a singleton with the innerpuzzle curried in
  ; puzzle-hash-of-curried-function is imported from curry-and-treehash.clib
  (defun-inline calculate_full_puzzle_hash (SINGLETON_STRUCT inner_puzzle_hash)
    (puzzle-hash-of-curried-function (f SINGLETON_STRUCT)
      inner_puzzle_hash
      (sha256tree SINGLETON_STRUCT)
    )
  )

  ; Given a singleton ID, generate the singleton struct
  (defun-inline get_singleton_struct (SINGLETON_STRUCT singleton_id)
    (c (f SINGLETON_STRUCT) (c singleton_id (r (r SINGLETON_STRUCT))))
  )

  (defun-inline calculate_percentage (amount percentage)
    (f (divmod (* amount percentage) TEN_THOUSAND))
  )

  ; Loop of the trade prices list and either assert a puzzle announcement or generate xch
  (defun parse_trade_prices_list (ROYALTY_ADDRESS TRADE_PRICE_PERCENTAGE trade_prices_list my_nft_id)
    (if trade_prices_list
        (c
          (list
            ASSERT_PUZZLE_ANNOUNCEMENT
            (sha256
              (f (r (f trade_prices_list)))
              (sha256tree (c my_nft_id (list (list ROYALTY_ADDRESS (calculate_percentage (f (f trade_prices_list)) TRADE_PRICE_PERCENTAGE) (list ROYALTY_ADDRESS)))))
            )
          )
          (parse_trade_prices_list ROYALTY_ADDRESS TRADE_PRICE_PERCENTAGE (r trade_prices_list) my_nft_id)
        )
        ()
    )
  )

  ; main
  ; Returning (new_owner new_transfer_program conditions)
  ; solution is (new_owner trade_prices_list new_did_inner_hash)
  (if solution
      (list
        (f solution)
        0
        (if (all (f solution) (not (= (f solution) Current_Owner)))
            (c
              (list
                ASSERT_PUZZLE_ANNOUNCEMENT
                (sha256
                  (calculate_full_puzzle_hash (get_singleton_struct SINGLETON_STRUCT (f solution)) (f (r (r solution))))
                  (f (r SINGLETON_STRUCT))
                )
              )
              (parse_trade_prices_list ROYALTY_ADDRESS TRADE_PRICE_PERCENTAGE (f (r solution)) (f (r SINGLETON_STRUCT)))
            )
            (parse_trade_prices_list ROYALTY_ADDRESS TRADE_PRICE_PERCENTAGE (f (r solution)) (f (r SINGLETON_STRUCT)))
        )
      )
      (list Current_Owner () ())
  )


)
