- Overview
- Setup
- Tutorials
- How Tos
- Reference
Registry Utility - Burn Request API Example¶
This example shows how to perform a burn request on CNU 0.12.x and later using the HTTP JSON API.
It is assumed that the burner has all the required credentials as issuer of the specific instrument.
Preparation¶
Add all the required information to the source.sh file:
1#!/usr/bin/env bash
2
3## =================================================================================================
4## Purpose: Configurations for this example, amend variables as needed.
5## Script: source.sh
6## =================================================================================================
7
8# Burner's details
9BURNER_TOKEN="<PASTE_BURNER_JWT_HERE>"
10BURNER_PARTY_ID="issuer::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b"
11BURNER_USER_ID="issuer"
12
13# Admin/Registrar details
14ADMIN_TOKEN="<PASTE_ADMIN_JWT_HERE>"
15ADMIN_PARTY_ID="registrar::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b"
16ADMIN_USER_ID="registrar"
17
18# Unique reference for the action
19BURN_REF="burn-ref-002"
20
21# update your asset and amount to be transferred
22ASSET_ID="INST"
23ASSET_AMOUNT="3.0"
24
25# Endpoints (pick one)
26# - Remote: BACKEND_API="https://<your-host>/api/utilities" HTTP_JSON_API="https://<your-host>/api/json-api"
27# - DevNet: BACKEND_API="https://api.utilities.digitalasset-dev.com/api/utilities" HTTP_JSON_API="https://utility.utility.cnu.devnet.da-int.net/api/json-api"
28# - Local: BACKEND_API="http://localhost:8080/api/utilities" HTTP_JSON_API="http://localhost:8001/api/json-api"
29BACKEND_API="http://localhost:8080/api/utilities"
30HTTP_JSON_API="http://localhost:8001/api/json-api"
31
32# Token standard holding interface, may change when new versions of splice exists
33HOLDING_INTERFACE="718a0f77e505a8de22f188bd4c87fe74101274e9d4cb1bfac7d09aec7158d35b:Splice.Api.Token.HoldingV1:Holding"
34
35# Utility templates, may change when new versions of utilities exists
36ALLOCATIONFACTORY_TEMPLATE="#utility-registry-app-v0:Utility.Registry.App.V0.Service.AllocationFactory:AllocationFactory"
37BURNREQUEST_TEMPLATE="#utility-registry-app-v0:Utility.Registry.App.V0.Model.Burn:BurnRequest"
The required information is:
Details of |
Description |
|---|---|
Burner |
JWT, user ID, and party ID of the sender |
Admin |
JWT, user ID, and party ID of the receiver |
Operator |
Backend API and JSON Ledger API |
Burn |
Instrument ID, amount to be burned, and reference |
If possible, open the CNU UIs for both the burner and the admin, to observe the request and change in holdings. These are the initial holdings of the burner for INST.
Step 1: Burner Requests a Burn¶
Step 1a - Obtain the Ledger End Offset¶
Run the following script to obtain the ledger end offset:
1#!/usr/bin/env bash
2
3## =================================================================================================
4## Burner requests a burn of its holdings
5## Step 1a: Retrieves the current ledger end offset from the ledger
6## Authorized by: Burner
7## Script: step-1a-burner-requests.sh
8## =================================================================================================
9
10SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11DATAFILE="${SCRIPT_DIR}/source.sh"
12source "$DATAFILE"
13
14OFFSET=$(curl -sS --fail-with-body --request GET \
15 --url "${HTTP_JSON_API}/v2/state/ledger-end" \
16 --header "Accept: application/json" \
17 --header "Authorization: Bearer ${BURNER_TOKEN}")
18
19echo "$OFFSET" | jq
20
21OUTPUTFILE="${SCRIPT_DIR}/response-step-1a.json"
22echo "$OFFSET" > "$OUTPUTFILE"
The result is the ledger end offset at this moment, stored in response-step-1a.json. For
example:
1{
2 "offset": 312
3}
Step 1b - Retrieve Holding Cids¶
Run the following script to retrieve the Holding Cids:
1#!/usr/bin/env bash
2
3## =================================================================================================
4## Burner requests a burn of its holdings
5## Step 1b: Retrieve the burner's holdings as of the offset from step 1a to use for the burn request
6## Authorized by: Burner
7## Script: step-1b-burner-requests.sh
8## =================================================================================================
9
10SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11DATAFILE="${SCRIPT_DIR}/source.sh"
12source "$DATAFILE"
13
14# Get offset from previous step
15if [[ -f "${SCRIPT_DIR}/response-step-1a.json" ]]; then
16 JSONCONTENT=$(cat "${SCRIPT_DIR}/response-step-1a.json")
17 OFFSET=$(echo "$JSONCONTENT" | jq -r ".offset")
18else
19 echo "Error: response-step-1a.json not found"
20 exit 1
21fi
22
23RESULT=$(
24 curl -sS --fail-with-body \
25 --url "${HTTP_JSON_API}/v2/state/active-contracts" \
26 --header "Authorization: Bearer ${BURNER_TOKEN}" \
27 --header "Content-Type: application/json" \
28 --request POST \
29 --data @- <<EOF
30{
31 "verbose": false,
32 "activeAtOffset": "${OFFSET}",
33 "filter": {
34 "filtersByParty": {
35 "${BURNER_PARTY_ID}": {
36 "cumulative": [{
37 "identifierFilter": {
38 "InterfaceFilter": {
39 "value": {
40 "interfaceId":"$HOLDING_INTERFACE",
41 "includeInterfaceView": true,
42 "includeCreatedEventBlob": false
43 }
44 }
45 }
46 }]
47 }
48 }
49 }
50}
51EOF
52)
53
54# Filter holdings for a specific holder, instrument ID, admin and extract contractId
55HOLDINGCIDS=$(echo "$RESULT" | jq \
56 --arg BURNER_PARTY_ID "$BURNER_PARTY_ID" \
57 --arg ASSET_ID "$ASSET_ID" \
58 --arg ADMIN_PARTY_ID "$ADMIN_PARTY_ID" \
59 '[
60 .[] as $c
61 | $c.contractEntry.JsActiveContract.createdEvent.interfaceViews[]
62 | select(
63 .viewValue.owner == $BURNER_PARTY_ID and
64 .viewValue.instrumentId.id == $ASSET_ID and
65 .viewValue.instrumentId.admin == $ADMIN_PARTY_ID
66 )
67 | $c.contractEntry.JsActiveContract.createdEvent.contractId
68 ]'
69)
70
71echo "--- Holdings of burner (${BURNER_USER_ID}) as of offset ${OFFSET} ---"
72echo "$HOLDINGCIDS" | jq
73
74OUTPUTFILE="${SCRIPT_DIR}/response-step-1b.json"
75echo "$HOLDINGCIDS" > "$OUTPUTFILE"
The result is the Holding Cids, stored in response-step-1b.json. For example:
1[
2 "003d2393840e95bbbf2e8643308ec74d3f737043a670b6b7b86d61d9397b2dcd5aca12122025ee4542ebdbd9147e9a212fcd982f1a235d10797842d0f3816c98c2fdea05e7"
3]
Step 1c - Access the Backend API¶
The request URL is ${BACKEND_API}/v0/registry/burn/v0/request. To hit this endpoint, run the
following script:
1#!/usr/bin/env bash
2
3## =================================================================================================
4## Burner requests a burn of its holdings
5## Step 1c: Gets choice context and disclosure for the burn-request command
6## Authorized by: anyone
7## Script: step-1c-burner-requests.sh
8## =================================================================================================
9
10SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11DATAFILE="${SCRIPT_DIR}/source.sh"
12source "$DATAFILE"
13
14DATE_FORMAT='+%Y-%m-%dT%H:%M:%SZ'
15NOW_ISO_TIMESTAMP=$(date -u "$DATE_FORMAT")
16ONEHOUR_ISO_TIMESTAMP=$(date -u -d '+1 hour' "$DATE_FORMAT")
17
18HOLDINGCIDS=$(cat "${SCRIPT_DIR}/response-step-1b.json")
19
20RESULT=$(
21 curl -sS --fail-with-body \
22 --url "${BACKEND_API}/v0/registry/burn/v0/request" \
23 --header "Content-Type: application/json" \
24 --request POST \
25 --data @- <<EOF
26{
27 "holder": "${BURNER_PARTY_ID}",
28 "holdingContractIds":${HOLDINGCIDS},
29 "instrumentId": {
30 "admin": "${ADMIN_PARTY_ID}",
31 "id": "${ASSET_ID}"
32 }
33}
34EOF
35)
36
37echo "--- Endpoint response ---"
38echo "$RESULT" | jq
39
40OUTPUTFILE="${SCRIPT_DIR}/response-step-1c.json"
41echo "$RESULT" > "$OUTPUTFILE"
The result contains the required choice context for executing the command, stored in
response-step-1c.json. For example:
1{
2 "factoryId": "001368a8998af3d6e8745632a5d41e3fccf9aa437a7e264dbcf676938d04cc2e46ca12122066a0e796c3b4ff283c4112c1cd156e8314137a3808cd4eab1489a6b07fed4acf",
3 "choiceContext": {
4 "choiceContextData": {
5 "values": {
6 "utility.digitalasset.com/instrument-configuration": {
7 "tag": "AV_ContractId",
8 "value": "0002c3fa81687da421f65cff2ce498c4651e713e23ac70fd24e3de66fbe5ad3382ca121220a17caca8d3c0910c6e6d1a8e3dfe23c92c064b3fda95ea2f1456070f458daf1c"
9 },
10 "utility.digitalasset.com/issuer-credentials": {
11 "tag": "AV_List",
12 "value": [
13 {
14 "tag": "AV_ContractId",
15 "value": "0031b3c5f51b96a7505199c150739a8e5b7933d018328b1d70f7cd4c3719500db4ca121220dfbec9c94dc61b6e892911fc2b23d4a38f77595e59ee7eb32c0b21c2590fad22"
16 }
17 ]
18 }
19 }
20 },
21 "disclosedContracts": [
22 {
23 "createdAt": "2026-03-20T13:52:52.239Z",
24 "contractId": "001368a8998af3d6e8745632a5d41e3fccf9aa437a7e264dbcf676938d04cc2e46ca12122066a0e796c3b4ff283c4112c1cd156e8314137a3808cd4eab1489a6b07fed4acf",
25 "templateId": "7a75ef6e69f69395a4e60919e228528bb8f3881150ccfde3f31bcc73864b18ab:Utility.Registry.App.V0.Service.AllocationFactory:AllocationFactory",
26 "synchronizerId": "global-domain::122090f9b95363b7ca407a1aacab116b997d4e6f326cc0576cfed6f45f979d8c60ee",
27 "domainId": "global-domain::122090f9b95363b7ca407a1aacab116b997d4e6f326cc0576cfed6f45f979d8c60ee",
28 "createdEventBlob": "CgMyLjESmQYKRQATaKiZivPW6HRWMqXUHj/M+apDen4mTbz2dpONBMwuRsoSEiBmoOeWw7T/KDxBEsHNFW6DFBN6OAjNTqsUiaawf+1KzxIXdXRpbGl0eS1yZWdpc3RyeS1hcHAtdjAajQEKQDdhNzVlZjZlNjlmNjkzOTVhNGU2MDkxOWUyMjg1MjhiYjhmMzg4MTE1MGNjZmRlM2YzMWJjYzczODY0YjE4YWISB1V0aWxpdHkSCFJlZ2lzdHJ5EgNBcHASAlYwEgdTZXJ2aWNlEhFBbGxvY2F0aW9uRmFjdG9yeRoRQWxsb2NhdGlvbkZhY3RvcnkigAJq/QEKUgpQOk5wcm92aWRlcjo6MTIyMDE2M2EyMDcwY2Q5Y2Y4MzE3MjFjNmE4NGUxOWI3NzI3Yjk4MjU2MzZlYTliMDlmMjQyMjlmNDVhMzQxZjdjNGIKUwpROk9yZWdpc3RyYXI6OjEyMjAxNjNhMjA3MGNkOWNmODMxNzIxYzZhODRlMTliNzcyN2I5ODI1NjM2ZWE5YjA5ZjI0MjI5ZjQ1YTM0MWY3YzRiClIKUDpOb3BlcmF0b3I6OjEyMjBhNmY0MTc3NTE3OTdiOTFhYjA4NDIzMjM2ZjhjMGQzYzUzZjFlYzYyZWQxYWZkNDYwMjgxNjM5MGI2OGJlOGYwKk5wcm92aWRlcjo6MTIyMDE2M2EyMDcwY2Q5Y2Y4MzE3MjFjNmE4NGUxOWI3NzI3Yjk4MjU2MzZlYTliMDlmMjQyMjlmNDVhMzQxZjdjNGIqT3JlZ2lzdHJhcjo6MTIyMDE2M2EyMDcwY2Q5Y2Y4MzE3MjFjNmE4NGUxOWI3NzI3Yjk4MjU2MzZlYTliMDlmMjQyMjlmNDVhMzQxZjdjNGIyTm9wZXJhdG9yOjoxMjIwYTZmNDE3NzUxNzk3YjkxYWIwODQyMzIzNmY4YzBkM2M1M2YxZWM2MmVkMWFmZDQ2MDI4MTYzOTBiNjhiZThmMDlYW1MAdU0GAEIqCiYKJAgBEiDr5DOYFISYl1HSJh5250E/vLVMYe9V3/y3afOCcws82BAe"
29 },
30 {
31 "createdAt": "2026-03-20T13:52:52.638Z",
32 "contractId": "0002c3fa81687da421f65cff2ce498c4651e713e23ac70fd24e3de66fbe5ad3382ca121220a17caca8d3c0910c6e6d1a8e3dfe23c92c064b3fda95ea2f1456070f458daf1c",
33 "templateId": "a236e8e22a3b5f199e37d5554e82bafd2df688f901de02b00be3964bdfa8c1ab:Utility.Registry.V0.Configuration.Instrument:InstrumentConfiguration",
34 "synchronizerId": "global-domain::122090f9b95363b7ca407a1aacab116b997d4e6f326cc0576cfed6f45f979d8c60ee",
35 "domainId": "global-domain::122090f9b95363b7ca407a1aacab116b997d4e6f326cc0576cfed6f45f979d8c60ee",
36 "createdEventBlob": "CgMyLjESpgkKRQACw/qBaH2kIfZc/yzkmMRlHnE+I6xw/STj3mb75a0zgsoSEiChfKyo08CRDG5tGo49/iPJLAZLP9qV6i8UVgcPRY2vHBITdXRpbGl0eS1yZWdpc3RyeS12MBqNAQpAYTIzNmU4ZTIyYTNiNWYxOTllMzdkNTU1NGU4MmJhZmQyZGY2ODhmOTAxZGUwMmIwMGJlMzk2NGJkZmE4YzFhYhIHVXRpbGl0eRIIUmVnaXN0cnkSAlYwEg1Db25maWd1cmF0aW9uEgpJbnN0cnVtZW50GhdJbnN0cnVtZW50Q29uZmlndXJhdGlvbiKRBWqOBQpSClA6Tm9wZXJhdG9yOjoxMjIwYTZmNDE3NzUxNzk3YjkxYWIwODQyMzIzNmY4YzBkM2M1M2YxZWM2MmVkMWFmZDQ2MDI4MTYzOTBiNjhiZThmMApSClA6TnByb3ZpZGVyOjoxMjIwMTYzYTIwNzBjZDljZjgzMTcyMWM2YTg0ZTE5Yjc3MjdiOTgyNTYzNmVhOWIwOWYyNDIyOWY0NWEzNDFmN2M0YgpTClE6T3JlZ2lzdHJhcjo6MTIyMDE2M2EyMDcwY2Q5Y2Y4MzE3MjFjNmE4NGUxOWI3NzI3Yjk4MjU2MzZlYTliMDlmMjQyMjlmNDVhMzQxZjdjNGIKgAEKfmp8ClMKUTpPcmVnaXN0cmFyOjoxMjIwMTYzYTIwNzBjZDljZjgzMTcyMWM2YTg0ZTE5Yjc3MjdiOTgyNTYzNmVhOWIwOWYyNDIyOWY0NWEzNDFmN2M0YgoICgZCBElOU1QKGwoZQhdSZWdpc3RyYXJJbnRlcm5hbFNjaGVtZQoECgJaAAqBAQp/Wn0Ke2p5ClMKUTpPcmVnaXN0cmFyOjoxMjIwMTYzYTIwNzBjZDljZjgzMTcyMWM2YTg0ZTE5Yjc3MjdiOTgyNTYzNmVhOWIwOWYyNDIyOWY0NWEzNDFmN2M0YgoiCiBaHgocahoKDgoMQgppc0lzc3Vlck9mCggKBkIESU5TVAqBAQp/Wn0Ke2p5ClMKUTpPcmVnaXN0cmFyOjoxMjIwMTYzYTIwNzBjZDljZjgzMTcyMWM2YTg0ZTE5Yjc3MjdiOTgyNTYzNmVhOWIwOWYyNDIyOWY0NWEzNDFmN2M0YgoiCiBaHgocahoKDgoMQgppc0hvbGRlck9mCggKBkIESU5TVCpOcHJvdmlkZXI6OjEyMjAxNjNhMjA3MGNkOWNmODMxNzIxYzZhODRlMTliNzcyN2I5ODI1NjM2ZWE5YjA5ZjI0MjI5ZjQ1YTM0MWY3YzRiKk9yZWdpc3RyYXI6OjEyMjAxNjNhMjA3MGNkOWNmODMxNzIxYzZhODRlMTliNzcyN2I5ODI1NjM2ZWE5YjA5ZjI0MjI5ZjQ1YTM0MWY3YzRiMk5vcGVyYXRvcjo6MTIyMGE2ZjQxNzc1MTc5N2I5MWFiMDg0MjMyMzZmOGMwZDNjNTNmMWVjNjJlZDFhZmQ0NjAyODE2MzkwYjY4YmU4ZjA5BXRZAHVNBgBCKgomCiQIARIgFEf6wa84J98UcQc3CZJZjqGyxzw0zQmxTTfXg7J5sZQQHg=="
37 },
38 {
39 "createdAt": "2026-03-20T13:52:46.863Z",
40 "contractId": "0031b3c5f51b96a7505199c150739a8e5b7933d018328b1d70f7cd4c3719500db4ca121220dfbec9c94dc61b6e892911fc2b23d4a38f77595e59ee7eb32c0b21c2590fad22",
41 "templateId": "5a29ead611a0abd5f5b3fc3caf7d0f67c0ff802032ab6d392824aa9060e56d70:Utility.Credential.V0.Credential:Credential",
42 "synchronizerId": "global-domain::122090f9b95363b7ca407a1aacab116b997d4e6f326cc0576cfed6f45f979d8c60ee",
43 "domainId": "global-domain::122090f9b95363b7ca407a1aacab116b997d4e6f326cc0576cfed6f45f979d8c60ee",
44 "createdEventBlob": "CgMyLjESrAcKRQAxs8X1G5anUFGZwVBzmo5beTPQGDKLHXD3zUw3GVANtMoSEiDfvsnJTcYbbokpEfwrI9Sjj3dZXlnufrMsCyHCWQ+tIhIVdXRpbGl0eS1jcmVkZW50aWFsLXYwGnMKQDVhMjllYWQ2MTFhMGFiZDVmNWIzZmMzY2FmN2QwZjY3YzBmZjgwMjAzMmFiNmQzOTI4MjRhYTkwNjBlNTZkNzASB1V0aWxpdHkSCkNyZWRlbnRpYWwSAlYwEgpDcmVkZW50aWFsGgpDcmVkZW50aWFsIrIDaq8DClMKUTpPcmVnaXN0cmFyOjoxMjIwMTYzYTIwNzBjZDljZjgzMTcyMWM2YTg0ZTE5Yjc3MjdiOTgyNTYzNmVhOWIwOWYyNDIyOWY0NWEzNDFmN2M0YgpQCk46TGlzc3Vlcjo6MTIyMDE2M2EyMDcwY2Q5Y2Y4MzE3MjFjNmE4NGUxOWI3NzI3Yjk4MjU2MzZlYTliMDlmMjQyMjlmNDVhMzQxZjdjNGIKDwoNQgtJTlNUX0lzc3VlcgoPCg1CC0lOU1RfSXNzdWVyCgQKAlIACgQKAlIACnQKclpwCm5qbApQCk5CTGlzc3Vlcjo6MTIyMDE2M2EyMDcwY2Q5Y2Y4MzE3MjFjNmE4NGUxOWI3NzI3Yjk4MjU2MzZlYTliMDlmMjQyMjlmNDVhMzQxZjdjNGIKDgoMQgppc0lzc3Vlck9mCggKBkIESU5TVApiCmBqXgpcClpiWApWClA6Tm9wZXJhdG9yOjoxMjIwYTZmNDE3NzUxNzk3YjkxYWIwODQyMzIzNmY4YzBkM2M1M2YxZWM2MmVkMWFmZDQ2MDI4MTYzOTBiNjhiZThmMBICCgAqTGlzc3Vlcjo6MTIyMDE2M2EyMDcwY2Q5Y2Y4MzE3MjFjNmE4NGUxOWI3NzI3Yjk4MjU2MzZlYTliMDlmMjQyMjlmNDVhMzQxZjdjNGIqT3JlZ2lzdHJhcjo6MTIyMDE2M2EyMDcwY2Q5Y2Y4MzE3MjFjNmE4NGUxOWI3NzI3Yjk4MjU2MzZlYTliMDlmMjQyMjlmNDVhMzQxZjdjNGIyTm9wZXJhdG9yOjoxMjIwYTZmNDE3NzUxNzk3YjkxYWIwODQyMzIzNmY4YzBkM2M1M2YxZWM2MmVkMWFmZDQ2MDI4MTYzOTBiNjhiZThmMDnkVAEAdU0GAEIqCiYKJAgBEiAUDmQMITzaQlqV1p4ylPiXqRp/00ozz4mYE2u7DATyXRAe"
45 }
46 ]
47 }
48}
Step 1d - Request the Burn¶
Finally, run the following script to request the burn:
1#!/usr/bin/env bash
2
3## =================================================================================================
4## Burner requests a burn of its holdings
5## Step 1d: Execute the burn-request command
6## Authorized by: Burner
7## Script: step-1d-burner-requests.sh
8## =================================================================================================
9
10SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11DATAFILE="${SCRIPT_DIR}/source.sh"
12source "$DATAFILE"
13
14DATE_FORMAT='+%Y-%m-%dT%H:%M:%SZ'
15NOW_ISO_TIMESTAMP=$(date -u "$DATE_FORMAT")
16ONEHOUR_ISO_TIMESTAMP=$(date -u -d '+1 hour' "$DATE_FORMAT")
17
18HOLDINGCIDS=$(cat "${SCRIPT_DIR}/response-step-1b.json")
19
20JSONCONTENT=$(cat "${SCRIPT_DIR}/response-step-1c.json")
21FACTORYID=$(echo $JSONCONTENT | jq .factoryId)
22CHOICECONTEXTDATA=$(echo $JSONCONTENT | jq .choiceContext.choiceContextData)
23DISCLOSEDCONTRACTS=$(echo $JSONCONTENT | jq .choiceContext.disclosedContracts)
24
25RESULT=$(
26 curl -sS --fail-with-body \
27 --url "${HTTP_JSON_API}/v2/commands/submit-and-wait-for-transaction" \
28 --header "Authorization: Bearer ${BURNER_TOKEN}" \
29 --header "Content-Type: application/json" \
30 --request POST \
31 --data @- <<EOF
32{
33 "commands":{
34 "commands":[
35 {
36 "ExerciseCommand":{
37 "templateId":"${ALLOCATIONFACTORY_TEMPLATE}",
38 "contractId":${FACTORYID},
39 "choice":"AllocationFactory_RequestBurn",
40 "choiceArgument":{
41 "expectedAdmin":"${ADMIN_PARTY_ID}",
42 "burn": {
43 "instrumentId": {
44 "admin": "${ADMIN_PARTY_ID}",
45 "id": "${ASSET_ID}"
46 },
47 "amount": "${ASSET_AMOUNT}",
48 "holder": "${BURNER_PARTY_ID}",
49 "reference": "${BURN_REF}",
50 "requestedAt": "${NOW_ISO_TIMESTAMP}",
51 "executeBefore": "${ONEHOUR_ISO_TIMESTAMP}",
52 "meta": {
53 "values": {}
54 }
55 },
56 "holdingCids":${HOLDINGCIDS},
57 "extraArgs":{
58 "context":${CHOICECONTEXTDATA},
59 "meta":{
60 "values":{
61 }
62 }
63 }
64 }
65 }
66 }
67 ],
68 "workflowId":"",
69 "userId":"${BURNER_USER_ID}",
70 "commandId":"$(uuidgen | tr -d '\n')",
71 "deduplicationPeriod":{
72 "DeduplicationDuration":{
73 "value":{
74 "seconds":30,
75 "nanos":0
76 }
77 }
78 },
79 "actAs":[
80 "${BURNER_PARTY_ID}"
81 ],
82 "readAs":[
83 ],
84 "submissionId":"$(uuidgen | tr -d '\n')",
85 "disclosedContracts": ${DISCLOSEDCONTRACTS},
86 "domainId":"",
87 "packageIdSelectionPreference":[]
88 }
89}
90EOF
91)
92
93echo "--- Command response ---"
94echo "$RESULT" | jq
95
96OUTPUTFILE="${SCRIPT_DIR}/response-step-1d.json"
97echo "$RESULT" > "$OUTPUTFILE"
After the exercise command is executed, the amount is locked by the admin.
Step 2: Admin Accepts Burn Reequest¶
Step 2a - Obtain the Ledger End Offset¶
To obtain the ledger end offset, run the following script:
1#!/usr/bin/env bash
2
3## =================================================================================================
4## Admin accepts the burn request
5## Step 2a: Obtains ledger end offset
6## Authorized by: Admin
7## Script: step-2a-admin-accepts.sh
8## =================================================================================================
9
10SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11DATAFILE="${SCRIPT_DIR}/source.sh"
12source "$DATAFILE"
13
14# Get offset from previous step
15OFFSET=$(curl -sS --fail-with-body --request GET \
16 --url "${HTTP_JSON_API}/v2/state/ledger-end" \
17 --header "Accept: application/json" \
18 --header "Authorization: Bearer ${ADMIN_TOKEN}")
19
20echo "$OFFSET" | jq
21
22OUTPUTFILE="${SCRIPT_DIR}/response-step-2a.json"
23echo "$OFFSET" > "$OUTPUTFILE"
The result is the ledger end offset at this moment, stored in response-step-2a.json. For
example:
1{
2 "offset": 321
3}
Step 2b - Retrieve Burn Request¶
To retrieve the Burn Request created in Step 1d, run the following script:
1#!/usr/bin/env bash
2
3## =================================================================================================
4## Admin accepts the burn request
5## Step 2b: Retrieves the burn request to accept
6## Authorized by: Admin
7## Script: step-2b-admin-accepts.sh
8## =================================================================================================
9
10SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11DATAFILE="${SCRIPT_DIR}/source.sh"
12source "$DATAFILE"
13
14JSONCONTENT=$(cat "${SCRIPT_DIR}/response-step-2a.json")
15OFFSET=$(echo "$JSONCONTENT" | jq -r ".offset")
16
17RESULT=$(
18 curl -sS --fail-with-body \
19 --url "${HTTP_JSON_API}/v2/state/active-contracts" \
20 --header "Authorization: Bearer ${ADMIN_TOKEN}" \
21 --header "Content-Type: application/json" \
22 --request POST \
23 --data @- <<EOF
24{
25 "verbose": false,
26 "activeAtOffset": "${OFFSET}",
27 "filter": {
28 "filtersByParty": {
29 "${ADMIN_PARTY_ID}": {
30 "cumulative": [{
31 "identifierFilter": {
32 "TemplateFilter": {
33 "value": {
34 "templateId":"${BURNREQUEST_TEMPLATE}",
35 "includeCreatedEventBlob": false
36 }
37 }
38 }
39 }]
40 }
41 }
42 }
43}
44EOF
45)
46
47echo "--- Burn Request ---"
48echo "$RESULT" | jq
49
50OUTPUTFILE="${SCRIPT_DIR}/response-step-2b.json"
51echo "$RESULT" > "$OUTPUTFILE"
The result is the Burn Request, stored in response-step-2b.json. For example,
1[
2 {
3 "workflowId": "",
4 "contractEntry": {
5 "JsActiveContract": {
6 "createdEvent": {
7 "offset": 313,
8 "nodeId": 7,
9 "contractId": "006f81dc9701e5e8713f57760a86333df046f2f008085a503d6c315b9f83cd398cca1212202029854f7bc478cf6e1bb22bdc64516a71ca9778b88a01d6f7ff98b403f2e6fd",
10 "templateId": "7a75ef6e69f69395a4e60919e228528bb8f3881150ccfde3f31bcc73864b18ab:Utility.Registry.App.V0.Model.Burn:BurnRequest",
11 "contractKey": null,
12 "createArgument": {
13 "operator": "operator::1220a6f417751797b91ab08423236f8c0d3c53f1ec62ed1afd4602816390b68be8f0",
14 "provider": "provider::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b",
15 "burn": {
16 "instrumentId": {
17 "admin": "registrar::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b",
18 "id": "INST"
19 },
20 "amount": "3.0000000000",
21 "holder": "issuer::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b",
22 "reference": "burn-ref-002",
23 "requestedAt": "2026-03-20T14:21:34Z",
24 "executeBefore": "2026-03-20T15:21:34Z",
25 "meta": {
26 "values": {}
27 }
28 },
29 "lockedHoldingCid": "0030ef439b73553e5dd2b58b4e2e2450e742c5d41aa6b67167c74947a9dfde7598ca121220d0e8ba95acd0611e867f05e4dac1ea80d0490fa0120342c66cab5e90d621a90a"
30 },
31 "createdEventBlob": "",
32 "interfaceViews": [],
33 "witnessParties": [
34 "registrar::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b"
35 ],
36 "signatories": [
37 "issuer::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b",
38 "provider::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b",
39 "registrar::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b"
40 ],
41 "observers": [
42 "operator::1220a6f417751797b91ab08423236f8c0d3c53f1ec62ed1afd4602816390b68be8f0"
43 ],
44 "createdAt": "2026-03-20T14:21:35.108732Z",
45 "packageName": "utility-registry-app-v0",
46 "representativePackageId": "7a75ef6e69f69395a4e60919e228528bb8f3881150ccfde3f31bcc73864b18ab",
47 "acsDelta": true
48 },
49 "synchronizerId": "global-domain::122090f9b95363b7ca407a1aacab116b997d4e6f326cc0576cfed6f45f979d8c60ee",
50 "reassignmentCounter": 0
51 }
52 }
53 }
54]
Step 2c - Access the Backend API¶
The request URL is “${BACKEND_API}/v0/registry/burn/v0/request/${BURNREQUEST_CID}/choice-contexts/accept”. To hit this endpoint, run the following script:
1#!/usr/bin/env bash
2
3## =================================================================================================
4## Admin accepts the burn request
5## Step 2c: Gets choice context and disclosure for the accept-burn-request command
6## Authorized by: anyone
7## Script: step-2c-admin-accepts.sh
8## =================================================================================================
9
10SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11DATAFILE="${SCRIPT_DIR}/source.sh"
12source "$DATAFILE"
13
14DATE_FORMAT='+%Y-%m-%dT%H:%M:%SZ'
15NOW_ISO_TIMESTAMP=$(date -u "$DATE_FORMAT")
16ONEHOUR_ISO_TIMESTAMP=$(date -u -d '+1 hour' "$DATE_FORMAT")
17
18BURNREQUESTS=$(cat "${SCRIPT_DIR}/response-step-2b.json")
19BURNREQUEST_CID=$(echo "$BURNREQUESTS" | jq -r --arg BURN_REF "$BURN_REF" '[.[] | select(.contractEntry.JsActiveContract.createdEvent.createArgument.burn.reference == $BURN_REF)][0].contractEntry.JsActiveContract.createdEvent.contractId')
20
21RESULT=$(
22 curl -sS --fail-with-body \
23 --url "${BACKEND_API}/v0/registry/burn/v0/request/${BURNREQUEST_CID}/choice-contexts/accept" \
24 --header "Content-Type: application/json" \
25 --request POST \
26 --data @- <<EOF
27{
28 "meta":{
29
30 },
31 "excludeDebugFields": true
32}
33EOF
34)
35
36echo "--- Endpoint response ---"
37echo "$RESULT" | jq
38
39OUTPUTFILE="${SCRIPT_DIR}/response-step-2c.json"
40echo "$RESULT" > "$OUTPUTFILE"
The result contains the required choice context for executing the command, stored in
response-step-2c.json. For example:
1{
2 "choiceContextData": {
3 "values": {
4 "utility.digitalasset.com/instrument-configuration": {
5 "tag": "AV_ContractId",
6 "value": "0002c3fa81687da421f65cff2ce498c4651e713e23ac70fd24e3de66fbe5ad3382ca121220a17caca8d3c0910c6e6d1a8e3dfe23c92c064b3fda95ea2f1456070f458daf1c"
7 },
8 "utility.digitalasset.com/issuer-credentials": {
9 "tag": "AV_List",
10 "value": [
11 {
12 "tag": "AV_ContractId",
13 "value": "0031b3c5f51b96a7505199c150739a8e5b7933d018328b1d70f7cd4c3719500db4ca121220dfbec9c94dc61b6e892911fc2b23d4a38f77595e59ee7eb32c0b21c2590fad22"
14 }
15 ]
16 },
17 "utility.digitalasset.com/enable-result-contracts": {
18 "tag": "AV_Bool",
19 "value": true
20 }
21 }
22 },
23 "disclosedContracts": [
24 {
25 "createdAt": "2026-03-20T13:52:46.863Z",
26 "contractId": "0031b3c5f51b96a7505199c150739a8e5b7933d018328b1d70f7cd4c3719500db4ca121220dfbec9c94dc61b6e892911fc2b23d4a38f77595e59ee7eb32c0b21c2590fad22",
27 "templateId": "5a29ead611a0abd5f5b3fc3caf7d0f67c0ff802032ab6d392824aa9060e56d70:Utility.Credential.V0.Credential:Credential",
28 "synchronizerId": "global-domain::122090f9b95363b7ca407a1aacab116b997d4e6f326cc0576cfed6f45f979d8c60ee",
29 "domainId": "global-domain::122090f9b95363b7ca407a1aacab116b997d4e6f326cc0576cfed6f45f979d8c60ee",
30 "createdEventBlob": "CgMyLjESrAcKRQAxs8X1G5anUFGZwVBzmo5beTPQGDKLHXD3zUw3GVANtMoSEiDfvsnJTcYbbokpEfwrI9Sjj3dZXlnufrMsCyHCWQ+tIhIVdXRpbGl0eS1jcmVkZW50aWFsLXYwGnMKQDVhMjllYWQ2MTFhMGFiZDVmNWIzZmMzY2FmN2QwZjY3YzBmZjgwMjAzMmFiNmQzOTI4MjRhYTkwNjBlNTZkNzASB1V0aWxpdHkSCkNyZWRlbnRpYWwSAlYwEgpDcmVkZW50aWFsGgpDcmVkZW50aWFsIrIDaq8DClMKUTpPcmVnaXN0cmFyOjoxMjIwMTYzYTIwNzBjZDljZjgzMTcyMWM2YTg0ZTE5Yjc3MjdiOTgyNTYzNmVhOWIwOWYyNDIyOWY0NWEzNDFmN2M0YgpQCk46TGlzc3Vlcjo6MTIyMDE2M2EyMDcwY2Q5Y2Y4MzE3MjFjNmE4NGUxOWI3NzI3Yjk4MjU2MzZlYTliMDlmMjQyMjlmNDVhMzQxZjdjNGIKDwoNQgtJTlNUX0lzc3VlcgoPCg1CC0lOU1RfSXNzdWVyCgQKAlIACgQKAlIACnQKclpwCm5qbApQCk5CTGlzc3Vlcjo6MTIyMDE2M2EyMDcwY2Q5Y2Y4MzE3MjFjNmE4NGUxOWI3NzI3Yjk4MjU2MzZlYTliMDlmMjQyMjlmNDVhMzQxZjdjNGIKDgoMQgppc0lzc3Vlck9mCggKBkIESU5TVApiCmBqXgpcClpiWApWClA6Tm9wZXJhdG9yOjoxMjIwYTZmNDE3NzUxNzk3YjkxYWIwODQyMzIzNmY4YzBkM2M1M2YxZWM2MmVkMWFmZDQ2MDI4MTYzOTBiNjhiZThmMBICCgAqTGlzc3Vlcjo6MTIyMDE2M2EyMDcwY2Q5Y2Y4MzE3MjFjNmE4NGUxOWI3NzI3Yjk4MjU2MzZlYTliMDlmMjQyMjlmNDVhMzQxZjdjNGIqT3JlZ2lzdHJhcjo6MTIyMDE2M2EyMDcwY2Q5Y2Y4MzE3MjFjNmE4NGUxOWI3NzI3Yjk4MjU2MzZlYTliMDlmMjQyMjlmNDVhMzQxZjdjNGIyTm9wZXJhdG9yOjoxMjIwYTZmNDE3NzUxNzk3YjkxYWIwODQyMzIzNmY4YzBkM2M1M2YxZWM2MmVkMWFmZDQ2MDI4MTYzOTBiNjhiZThmMDnkVAEAdU0GAEIqCiYKJAgBEiAUDmQMITzaQlqV1p4ylPiXqRp/00ozz4mYE2u7DATyXRAe"
31 }
32 ]
33}
Step 2d - Accept the Burn Request¶
To finalize the burn and remove the asset for the burner, execute the following script:
1#!/usr/bin/env bash
2
3## =================================================================================================
4## Admin accepts the burn request
5## Step 2d: Executes the accept-burn-request command
6## Authorized by: Admin
7## Script: step-2d-admin-accepts.sh
8## =================================================================================================
9
10SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11DATAFILE="${SCRIPT_DIR}/source.sh"
12source "$DATAFILE"
13
14BURNREQUESTS=$(cat "${SCRIPT_DIR}/response-step-2b.json")
15BURNREQUEST=$(echo "$BURNREQUESTS" | jq -r --arg BURN_REF "$BURN_REF" '[.[] | select(.contractEntry.JsActiveContract.createdEvent.createArgument.burn.reference == $BURN_REF)][0]')
16BURNREQUEST_CID=$(echo "$BURNREQUEST" | jq -r .contractEntry.JsActiveContract.createdEvent.contractId)
17BURNREQUEST_TEMPLATE=$(echo "$BURNREQUEST" | jq -r .contractEntry.JsActiveContract.createdEvent.templateId)
18
19JSONCONTENT=$(cat "${SCRIPT_DIR}/response-step-2c.json")
20CHOICECONTEXTDATA=$(echo $JSONCONTENT | jq .choiceContextData)
21DISCLOSEDCONTRACTS=$(echo $JSONCONTENT | jq .disclosedContracts)
22
23RESULT=$(
24 curl -sS --fail-with-body \
25 --url "${HTTP_JSON_API}/v2/commands/submit-and-wait-for-transaction" \
26 --header "Authorization: Bearer ${ADMIN_TOKEN}" \
27 --header "Content-Type: application/json" \
28 --request POST \
29 --data @- <<EOF
30{
31 "commands":{
32 "commands":[
33 {
34 "ExerciseCommand":{
35 "templateId":"${BURNREQUEST_TEMPLATE}",
36 "contractId":"${BURNREQUEST_CID}",
37 "choice":"BurnRequest_Accept",
38 "choiceArgument":{
39 "extraArgs": {
40 "context": $CHOICECONTEXTDATA,
41 "meta":{
42 "values":{
43 }
44 }
45 }
46 }
47 }
48 }
49 ],
50 "workflowId":"",
51 "userId":"${ADMIN_USER_ID}",
52 "commandId":"$(uuidgen | tr -d '\n')",
53 "deduplicationPeriod":{
54 "DeduplicationDuration":{
55 "value":{
56 "seconds":30,
57 "nanos":0
58 }
59 }
60 },
61 "actAs":[
62 "${ADMIN_PARTY_ID}"
63 ],
64 "readAs":[
65
66 ],
67 "submissionId":"$(uuidgen | tr -d '\n')",
68 "disclosedContracts": ${DISCLOSEDCONTRACTS},
69 "domainId":"",
70 "packageIdSelectionPreference":[]
71 }
72}
73EOF
74)
75
76echo "--- Command response ---"
77echo "$RESULT" | jq
78
79OUTPUTFILE="${SCRIPT_DIR}/response-step-2d.json"
80echo "$RESULT" > "$OUTPUTFILE"
For example, this is the response of this command:
1{
2 "transaction": {
3 "updateId": "1220c3b37c402673a10cd3844e4074e47221a8b127e205465936ce87ab5cfdf3de53",
4 "commandId": "BDC4B8B2-9FD6-4014-813D-125B67E484BE",
5 "workflowId": "",
6 "effectiveAt": "2026-03-20T14:23:15.286159Z",
7 "events": [
8 {
9 "ArchivedEvent": {
10 "offset": 324,
11 "nodeId": 0,
12 "contractId": "006f81dc9701e5e8713f57760a86333df046f2f008085a503d6c315b9f83cd398cca1212202029854f7bc478cf6e1bb22bdc64516a71ca9778b88a01d6f7ff98b403f2e6fd",
13 "templateId": "7a75ef6e69f69395a4e60919e228528bb8f3881150ccfde3f31bcc73864b18ab:Utility.Registry.App.V0.Model.Burn:BurnRequest",
14 "witnessParties": [
15 "registrar::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b"
16 ],
17 "packageName": "utility-registry-app-v0",
18 "implementedInterfaces": []
19 }
20 },
21 {
22 "ArchivedEvent": {
23 "offset": 324,
24 "nodeId": 2,
25 "contractId": "0030ef439b73553e5dd2b58b4e2e2450e742c5d41aa6b67167c74947a9dfde7598ca121220d0e8ba95acd0611e867f05e4dac1ea80d0490fa0120342c66cab5e90d621a90a",
26 "templateId": "8107899ac4723ce986bf7d27416534e576e54b92161e46150a595fb78ff3d3a1:Utility.Registry.Holding.V0.Holding:Holding",
27 "witnessParties": [
28 "registrar::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b"
29 ],
30 "packageName": "utility-registry-holding-v0",
31 "implementedInterfaces": []
32 }
33 },
34 {
35 "CreatedEvent": {
36 "offset": 324,
37 "nodeId": 5,
38 "contractId": "00423cc7b716d59efdcd15464ac784f80c92e79645aa606e21ca188ca698d40a76ca1212207ba3f23d59704c30ccd962e71beedfbb5da07290aa4a6354367d5bbc04167d24",
39 "templateId": "7a75ef6e69f69395a4e60919e228528bb8f3881150ccfde3f31bcc73864b18ab:Utility.Registry.App.V0.Model.Burn:ExecutedBurn",
40 "contractKey": null,
41 "createArgument": {
42 "operator": "operator::1220a6f417751797b91ab08423236f8c0d3c53f1ec62ed1afd4602816390b68be8f0",
43 "provider": "provider::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b",
44 "burn": {
45 "instrumentId": {
46 "admin": "registrar::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b",
47 "id": "INST"
48 },
49 "amount": "3.0000000000",
50 "holder": "issuer::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b",
51 "reference": "burn-ref-002",
52 "requestedAt": "2026-03-20T14:21:34Z",
53 "executeBefore": "2026-03-20T15:21:34Z",
54 "meta": {
55 "values": {}
56 }
57 },
58 "operatorIsObserver": false
59 },
60 "createdEventBlob": "",
61 "interfaceViews": [],
62 "witnessParties": [
63 "registrar::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b"
64 ],
65 "signatories": [
66 "registrar::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b"
67 ],
68 "observers": [
69 "issuer::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b",
70 "provider::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b"
71 ],
72 "createdAt": "2026-03-20T14:23:15.286159Z",
73 "packageName": "utility-registry-app-v0",
74 "representativePackageId": "7a75ef6e69f69395a4e60919e228528bb8f3881150ccfde3f31bcc73864b18ab",
75 "acsDelta": true
76 }
77 }
78 ],
79 "offset": 324,
80 "synchronizerId": "global-domain::122090f9b95363b7ca407a1aacab116b997d4e6f326cc0576cfed6f45f979d8c60ee",
81 "traceContext": {
82 "traceparent": "00-ef8323bc949e4b6b2af338e3fed34e67-bdd9b801cdaa68af-01",
83 "tracestate": null
84 },
85 "recordTime": "2026-03-20T14:23:15.337687Z",
86 "externalTransactionHash": null
87 }
88}
After the exercise command is executed, the burn is complete.