dazl

dazl.ledger

The dazl.ledger module provides a way of connecting to Daml ledgers via the gRPC Ledger API or HTTP JSON API.

Example

Note

These examples are targeted to Python 3.7+ and later, particularly the use of asyncio.run(). For Python 3.6, replace calls to asyncio.run(main()) with:

loop = asyncio.get_event_loop()
loop.run_until_complete(main())

Connecting to a ledger, and printing out all create events that Alice can see (using the asyncio API):

import asyncio
import dazl

async def main():
   async with dazl.connect(url='localhost:6865', read_as='Alice') as conn:
      async with conn.query('*') as stream:
         async for event in stream.creates():
            print(event.contract_id, event.payload)

# Python 3.7+ or later
asyncio.run(main())
dazl.ledger.connect(**kwargs)

Create a connection from the supplied parameters. All of the parameters are optional, but you will have to supply at least read_as, act_as, admin, oauth_token, or oauth_token_file (see the section on Access config below).

Parameters
  • url (str) – The URL to connect to. Can be used as an alternative to supplying host, port, and scheme as individual values. If none of of url, host, port or scheme are specified, the value from the environment variable DAML_LEDGER_URL is used instead.

  • host (str) – The host to connect to. Can be used as an alternative to supplying url as a combined value. If none of of url, host, port or scheme are specified, the value from the environment variable DAML_LEDGER_HOST is used instead.

  • port (int) – The port to connect to. Can be used as an alternative to supplying url as a combined value. If none of of url, host, port or scheme are specified, the value from the environment variable DAML_LEDGER_PORT is used instead.

  • scheme (str) – The scheme to connect to. Can be used as an alternative to supplying url as a combined value. If none of of url, host, port or scheme are specified, the value from the environment variable DAML_LEDGER_SCHEME is used instead.

  • connect_timeout (float or datetime.timedelta) – Length of time to wait before giving up connecting to the remote and declaring an error. The default value is 30 seconds. If a number is supplied instead of a timedelta, it is assumed to mean seconds.

  • use_http_proxy (bool) – True to use an HTTP(S) proxy server if configured; False to avoid using any configured server. If unspecified and the host is localhost, the proxy server is avoided; otherwise the proxy server is used.

  • ca (bytes) – A certificate authority to use to validate the server’s certificate. If not supplied, the operating system’s default trust store is used. Cannot be specified with ca_file.

  • ca_file (os.PathLike) – A file containing the certificate authority to use to validate the server’s certificate. If not supplied, the operating system’s default trust store is used. Cannot be specified with ca.

  • cert (bytes) – A client-side certificate to be used when connecting to a server that requires mutual TLS. Cannot be specified with cert_file.

  • cert_file (os.PathLike) – A file containing the client-side certificate to be used when connecting to a server that requires mutual TLS. Cannot be specified with cert.

  • cert_key (bytes) – A client-side private key to be used when connecting to a server that requires mutual TLS. Cannot be specified with cert_key_file.

  • cert_key_file (os.PathLike) – A client-side private key to be used when connecting to a server that requires mutual TLS. Cannot be specified with cert_key.

  • read_as (str or Collection[str]) – A party or set of parties on whose behalf (in addition to all parties listed in act_as) contracts can be retrieved. Cannot be specified if oauth_token or oauth_token_file is specified. If none of of read_as, act_as, admin, ledger_id, application_name, oauth_token, or oauth_token_file are specified, the value from the environment variable DAML_LEDGER_ACT_AS is used instead.

  • act_as (str or Collection[str]) – A party or set of parties on whose behalf commands should be executed. Parties here are also implicitly granted read_as access as well. Cannot be specified if oauth_token or oauth_token_file is specified. If none of of read_as, act_as, admin, ledger_id, application_name, oauth_token, or oauth_token_file are specified, the value from the environment variable DAML_LEDGER_ACT_AS is used instead.

  • admin (bool) – HTTP JSON API only: allow admin endpoints to be used. This flag is ignored when connecting to gRPC Ledger API implementations. Cannot be specified if oauth_token or oauth_token_file is specified.

  • ledger_id (str) – The ledger ID to connect to. For the HTTP JSON API, this value is required. For the gRPC Ledger API, if this value is _not_ supplied, its value will be retrieved from the server. Cannot be specified if oauth_token or oauth_token_file is specified. If none of of read_as, act_as, admin, ledger_id, application_name, oauth_token, or oauth_token_file are specified, the value from the environment variable DAML_LEDGER_ID is used instead.

  • application_name (str) – A string that identifies this application. This is used for tracing purposes on the server-side. Cannot be specified if oauth_token or oauth_token_file is specified. If none of of read_as, act_as, admin, ledger_id, application_name, oauth_token, or oauth_token_file are specified, the value from the environment variable DAML_LEDGER_APPLICATION_NAME is used instead.

  • oauth_token (bytes) – The OAuth bearer token to be used on all requests. Cannot be specified if read_as, act_as, admin, ledger_id, application_name, or oauth_token_file is specified. If none of of read_as, act_as, admin, ledger_id, application_name, oauth_token, or oauth_token_file are specified, the value from the environment variable DAML_LEDGER_OAUTH_TOKEN is used instead.

  • oauth_token_file (os.PathLike) – A file that contains the OAuth bearer token to be used on all requests. Cannot be specified if read_as, act_as, admin, ledger_id, application_name, or oauth_token is specified. If none of of read_as, act_as, admin, ledger_id, application_name, oauth_token, or oauth_token_file are specified, the value from the environment variable DAML_LEDGER_OAUTH_TOKEN_FILE is used instead.

  • logger (logging.Logger) – The logger to use for connections created from this configuration. If not supplied, a logger will be created.

  • logger_name (str) – The name of the logger. Only used if logger is not provided.

  • log_level (int or str) – The logging level for the logger. The default is warn. Only used if logger is not provided. This function accepts any valid Python logging level.

