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.

Initial positions

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.

Positions after the sender has offered the transfer

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.

Positions after the receiver has accepted the transfer offer