Skip to content

Latest commit

 

History

History
76 lines (52 loc) · 3.05 KB

contract-environment.md

File metadata and controls

76 lines (52 loc) · 3.05 KB

Contract environment

CTL environment (ContractEnv type) consists of:

  • various settings
  • network protocol parameters (fetched once on initialization)
  • active Ogmios WebSocket (optional)
  • CIP-30 wallet connection (optional)
  • internal state used by synchronization primitives

ContractEnv management

Initialization is a costly operation, and having multiple distinct runtimes may lead to problems with state synchronization and excessive WebSocket use, so it is recommended to use only one runtime at any point in time.

If only one Contract is ever executed, just using runContract is perfectly fine. Otherwise, there are two better approaches:

Following the bracket pattern

Bracket pattern in functional programming world is commonly used to safely manage resources. In our case, withContractEnv should be used to initialize and finalize a ContractEnv. runContractEnv should be used to run a Contract within the environment:

withContractEnv :: forall (a :: Type). ContractParams -> (ContractEnv -> Aff a) -> Aff a
runContractInEnv :: forall (a :: Type). ContractEnv -> Contract a -> Aff a

myContract1 :: Contract Uni
myContract2 :: Contract Uni

myRunner :: ContractParams -> Aff Unit
myRunner params = withContractEnv params \env -> do
  runContractInEnv env myContract1
  runContractInEnv env myContract2

Using bracket functions is safe, but is not always convenient, because withContractEnv callback must hold the Aff context until all Contracts exit.

Manually passing the environment

Another approach is using mkContractEnv coupled with runContractInEnv and stopContractEnv.

Here's an example:

mkContractEnv :: ContractParams -> Aff ContractEnv
stopContractEnv :: ContractEnv -> Aff Unit

myContract1 :: Contract Uni
myContract2 :: Contract Uni

myRunner :: ContractParams -> Aff Unit
myRunner params = do
  env <- mkContractEnv
  void $ try do
    runContractInEnv env myContract1
    runContractInEnv env myContract2
  stopContractEnv env

This approach is less safe in general, and it's fairly easy to hit the max WebSocket connections limit (which is 200 for Firefox) due to a forgotten stopContractEnv call (e.g. due to an exception), not to mention that any websocket that is not closed will force the server to also keep the connection.

This approach, however, is better suited for use when creating custom JavaScript SDKs.

See also