The remote can be configured either by supplying a URL or by supplying a host (and optional port and scheme). If none of url, host, port, or scheme are supplied, then environment variables are consulted; if no environment variables are specified either, then default values are used.

When the URL scheme is http or https, dazl will first attempt to connect assuming the HTTP JSON API; if this fails, gRPC Ledger API is attempted.

If oauth_token is supplied and non-empty, then token-based access is used to connect to the ledger. (Note that you cannot specify both oauth_token and oauth_token_file.)

If other fields are specified, then property-based access is used. At least one of read_as, act_as, or admin must be supplied. For the HTTP JSON API, ledger_id MUST be supplied.

If no fields are specified, this is an error unless environment variables supply an alternate source of configuration.

function argument

environment variable

default value

Connection config

Specifying any of url, host, port, or scheme causes all of these environment variables to be ignored

url

DAML_LEDGER_URL

localhost:6865

host

DAML_LEDGER_HOST

localhost

port

DAML_LEDGER_PORT

6865, unless scheme is specified:
• 80 for http
• 443 for https
• 6865 for grpc

scheme

DAML_LEDGER_SCHEME

https for port 443 or 8443
http for port 80, 7575 or 8080
grpc for port 6865
https for all other ports

Access config

Specifying any of act_as, read_as, admin, ledger_id, application_name, oauth_token, or oauth_token_file causes all of these environment variables to be ignored

act_as

DAML_LEDGER_ACT_AS (as a comma-separated list of parties)

read_as

DAML_LEDGER_READ_AS (as a comma-separated list of parties)

ledger_id

DAML_LEDGER_ID

application_name

DAML_LEDGER_APPLICATION_NAME

oauth_token

DAML_LEDGER_OAUTH_TOKEN

oauth_token_file

DAML_LEDGER_OAUTH_TOKEN_FILE

Note

When connecting to the gRPC Ledger API, note that gRPC environment variables are also respected. You can configure the gRPC client in much more detail with these flags.

