October 20

Гайд по виконанню шостого завдання в проекті Canton

Крипто-подорожі з Дмитром - канал про ретродропи, тестнети, блокчейни, скрипти, NFT, криптобіржі, коротше, про все цікаве зі світу криптовалюти. Впевнений, тобі буде цікаво та корисно.
Чат каналу - ласкаво прошу, спілкуємось, ділимося новими активностями, допомагаємо один одному.

Привіт всім.

Отже, сьогодні виконуємо п'яте завдання для проекту Canton, в якого 400 лямів інвесту. Перше, друге, третє і четверте я розписав в своєму ТГ каналі, можете ознайомитись:
Перше
Друге

Третє

Четверте

П'яте

Посилання на сторінку з завданням:
https://earn.stackup.dev/campaigns/unlocking-canton-with-daml-unifying-traditional-and-crypto-markets-on-chain/quests/capstone-developing-and-prototyping-smart-contract-logic-5889

Результатом виконання завдання має бути скрін, який ви бачите зверху. Погнали?

Це завдання найкраще виконувати на сервері Linux з будь якими характеристиками. Я спочатку пару годин витратив на термінал в Віндовс, але там інші команди, синтаксис відрізняється, тому все ж зній с одного сервера Nexus і все чудово зробив.

Попереджаю, що вам доведеться копіювати багато даних з попередніх кроків і вставляти їх в наступні. Я спочатку це робив вручну, а потім просто кожен результат з терміналу скидав в Перплексіті і казав йому запам'ятати всі потрібні дані. Потім скидав наступне завдання і просив автоматично заповнити моїми даними. Так швидше і простіше.

Скачуємо Daml:

curl -sSL https://get.daml.com/ | sh -s 3.3.0-snapshot.20250930.0
export PATH="$HOME/.daml/bin:$PATH"
daml new capstone --template quickstart-java
cd capstone
ls

Після LS має з’явитися папка daml, файл daml.yaml, pom.xml і т.д.

daml build
ls .daml/dist


Має написати у відповіді щось про файл quickstart-0.0.1.dar

Встановлюємо Java:

apt update
apt install -y openjdk-17-jre
daml test

буде довго думати, потім виведе результат тесту.
Запускаємо пісочницю:

daml sandbox --json-api-port 7575

Напише, що пісочниця запущена, залишаєте це вікно активним і відкриваєте новий термінал

cd ~/capstone

Перевіряємо файл:

head -n 5 openapi.yaml

має бути щось типу

openapi: 3.0.3
info:
title: JSON Ledger API HTTP endpoints
version: 3.3.0-SNAPSHOT

Завантажуємо DAR файл:

curl -v -X POST 'http://localhost:7575/v2/packages' \
-H "Content-Type: application/octet-stream" \
--data-binary @.daml/dist/quickstart-0.0.1.dar

Має показати багато тексту, але обов'язково "HTTP/1.1 200 OK"

Створюємо по черзі 4 партії:

curl -d '{"partyIdHint":"Alice","identityProviderId":""}' -H "Content-Type: application/json" -X POST localhost:7575/v2/parties
curl -d '{"partyIdHint":"Bob","identityProviderId":""}' -H "Content-Type: application/json" -X POST localhost:7575/v2/parties
curl -d '{"partyIdHint":"USD_Bank","identityProviderId":""}' -H "Content-Type: application/json" -X POST localhost:7575/v2/parties
curl -d '{"partyIdHint":"EUR_Bank","identityProviderId":""}' -H "Content-Type: application/json" -X POST localhost:7575/v2/parties

Має писати таке: {"partyDetails":{"party":"Alice::1220ed3dd5da9ea12bab4a659a3111edf4a7f41e8402d9d754edabf023d5247ea457","isLocal":true,"localMetadata":{"resourceVersion":"0","annotations":{}},"identityProviderId":""}}root@vm704:~/capstone#
І треба зберегти всі 4 ID - Alice::1220ed3dd5da9ea12bab4a659a3111edf4a7f41e8402d9d754edabf023d5247ea457 і всі інші.

По факту вони будуть однаковими, відрізняються тільки початком: Alice::, Bob:: і так далі. В завданні не сказано замоврачуватись з різними ідентифікаторами, тому вони будуть відрізнятись назвою.

Далі вони будуть називатись <ALICE_ID> <BOB_ID> <USD_BANK> <EUR_BANK>

