Source code on Github
------------------------------------------------------------------------
-- BitML datatypes: Contracts & Ads
------------------------------------------------------------------------
open import Prelude.Init; open SetAsType
open import Prelude.DecEq

open import BitML.BasicTypes
open import BitML.Predicate

module BitML.Contracts.Types ⋯ (let open ⋯ ⋯) where

variable A B A′ B′ : Participant

------------------------------------------------------------------------
-- Contracts

data Branch : Type
Contract    = List Branch
Contracts   = List Contract
VContracts  = List (Value × Contract)
VIContracts = List (Value × Contract × Id)

data Branch where

  -- collect deposits and secrets
  put_&reveal_if_⇒_ : Ids → Secrets → Predicate → Contract → Branch

  -- transfer the balance to a participant
  withdraw : Participant → Branch

  -- split the balance
  -- T0D0: phrase as percentages to mitigate the need for `Validity.splitsOK`
  split : VContracts → Branch

  -- wait for participant's authorization
  _∶_ : Participant → Branch → Branch

  -- wait of a period of time
  after_∶_ : Time → Branch → Branch

{-# TERMINATING #-}
unquoteDecl DecEq-Branch = DERIVE DecEq [ quote Branch , DecEq-Branch ]

variable
  d d′ d″ : Branch
  ds ds′ ds″ c c′ c″ : Contract
  cs cs′ cs″ : Contracts
  vcs vcs′ vcs″ : VContracts

pattern put_&reveal_⇒_ xs as c = put xs &reveal as if `true ⇒ c
pattern put_⇒_ xs c            = put xs &reveal []          ⇒ c
pattern put_if_⇒_ xs p c       = put xs &reveal [] if p     ⇒ c
pattern reveal_if_⇒_ as p c    = put [] &reveal as if p     ⇒ c
pattern reveal_⇒_ as c         = put [] &reveal as          ⇒ c

-------------------------------------------------------------------
-- Contract preconditions.

data Precondition : Type where

  -- volatile deposit
  _:?_at_ : Participant → Value → Id → Precondition

  -- persistent deposit
  _:!_at_ : Participant → Value → Id → Precondition

  -- committed secret (random nonce) by <Participant>
  _:secret_ : Participant → Secret → Precondition

  -- composition
  _∣_ : Op₂ Precondition

unquoteDecl DecEq-PreC = DERIVE DecEq [ quote Precondition , DecEq-PreC ]

variable g g′ g″ : Precondition

------------------------------------------------------------------------
-- Advertisements.

record Ad : Type where
  constructor ⟨_⟩_
  field
    G : Precondition
    C : Contract
open Ad public
unquoteDecl DecEq-Ad = DERIVE DecEq [ quote Ad , DecEq-Ad ]

variable ad ad′ ad″ : Ad

------------------------------------------------------------------------
-- Auxiliary types.

data DepositType : Type where
  volatile persistent : DepositType

DepositRef   = Participant × Value × Id
DepositRefs  = List DepositRef
TDepositRef  = DepositType × DepositRef
TDepositRefs = List TDepositRef

PutComponent = Ids × Secrets × Predicate

-- Notation.

private variable X Y Z : Type

import Prelude.Lists.NoNil as NN
open NN using (List?; toL) public
instance
  ⊕-notation-𝕃 = NN.Pick𝕃
  ⊕-notation-ℝ = NN.Pickℝ
_⊕_ = NN._⊕_ {X = Branch}
_⊗_ = Op₂ VContracts ∋ _++_

_⊸_ : Value → X → ⦃ List? Branch X ⦄ → VContracts
v ⊸ c = [ v , toL c ]

open import Prelude.General; open MultiTest
module _ (b b′ : Branch) (c c′ : Contract) where
  _ = Contract
   ∋⋮ b ⊕ b′
    ⋮ b ⊕ c
    ⋮ c ⊕ b
    ⋮ c ⊕ c′
    ⋮∅

module _ ⦃ _ : List? Id X ⦄ ⦃ _ : List? Secret Y ⦄ ⦃ _ : List? Branch Z ⦄ where
  put_&reveal_if_._ : X → Y → Predicate → Z → Branch
  put xs &reveal as if p . bs = put toL xs &reveal toL as if p ⇒ toL bs

  put_&reveal_._ : X → Y → Z → Branch
  put xs &reveal as . bs = put toL xs &reveal toL as ⇒ toL bs

  infix 8 put_&reveal_if_._ put_&reveal_._

module _ ⦃ _ : List? String X ⦄ ⦃ _ : List? Branch Y ⦄ where
  put_._ reveal_._ : X → Y → Branch
  put    xs . bs = put    toL xs ⇒ toL bs
  reveal as . bs = reveal toL as ⇒ toL bs

  put_if_._ reveal_if_._ : X → Predicate → Y → Branch
  put    xs if p . bs = put    toL xs if p ⇒ toL bs
  reveal as if p . bs = reveal toL as if p ⇒ toL bs

  infix 8 put_._ put_if_._ reveal_._ reveal_if_._

infix  7 _:?_at_ _:!_at_ _:secret_
infixl 6 _∣_
infix  0 ⟨_⟩_

infixr 9 _∶_ after_∶_
infix  8 put_&reveal_if_⇒_ put_&reveal_⇒_ put_⇒_ put_if_⇒_ reveal_⇒_ reveal_if_⇒_
infixr 5 _⊕_
infix  4 _⊸_
infixr 3 _⊗_

-- Examples.

module _ (A B : Participant) where
  _ = Contract
   ∋⋮ [ withdraw A ]
    ⋮ A ∶ withdraw A
    ⊕ put [] . withdraw A
    ⋮ [ put "x" . withdraw A ]
    ⋮ A ∶ withdraw B
    ⊕ B ∶ split ( 2 ⊸ withdraw A
                ⊗ 3 ⊸ after 100 ∶ withdraw B
                    ⊕ after 200 ∶ withdraw A
                ⊗ 0 ⊸ put "y" . (A ∶ withdraw B))
    ⋮∅

  _ = Ad
   ∋⋮ ⟨ B :! 2 at "x" ∣ A :! 3 at "y" ∣ B :? 100 at "z" ⟩
      [ put "z" . withdraw A ]
    ⋮∅