Data Model

Commands

Command

abstract base class of all commands

CreateCommand

create a contract

CreateAndExerciseCommand

create a contract and immediately exercise a choice on the newly created contract in a single transaction

ExerciseCommand

exercise a choice on a contract identified by its contract ID

ExerciseByKeyCommand

exercise a choice on a contract identified by its contract key

CommandMeta

additional fields that can accompany a command submission

Events and Responses

CreateEvent

event raised when a contract is created, either as part of the active contract set or on the transaction stream

ArchiveEvent

event raised when a contract is archived on the transaction stream

ExerciseResponse

the response from an exercise, including the choice’s return value (if any)

Boundary

indicates a point where an event stream can be subsequently resumed

Other

PartyInfo

metadata about a party

Connections

class dazl.ledger.Connection

Protocol that describes a connection to a ledger. You will typically work with the more specific protocols dazl.ledger.aio.Connection or dazl.ledger.blocking.Connection that are tailored towards connections with asyncio or thread-blocking semantics, respectively.

On asynchronous connections:

  • the command submission methods create(), exercise(), submit() are coroutines.

  • the stream methods query(), query_many(), stream(), and stream_many(), return asynchronous context managers and asynchronous iterators

On blocking connections:

  • the command submission methods create(), exercise(), submit() block the current thread until the command submission succeeds or fails.

  • the stream methods query(), query_many(), stream(), and stream_many(), return context managers and blocking iterators.

exercise(contract_id, choice_name, [argument, ]/, *, workflow_id=None, command_id=None)

Exercise a choice on a contract identified by its contract ID.

Parameters
  • contract_id (dazl.prim.ContractId) – The contract ID of the contract to exercise.

  • choice_name (str) – The name of the choice to exercise.

  • argument (dict or None) – The choice arguments. Can be omitted for choices that take no argument.

  • workflow_id (str or None) – An optional workflow ID.

  • command_id (str or None) – An optional command ID. If unspecified, a random one will be created.

archive(contract_id, /, *, workflow_id=None, command_id=None)

Archive a choice on a contract identified by its contract ID.

Parameters
  • contract_id (dazl.prim.ContractId) – The contract ID of the contract to archive.

  • workflow_id (str or None) – An optional workflow ID.

  • command_id (str or None) – An optional command ID. If unspecified, a random one will be created.

class dazl.ledger.QueryStream

Protocol for classes that provide for reading from a stream of events from a Daml ledger. Like Connection, there are async query streams (dazl.ledger.aio.QueryStream) and blocking query streams (dazl.ledger.blocking.QueryStream).

The methods of QueryStream consume the stream: you cannot replay a QueryStream’s contents simply by trying to iterate over it again.

On asynchronous connections, the methods on QueryStream return asynchronous iterators: use async for to iterate over their contents.

On blocking connections, the methods on QueryStream return blocking iterators: use for to iterate over their contents.

Note that the events() and items() streams may return ArchiveEvent objects that had no CreateEvent predecessor. This may happen for a number of reasons:

  • You started requesting a stream at a specific offset. When resuming from an offset, no events (CreateEvent or ArchiveEvent) that preceded the specified offset are returned.

  • You are filtering events; event filtering only applies to CreateEvent instances and not ArchiveEvent.

  • You are learning of an archive of a divulged contract. Note that dazl does not have an API for retrieving divulged contracts.

Reading from and controlling the stream

The creates(), events(), and items() methods are used to receive events from the stream; run() can be used to consume the stream without iterating yourself, and close() stops the stream.

# asynchronous connections
async with conn.stream() as stream:
   async for event in stream.creates():
      # print every contract create...forever
      print(event.contract_id, event.payload)

# blocking connections
with conn.stream() as stream:
   for event in stream.creates():
      # print every contract create...forever
      print(event.contract_id, event.payload)
creates()

Return an iterator (or async iterator) over only CreateEvent instances.

events()