Перевіряємо список:

daml ledger list-parties

Мають бути 5 записів - Аліса, Боб, бакси, євро і пісочниця

curl -X GET 'http://localhost:7575/v2/interactive-submission/preferred-package-version?package-name=quickstart&parties=Alice::ТУТ_СВІЙ_ID' | jq .

В результаті буде щось типу

{
"packagePreference": {
"packageReference": {
"packageId": "2fa7fec894ed2f78a52c03d35cd5bbd283dd2f415fd6bf40530c50a6445bbd7b",
"packageName": "quickstart",
"packageVersion": "0.0.1"
},
"synchronizerId": "mysynchronizer::122108371738aea79c5f458a3a04dfdbe94b363347ea9c9b7b4df7bf9ba7902295ca"
}
}

Потрібно записати свій packageId

Тепер створюємо багато файлів і заповнюємо їх своїми даними. Потім після кожного файлу пишемо команду і записуємо з результату свої дані:

Створюємо перший файл:

cat > issue_eur.json << 'EOF'
{
  "commands": {
    "commands": [
      {
        "CreateAndExerciseCommand": {
          "templateId": "СЮДИ_СВІЙ_packageId:Iou:Iou",
          "createArguments": {
            "issuer": "EUR_Bank::СЮДИ_СВІЙ_ID",
            "owner": "EUR_Bank::СЮДИ_СВІЙ_ID",
            "currency": "EUR",
            "amount": "100.0",
            "observers": []
          },
          "choice": "Iou_Transfer",
          "choiceArgument": {
            "newOwner": "Alice::СЮДИ_СВІЙ_ID"
          }
        }
      }
    ],
    "userId": "eur-bank-user",
    "commandId": "issue-eur-to-alice-1",
    "actAs": [
      "EUR_Bank::СЮДИ_СВІЙ_ID"
    ]
  }
}
EOF

Пишемо команду:

curl -X POST 'http://localhost:7575/v2/commands/submit-and-wait-for-transaction' \
  -H "Content-Type: application/json" \
  -d @issue_eur.json | jq .

Записуєте собі contractId (<ALICE_TRANSFER_CID>) і offset. Перше дуже довге, друге двозначне (43, наприклад).

Створюємо другий файл:

cat > issue_usd.json << 'EOF'
{
  "commands": {
    "commands": [
      {
        "CreateAndExerciseCommand": {
          "templateId": "СЮДИ_СВІЙ_packageId:Iou:Iou",
          "createArguments": {
            "issuer": "USD_Bank::СЮДИ_СВІЙ_ID",
            "owner": "USD_Bank::СЮДИ_СВІЙ_ID",
            "currency": "USD",
            "amount": "110.0",
            "observers": []
          },
          "choice": "Iou_Transfer",
          "choiceArgument": {
            "newOwner": "Bob::СЮДИ_СВІЙ_ID"
          }
        }
      }
    ],
    "userId": "usd-bank-user",
    "commandId": "issue-usd-to-bob-1",
    "actAs": [
      "USD_Bank::СЮДИ_СВІЙ_ID"
    ]
  }
}
EOF

Запускаємо:

curl -X POST 'http://localhost:7575/v2/commands/submit-and-wait-for-transaction' \
  -H "Content-Type: application/json" \
  -d @issue_usd.json | jq .

Знову копіюємо собі contractId (<BOB_TRANSFER_CID>) і offset

Створюємо третій файл:

cat > alice_trf.json << 'EOF'
{
  "commands": {
    "commands": [
      {
        "ExerciseCommand": {
          "templateId": "СЮДИ_СВІЙ_packageId:Iou:IouTransfer",
          "contractId": "<СЮДИ_ALICE_TRANSFER_CID>",
          "choice": "IouTransfer_Accept",
          "choiceArgument": {}
        }
      }
    ],
    "userId": "alice-user",
    "commandId": "alice-accept-eur-transfer",
    "actAs": [
      "Alice::СЮДИ_СВІЙ_ID"
    ]
  }
}
EOF
curl -X POST 'http://localhost:7575/v2/commands/submit-and-wait-for-transaction' \
  -H "Content-Type: application/json" \
  -d @alice_trf.json | jq .

Зберігаєте contractId (<ALICE_ACCEPT_EUR>) з блоку CreatedEvent

Створюємо четвертий файл:

