Release of DAML SDK 1.7.0
DAML SDK 1.7.0 has been released on November 11th 2020. You can install it using:
daml install latest
If you're using the DAML Triggers Early Access you'll need to migrate to the new API. No other mandatory changes are required for this release but other impacts and migrations are detailed below.
Interested in what's happening in the DAML community and its ecosystem? If so we've got a jam packed summary for you in our latest community update.
Highlights
- DAML Connect has been introduced as a logical grouping for all those components a developer needs to connect to a DAML network.
- JSON API, DAML Script, and the JavaScript Client Libraries now support reading as multiple parties.
daml start
can now perform code generation, and has a quick-reload feature for fast iterative app development- Support for multi-key/query streaming queries in React Hooks
- New query functions accepting multiple keys supersede the old single-key/query versions, which are now deprecated.
- DAML Triggers (Early Access) have an overhauled API that is more aligned with DAML Script
- This change requires a migration detailed below.
Impact and Migration
- The compiler now emits warnings if you use advanced and undocumented language features which are not supported by data-dependencies. This only affects you if you use language extensions not documented on docs.daml.com or import
DA.Generics
. If you receive such warnings, it is recommended that you move off them. If you are getting unexpected warnings, or don’t know how to migrate, please get in touch with us via the public forum or support.digitalasset.com (for registered users). - If you are using stream queries in the React Hooks, we recommend you migrate to the new multi-key versions. The migration is detailed below. The old functions are now deprecated, meaning they may be removed with a major release 12 months from now.
- If you are using DAML Triggers, you’ll need to migrate them to the new API.
What’s New
Clearer Segmentation of the DAML stack with DAML Connect
Background
With Release 1.6 work started to clarify the DAML stack in many respects: What it consists of, what state different pieces are in, and what stability and compatibility guarantees users can expect. However, the ecosystem overview page highlighted that there was a lack of good terminology of the sets of components users needed to either establish a DAML network, or to connect to a DAML network. Previously the label “SDK” was sometimes used to refer to the latter, but that was inaccurate since the SDK only contains components intended to be used at development time. With release 1.7 this has been tidied up with clearer terminology for different layers of the stack. DAML Connect describes all those pieces that are needed to connect to a DAML network:
- Runtime Components like the JSON API
- Libraries like the Java Ledger API bindings and JavaScript client library
- Generated Code from the
daml codegen
commands - Developer tools like the IDE, collectively called the SDK
Specific Changes
The ecosystem overview docs page has been improved, and naming has been adjusted throughout docs and artifacts to incorporate these changes.
Impact and Migration
This change only affects documentation and help text. There are no API changes.
Multi-Party Read in JSON API, Script, and JS Client Libs
Background
The DAML Ledger API has supported multi-party transaction subscriptions for a long time, but until now, the runtime components like JSON API, and DAML Script and REPL were only able to query as a single party. As a first step towards enhancing DAML’s capabilities in sharing data in more flexible ways than the observer
concept, the runtime components have now gained features to query contracts on behalf of multiple parties at the same time. Since read-access via the JSON API is controlled using JWTs, any client of the JSON API, including the JavaScript client libraries, can profit from these improvements provided the token issuer is able to issue appropriate tokens.
Specific Changes
- The JSON API now accepts tokens with multiple parties specified in the
readAs
field. In queries, contracts known to any of the known parties will be returned. In command submissions, thereadAs
field is ignored.actAs
is still limited to a single party.- Before this change, the JSON API would accept tokens with only a
readAs
party, and noactAs
party set for command submission endpoints. When working with unauthenticated ledgers, this could lead to successful command submission without anactAs
party set. This bug has been fixed as part of this change. If you were previously exploiting this bug during development, please move the submitting party fromreadAs
toactAs
.
- Before this change, the JSON API would accept tokens with only a
- In DAML Script, the
query
,queryContractId
, andqueryContractKey
now accept multiple parties using theIsParties
abstraction used bysignatory
,observer
, and other fields. Specifically this means they accept single parties, lists of parties, and sets of parties interchangeably. They will return all contracts for which any of the given parties is a stakeholder.
Impact and Migration
As mentioned above, a bug was fixed in which a command submission could be successful via the JSON API if only the readAs
field in the JWT was set, and the underlying Ledger API was running in unauthenticated mode. This is no longer possible. The submitting party has to be set in the actAs
field.
Better (re)build with daml start
Background
daml start
is the primary command allowing quick testing of a DAML application. It compiles DAML contracts, starts up a Sandbox and a Navigator, and runs initialization scripts. However, it didn’t run code-generation, nor did it have any functionality for re-building and deploying after a change, requiring developers to manually shut it down, re-generate code, and restart. With this release, that manual and error-prone process has been replaced with automatic refreshes including codegen.
Note that if you use Navigator, you might still want to do a full restart to clear old contracts and packages.
Specific Changes
You can now press 'r' (or 'r' + 'Enter' on Windows) in the terminal where daml start
is running to rebuild the DAR package and generate JavaScript/Java/Scala bindings and upload the new package to the Sandbox. This frees the user from killing and restarting daml start
.
The daml start
now runs all the code generators specified in the daml.yaml
project configuration file under the codegen
stanza. This frees the user from having to do so manually on every change to the DAML model.
For example, instead of running the JavaScript codegen manually as part of the create-daml-app, it is now included in the daml.yaml
.
Before: Manual run of
daml codegen js .daml/dist/create-daml-app-0.1.0.dar -o daml.js
After: stanza in daml.yaml
Impact and Migration
This is a purely additive change.
API Alignment of Triggers (Early Access)
Background
The DAML API of Triggers has been brought further inline with those of DAML Script and REPL, at the same time allowing for more efficient implementation of high-level triggers under the hood. Before, all the information consumable by the trigger rule, initialization, and update functions was passed in as function arguments. With this iteration, state, active contracts, and time are accessible using actions (using <-
notation) instead.
Specific Changes
- Trigger
updateState
,rule
, andinitialize
functions no longer accept anACS
argument; instead, they must use thequery
action to query the active contract set, similar to the same function in DAML Script. See issue #7632. - Instead of taking a state argument, the
TriggerA
action now has functions toget
,put
andmodify
user defined state. - The
Time
argument was removed from the trigger rule function; instead, it can be fetched within theTriggerA
do
block bygetTime
, as withUpdate
andScript
. - The "commands in flight" of type
Map CommandId [Command]
argument has been removed from high-level triggerrule
functions; instead, the current commands-in-flight can be retrieved with the newgetCommandsInFlight
function. See issue #7600. initialize
is now aTriggerInitializeA
action, which is able to query the ledger usingquery
and related functions, and returns the initial state.- The
updateState
function now takes just a message and returns aTriggerStateA
which allows querying the ledger usingquery
and related functions, and modifying state using theget
,put
, andmodify
functions. See issue #7621. - Two new functions are available for querying the ledger:
queryContractId
, for looking up a contract by ID, andqueryContractKey
for looking one up by key. See issue #7726.
Impact and Migration
1. To migrate an existing initialize
function acs -> expr
, write a do
block with query
taking the place of any getContracts
occurrences. For example
For triggers without custom state (ie s == ()
), pure ()
is the right expression for initialize
.
2. To migrate an existing updateState
function, deal with ACS access as in 1. In addition, replace the state argument by calls with a call to modify.
For triggers without custom state (ie s == ()
), \msg -> pure ()
is the right expression for initialize
.
3. To migrate an existing rule
function, deal with ACS access as in 1., replace the state argument with a call to get, and in addition replace time and commands-in-flight access using the new accessor functions.
time, commandsInFlight, and state are each optional; if they are not used, the lines that “get” them may be removed.
React Hooks Multi-query streams
Background
Since version 1.6 the JSON API and JavaScript client libraries have had support for stream requests with multiple keys or queries. As of 1.7, this functionality is also available in the React Hooks, allowing for more efficient binding of ledger data to UI elements.
Specific Changes
- The React bindings now expose the recent addition of multi-key and multi-query streams, with the new
useStreamQueries
anduseStreamFetchByKeys
hooks in @daml/react mapping to, respectively,streamQueries
andstreamFetchByKeys
in @daml/ledger. - The singular versions are marked as deprecated as they have become redundant.
Impact and Migration
The change is fully backwards compatible as the old singular functions are merely deprecated, not removed. The below describes the upgrade path for the new multi-query versions.
Upgrading useStreamQuery
is straightforward: the query factory remains optional, but if specified it should return an array of queries instead of a single query. The array may be empty, which will return all contracts for that template, similar to not passing in a query factory. The return values of useStreamQuery
and useStreamQueries
have the same type.
Upgrading useStreamFetchByKey
is only slightly more involved as the return type of useStreamFetchByKeys
is different, called FetchByKeysResult
instead of the existing FetchResult
. FetchByKeysResult
differs from FetchResult
in that it contains a contracts
field with an array of contracts instead of a singular contract
field. It differs from QueryResult
in that each element of the returned array can also be null
, if there is no corresponding active contract. Call sites can be updated as follows:
Minor Improvements
- The Ledger API is now independently versioned instead of inheriting its version from the release of the Integration Kit components. This allows for cleaner cross-compatibility guarantees as described in the compatibility documentation. Every participant node from this release onwards advertises its Ledger API version via the version service.
- The
daml ledger list-parties
command can now query the ledger for known parties via the HTTP JSON API instead of the gRPC API. This requires setting the--json-api
flag. - The JSON API’s JDBC url can now also be specified via an environment variable set with the CLI flag
--query-store-jdbc-config-env
. - The JSON API has gained
/livez
and/readyz
health check endpoints for easier integration with k8s and other schedulers. - The JavaScript client library’s stream queries
useStreamQueries
anduseStreamFetchByKeys
as well as their (deprecated) singular counterparts now accept an optionalcloseHandler
callback, which will be called if the underlying WebSocket connection get closed due to an error or becauseclose
was called.
The same functions previously logged everyclose
event as an error. However, there are legitimate cases for the connection to be closed (e.g. the component has been unmounted). The default behaviour will now be to log only unexpected disconnects and be silent on deliberate connection closes. This can be customized using thecloseHandler
. - The JavaScript client library’s
reconnectThreshold
can now be configured through theLedgerProps
of theReact
wrapper. - The Standard Library’s
DA.Date
type now hasEnum
andBounded
instances allowing the use of ranges. Eg-- Create a list of all Sundays in 2020
[date 2020 Jan 5, date 2020 Jan 12 .. date 2020 Dec 31]
- Performance improvements in the DAML Engine when using typeclasses.
- From this release, the digitalasset/daml-sdk docker image on DockerHub will be signed.
Bug Fixes
- The DAML compiler shows the correct column numbers in error locations produced by command line tools like
daml build
. - The DAML Engine now properly enforces that the list of maintainers is non-empty. Before this version, it was possible on some DAML Ledgers to create contracts with empty maintainer lists. Such contracts can still be used when referenced by ContractId, but none of the key operations will work, and no new contracts with an empty maintainer list can be created.
- A bug in the JavaScript Client Libraries was fixed, which caused the
useStreamFetchByKeys
hook to sometimes report a "ready" state (i.e.loading: false
) even though the underlying connection had not yet been fully established. - A bug in DAML REPL was fixed, which caused errors about ambiguous names, even if names were fully qualified.
- The compiler now writes the proper SDK version in the DAR manifest for snapshot releases instead of a sanitized version.
daml ledger upload-dar
now exits with a non-zero exit code on failures and no longer prints "DAR upload succeeded" in error cases. This was a regression.- Contract Key lookup mismatches are now consistently reported as Inconsistent rather than Disputed. Sandbox-classic, in particular, previously reported Disputed, which implies malicious intent or malfunctioning of the submitter.
DAML Driver for PostgreSQL
- New metrics tracking the pending submissions and completions on the CommandService have been added. Check out the monitoring section in the documentation for more details. The new metrics are
daml.commands.<party_name>.input_buffer_size
daml.commands.<party_name>.input_buffer_saturation
daml.commands.<party_name>.max_in_flight_size
daml.commands.<party_name>.max_in_flight_saturation
- Add new metrics for measuring the number of concurrent command executions. The metrics are:
daml.commands.submissions_running
daml.execution.total_running
daml.execution.engine_running
Integration Kit
- The Ledger API test tool’s
--ledger-clock-granularity
option now takes a time duration (e.g. "10s" or "5m"), rather than an integer number of milliseconds. - The Ledger API test tool now defaults to a ledger clock granularity of 1 second, not 10s, in line with most ledger implementations.
- The Ledger API test tool has a new command line argument
skip-dar-upload
. See docs. - The Integration Kit’s
ResourceOwner
type is now parameterized by aContext
, which is filled in by the correspondingContext
class in the ledger-resources dependency. This allows us to pass extra information through resource acquisition. - The kvutils have a new metric
daml.kvutils.committer.package_upload.validate_timer
to track package validation time. - The Ledger API Server’s previously hardcoded timeout for party allocation and package uploads can now be configured via
ParticipantConfig
and the default value is now set to 2 minutes. See issue #6880.