Return an iterator (or async iterator) over CreateEvent and ArchiveEvent instances.

items()

Return an iterator (or async iterator) over all objects (CreateEvent, ArchiveEvent, and Boundary).

run()

Block until the stream has been fully consumed. This method normally only makes sense to use in conjunction with callbacks (on_create(), on_archive(), and on_boundary()). For async connections, this is a coroutine.

close()

Stops the iterator and aborts the stream. For async connections, this is a coroutine.

Registering Callbacks

Callbacks can be used as an alternative to reading events from the stream.

The callable must take a CreateEvent, ArchiveEvent, or Boundary as its only parameter and should generally return None. However the callback can also return CreateEvent or ExerciseResponse, mostly so that one-line lambdas that call ledger methods can be used:

# registering a callback as a lambda
stream.on_create("My:Tmpl", lambda event: conn.exercise(event.cid, "Accept"))

# registering a callback using a decorator
@stream.on_create("My:Tmpl")
def handle(event):
    conn.exercise(event.cid, "Accept")
on_create(fn)
on_create(name, fn)
@on_create
@on_create(name)

Register a callback that is triggered whenever a CreateEvent is read through the stream.

Parameters

name (str or dazl.damlast.TypeConName) – An optional name of a template to further filter CreateEvent.

on_archive(fn)
on_archive(name, fn)
@on_archive
@on_archive(name)

Register a callback that is triggered whenever a ArchiveEvent is read through the stream.

Parameters

name (str or dazl.damlast.TypeConName) – An optional name of a template to further filter ArchiveEvent.

on_boundary(fn)
@on_boundary

Register a callback that is triggered whenever a Boundary is read through the stream.

Write-side types

Daml ledger state can be updated by submitting commands to the ledger. You should prefer using Connection.create(), Connection.create_and_exercise(), Connection.exercise(), and Connection.exercise_by_key() over constructing instances of these commands, as those methods can give you more information about what happened.

class dazl.ledger.Command

Base class for write-side commands.

This class provides no functionality on its own.

class dazl.ledger.CreateCommand(template_id: Union[str, dazl.damlast.daml_lf_1.TypeConName], payload: Mapping[str, Any])

A command that creates a contract without any predecessors.

property payload: Mapping[str, Any]

Return the template arguments for the contract to be created.

property template_id: dazl.damlast.daml_lf_1.TypeConName

Return the template of the contract to be created.

class dazl.ledger.CreateAndExerciseCommand(template_id: Union[str, dazl.damlast.daml_lf_1.TypeConName], payload: Mapping[str, Any], choice: str, argument: Optional[Any] = None)

A command that exercises a choice on a newly-created contract in a single transaction.

Instead of creating an instance of this command and submitting it with Connection.submit(), consider using Connection.create_and_exercise() instead, which also gives you access to the result of exercising the choice.

property argument: Any

The choice arguments.

property choice: str

The choice to exercise.

property payload: Mapping[str, Any]

The template arguments for the contract to be created.

property template_id: dazl.damlast.daml_lf_1.TypeConName

The template of the contract to be created.

class dazl.ledger.ExerciseCommand(contract_id: dazl.prim.contracts.ContractId, choice: str, argument: Optional[Any] = None, choice_interface_id: Optional[dazl.damlast.daml_lf_1.TypeConName] = None)

A command that exercises a choice on a contract identified by its contract ID.

Instead of creating an instance of this command and submitting it with Connection.submit(), consider using Connection.exercise() instead, which also gives you access to the result of exercising the choice.

property argument: Any

The choice arguments.

property choice: str

The choice to exercise.

property choice_interface_id: Optional[dazl.damlast.daml_lf_1.TypeConName]

The interface ID, if this choice is meant to be exercised on an interface.

property contract_id: dazl.prim.contracts.ContractId

The contract ID of the contract to exercise.

class dazl.ledger.ExerciseByKeyCommand(template_id: Union[str, dazl.damlast.daml_lf_1.TypeConName], key: Any, choice: str, argument: Optional[Any] = None)