cat > bob_trf.json << 'EOF'
{
  "commands": {
    "commands": [
      {
        "ExerciseCommand": {
          "templateId": "СЮДИ_СВІЙ_packageId:Iou:IouTransfer",
          "contractId": "СЮДИ_BOB_TRANSFER_CID",
          "choice": "IouTransfer_Accept",
          "choiceArgument": {}
        }
      }
    ],
    "userId": "bob-user",
    "commandId": "bob-accept-usd-transfer",
    "actAs": [
      "Bob::СЮДИ_СВІЙ_ID"
    ]
  }
}
EOF
curl -X POST 'http://localhost:7575/v2/commands/submit-and-wait-for-transaction' \
  -H "Content-Type: application/json" \
  -d @bob_trf.json | jq .

Зберігаєте contractId (<BOB_ACCEPT_USD>) з блоку CreatedEvent

Створюємо п'ятий файл:

{
  "commands": {
    "commands": [
      {
        "ExerciseCommand": {
          "templateId": "<PACKAGE_ID>:Iou:Iou",
          "contractId": "<ALICE_ACCEPT_EUR>",
          "choice": "Iou_AddObserver",
          "choiceArgument": {
            "newObserver": "<BOB_ID>"
          }
        }
      }
],
"userId": "alice-user",
    "commandId": "iou-disclosure-split-1",
    "actAs": [
      "<ALICE_ID>"
]
}
}
EOF
curl -X POST 'http://localhost:7575/v2/commands/submit-and-wait-for-transaction' \
  -H "Content-Type: application/json" \
  -d @add_observer.json | jq .

Зберігаєте contractId (<NEW_IOU>) з блоку CreatedEvent

Створюємо шостий файл:

{
  "commands": {
    "commands": [
            {
        "CreateCommand": {
          "templateId": "<PACKAGE_ID>:IouTrade:IouTrade",
          "createArguments": {
            "buyer": "<ALICE_ID>",
            "seller": "<BOB_ID>",
            "baseIouCid": "<NEW_IOU>",
            "baseIssuer": "<EUR_BANK>",
            "baseCurrency": "EUR",
            "baseAmount": "100.0",
            "quoteIssuer": "<USD_BANK>",
            "quoteCurrency": "USD",
            "quoteAmount": "110.0"
          }
        }
      }
    ],
    "userId": "alice-user",
    "commandId": "trade-proposal-1",
    "actAs": [
      "<ALICE_ID>"
    ]
  }
}
EOF
curl -X POST 'http://localhost:7575/v2/commands/submit-and-wait-for-transaction' \
  -H "Content-Type: application/json" \
  -d @propose_trade.json | jq .

Зберігаєте contractId (<TRADE_PROPOSAL_CID>) з блоку CreatedEvent

Створюємо сьомий файл:

{
 "commands": {
   "commands": [
     {
       "ExerciseCommand": {
         "templateId": "<PACKAGE_ID>:IouTrade:IouTrade",
         "contractId": "<TRADE_PROPOSAL_CID>",
         "choice": "IouTrade_Accept",
         "choiceArgument": {
           "quoteIouCid": "<BOB_ACCEPT_USD>"
         }
       }
     }
   ],
   "userId": "bob-user",
   "commandId": "trade-acceptance-1",
   "actAs": [
     "<BOB_ID>"
   ]
 }
}
EOF
curl -X POST 'http://localhost:7575/v2/commands/submit-and-wait-for-transaction' \
  -H "Content-Type: application/json" \
  -d @accept_trade.json | jq .

Те, що ви побачите після цієї команди, і є результатом роботи. Має бути щось типу такого, але з вашими даними:

Робите скрін всього екрану, щоб ці дані було видно, називаєте файл C52Q6_ваше_ім’я_в_проекті і скидаєте на перевірку

Якщо хочеш читати всі актуальні новини і гайди, підписуйся на мій канал:

https://t.me/CryptoTravelsWithDmytro

Якщо маєш запитання по відпрацюванні якогось проекту, приєднуйся до чату:

https://t.me/+O07RU8qeDoUwZGFi

Якщо маєш пропозиції по співпраці або будь які запитання особисто до мене, пиши:

https://t.me/aquada_vn

Дякую, що був зі мною до кінця статті!!!

Багато тобі щедрих дропів, гарного настрою і кайфового ворку!!!