- Overview
- Setup
- Tutorials
- How Tos
- Reference
Registry Utility - Transfer API Example¶
This example shows how to perform a transfer offer on CNU 0.12.x and later using the HTTP JSON API.
It is assumed that both the sender and receiver have all the required credentials as holders 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# Sender's details
9SENDER_TOKEN="<PASTE_SENDER_JWT_HERE>"
10SENDER_PARTY_ID="issuer::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b"
11SENDER_USER_ID="issuer"
12
13# Receiver's details
14RECEIVER_TOKEN="<PASTE_RECEIVER_JWT_HERE>"
15RECEIVER_PARTY_ID="holder::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b"
16RECEIVER_USER_ID="holder"
17
18# Update your asset and amount to be transferred
19ADMIN_PARTY_ID="registrar::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b"
20
21# Asset and amount to be transferred
22ASSET_ID="INST"
23ASSET_AMOUNT="1.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/token-standard"
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="#splice-api-token-holding-v1:Splice.Api.Token.HoldingV1:Holding"
34TRANSFERFACTORY_INTERFACE="#splice-api-token-transfer-instruction-v1:Splice.Api.Token.TransferInstructionV1:TransferFactory"
35TRANSFER_INSTRUCTION_INTERFACE="#splice-api-token-transfer-instruction-v1:Splice.Api.Token.TransferInstructionV1:TransferInstruction"
The required information is:
Details of |
Description |
|---|---|
Sender |
JWT, user ID, and party ID of the sender |
Receiver |
JWT, user ID, and party ID of the receiver |
Operator |
Backend API and JSON Ledger API |
Transfer |
Instrument ID and amount to be transferred |
If possible, open three CNU UI windows, one each for the admin, sender, and receiver. This allows you to observe changes in holdings for the parties throughout the transfer process. The image below shows the initial holdings for both the sender (issuer) and the receiver (holder) for the instrument INST.
Step 1: Sender Offers a Transfer¶
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## Sender offers a transfer
5## Step 1a: Obtains ledger end offset
6## Authorized by: Sender
7## Script: step-1a-sender-offers.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 ${SENDER_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": 339
3}
Step 1b - Retrieve Holding Cids¶
Run the following script to retrieve the Holding Cids:
1#!/usr/bin/env bash
2
3## =================================================================================================
4## Sender offers a transfer
5## Step 1b: Retrieve sender's holdings as of the offset from step 1a to use for the transfer
6## Authorized by: Sender
7## Script: step-1b-sender-offers.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 ${SENDER_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 "${SENDER_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
55# Filter holdings for a specific holder, instrument ID, admin and extract contractId
56HOLDINGCIDS=$(echo "$RESULT" | jq \
57 --arg SENDER_PARTY_ID "$SENDER_PARTY_ID" \
58 --arg ASSET_ID "$ASSET_ID" \
59 --arg ADMIN_PARTY_ID "$ADMIN_PARTY_ID" \
60 '[
61 .[] as $c
62 | $c.contractEntry.JsActiveContract.createdEvent.interfaceViews[]
63 | select(
64 .viewValue.owner == $SENDER_PARTY_ID and
65 .viewValue.instrumentId.id == $ASSET_ID and
66 .viewValue.instrumentId.admin == $ADMIN_PARTY_ID
67 )
68 | $c.contractEntry.JsActiveContract.createdEvent.contractId
69 ]'
70)
71
72echo "--- Holdings of sender (${SENDER_USER_ID}) as of offset ${OFFSET} ---"
73echo "$HOLDINGCIDS" | jq
74
75OUTPUTFILE="${SCRIPT_DIR}/response-step-1b.json"
76echo "$HOLDINGCIDS" > "$OUTPUTFILE"
The result is the Holding Cids, stored in response-step-1b.json. For example:
1[
2 "00f30807d6b52c812171bfc7024119ab211c94f98565c044210b4a00783e182276ca12122079b824afe91e0a0c12cfe08228228e0b730d0cd9924ddab4ff001869be4d02a6"
3]
Step 1c - Access the Backend API¶
The request URL is
${BACKEND_API}/v0/registrars/${ADMIN_PARTY_ID}/registry/transfer-instruction/v1/transfer-factory.
To hit this endpoint, run the following script:
1#!/usr/bin/env bash
2
3## =================================================================================================
4## Sender offers a transfer
5## Step 1c: Gets choice context and disclosure for the transfer-offer command
6## Authorized by: anyone
7## Script: step-1c-sender-offers.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/registrars/${ADMIN_PARTY_ID}/registry/transfer-instruction/v1/transfer-factory" \
23 --header "Content-Type: application/json" \
24 --request POST \
25 --data @- <<EOF
26{
27 "choiceArguments":{
28 "expectedAdmin":"${ADMIN_PARTY_ID}",
29 "transfer":{
30 "sender":"${SENDER_PARTY_ID}",
31 "receiver":"${RECEIVER_PARTY_ID}",
32 "amount":"${ASSET_AMOUNT}",
33 "instrumentId":{
34 "admin":"${ADMIN_PARTY_ID}",
35 "id":"${ASSET_ID}"
36 },
37 "requestedAt":"${NOW_ISO_TIMESTAMP}",
38 "executeBefore":"${ONEHOUR_ISO_TIMESTAMP}",
39 "inputHoldingCids":${HOLDINGCIDS},
40 "meta":{
41 "values":{
42 "splice.lfdecentralizedtrust.org/reason":""
43 }
44 }
45 },
46 "extraArgs":{
47 "context":{
48 "values":{
49
50 }
51 },
52 "meta":{
53 "values":{
54
55 }
56 }
57 }
58 },
59 "excludeDebugFields":true
60}
61EOF
62)
63
64echo "--- Endpoint response ---"
65echo "$RESULT" | jq
66
67OUTPUTFILE="${SCRIPT_DIR}/response-step-1c.json"
68echo "$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 "transferKind": "offer",
4 "choiceContext": {
5 "choiceContextData": {
6 "values": {
7 "utility.digitalasset.com/instrument-configuration": {
8 "tag": "AV_ContractId",
9 "value": "0002c3fa81687da421f65cff2ce498c4651e713e23ac70fd24e3de66fbe5ad3382ca121220a17caca8d3c0910c6e6d1a8e3dfe23c92c064b3fda95ea2f1456070f458daf1c"
10 },
11 "utility.digitalasset.com/sender-credentials": {
12 "tag": "AV_List",
13 "value": [
14 {
15 "tag": "AV_ContractId",
16 "value": "00e4e3405e422c0d0b8ee71847212d4ac5f7c45dbb59ce5d4e2acdc7d688a62b3aca12122037516f1734f137d24aacb957edfeaf6b48142d417c993ebc6ad4e1349b336537"
17 }
18 ]
19 }
20 }
21 },
22 "disclosedContracts": [
23 {
24 "templateId": "7a75ef6e69f69395a4e60919e228528bb8f3881150ccfde3f31bcc73864b18ab:Utility.Registry.App.V0.Service.AllocationFactory:AllocationFactory",
25 "contractId": "001368a8998af3d6e8745632a5d41e3fccf9aa437a7e264dbcf676938d04cc2e46ca12122066a0e796c3b4ff283c4112c1cd156e8314137a3808cd4eab1489a6b07fed4acf",
26 "createdEventBlob": "CgMyLjESmQYKRQATaKiZivPW6HRWMqXUHj/M+apDen4mTbz2dpONBMwuRsoSEiBmoOeWw7T/KDxBEsHNFW6DFBN6OAjNTqsUiaawf+1KzxIXdXRpbGl0eS1yZWdpc3RyeS1hcHAtdjAajQEKQDdhNzVlZjZlNjlmNjkzOTVhNGU2MDkxOWUyMjg1MjhiYjhmMzg4MTE1MGNjZmRlM2YzMWJjYzczODY0YjE4YWISB1V0aWxpdHkSCFJlZ2lzdHJ5EgNBcHASAlYwEgdTZXJ2aWNlEhFBbGxvY2F0aW9uRmFjdG9yeRoRQWxsb2NhdGlvbkZhY3RvcnkigAJq/QEKUgpQOk5wcm92aWRlcjo6MTIyMDE2M2EyMDcwY2Q5Y2Y4MzE3MjFjNmE4NGUxOWI3NzI3Yjk4MjU2MzZlYTliMDlmMjQyMjlmNDVhMzQxZjdjNGIKUwpROk9yZWdpc3RyYXI6OjEyMjAxNjNhMjA3MGNkOWNmODMxNzIxYzZhODRlMTliNzcyN2I5ODI1NjM2ZWE5YjA5ZjI0MjI5ZjQ1YTM0MWY3YzRiClIKUDpOb3BlcmF0b3I6OjEyMjBhNmY0MTc3NTE3OTdiOTFhYjA4NDIzMjM2ZjhjMGQzYzUzZjFlYzYyZWQxYWZkNDYwMjgxNjM5MGI2OGJlOGYwKk5wcm92aWRlcjo6MTIyMDE2M2EyMDcwY2Q5Y2Y4MzE3MjFjNmE4NGUxOWI3NzI3Yjk4MjU2MzZlYTliMDlmMjQyMjlmNDVhMzQxZjdjNGIqT3JlZ2lzdHJhcjo6MTIyMDE2M2EyMDcwY2Q5Y2Y4MzE3MjFjNmE4NGUxOWI3NzI3Yjk4MjU2MzZlYTliMDlmMjQyMjlmNDVhMzQxZjdjNGIyTm9wZXJhdG9yOjoxMjIwYTZmNDE3NzUxNzk3YjkxYWIwODQyMzIzNmY4YzBkM2M1M2YxZWM2MmVkMWFmZDQ2MDI4MTYzOTBiNjhiZThmMDlYW1MAdU0GAEIqCiYKJAgBEiDr5DOYFISYl1HSJh5250E/vLVMYe9V3/y3afOCcws82BAe",
27 "synchronizerId": "global-domain::122090f9b95363b7ca407a1aacab116b997d4e6f326cc0576cfed6f45f979d8c60ee",
28 "debugPackageName": null,
29 "debugPayload": null,
30 "debugCreatedAt": null
31 },
32 {
33 "templateId": "a236e8e22a3b5f199e37d5554e82bafd2df688f901de02b00be3964bdfa8c1ab:Utility.Registry.V0.Configuration.Instrument:InstrumentConfiguration",
34 "contractId": "0002c3fa81687da421f65cff2ce498c4651e713e23ac70fd24e3de66fbe5ad3382ca121220a17caca8d3c0910c6e6d1a8e3dfe23c92c064b3fda95ea2f1456070f458daf1c",
35 "createdEventBlob": "CgMyLjESpgkKRQACw/qBaH2kIfZc/yzkmMRlHnE+I6xw/STj3mb75a0zgsoSEiChfKyo08CRDG5tGo49/iPJLAZLP9qV6i8UVgcPRY2vHBITdXRpbGl0eS1yZWdpc3RyeS12MBqNAQpAYTIzNmU4ZTIyYTNiNWYxOTllMzdkNTU1NGU4MmJhZmQyZGY2ODhmOTAxZGUwMmIwMGJlMzk2NGJkZmE4YzFhYhIHVXRpbGl0eRIIUmVnaXN0cnkSAlYwEg1Db25maWd1cmF0aW9uEgpJbnN0cnVtZW50GhdJbnN0cnVtZW50Q29uZmlndXJhdGlvbiKRBWqOBQpSClA6Tm9wZXJhdG9yOjoxMjIwYTZmNDE3NzUxNzk3YjkxYWIwODQyMzIzNmY4YzBkM2M1M2YxZWM2MmVkMWFmZDQ2MDI4MTYzOTBiNjhiZThmMApSClA6TnByb3ZpZGVyOjoxMjIwMTYzYTIwNzBjZDljZjgzMTcyMWM2YTg0ZTE5Yjc3MjdiOTgyNTYzNmVhOWIwOWYyNDIyOWY0NWEzNDFmN2M0YgpTClE6T3JlZ2lzdHJhcjo6MTIyMDE2M2EyMDcwY2Q5Y2Y4MzE3MjFjNmE4NGUxOWI3NzI3Yjk4MjU2MzZlYTliMDlmMjQyMjlmNDVhMzQxZjdjNGIKgAEKfmp8ClMKUTpPcmVnaXN0cmFyOjoxMjIwMTYzYTIwNzBjZDljZjgzMTcyMWM2YTg0ZTE5Yjc3MjdiOTgyNTYzNmVhOWIwOWYyNDIyOWY0NWEzNDFmN2M0YgoICgZCBElOU1QKGwoZQhdSZWdpc3RyYXJJbnRlcm5hbFNjaGVtZQoECgJaAAqBAQp/Wn0Ke2p5ClMKUTpPcmVnaXN0cmFyOjoxMjIwMTYzYTIwNzBjZDljZjgzMTcyMWM2YTg0ZTE5Yjc3MjdiOTgyNTYzNmVhOWIwOWYyNDIyOWY0NWEzNDFmN2M0YgoiCiBaHgocahoKDgoMQgppc0lzc3Vlck9mCggKBkIESU5TVAqBAQp/Wn0Ke2p5ClMKUTpPcmVnaXN0cmFyOjoxMjIwMTYzYTIwNzBjZDljZjgzMTcyMWM2YTg0ZTE5Yjc3MjdiOTgyNTYzNmVhOWIwOWYyNDIyOWY0NWEzNDFmN2M0YgoiCiBaHgocahoKDgoMQgppc0hvbGRlck9mCggKBkIESU5TVCpOcHJvdmlkZXI6OjEyMjAxNjNhMjA3MGNkOWNmODMxNzIxYzZhODRlMTliNzcyN2I5ODI1NjM2ZWE5YjA5ZjI0MjI5ZjQ1YTM0MWY3YzRiKk9yZWdpc3RyYXI6OjEyMjAxNjNhMjA3MGNkOWNmODMxNzIxYzZhODRlMTliNzcyN2I5ODI1NjM2ZWE5YjA5ZjI0MjI5ZjQ1YTM0MWY3YzRiMk5vcGVyYXRvcjo6MTIyMGE2ZjQxNzc1MTc5N2I5MWFiMDg0MjMyMzZmOGMwZDNjNTNmMWVjNjJlZDFhZmQ0NjAyODE2MzkwYjY4YmU4ZjA5BXRZAHVNBgBCKgomCiQIARIgFEf6wa84J98UcQc3CZJZjqGyxzw0zQmxTTfXg7J5sZQQHg==",
36 "synchronizerId": "global-domain::122090f9b95363b7ca407a1aacab116b997d4e6f326cc0576cfed6f45f979d8c60ee",
37 "debugPackageName": null,
38 "debugPayload": null,
39 "debugCreatedAt": null
40 }
41 ]
42 }
43}
Step 1d - Offer the Transfer¶
Finally, run the following script to offer the transfer:
1#!/usr/bin/env bash
2
3## =================================================================================================
4## Sender offers a transfer
5## Step 1d: Executes the transfer-offer command
6## Authorized by: Sender
7## Script: step-1d-sender-offers.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 ${SENDER_TOKEN}" \
29 --header "Content-Type: application/json" \
30 --request POST \
31 --data @- <<EOF
32{
33 "commands":{
34 "commands":[
35 {
36 "ExerciseCommand":{
37 "templateId":"${TRANSFERFACTORY_INTERFACE}",
38 "contractId":${FACTORYID},
39 "choice":"TransferFactory_Transfer",
40 "choiceArgument":{
41 "expectedAdmin":"${ADMIN_PARTY_ID}",
42 "transfer":{
43 "sender":"${SENDER_PARTY_ID}",
44 "receiver":"${RECEIVER_PARTY_ID}",
45 "amount":"${ASSET_AMOUNT}",
46 "instrumentId":{
47 "admin":"${ADMIN_PARTY_ID}",
48 "id":"${ASSET_ID}"
49 },
50 "requestedAt":"${NOW_ISO_TIMESTAMP}",
51 "executeBefore":"${ONEHOUR_ISO_TIMESTAMP}",
52 "inputHoldingCids":${HOLDINGCIDS},
53 "meta":{
54 "values":{
55 "splice.lfdecentralizedtrust.org/reason":""
56 }
57 }
58 },
59 "extraArgs":{
60 "context":${CHOICECONTEXTDATA},
61 "meta":{
62 "values":{
63 }
64 }
65 }
66 }
67 }
68 }
69 ],
70 "workflowId":"",
71 "userId":"${SENDER_USER_ID}",
72 "commandId":"$(uuidgen | tr -d '\n')",
73 "deduplicationPeriod":{
74 "DeduplicationDuration":{
75 "value":{
76 "seconds":30,
77 "nanos":0
78 }
79 }
80 },
81 "actAs":[
82 "${SENDER_PARTY_ID}"
83 ],
84 "readAs":[
85
86 ],
87 "submissionId":"$(uuidgen | tr -d '\n')",
88 "disclosedContracts": ${DISCLOSEDCONTRACTS},
89 "domainId":"",
90 "packageIdSelectionPreference":[]
91 }
92}
93EOF
94)
95
96echo "--- Command response ---"
97echo "$RESULT" | jq
98
99OUTPUTFILE="${SCRIPT_DIR}/response-step-1d.json"
100echo "$RESULT" > "$OUTPUTFILE"
For example, this is the response of this command:
1{
2 "transaction": {
3 "updateId": "1220570fc1f2761b906e63f25548574f99c6de8ba59b3a0c1e3231fefccff5117c8f",
4 "commandId": "2EE5ABB1-0A0B-42DD-B4D5-42F98DE1A64A",
5 "workflowId": "",
6 "effectiveAt": "2026-03-20T14:30:47.502479Z",
7 "events": [
8 {
9 "ArchivedEvent": {
10 "offset": 355,
11 "nodeId": 5,
12 "contractId": "00f30807d6b52c812171bfc7024119ab211c94f98565c044210b4a00783e182276ca12122079b824afe91e0a0c12cfe08228228e0b730d0cd9924ddab4ff001869be4d02a6",
13 "templateId": "8107899ac4723ce986bf7d27416534e576e54b92161e46150a595fb78ff3d3a1:Utility.Registry.Holding.V0.Holding:Holding",
14 "witnessParties": [
15 "issuer::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b"
16 ],
17 "packageName": "utility-registry-holding-v0",
18 "implementedInterfaces": []
19 }
20 },
21 {
22 "CreatedEvent": {
23 "offset": 355,
24 "nodeId": 6,
25 "contractId": "00b43f4eb9d53d55f0ee79a1477c118ec4fca8553d8b3d83621980b11b6ee63d6fca121220be54f9cc2feef6e677b0a92609e61fb37382b04c2feaa0bfb08d699e99b4f315",
26 "templateId": "8107899ac4723ce986bf7d27416534e576e54b92161e46150a595fb78ff3d3a1:Utility.Registry.Holding.V0.Holding:Holding",
27 "contractKey": null,
28 "createArgument": {
29 "operator": "operator::1220a6f417751797b91ab08423236f8c0d3c53f1ec62ed1afd4602816390b68be8f0",
30 "provider": "provider::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b",
31 "registrar": "registrar::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b",
32 "owner": "issuer::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b",
33 "instrument": {
34 "source": "registrar::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b",
35 "id": "INST",
36 "scheme": "RegistrarInternalScheme"
37 },
38 "label": "",
39 "amount": "1.0000000000",
40 "lock": {
41 "lockers": {
42 "map": [
43 [
44 "registrar::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b",
45 {}
46 ]
47 ]
48 },
49 "context": "",
50 "observers": {
51 "map": [
52 [
53 "holder::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b",
54 {}
55 ]
56 ]
57 }
58 }
59 },
60 "createdEventBlob": "",
61 "interfaceViews": [],
62 "witnessParties": [
63 "issuer::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b"
64 ],
65 "signatories": [
66 "issuer::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b",
67 "registrar::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b"
68 ],
69 "observers": [
70 "holder::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b",
71 "operator::1220a6f417751797b91ab08423236f8c0d3c53f1ec62ed1afd4602816390b68be8f0",
72 "provider::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b"
73 ],
74 "createdAt": "2026-03-20T14:30:47.502479Z",
75 "packageName": "utility-registry-holding-v0",
76 "representativePackageId": "8107899ac4723ce986bf7d27416534e576e54b92161e46150a595fb78ff3d3a1",
77 "acsDelta": true
78 }
79 },
80 {
81 "CreatedEvent": {
82 "offset": 355,
83 "nodeId": 7,
84 "contractId": "0008f04552564707be37dda82b280c0616db4eca600b3be34572ea85c19b640202ca12122087e00468e0c9423f45df2de5f57e707bbe448b4e84a7af2fd4ab50e83a455471",
85 "templateId": "8107899ac4723ce986bf7d27416534e576e54b92161e46150a595fb78ff3d3a1:Utility.Registry.Holding.V0.Holding:Holding",
86 "contractKey": null,
87 "createArgument": {
88 "operator": "operator::1220a6f417751797b91ab08423236f8c0d3c53f1ec62ed1afd4602816390b68be8f0",
89 "provider": "provider::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b",
90 "registrar": "registrar::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b",
91 "owner": "issuer::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b",
92 "instrument": {
93 "source": "registrar::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b",
94 "id": "INST",
95 "scheme": "RegistrarInternalScheme"
96 },
97 "label": "",
98 "amount": "1.0000000000"
99 },
100 "createdEventBlob": "",
101 "interfaceViews": [],
102 "witnessParties": [
103 "issuer::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b"
104 ],
105 "signatories": [
106 "issuer::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b",
107 "registrar::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b"
108 ],
109 "observers": [
110 "operator::1220a6f417751797b91ab08423236f8c0d3c53f1ec62ed1afd4602816390b68be8f0",
111 "provider::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b"
112 ],
113 "createdAt": "2026-03-20T14:30:47.502479Z",
114 "packageName": "utility-registry-holding-v0",
115 "representativePackageId": "8107899ac4723ce986bf7d27416534e576e54b92161e46150a595fb78ff3d3a1",
116 "acsDelta": true
117 }
118 },
119 {
120 "CreatedEvent": {
121 "offset": 355,
122 "nodeId": 8,
123 "contractId": "00b0e960e767ea1623c8e7585190ed0e1d7fbe5dcc75f26235c7af90df9dc6fd81ca121220384487062561e5c4bc4372508d405a12eeedd7133bd3084d7587c74cd89c217e",
124 "templateId": "7a75ef6e69f69395a4e60919e228528bb8f3881150ccfde3f31bcc73864b18ab:Utility.Registry.App.V0.Model.Transfer:TransferOffer",
125 "contractKey": null,
126 "createArgument": {
127 "operator": "operator::1220a6f417751797b91ab08423236f8c0d3c53f1ec62ed1afd4602816390b68be8f0",
128 "provider": "provider::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b",
129 "transfer": {
130 "sender": "issuer::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b",
131 "receiver": "holder::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b",
132 "amount": "1.0000000000",
133 "instrumentId": {
134 "admin": "registrar::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b",
135 "id": "INST"
136 },
137 "requestedAt": "2026-03-20T14:30:47Z",
138 "executeBefore": "2026-03-20T15:30:47Z",
139 "inputHoldingCids": [
140 "00b43f4eb9d53d55f0ee79a1477c118ec4fca8553d8b3d83621980b11b6ee63d6fca121220be54f9cc2feef6e677b0a92609e61fb37382b04c2feaa0bfb08d699e99b4f315"
141 ],
142 "meta": {
143 "values": {
144 "splice.lfdecentralizedtrust.org/reason": ""
145 }
146 }
147 }
148 },
149 "createdEventBlob": "",
150 "interfaceViews": [],
151 "witnessParties": [
152 "issuer::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b"
153 ],
154 "signatories": [
155 "issuer::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b",
156 "provider::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b",
157 "registrar::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b"
158 ],
159 "observers": [
160 "holder::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b",
161 "operator::1220a6f417751797b91ab08423236f8c0d3c53f1ec62ed1afd4602816390b68be8f0"
162 ],
163 "createdAt": "2026-03-20T14:30:47.502479Z",
164 "packageName": "utility-registry-app-v0",
165 "representativePackageId": "7a75ef6e69f69395a4e60919e228528bb8f3881150ccfde3f31bcc73864b18ab",
166 "acsDelta": true
167 }
168 }
169 ],
170 "offset": 355,
171 "synchronizerId": "global-domain::122090f9b95363b7ca407a1aacab116b997d4e6f326cc0576cfed6f45f979d8c60ee",
172 "traceContext": {
173 "traceparent": "00-4897f21b08ac395230966d8f67eb1593-038139d480d9722a-01",
174 "tracestate": null
175 },
176 "recordTime": "2026-03-20T14:30:47.559276Z",
177 "externalTransactionHash": null
178 }
179}
After the exercise command is executed, the amount is locked by the admin.
Step 2: Receiver Accepts the Transfer Offer¶
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## Receiver accepts offer
5## Step 2a: Obtains ledger end offset
6## Authorized by: Receiver
7## Script: step-2a-receiver-accepts.sh
8## =================================================================================================
9
10SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11DATAFILE="${SCRIPT_DIR}/source.sh"
12source "$DATAFILE"
13
14# obtain ledger end
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 ${RECEIVER_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": 359
3}
Step 2b - Retrieve Transfer Offer¶
To retrieve the Transfer Offer created in Step 1d, run the following script:
1#!/usr/bin/env bash
2
3## =================================================================================================
4## Receiver accepts offer
5## Step 2b: Retrieves the transfer offer to accept
6## Authorized by: Receiver
7## Script: step-2b-receiver-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 ${RECEIVER_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 "${RECEIVER_PARTY_ID}": {
30 "cumulative": [{
31 "identifierFilter": {
32 "InterfaceFilter": {
33 "value": {
34 "interfaceId":"$TRANSFER_INSTRUCTION_INTERFACE",
35 "includeInterfaceView": true,
36 "includeCreatedEventBlob": false
37 }
38 }
39 }
40 }]
41 }
42 }
43 }
44}
45EOF
46)
47
48echo "--- Transfer Offer for Sender ---"
49echo "$RESULT" | jq
50
51OUTPUTFILE="${SCRIPT_DIR}/response-step-2b.json"
52echo "$RESULT" > "$OUTPUTFILE"
The result is the Transfer Offer, stored in response-step-2b.json. For example,
1[
2 {
3 "workflowId": "",
4 "contractEntry": {
5 "JsActiveContract": {
6 "createdEvent": {
7 "offset": 355,
8 "nodeId": 8,
9 "contractId": "00b0e960e767ea1623c8e7585190ed0e1d7fbe5dcc75f26235c7af90df9dc6fd81ca121220384487062561e5c4bc4372508d405a12eeedd7133bd3084d7587c74cd89c217e",
10 "templateId": "7a75ef6e69f69395a4e60919e228528bb8f3881150ccfde3f31bcc73864b18ab:Utility.Registry.App.V0.Model.Transfer:TransferOffer",
11 "contractKey": null,
12 "createArgument": {
13 "operator": "operator::1220a6f417751797b91ab08423236f8c0d3c53f1ec62ed1afd4602816390b68be8f0",
14 "provider": "provider::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b",
15 "transfer": {
16 "sender": "issuer::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b",
17 "receiver": "holder::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b",
18 "amount": "1.0000000000",
19 "instrumentId": {
20 "admin": "registrar::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b",
21 "id": "INST"
22 },
23 "requestedAt": "2026-03-20T14:30:47Z",
24 "executeBefore": "2026-03-20T15:30:47Z",
25 "inputHoldingCids": [
26 "00b43f4eb9d53d55f0ee79a1477c118ec4fca8553d8b3d83621980b11b6ee63d6fca121220be54f9cc2feef6e677b0a92609e61fb37382b04c2feaa0bfb08d699e99b4f315"
27 ],
28 "meta": {
29 "values": {
30 "splice.lfdecentralizedtrust.org/reason": ""
31 }
32 }
33 }
34 },
35 "createdEventBlob": "",
36 "interfaceViews": [
37 {
38 "interfaceId": "55ba4deb0ad4662c4168b39859738a0e91388d252286480c7331b3f71a517281:Splice.Api.Token.TransferInstructionV1:TransferInstruction",
39 "viewStatus": {
40 "code": 0,
41 "message": "",
42 "details": []
43 },
44 "viewValue": {
45 "originalInstructionCid": null,
46 "transfer": {
47 "sender": "issuer::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b",
48 "receiver": "holder::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b",
49 "amount": "1.0000000000",
50 "instrumentId": {
51 "admin": "registrar::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b",
52 "id": "INST"
53 },
54 "requestedAt": "2026-03-20T14:30:47Z",
55 "executeBefore": "2026-03-20T15:30:47Z",
56 "inputHoldingCids": [
57 "00b43f4eb9d53d55f0ee79a1477c118ec4fca8553d8b3d83621980b11b6ee63d6fca121220be54f9cc2feef6e677b0a92609e61fb37382b04c2feaa0bfb08d699e99b4f315"
58 ],
59 "meta": {
60 "values": {
61 "splice.lfdecentralizedtrust.org/reason": ""
62 }
63 }
64 },
65 "status": {
66 "tag": "TransferPendingReceiverAcceptance",
67 "value": {}
68 },
69 "meta": {
70 "values": {}
71 }
72 }
73 }
74 ],
75 "witnessParties": [
76 "holder::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b"
77 ],
78 "signatories": [
79 "issuer::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b",
80 "provider::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b",
81 "registrar::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b"
82 ],
83 "observers": [
84 "holder::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b",
85 "operator::1220a6f417751797b91ab08423236f8c0d3c53f1ec62ed1afd4602816390b68be8f0"
86 ],
87 "createdAt": "2026-03-20T14:30:47.502479Z",
88 "packageName": "utility-registry-app-v0",
89 "representativePackageId": "7a75ef6e69f69395a4e60919e228528bb8f3881150ccfde3f31bcc73864b18ab",
90 "acsDelta": true
91 },
92 "synchronizerId": "global-domain::122090f9b95363b7ca407a1aacab116b997d4e6f326cc0576cfed6f45f979d8c60ee",
93 "reassignmentCounter": 0
94 }
95 }
96 }
97]
Step 2c - Access the Backend API¶
The request URL is
${BACKEND_API}/v0/registrars/${ADMIN_PARTY_ID}/registry/transfer-instruction/v1/${TRANSFEROFFER_CID}/choice-contexts/accept.
To hit this endpoint, run the following script:
1#!/usr/bin/env bash
2
3## =================================================================================================
4## Receiver accepts offer
5## Step 2c: Gets choice context and disclosure for the accept-transfer-offer command
6## Authorized by: anyone
7## Script: step-2c-receiver-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
18TRANSFEROFFER=$(cat "${SCRIPT_DIR}/response-step-2b.json")
19TRANSFEROFFER_CID=$(echo $TRANSFEROFFER |jq '.[] | .contractEntry.JsActiveContract.createdEvent.contractId' | tr -d '"')
20
21RESULT=$(
22 curl -sS --fail-with-body \
23 --url "${BACKEND_API}/v0/registrars/${ADMIN_PARTY_ID}/registry/transfer-instruction/v1/${TRANSFEROFFER_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/receiver-credentials": {
5 "tag": "AV_List",
6 "value": [
7 {
8 "tag": "AV_ContractId",
9 "value": "00215449447d574da3b89f8f9f4c6052445bcdc6b55d44f9a3368ae1a61f55235aca121220e0bc50285d6f592ad294cb7e481c59068bdadd0e1b1324fb689c34a7f6b57e18"
10 }
11 ]
12 },
13 "utility.digitalasset.com/transfer-rule": {
14 "tag": "AV_ContractId",
15 "value": "00f29664468c3e64b9ee11029d6758e42b02b5f521a322c0ceafb47ea5199661c5ca1212205d3967770942af04654b6e3c5be59c2c207c49ca5c1a7aac7813e977a4b418ce"
16 },
17 "utility.digitalasset.com/sender-credentials": {
18 "tag": "AV_List",
19 "value": [
20 {
21 "tag": "AV_ContractId",
22 "value": "00e4e3405e422c0d0b8ee71847212d4ac5f7c45dbb59ce5d4e2acdc7d688a62b3aca12122037516f1734f137d24aacb957edfeaf6b48142d417c993ebc6ad4e1349b336537"
23 }
24 ]
25 },
26 "utility.digitalasset.com/enable-result-contracts": {
27 "tag": "AV_Bool",
28 "value": true
29 },
30 "utility.digitalasset.com/instrument-configuration": {
31 "tag": "AV_ContractId",
32 "value": "0002c3fa81687da421f65cff2ce498c4651e713e23ac70fd24e3de66fbe5ad3382ca121220a17caca8d3c0910c6e6d1a8e3dfe23c92c064b3fda95ea2f1456070f458daf1c"
33 }
34 }
35 },
36 "disclosedContracts": [
37 {
38 "templateId": "a236e8e22a3b5f199e37d5554e82bafd2df688f901de02b00be3964bdfa8c1ab:Utility.Registry.V0.Configuration.Instrument:InstrumentConfiguration",
39 "contractId": "0002c3fa81687da421f65cff2ce498c4651e713e23ac70fd24e3de66fbe5ad3382ca121220a17caca8d3c0910c6e6d1a8e3dfe23c92c064b3fda95ea2f1456070f458daf1c",
40 "createdEventBlob": "CgMyLjESpgkKRQACw/qBaH2kIfZc/yzkmMRlHnE+I6xw/STj3mb75a0zgsoSEiChfKyo08CRDG5tGo49/iPJLAZLP9qV6i8UVgcPRY2vHBITdXRpbGl0eS1yZWdpc3RyeS12MBqNAQpAYTIzNmU4ZTIyYTNiNWYxOTllMzdkNTU1NGU4MmJhZmQyZGY2ODhmOTAxZGUwMmIwMGJlMzk2NGJkZmE4YzFhYhIHVXRpbGl0eRIIUmVnaXN0cnkSAlYwEg1Db25maWd1cmF0aW9uEgpJbnN0cnVtZW50GhdJbnN0cnVtZW50Q29uZmlndXJhdGlvbiKRBWqOBQpSClA6Tm9wZXJhdG9yOjoxMjIwYTZmNDE3NzUxNzk3YjkxYWIwODQyMzIzNmY4YzBkM2M1M2YxZWM2MmVkMWFmZDQ2MDI4MTYzOTBiNjhiZThmMApSClA6TnByb3ZpZGVyOjoxMjIwMTYzYTIwNzBjZDljZjgzMTcyMWM2YTg0ZTE5Yjc3MjdiOTgyNTYzNmVhOWIwOWYyNDIyOWY0NWEzNDFmN2M0YgpTClE6T3JlZ2lzdHJhcjo6MTIyMDE2M2EyMDcwY2Q5Y2Y4MzE3MjFjNmE4NGUxOWI3NzI3Yjk4MjU2MzZlYTliMDlmMjQyMjlmNDVhMzQxZjdjNGIKgAEKfmp8ClMKUTpPcmVnaXN0cmFyOjoxMjIwMTYzYTIwNzBjZDljZjgzMTcyMWM2YTg0ZTE5Yjc3MjdiOTgyNTYzNmVhOWIwOWYyNDIyOWY0NWEzNDFmN2M0YgoICgZCBElOU1QKGwoZQhdSZWdpc3RyYXJJbnRlcm5hbFNjaGVtZQoECgJaAAqBAQp/Wn0Ke2p5ClMKUTpPcmVnaXN0cmFyOjoxMjIwMTYzYTIwNzBjZDljZjgzMTcyMWM2YTg0ZTE5Yjc3MjdiOTgyNTYzNmVhOWIwOWYyNDIyOWY0NWEzNDFmN2M0YgoiCiBaHgocahoKDgoMQgppc0lzc3Vlck9mCggKBkIESU5TVAqBAQp/Wn0Ke2p5ClMKUTpPcmVnaXN0cmFyOjoxMjIwMTYzYTIwNzBjZDljZjgzMTcyMWM2YTg0ZTE5Yjc3MjdiOTgyNTYzNmVhOWIwOWYyNDIyOWY0NWEzNDFmN2M0YgoiCiBaHgocahoKDgoMQgppc0hvbGRlck9mCggKBkIESU5TVCpOcHJvdmlkZXI6OjEyMjAxNjNhMjA3MGNkOWNmODMxNzIxYzZhODRlMTliNzcyN2I5ODI1NjM2ZWE5YjA5ZjI0MjI5ZjQ1YTM0MWY3YzRiKk9yZWdpc3RyYXI6OjEyMjAxNjNhMjA3MGNkOWNmODMxNzIxYzZhODRlMTliNzcyN2I5ODI1NjM2ZWE5YjA5ZjI0MjI5ZjQ1YTM0MWY3YzRiMk5vcGVyYXRvcjo6MTIyMGE2ZjQxNzc1MTc5N2I5MWFiMDg0MjMyMzZmOGMwZDNjNTNmMWVjNjJlZDFhZmQ0NjAyODE2MzkwYjY4YmU4ZjA5BXRZAHVNBgBCKgomCiQIARIgFEf6wa84J98UcQc3CZJZjqGyxzw0zQmxTTfXg7J5sZQQHg==",
41 "synchronizerId": "global-domain::122090f9b95363b7ca407a1aacab116b997d4e6f326cc0576cfed6f45f979d8c60ee",
42 "debugPackageName": "utility-registry-v0",
43 "debugPayload": {
44 "operator": "operator::1220a6f417751797b91ab08423236f8c0d3c53f1ec62ed1afd4602816390b68be8f0",
45 "provider": "provider::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b",
46 "registrar": "registrar::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b",
47 "defaultIdentifier": {
48 "source": "registrar::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b",
49 "id": "INST",
50 "scheme": "RegistrarInternalScheme"
51 },
52 "additionalIdentifiers": [],
53 "issuerRequirements": [
54 {
55 "issuer": "registrar::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b",
56 "requiredClaims": [
57 {
58 "_1": "isIssuerOf",
59 "_2": "INST"
60 }
61 ]
62 }
63 ],
64 "holderRequirements": [
65 {
66 "issuer": "registrar::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b",
67 "requiredClaims": [
68 {
69 "_1": "isHolderOf",
70 "_2": "INST"
71 }
72 ]
73 }
74 ],
75 "providerAppRewardBeneficiaries": null
76 },
77 "debugCreatedAt": "2026-03-20T13:52:52.638Z"
78 },
79 {
80 "templateId": "a236e8e22a3b5f199e37d5554e82bafd2df688f901de02b00be3964bdfa8c1ab:Utility.Registry.V0.Rule.Transfer:TransferRule",
81 "contractId": "00f29664468c3e64b9ee11029d6758e42b02b5f521a322c0ceafb47ea5199661c5ca1212205d3967770942af04654b6e3c5be59c2c207c49ca5c1a7aac7813e977a4b418ce",
82 "createdEventBlob": "CgMyLjES/gUKRQDylmRGjD5kue4RAp1nWOQrArX1IaMiwM6vtH6lGZZhxcoSEiBdOWd3CUKvBGVLbjxb5ZwsIHxJylwaeqx4E+l3pLQYzhITdXRpbGl0eS1yZWdpc3RyeS12MBp3CkBhMjM2ZThlMjJhM2I1ZjE5OWUzN2Q1NTU0ZTgyYmFmZDJkZjY4OGY5MDFkZTAyYjAwYmUzOTY0YmRmYThjMWFiEgdVdGlsaXR5EghSZWdpc3RyeRICVjASBFJ1bGUSCFRyYW5zZmVyGgxUcmFuc2ZlclJ1bGUigAJq/QEKUgpQOk5vcGVyYXRvcjo6MTIyMGE2ZjQxNzc1MTc5N2I5MWFiMDg0MjMyMzZmOGMwZDNjNTNmMWVjNjJlZDFhZmQ0NjAyODE2MzkwYjY4YmU4ZjAKUgpQOk5wcm92aWRlcjo6MTIyMDE2M2EyMDcwY2Q5Y2Y4MzE3MjFjNmE4NGUxOWI3NzI3Yjk4MjU2MzZlYTliMDlmMjQyMjlmNDVhMzQxZjdjNGIKUwpROk9yZWdpc3RyYXI6OjEyMjAxNjNhMjA3MGNkOWNmODMxNzIxYzZhODRlMTliNzcyN2I5ODI1NjM2ZWE5YjA5ZjI0MjI5ZjQ1YTM0MWY3YzRiKk5wcm92aWRlcjo6MTIyMDE2M2EyMDcwY2Q5Y2Y4MzE3MjFjNmE4NGUxOWI3NzI3Yjk4MjU2MzZlYTliMDlmMjQyMjlmNDVhMzQxZjdjNGIqT3JlZ2lzdHJhcjo6MTIyMDE2M2EyMDcwY2Q5Y2Y4MzE3MjFjNmE4NGUxOWI3NzI3Yjk4MjU2MzZlYTliMDlmMjQyMjlmNDVhMzQxZjdjNGIyTm9wZXJhdG9yOjoxMjIwYTZmNDE3NzUxNzk3YjkxYWIwODQyMzIzNmY4YzBkM2M1M2YxZWM2MmVkMWFmZDQ2MDI4MTYzOTBiNjhiZThmMDlYW1MAdU0GAEIqCiYKJAgBEiDCziD4NUprWW001ZYBLqKtwrtBlKdXzDNFnt/i5GRI2hAe",
83 "synchronizerId": "global-domain::122090f9b95363b7ca407a1aacab116b997d4e6f326cc0576cfed6f45f979d8c60ee",
84 "debugPackageName": "utility-registry-v0",
85 "debugPayload": {
86 "operator": "operator::1220a6f417751797b91ab08423236f8c0d3c53f1ec62ed1afd4602816390b68be8f0",
87 "provider": "provider::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b",
88 "registrar": "registrar::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b"
89 },
90 "debugCreatedAt": "2026-03-20T13:52:52.239Z"
91 },
92 {
93 "templateId": "5a29ead611a0abd5f5b3fc3caf7d0f67c0ff802032ab6d392824aa9060e56d70:Utility.Credential.V0.Credential:Credential",
94 "contractId": "00e4e3405e422c0d0b8ee71847212d4ac5f7c45dbb59ce5d4e2acdc7d688a62b3aca12122037516f1734f137d24aacb957edfeaf6b48142d417c993ebc6ad4e1349b336537",
95 "createdEventBlob": "CgMyLjESrAcKRQDk40BeQiwNC47nGEchLUrF98Rdu1nOXU4qzcfWiKYrOsoSEiA3UW8XNPE30kqsuVft/q9rSBQtQXyZPrxq1OE0mzNlNxIVdXRpbGl0eS1jcmVkZW50aWFsLXYwGnMKQDVhMjllYWQ2MTFhMGFiZDVmNWIzZmMzY2FmN2QwZjY3YzBmZjgwMjAzMmFiNmQzOTI4MjRhYTkwNjBlNTZkNzASB1V0aWxpdHkSCkNyZWRlbnRpYWwSAlYwEgpDcmVkZW50aWFsGgpDcmVkZW50aWFsIrIDaq8DClMKUTpPcmVnaXN0cmFyOjoxMjIwMTYzYTIwNzBjZDljZjgzMTcyMWM2YTg0ZTE5Yjc3MjdiOTgyNTYzNmVhOWIwOWYyNDIyOWY0NWEzNDFmN2M0YgpQCk46TGlzc3Vlcjo6MTIyMDE2M2EyMDcwY2Q5Y2Y4MzE3MjFjNmE4NGUxOWI3NzI3Yjk4MjU2MzZlYTliMDlmMjQyMjlmNDVhMzQxZjdjNGIKDwoNQgtJTlNUX0hvbGRlcgoPCg1CC0lOU1RfSG9sZGVyCgQKAlIACgQKAlIACnQKclpwCm5qbApQCk5CTGlzc3Vlcjo6MTIyMDE2M2EyMDcwY2Q5Y2Y4MzE3MjFjNmE4NGUxOWI3NzI3Yjk4MjU2MzZlYTliMDlmMjQyMjlmNDVhMzQxZjdjNGIKDgoMQgppc0hvbGRlck9mCggKBkIESU5TVApiCmBqXgpcClpiWApWClA6Tm9wZXJhdG9yOjoxMjIwYTZmNDE3NzUxNzk3YjkxYWIwODQyMzIzNmY4YzBkM2M1M2YxZWM2MmVkMWFmZDQ2MDI4MTYzOTBiNjhiZThmMBICCgAqTGlzc3Vlcjo6MTIyMDE2M2EyMDcwY2Q5Y2Y4MzE3MjFjNmE4NGUxOWI3NzI3Yjk4MjU2MzZlYTliMDlmMjQyMjlmNDVhMzQxZjdjNGIqT3JlZ2lzdHJhcjo6MTIyMDE2M2EyMDcwY2Q5Y2Y4MzE3MjFjNmE4NGUxOWI3NzI3Yjk4MjU2MzZlYTliMDlmMjQyMjlmNDVhMzQxZjdjNGIyTm9wZXJhdG9yOjoxMjIwYTZmNDE3NzUxNzk3YjkxYWIwODQyMzIzNmY4YzBkM2M1M2YxZWM2MmVkMWFmZDQ2MDI4MTYzOTBiNjhiZThmMDmRfR4AdU0GAEIqCiYKJAgBEiAMsxMGdGcKGp3ptTJXrha4DhhDG8xPMZ9QKBBMZTC4YBAe",
96 "synchronizerId": "global-domain::122090f9b95363b7ca407a1aacab116b997d4e6f326cc0576cfed6f45f979d8c60ee",
97 "debugPackageName": "utility-credential-v0",
98 "debugPayload": {
99 "issuer": "registrar::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b",
100 "holder": "issuer::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b",
101 "id": "INST_Holder",
102 "description": "INST_Holder",
103 "validFrom": null,
104 "validUntil": null,
105 "claims": [
106 {
107 "subject": "issuer::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b",
108 "property": "isHolderOf",
109 "value": "INST"
110 }
111 ],
112 "observers": {
113 "map": [
114 [
115 "operator::1220a6f417751797b91ab08423236f8c0d3c53f1ec62ed1afd4602816390b68be8f0",
116 {}
117 ]
118 ]
119 }
120 },
121 "debugCreatedAt": "2026-03-20T13:52:48.774Z"
122 }
123 ]
124}
Step 2d - Accept the Transfer Offer¶
To finalize the transfer and move the asset from the sender to the receiver, execute the following script:
1#!/usr/bin/env bash
2
3## =================================================================================================
4## Receiver accepts offer
5## Step 2d: Executes the accept transfer command
6## Authorized by: Receiver
7## Script: step-2d-receiver-accepts.sh
8## =================================================================================================
9
10SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11DATAFILE="${SCRIPT_DIR}/source.sh"
12source "$DATAFILE"
13
14INSTRUCTION=$(cat "${SCRIPT_DIR}/response-step-2b.json")
15INSTRUCTION_TEMPLATE=$(echo $INSTRUCTION | jq '.[] | .contractEntry.JsActiveContract.createdEvent.interfaceViews[0].interfaceId' | tr -d '"')
16INSTRUCTION_CID=$(echo $INSTRUCTION | jq '.[] | .contractEntry.JsActiveContract.createdEvent.contractId')
17
18JSONCONTENT=$(cat "${SCRIPT_DIR}/response-step-2c.json")
19CHOICECONTEXTDATA=$(echo $JSONCONTENT | jq .choiceContextData)
20DISCLOSEDCONTRACTS=$(echo $JSONCONTENT | jq .disclosedContracts)
21
22RESULT=$(
23 curl -sS --fail-with-body \
24 --url "${HTTP_JSON_API}/v2/commands/submit-and-wait-for-transaction" \
25 --header "Authorization: Bearer ${RECEIVER_TOKEN}" \
26 --header "Content-Type: application/json" \
27 --request POST \
28 --data @- <<EOF
29{
30 "commands":{
31 "commands":[
32 {
33 "ExerciseCommand":{
34 "templateId":"${INSTRUCTION_TEMPLATE}",
35 "contractId":${INSTRUCTION_CID},
36 "choice":"TransferInstruction_Accept",
37 "choiceArgument":{
38 "extraArgs": {
39 "context": $CHOICECONTEXTDATA,
40 "meta":{
41 "values":{
42
43 }
44 }
45 }
46 }
47 }
48 }
49 ],
50 "workflowId":"",
51 "userId":"${RECEIVER_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 "${RECEIVER_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": "1220cde5d0bcfea3b49e90b3258b79b5edf80e3a00f2668a1cb70e0e2fc684508297",
4 "commandId": "E7613E19-E806-4231-9EDE-75BB290342AC",
5 "workflowId": "",
6 "effectiveAt": "2026-03-20T14:31:58.496997Z",
7 "events": [
8 {
9 "ArchivedEvent": {
10 "offset": 364,
11 "nodeId": 0,
12 "contractId": "00b0e960e767ea1623c8e7585190ed0e1d7fbe5dcc75f26235c7af90df9dc6fd81ca121220384487062561e5c4bc4372508d405a12eeedd7133bd3084d7587c74cd89c217e",
13 "templateId": "7a75ef6e69f69395a4e60919e228528bb8f3881150ccfde3f31bcc73864b18ab:Utility.Registry.App.V0.Model.Transfer:TransferOffer",
14 "witnessParties": [
15 "holder::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b"
16 ],
17 "packageName": "utility-registry-app-v0",
18 "implementedInterfaces": []
19 }
20 },
21 {
22 "ArchivedEvent": {
23 "offset": 364,
24 "nodeId": 6,
25 "contractId": "00b43f4eb9d53d55f0ee79a1477c118ec4fca8553d8b3d83621980b11b6ee63d6fca121220be54f9cc2feef6e677b0a92609e61fb37382b04c2feaa0bfb08d699e99b4f315",
26 "templateId": "8107899ac4723ce986bf7d27416534e576e54b92161e46150a595fb78ff3d3a1:Utility.Registry.Holding.V0.Holding:Holding",
27 "witnessParties": [
28 "holder::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b"
29 ],
30 "packageName": "utility-registry-holding-v0",
31 "implementedInterfaces": []
32 }
33 },
34 {
35 "CreatedEvent": {
36 "offset": 364,
37 "nodeId": 7,
38 "contractId": "001f7bd95fc4abcceded8db23ac1c405b61eb4f1247091d31515a0e5d16df31d6bca121220f7d44b5e0ce34e246fe02d48ef3be6867ad67f687174c01b7b1999d9a04d7e66",
39 "templateId": "8107899ac4723ce986bf7d27416534e576e54b92161e46150a595fb78ff3d3a1:Utility.Registry.Holding.V0.Holding:Holding",
40 "contractKey": null,
41 "createArgument": {
42 "operator": "operator::1220a6f417751797b91ab08423236f8c0d3c53f1ec62ed1afd4602816390b68be8f0",
43 "provider": "provider::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b",
44 "registrar": "registrar::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b",
45 "owner": "holder::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b",
46 "instrument": {
47 "source": "registrar::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b",
48 "id": "INST",
49 "scheme": "RegistrarInternalScheme"
50 },
51 "label": "",
52 "amount": "1.0000000000"
53 },
54 "createdEventBlob": "",
55 "interfaceViews": [],
56 "witnessParties": [
57 "holder::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b"
58 ],
59 "signatories": [
60 "holder::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b",
61 "registrar::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b"
62 ],
63 "observers": [
64 "operator::1220a6f417751797b91ab08423236f8c0d3c53f1ec62ed1afd4602816390b68be8f0",
65 "provider::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b"
66 ],
67 "createdAt": "2026-03-20T14:31:58.496997Z",
68 "packageName": "utility-registry-holding-v0",
69 "representativePackageId": "8107899ac4723ce986bf7d27416534e576e54b92161e46150a595fb78ff3d3a1",
70 "acsDelta": true
71 }
72 },
73 {
74 "CreatedEvent": {
75 "offset": 364,
76 "nodeId": 8,
77 "contractId": "007724a5df31c7f6292a821e287f1fb0ef88ffee36a503919c38bcfb14bed47698ca121220105a0dce75530206f268ea1434f2852c9109beddb5f7d187e4c9ebf9fe10c278",
78 "templateId": "a236e8e22a3b5f199e37d5554e82bafd2df688f901de02b00be3964bdfa8c1ab:Utility.Registry.V0.Holding.Transfer:ExecutedTransfer",
79 "contractKey": null,
80 "createArgument": {
81 "transfer": {
82 "operator": "operator::1220a6f417751797b91ab08423236f8c0d3c53f1ec62ed1afd4602816390b68be8f0",
83 "provider": "provider::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b",
84 "registrar": "registrar::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b",
85 "sender": "issuer::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b",
86 "receiver": "holder::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b",
87 "instrumentIdentifier": {
88 "source": "registrar::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b",
89 "id": "INST",
90 "scheme": "RegistrarInternalScheme"
91 },
92 "amount": "1.0000000000",
93 "reference": "",
94 "batch": {
95 "id": "",
96 "size": "1"
97 }
98 },
99 "senderLabel": "",
100 "receiverLabel": "",
101 "observers": null,
102 "operatorIsObserver": false
103 },
104 "createdEventBlob": "",
105 "interfaceViews": [],
106 "witnessParties": [
107 "holder::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b"
108 ],
109 "signatories": [
110 "registrar::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b"
111 ],
112 "observers": [
113 "holder::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b",
114 "issuer::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b",
115 "provider::1220163a2070cd9cf831721c6a84e19b7727b9825636ea9b09f24229f45a341f7c4b"
116 ],
117 "createdAt": "2026-03-20T14:31:58.496997Z",
118 "packageName": "utility-registry-v0",
119 "representativePackageId": "a236e8e22a3b5f199e37d5554e82bafd2df688f901de02b00be3964bdfa8c1ab",
120 "acsDelta": true
121 }
122 }
123 ],
124 "offset": 364,
125 "synchronizerId": "global-domain::122090f9b95363b7ca407a1aacab116b997d4e6f326cc0576cfed6f45f979d8c60ee",
126 "traceContext": {
127 "traceparent": "00-68b2515031b21c69aa8cf0e22e4ef2dc-6a6845aa705830e9-01",
128 "tracestate": null
129 },
130 "recordTime": "2026-03-20T14:31:58.540086Z",
131 "externalTransactionHash": null
132 }
133}
After the exercise command is executed, the transfer is complete.