A command that exercises a choice on a contract identified by its contract key.

Instead of creating an instance of this command and submitting it with Connection.submit(), consider using Connection.exercise_by_key() instead, which also gives you access to the result of exercising the choice.

property argument: Any

The choice arguments.

property choice: str

The choice to exercise.

property key: Any

The contract key of the contract to exercise.

property template_id: dazl.damlast.daml_lf_1.TypeConName

The contract template type.

class dazl.ledger.CommandMeta(workflow_id: Optional[str], command_id: Optional[str], read_as: Union[None, dazl.prim.party.Party, Collection[dazl.prim.party.Party]], act_as: Union[None, dazl.prim.party.Party, Collection[dazl.prim.party.Party]])

Additional fields that accompany a command submission.

workflow_id: str | None

An optional workflow ID.

command_id: str | None

An optional command ID. If unspecified, a random one will be created.

read_as: Collection[Party] | None

An optional set of read-as parties to use to submit this command. Note that for a ledger with authorization, these parties must be a subset of the parties in the token.

act_as: Collection[Party] | None

An optional set of act-as parties to use to submit this command. Note that for a ledger with authorization, these parties must be a subset of the parties in the token.

Read-side types

An Event in a transaction is either a CreateEvent or an ArchiveEvent`.

You can resume a stream of events from a previous point by using stream.items() and looking for Boundary objects.

More detailed information about exercises, including the return value and events that occurred as a result of an exercise, is available from ExerciseResponse objects as returned from Connection.create_and_exercise(), Connection.exercise(), and Connection.exercise_by_key().

class dazl.ledger.CreateEvent(contract_id: dazl.prim.contracts.ContractId, payload: Mapping[str, Any], signatories: Collection[dazl.prim.party.Party], observers: Collection[dazl.prim.party.Party], agreement_text: Optional[str], key: Optional[Any])

An event that indicates a newly-created contract.

property agreement_text: Optional[str]

The agreement text of the contract.

property contract_id: dazl.prim.contracts.ContractId

The ID of the created contract.

property key: Optional[Any]

The key of the contract, if defined.

property observers: AbstractSet[dazl.prim.party.Party]

The observers for this contract as specified explicitly by the template or implicitly as choice controllers.

property payload: Mapping[str, Any]

The parameters that were used to create the contract.

property signatories: AbstractSet[dazl.prim.party.Party]

The signatories for this contract as specified by the template.

class dazl.ledger.ArchiveEvent(contract_id: dazl.prim.contracts.ContractId)

An event that indicates a contract was archived.

property contract_id: dazl.prim.contracts.ContractId

The contract ID of the archived contract.

class dazl.ledger.Boundary(offset: Optional[str])

An event that indicates a boundary in a query stream where events can be resumed.

property offset: Optional[str]

The offset at which this boundary occurred.

If this is None, that indicates that an active contract set was requested, but the ledger is completely empty.

class dazl.ledger.ExerciseResponse(result: Optional[Any], events: Sequence[Union[dazl.ledger.api_types.CreateEvent, dazl.ledger.api_types.ArchiveEvent]])

Returned when directly exercising a choice using Connection.create_and_exercise(), Connection.exercise(), or Connection.exercise_by_key().

property events: Sequence[Union[dazl.ledger.api_types.CreateEvent, dazl.ledger.api_types.ArchiveEvent]]

All of the events that occurred as a result of exercising the choice, including the archive event for the contract if the choice is consuming (or otherwise archives it as part of its execution).

property result: Optional[Any]

The return value of the choice.

Other

class dazl.ledger.PartyInfo(party: dazl.prim.party.Party, display_name: str, is_local: bool)

Full information about a Party.

property display_name: str

The human-readable name associated with the Party.

property is_local: bool

Indicates if the Party is hosted by the backing participant.

property party: dazl.prim.party.Party

The stable unique identifier of a Daml Party.