diff --git a/00-preliminaries.ipynb b/00-preliminaries.ipynb index 509b2cb..5185250 100644 --- a/00-preliminaries.ipynb +++ b/00-preliminaries.ipynb @@ -335,11 +335,11 @@ "name": "stdout", "output_type": "stream", "text": [ - "block: 728210\n", + "block: 731649\n", "epoch: 57\n", "era: Babbage\n", - "hash: 7bdedcb169e17268b48669ac469b1901b702cab7014a5ef6c00011d7e7bcda2a\n", - "slot: 23218657\n", + "hash: ad9ed62386341677ada848804618b6198c1d4187a0bfbd008500d2ef9595943b\n", + "slot: 23307149\n", "syncProgress: '100.00'\n" ] } @@ -414,7 +414,7 @@ "output_type": "stream", "text": [ "HTTP/1.1 200 OK\n", - "\u001b[1mDate\u001b[0m: Wed, 15 Mar 2023 17:38:17 GMT\n", + "\u001b[1mDate\u001b[0m: Thu, 16 Mar 2023 18:12:51 GMT\n", "\u001b[1mServer\u001b[0m: Warp/3.3.24\n", "\u001b[1mContent-Type\u001b[0m: application/json;charset=utf-8\n", "\n" @@ -689,6 +689,87 @@ "echo \"BORROWER_ADDR = $BORROWER_ADDR\"" ] }, + { + "cell_type": "markdown", + "id": "a888e3e6-bdab-4763-8f7f-5c72c990ea90", + "metadata": {}, + "source": [ + "### The Mediator\n", + "\n", + "Set the file names for this party's signing key and verification key." + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "89967b6a-01a0-42a6-ba70-258f67a2ddba", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "MEDIATOR_SKEY=keys/mediator.skey\n", + "MEDIATOR_VKEY=keys/mediator.vkey" + ] + }, + { + "cell_type": "markdown", + "id": "40dd9cf7-5931-47a4-a6c3-6bfcc7031963", + "metadata": {}, + "source": [ + "Generate the keys if they haven't already been generated." + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "81238600-8ae9-43fd-881f-5bb1ab85688d", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "if [[ ! -e \"$MEDIATOR_SKEY\" ]]\n", + "then\n", + " cardano-cli address key-gen \\\n", + " --signing-key-file \"$MEDIATOR_SKEY\" \\\n", + " --verification-key-file \"$MEDIATOR_VKEY\"\n", + "fi" + ] + }, + { + "cell_type": "markdown", + "id": "8ddf1475-a5a1-4d63-a83d-311cb7391500", + "metadata": {}, + "source": [ + "Compute the party's address on the testnet." + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "16cd8dd9-153c-4abc-903e-a91e742044ca", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "MEDIATOR_ADDR = addr_test1vr6tytqs3x8qgewhw89m3xrz58t3tqu2hfsecw0u06lf3hg052wsv\n" + ] + } + ], + "source": [ + "MEDIATOR_ADDR=$(cardano-cli address build --testnet-magic \"$CARDANO_TESTNET_MAGIC\" --payment-verification-key-file \"$MEDIATOR_VKEY\" )\n", + "if [[ ! -e keys/mediator.address ]]\n", + "then\n", + " echo \"$MEDIATOR_ADDR\" > keys/mediator.address\n", + "fi\n", + "echo \"MEDIATOR_ADDR = $MEDIATOR_ADDR\"" + ] + }, { "cell_type": "markdown", "id": "74ea3de1-6c14-4ef6-a5ab-e8784cc879cc", @@ -705,7 +786,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 21, "id": "73e739b1-9d2f-4f36-b1ce-24e9e6c88f4b", "metadata": { "tags": [] @@ -735,7 +816,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 22, "id": "7c2069be-6817-4193-90bf-fd2a5fb26de7", "metadata": { "tags": [] @@ -746,13 +827,15 @@ "output_type": "stream", "text": [ "LENDER_ADDR = addr_test1vqd3yrtjyx49uld43lvwqaf7z4k03su8gf2x4yr7syzvckgfzm4ck\n", - "BORROWER_ADDR = addr_test1vpy4n4peh4suv0y55yptur0066j5kds8r4ncnuzm0vpzfgg0dhz6d\n" + "BORROWER_ADDR = addr_test1vpy4n4peh4suv0y55yptur0066j5kds8r4ncnuzm0vpzfgg0dhz6d\n", + "MEDIATOR_ADDR = addr_test1vr6tytqs3x8qgewhw89m3xrz58t3tqu2hfsecw0u06lf3hg052wsv\n" ] } ], "source": [ "echo \"LENDER_ADDR = $LENDER_ADDR\"\n", - "echo \"BORROWER_ADDR = $BORROWER_ADDR\"" + "echo \"BORROWER_ADDR = $BORROWER_ADDR\"\n", + "echo \"MEDIATOR_ADDR = $MEDIATOR_ADDR\"" ] }, { @@ -779,7 +862,7 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 23, "id": "5bcf4056-963b-41e1-b963-6af2c09498b5", "metadata": { "tags": [] @@ -789,7 +872,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "TxId \"78690d72c67960d4600889d7dd7da2069f14658ed6791c8838dccdd33fe3971f\"\n" + "TxId \"dd3a06e118f9ccfdc6d8721779228d1730a606cf183489e679f2584b4445d883\"\n" ] } ], @@ -808,7 +891,7 @@ " --out-file /dev/null \\\n", " --source-wallet-credentials \"$FAUCET_ADDR:$FAUCET_SKEY\" \\\n", " --submit 600 \\\n", - " \"$LENDER_ADDR\" \"$BORROWER_ADDR\"" + " \"$LENDER_ADDR\" \"$BORROWER_ADDR\" \"$MEDIATOR_ADDR\"" ] }, { @@ -821,7 +904,7 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": 24, "id": "d4f822da-45bf-4222-95fa-5ce6a912869b", "metadata": { "tags": [] @@ -835,13 +918,19 @@ "Lender @ addr_test1vqd3yrtjyx49uld43lvwqaf7z4k03su8gf2x4yr7syzvckgfzm4ck\n", " TxHash TxIx Amount\n", "--------------------------------------------------------------------------------------\n", - "78690d72c67960d4600889d7dd7da2069f14658ed6791c8838dccdd33fe3971f 1 1000000000 lovelace + TxOutDatumNone\n", + "dd3a06e118f9ccfdc6d8721779228d1730a606cf183489e679f2584b4445d883 1 1000000000 lovelace + TxOutDatumNone\n", "\n", "\n", "Borrower @ addr_test1vpy4n4peh4suv0y55yptur0066j5kds8r4ncnuzm0vpzfgg0dhz6d\n", " TxHash TxIx Amount\n", "--------------------------------------------------------------------------------------\n", - "78690d72c67960d4600889d7dd7da2069f14658ed6791c8838dccdd33fe3971f 2 1000000000 lovelace + TxOutDatumNone\n", + "dd3a06e118f9ccfdc6d8721779228d1730a606cf183489e679f2584b4445d883 2 1000000000 lovelace + TxOutDatumNone\n", + "\n", + "\n", + "Borrower @ addr_test1vr6tytqs3x8qgewhw89m3xrz58t3tqu2hfsecw0u06lf3hg052wsv\n", + " TxHash TxIx Amount\n", + "--------------------------------------------------------------------------------------\n", + "dd3a06e118f9ccfdc6d8721779228d1730a606cf183489e679f2584b4445d883 3 1000000000 lovelace + TxOutDatumNone\n", "\n" ] } @@ -855,6 +944,10 @@ "echo\n", "echo \"Borrower @ $BORROWER_ADDR\"\n", "cardano-cli query utxo --testnet-magic \"$CARDANO_TESTNET_MAGIC\" --address \"$BORROWER_ADDR\"\n", + "echo\n", + "echo\n", + "echo \"Borrower @ $MEDIATOR_ADDR\"\n", + "cardano-cli query utxo --testnet-magic \"$CARDANO_TESTNET_MAGIC\" --address \"$MEDIATOR_ADDR\"\n", "echo" ] } diff --git a/01-runtime-cli/ReadMe.ipynb b/01-runtime-cli/ReadMe.ipynb index 4d12180..6b9a1b1 100644 --- a/01-runtime-cli/ReadMe.ipynb +++ b/01-runtime-cli/ReadMe.ipynb @@ -79,11 +79,11 @@ "\n", "It also assumes that the Lender and Borrower parties have addresses, signing keys, and funds.\n", "- Lender\n", - " - `LENDER_ADDR`: Cardano address for the lender\n", - " - `LENDER_SKEY`: location of signing key file for the lender\n", + " - [../keys/lender.address](../keys/lender.address): Cardano address for the lender\n", + " - [../keys/lender.skey](../keys/lender.skey): location of signing key file for the lender\n", "- Borrower\n", - " - `BORROWER_ADDR`: Cardano address for the borrower\n", - " - `BORROWER_SKEY`: locatio nof signing key file for the borrower" + " - [../keys/borrower.address](../keys/borrower.address): Cardano address for the borrower\n", + " - [../keys/borrower.skey](../keys/borrower.skey): location of signing key file for the borrower" ] }, { diff --git a/02-runtime-rest/ReadMe.ipynb b/02-runtime-rest/ReadMe.ipynb index e9bc565..4d45b6b 100644 --- a/02-runtime-rest/ReadMe.ipynb +++ b/02-runtime-rest/ReadMe.ipynb @@ -6,6 +6,7 @@ "metadata": {}, "source": [ "# Zero-Coupon Bond Using Marlowe Runtime\\'s REST API\n", + "\n", "The zero-coupon bond example is a simple Marlowe contract where a lender provides principal to a borrower who repays it back with interest.\n", "\n", "In this demonsration we use Marlowe Runtime\\'s REST API, served via `marlowe-web-server`, to run this contract on Cardano\\'s `preprod` public testnet. Marlowe contracts may use either addresses or role tokens for authorization: here we use role tokens and we have Marlowe Runtime mint them.\n", @@ -76,11 +77,11 @@ "\n", "It also assumes that the Lender and Borrower parties have addresses, signing keys, and funds.\n", "- Lender\n", - " - `LENDER_ADDR`: Cardano address for the lender\n", - " - `LENDER_SKEY`: location of signing key file for the lender\n", + " - [../keys/lender.address](../keys/lender.address): Cardano address for the lender\n", + " - [../keys/lender.skey](../keys/lender.skey): location of signing key file for the lender\n", "- Borrower\n", - " - `BORROWER_ADDR`: Cardano address for the borrower\n", - " - `BORROWER_SKEY`: locatio nof signing key file for the borrower" + " - [../keys/borrower.address](../keys/borrower.address): Cardano address for the borrower\n", + " - [../keys/borrower.skey](../keys/borrower.skey): location of signing key file for the borrower" ] }, { @@ -370,7 +371,7 @@ } ], "source": [ - "ADA=1000000 # 1 ada = 1,000,000 lovelace\n", + "ADA=1000000 # 1 ada = 1,000,000 lovelace\n", "PRINCIPAL=$((80 * ADA))\n", "INTEREST=$((5 * ADA))\n", "echo \"PRINCIPAL = $PRINCIPAL lovelace\"\n", @@ -438,7 +439,6 @@ "1. Visit https://play.marlowe-finance.io/ in a web browser.\n", "2. Select \"Open an Example\".\n", "3. Select \"Marlowe\" or \"Blockly\" under \"Zero Coupon Bond\".\n", - "4. Edit the contract set set\n", "4. Select \"Send to Simulator\".\n", "5. Set the \"Loan Deadline\" to one hour into the future.\n", "6. Set the \"Payback Deadline\" to three hours into the future.\n", @@ -673,7 +673,7 @@ "\n", "Here are the steps for checking the safety of a contract:\n", "\n", - "1. Understand the [Marlowe Language](https://marlowe-finance.io/)\n", + "1. Understand the [Marlowe Language](https://marlowe-finance.io/).\n", "2. Understand Cardano\\'s [Extended UTxO Model](https://docs.cardano.org/learn/eutxo-explainer).\n", "3. Read and understand the [Marlowe Best Practices Guide](https://github.com/input-output-hk/marlowe-cardano/blob/main/marlowe/best-practices.md).\n", "4. Read and understand the [Marlowe Security Guide](https://github.com/input-output-hk/marlowe-cardano/blob/main/marlowe/security.md).\n", @@ -1536,7 +1536,7 @@ "source": [ "## Transaction 3. The borrower withdraws the principal\n", "\n", - "The principal of 80 ada is help at Marlowe's role-payout address for the benefit of the borrower. The borrower can withdraw these funds at any time. The contract ID and role name are included in the request body for a withdrawal." + "The principal of 80 ada is held at Marlowe's role-payout address for the benefit of the borrower. The borrower can withdraw these funds at any time. The contract ID and role name are included in the request body for a withdrawal." ] }, { diff --git a/03-marlowe-cli/ReadMe.ipynb b/03-marlowe-cli/ReadMe.ipynb index a57bf73..cfa5127 100644 --- a/03-marlowe-cli/ReadMe.ipynb +++ b/03-marlowe-cli/ReadMe.ipynb @@ -77,11 +77,11 @@ "\n", "It also assumes that the Lender and Borrower parties have addresses, signing keys, and funds.\n", "- Lender\n", - " - `LENDER_ADDR`: Cardano address for the lender\n", - " - `LENDER_SKEY`: location of signing key file for the lender\n", + " - [../keys/lender.address](../keys/lender.address): Cardano address for the lender\n", + " - [../keys/lender.skey](../keys/lender.skey): location of signing key file for the lender\n", "- Borrower\n", - " - `BORROWER_ADDR`: Cardano address for the borrower\n", - " - `BORROWER_SKEY`: locatio nof signing key file for the borrower" + " - [../keys/borrower.address](../keys/borrower.address): Cardano address for the borrower\n", + " - [../keys/borrower.skey](../keys/borrower.skey): location of signing key file for the borrower" ] }, { @@ -621,7 +621,7 @@ "\n", "Here are the steps for checking the safety of a contract:\n", "\n", - "1. Understand the [Marlowe Language](https://marlowe-finance.io/)\n", + "1. Understand the [Marlowe Language](https://marlowe-finance.io/).\n", "2. Understand Cardano\\'s [Extended UTxO Model](https://docs.cardano.org/learn/eutxo-explainer).\n", "3. Read and understand the [Marlowe Best Practices Guide](https://github.com/input-output-hk/marlowe-cardano/blob/main/marlowe/best-practices.md).\n", "4. Read and understand the [Marlowe Security Guide](https://github.com/input-output-hk/marlowe-cardano/blob/main/marlowe/security.md).\n", diff --git a/04-escrow-rest/ReadMe.ipynb b/04-escrow-rest/ReadMe.ipynb new file mode 100644 index 0000000..66e55a3 --- /dev/null +++ b/04-escrow-rest/ReadMe.ipynb @@ -0,0 +1,3064 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "a8b9d3ec-9b61-4c11-8465-504673116f9d", + "metadata": {}, + "source": [ + "# Escrow Using Marlowe Runtime\\'s REST API\n", + "\n", + "The escrow contract example is a simple Marlowe contract where a seller offers merchandise for sale and a buyer purchases it; if the buyer is not satisfied with the merchandise, they may dispute the purchase, in which case a mediator may rule for the buyer or seller.\n", + "\n", + "In this demonsration we use Marlowe Runtime\\'s REST API, served via `marlowe-web-server`, to run this contract on Cardano\\'s `preprod` public testnet. Marlowe contracts may use either addresses or role tokens for authorization: here we use role tokens and we have Marlowe Runtime mint them.\n", + "\n", + "In [Marlowe Playground](https://play.marlowe-finance.io/), the contract looks like this in Blockly format.\n", + "\n", + "![Marlowe contract for escrow](../images/escrow-playground.png)\n", + "\n", + "In Marlowe format it appears as\n", + "```\n", + "When [\n", + " (Case\n", + " (Deposit Role \"Seller\" Role \"Buyer\"\n", + " (Token \"\" \"\")\n", + " (ConstantParam \"Price\"))\n", + " (When [\n", + " (Case\n", + " (Choice\n", + " (ChoiceId \"Everything is alright\" Role \"Buyer\") [\n", + " (Bound 0 0)]) Close)\n", + " ,\n", + " (Case\n", + " (Choice\n", + " (ChoiceId \"Report problem\" Role \"Buyer\") [\n", + " (Bound 1 1)])\n", + " (Pay Role \"Seller\"\n", + " (Account Role \"Buyer\")\n", + " (Token \"\" \"\")\n", + " (ConstantParam \"Price\")\n", + " (When [\n", + " (Case\n", + " (Choice\n", + " (ChoiceId \"Confirm problem\" Role \"Seller\") [\n", + " (Bound 1 1)]) Close)\n", + " ,\n", + " (Case\n", + " (Choice\n", + " (ChoiceId \"Dispute problem\" Role \"Seller\") [\n", + " (Bound 0 0)])\n", + " (When [\n", + " (Case\n", + " (Choice\n", + " (ChoiceId \"Dismiss claim\" Role \"Mediator\") [\n", + " (Bound 0 0)])\n", + " (Pay Role \"Buyer\"\n", + " (Party Role \"Seller\")\n", + " (Token \"\" \"\")\n", + " (ConstantParam \"Price\") Close))\n", + " ,\n", + " (Case\n", + " (Choice\n", + " (ChoiceId \"Confirm problem\" Role \"Mediator\") [\n", + " (Bound 1 1)]) Close)]\n", + " (TimeParam \"Mediation deadline\") Close))] \n", + " (TimeParam \"Complaint response deadline\") Close)))] \n", + " (TimeParam \"Complaint deadline\") Close))] \n", + " (TimeParam \"Payment deadline\") Close\n", + "```\n", + "\n", + "The flow chart below shows the possible execution paths of the escrow contract. This example demonstrates the shaded path.\n", + "\n", + "![Flow chart for escrow contract, with the \"dismiss claim\" execution path highlighted](dismiss-claim.svg)" + ] + }, + { + "cell_type": "markdown", + "id": "f128e27a-afe6-4d03-8c46-ef6e5753e4a8", + "metadata": {}, + "source": [ + "## Prelminaries\n", + "\n", + "See [Lesson 0. Preliminaries](../00-preliminaries.ipynb) for information on setting up one's environment for using this tutorial.\n", + "\n", + "The lesson assumes that the following environment variables have been set.\n", + "- `CARDANO_NODE_SOCKET_PATH`: location of Cardano node's socket.\n", + "- `CARDANO_TESTNET_MAGIC`: testnet magic number.\n", + "- `CARDANO_RT_WEBSERVER_HOST`: IP address of the Marlowe Runtime web server.\n", + "- `CARDANO_RT_WEBSERVER_PORT`: Port number for the Marlowe Runtime web server.\n", + "\n", + "It also assumes that the Lender and Borrower parties have addresses, signing keys, and funds.\n", + "- Seller\n", + " - [../keys/lender.address](../keys/lender.address): Cardano address for the seller\n", + " - [../keys/lender.skey](../keys/lender.skey): location of signing key file for the seller\n", + "- Buyer\n", + " - [../keys/borrower.address](../keys/borrower.address): Cardano address for the buyer\n", + " - [../keys/borrower.skey](../keys/borrower.skey): location of signing key file for the buyer\n", + "- Mediator\n", + " - [../keys/mediator.address](../keys/mediator.address): Cardano address for the mediator\n", + " - [../keys/mediator.skey](../keys/mediator.skey): location of signing key file for the mediator" + ] + }, + { + "cell_type": "markdown", + "id": "053cac6c-9bfc-4c47-ba48-c5cc145734d7", + "metadata": {}, + "source": [ + "### Access to Cardano node and Marlowe Runtime\n", + "\n", + "***One can skip this section if one is using [demeter.run](https://demeter.run/)'s Cardano Marlowe Runtime extension.***\n", + "\n", + "If we're using [demeter.run](https://demeter.run/)'s Cardano Marlowe Runtime extension, then we already have access to Cardano Node and Marlowe Runtime. If not, set the required environment variables to use a local docker deployment on the default ports." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "e1859d35-ded3-4e16-be43-b1ef030d7f16", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CARDANO_NODE_SOCKET_PATH = /home/bbush/.local/share/containers/storage/volumes/marlowe-compose_shared/_data/node.socket\n", + "CARDANO_TESTNET_MAGIC = 1\n", + "MARLOWE_RT_WEBSERVER_HOST = 127.0.0.1\n", + "MARLOWE_RT_WEBSERVER_PORT = 3780\n", + "MARLOWE_RT_WEBSERVER_URL = http://127.0.0.1:3780\n" + ] + } + ], + "source": [ + "if [[ -z \"$MARLOWE_RT_WEBSERVER_PORT\" ]]\n", + "then\n", + "\n", + " if command -v podman > /dev/null\n", + " then\n", + " DOCKER_CLI=podman\n", + " else\n", + " DOCKER_CLI=docker\n", + " fi\n", + " \n", + " # Only required for `marlowe-cli` and `cardano-cli`.\n", + " export CARDANO_NODE_SOCKET_PATH=\"$($DOCKER_CLI volume inspect marlowe-compose_shared | jq -r '.[0].Mountpoint')/node.socket\"\n", + " export CARDANO_TESTNET_MAGIC=1 # Note that preprod=1 and preview=2. Do not set this variable if using mainnet.\n", + "\n", + " # Only required for `marlowe`.\n", + " export MARLOWE_RT_WEBSERVER_HOST=\"127.0.0.1\"\n", + " export MARLOWE_RT_WEBSERVER_PORT=3780\n", + "\n", + "fi\n", + "\n", + "case \"$CARDANO_TESTNET_MAGIC\" in\n", + " 1)\n", + " export \"EXPLORER_URL=https://preprod.cardanoscan.io\"\n", + " ;;\n", + " 2)\n", + " export \"EXPLORER_URL=https://preview.cardanoscan.io\"\n", + " ;;\n", + " *)\n", + " # Use `mainnet` as the default.\n", + " export \"EXPLORER_URL=https://cardanoscan.io\"\n", + " ;;\n", + "esac\n", + "\n", + "MARLOWE_RT_WEBSERVER_URL=\"http://$MARLOWE_RT_WEBSERVER_HOST:$MARLOWE_RT_WEBSERVER_PORT\"\n", + "\n", + "echo \"CARDANO_NODE_SOCKET_PATH = $CARDANO_NODE_SOCKET_PATH\"\n", + "echo \"CARDANO_TESTNET_MAGIC = $CARDANO_TESTNET_MAGIC\"\n", + "echo \"MARLOWE_RT_WEBSERVER_HOST = $MARLOWE_RT_WEBSERVER_HOST\"\n", + "echo \"MARLOWE_RT_WEBSERVER_PORT = $MARLOWE_RT_WEBSERVER_PORT\"\n", + "echo \"MARLOWE_RT_WEBSERVER_URL = $MARLOWE_RT_WEBSERVER_URL\"" + ] + }, + { + "cell_type": "markdown", + "id": "1f209e22-2e7c-444c-a72b-aa88d676e0f8", + "metadata": { + "tags": [] + }, + "source": [ + "### Seller address and funds\n", + "\n", + "Check that an address and key has been created for the seller. If not, see \"Creating Addresses and Signing Keys\" in [Lesson 0. Preliminaries](../00-preliminaries.ipynb)." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "38d0bad1-3b9e-4d80-9aec-a4357c8dc79a", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "SELLER_ADDR = addr_test1vqd3yrtjyx49uld43lvwqaf7z4k03su8gf2x4yr7syzvckgfzm4ck\n" + ] + } + ], + "source": [ + "SELLER_SKEY=../keys/lender.skey\n", + "SELLER_ADDR=$(cat ../keys/lender.address)\n", + "echo \"SELLER_ADDR = $SELLER_ADDR\"" + ] + }, + { + "cell_type": "markdown", + "id": "112cbd18-2567-4563-a452-e4a5c529a171", + "metadata": {}, + "source": [ + "Check that the seller has at least one hundred ada." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "a16fd543-cabf-4540-879c-ed0594ca5ff1", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " TxHash TxIx Amount\n", + "--------------------------------------------------------------------------------------\n", + "b32eab58a670cc0164c9c2c615c81b40dc9229ab8d899db8f232bbede0984107 2 1000000000 lovelace + TxOutDatumNone\n" + ] + } + ], + "source": [ + "cardano-cli query utxo --testnet-magic \"$CARDANO_TESTNET_MAGIC\" --address \"$SELLER_ADDR\"" + ] + }, + { + "cell_type": "markdown", + "id": "d23a2695-2d68-4fa3-80cb-3afe5afe2196", + "metadata": {}, + "source": [ + "One can view the address on a Cardano explorer. It sometimes takes thirty seconds or so for the transaction to be visible in an explorer." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "b1d78493-a1a1-4739-b911-02b901c73bda", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "https://preprod.cardanoscan.io/address/addr_test1vqd3yrtjyx49uld43lvwqaf7z4k03su8gf2x4yr7syzvckgfzm4ck\n" + ] + } + ], + "source": [ + "echo \"$EXPLORER_URL/address/$SELLER_ADDR\"" + ] + }, + { + "cell_type": "markdown", + "id": "754f546b-b42d-434c-ad78-b4e1fada39b9", + "metadata": { + "tags": [] + }, + "source": [ + "### Buyer address and funds\n", + "\n", + "Check that an address and key has been created for the buyer. If not, see \"Creating Addresses and Signing Keys\" in [Lesson 0. Preliminaries](../00-preliminaries.ipynb)." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "5103b793-05a7-4a9c-bb5b-ed250bcbcc1e", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "BUYER_ADDR = addr_test1vpy4n4peh4suv0y55yptur0066j5kds8r4ncnuzm0vpzfgg0dhz6d\n" + ] + } + ], + "source": [ + "BUYER_SKEY=../keys/borrower.skey\n", + "BUYER_ADDR=$(cat ../keys/borrower.address)\n", + "echo \"BUYER_ADDR = $BUYER_ADDR\"" + ] + }, + { + "cell_type": "markdown", + "id": "41a004a6-8681-4ce1-b07e-6d6d07ee1b38", + "metadata": {}, + "source": [ + "Check that the buyer has at least one hundred ada." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "3af7a962-3038-4b55-a31a-cd7ade94b5ec", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " TxHash TxIx Amount\n", + "--------------------------------------------------------------------------------------\n", + "b32eab58a670cc0164c9c2c615c81b40dc9229ab8d899db8f232bbede0984107 3 1000000000 lovelace + TxOutDatumNone\n" + ] + } + ], + "source": [ + "cardano-cli query utxo --testnet-magic \"$CARDANO_TESTNET_MAGIC\" --address \"$BUYER_ADDR\"" + ] + }, + { + "cell_type": "markdown", + "id": "0bf7ec49-14c5-4f3a-9eb7-c97cd38fcfcf", + "metadata": {}, + "source": [ + "One can view the address on a Cardano explorer. It sometimes takes thirty seconds or so for the transaction to be visible in an explorer." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "3455b47d-45f9-4d31-aebe-ab0ea7b36aa9", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "https://preprod.cardanoscan.io/address/\n" + ] + } + ], + "source": [ + "echo \"$EXPLORER_URL/address/$BORROWER_ADDR\"" + ] + }, + { + "cell_type": "markdown", + "id": "e9e994d8-95b4-4175-a26e-1d1da2fe103a", + "metadata": { + "tags": [] + }, + "source": [ + "### Mediator address and funds\n", + "\n", + "Check that an address and key has been created for the mediator. If not, see \"Creating Addresses and Signing Keys\" in [Lesson 0. Preliminaries](../00-preliminaries.ipynb)." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "4f9e1680-77da-43f9-9495-14d8a8a9929b", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "MEDIATOR_ADDR = addr_test1vr6tytqs3x8qgewhw89m3xrz58t3tqu2hfsecw0u06lf3hg052wsv\n" + ] + } + ], + "source": [ + "MEDIATOR_SKEY=../keys/mediator.skey\n", + "MEDIATOR_ADDR=$(cat ../keys/mediator.address)\n", + "echo \"MEDIATOR_ADDR = $MEDIATOR_ADDR\"" + ] + }, + { + "cell_type": "markdown", + "id": "7ee5fc4d-f900-4d22-b0a4-bb2cc56fe025", + "metadata": {}, + "source": [ + "Check that the mediator has at least one hundred ada." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "ca1d52a9-8499-4ccc-ab2a-ff9aed202944", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " TxHash TxIx Amount\n", + "--------------------------------------------------------------------------------------\n", + "b32eab58a670cc0164c9c2c615c81b40dc9229ab8d899db8f232bbede0984107 4 1000000000 lovelace + TxOutDatumNone\n" + ] + } + ], + "source": [ + "cardano-cli query utxo --testnet-magic \"$CARDANO_TESTNET_MAGIC\" --address \"$MEDIATOR_ADDR\"" + ] + }, + { + "cell_type": "markdown", + "id": "0650ca57-f643-4111-9741-e7c893f45bf4", + "metadata": {}, + "source": [ + "One can view the address on a Cardano explorer. It sometimes takes thirty seconds or so for the transaction to be visible in an explorer." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "d9d17190-eed0-456f-8aa0-6f0a2b4d83dc", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "https://preprod.cardanoscan.io/address/addr_test1vr6tytqs3x8qgewhw89m3xrz58t3tqu2hfsecw0u06lf3hg052wsv\n" + ] + } + ], + "source": [ + "echo \"$EXPLORER_URL/address/$MEDIATOR_ADDR\"" + ] + }, + { + "cell_type": "markdown", + "id": "00396fbb-ce2d-4666-9bac-85a8ccd7945b", + "metadata": {}, + "source": [ + "## Design the contract\n", + "\n", + "The escrow contract can be downloaded from the [Marlowe Playground](https://play.marlowe-finance.io/) as a JSON file, or it can be generated using [Marlowe CLI](https://github.com/input-output-hk/marlowe-cardano/tree/main/marlowe-cli#readme) using the `marlowe-cli template` command.\n", + "\n", + "Set the purchase prices to 75 ada." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "8d28fcbc-c73f-4c27-8d68-069d8ebe98ce", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "PRICE = 75000000 lovelace\n" + ] + } + ], + "source": [ + "ADA=1000000 # 1 ada = 1,000,000 lovelace\n", + "PRICE=$((75 * ADA))\n", + "echo \"PRICE = $PRICE lovelace\"" + ] + }, + { + "cell_type": "markdown", + "id": "5a11195d-000f-44e4-a217-50e5d7de01ed", + "metadata": {}, + "source": [ + "On the Cardano blockchain, the protocol parameters require that each UTxO contain at least some ada. Here we will start the contract with 2 ada." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "8f699238-b0a0-4626-b04f-e93d93b0f458", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "MIN_LOVELACE = 2000000 lovelace\n" + ] + } + ], + "source": [ + "MIN_LOVELACE=\"$((2 * ADA))\"\n", + "echo \"MIN_LOVELACE = $MIN_LOVELACE lovelace\"" + ] + }, + { + "cell_type": "markdown", + "id": "0b4c28e3-3f4b-4fa8-8dd4-aa7b51921132", + "metadata": {}, + "source": [ + "Later in the example we will need some constants for converting times." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "d06a9229-9e53-4a00-accf-ae06b115ff39", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "SECOND=1000 # 1 second = 1000 milliseconds\n", + "MINUTE=$((60 * SECOND)) # 1 minute = 60 seconds\n", + "HOUR=$((60 * MINUTE)) # 1 hour = 60 minutes" + ] + }, + { + "cell_type": "markdown", + "id": "94d3ddb1-35e9-49ff-9062-1854febca9b7", + "metadata": {}, + "source": [ + "### *Alternative 1:* Use Marlowe Playground to design the contract\n", + "\n", + "If you want to create the contract in Marlowe Playground, do the following:\n", + "\n", + "1. Visit https://play.marlowe-finance.io/ in a web browser.\n", + "2. Select \"Open an Example\".\n", + "3. Select \"Marlowe\" or \"Blockly\" under \"Escrow\".\n", + "4. Select \"Send to Simulator\".\n", + "5. Set the \"Payment deadline\" to one hour into the future.\n", + "6. Set the \"Complaint deadline\" to two hours into the future\n", + "7. Set the \"Complaint response deadline\" to three hours into the future.\n", + "8. Set the \"Mediation deadline\" to four hours into the future.\n", + "9. Set the \"Price\" to 75 ada.\n", + "10. Select \"Download as JSON\", set the file name to \"escrow-contract.json\", and store the file in this folder, namely [marlowe-starter-kit/04-escrow-rest/](.).\n", + "\n", + "![Setting parameters for the escrow bond contract in Marlowe Playground](../images/escrow-simulation.png)" + ] + }, + { + "cell_type": "markdown", + "id": "0073090c-205c-4037-814c-b3053bbc81d6", + "metadata": {}, + "source": [ + "### *Alternative 2:* Use Marlowe CLI to generate the contract\n", + "\n", + "Below we generate the contract using Marlowe CLI.\n", + "\n", + "First find the current time, measured in [POSIX milliseconds](https://en.wikipedia.org/wiki/Unix_time)." + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "327df025-16bf-4f69-acfc-02e3ce56e795", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "NOW = 1679000784000 POSIX milliseconds = Thu Mar 16 03:06:24 PM MDT 2023\n" + ] + } + ], + "source": [ + "NOW=\"$(($(date -u +%s) * SECOND))\"\n", + "echo \"NOW = $NOW POSIX milliseconds = $(date -d @$((NOW / SECOND)))\"" + ] + }, + { + "cell_type": "markdown", + "id": "d3686e55-0139-4e49-a4cc-8d7e5ef4491a", + "metadata": {}, + "source": [ + "The contract has four deadlines. For convenience in this example, set the deadlines to the near future." + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "f1797871-350b-400b-b12f-5bc877efca94", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "PAYMENT_DEADLINE = 1679004384000 POSIX milliseconds = Thu Mar 16 04:06:24 PM MDT 2023\n", + "COMPLAINT_DEADLINE = 1679007984000 POSIX milliseconds = Thu Mar 16 05:06:24 PM MDT 2023\n", + "DISPUTE_DEADLINE = 1679011584000 POSIX milliseconds = Thu Mar 16 06:06:24 PM MDT 2023\n", + "MEDIATION_DEADLINE = 1679015184000 POSIX milliseconds = Thu Mar 16 07:06:24 PM MDT 2023\n" + ] + } + ], + "source": [ + "PAYMENT_DEADLINE=$((NOW+1*HOUR)) # The payment deadline, one hour from now.\n", + "COMPLAINT_DEADLINE=$((NOW+2*HOUR)) # The complaint deadline, two hours from now.\n", + "DISPUTE_DEADLINE=$((NOW+3*HOUR)) # The dispute deadline, three hours from now.\n", + "MEDIATION_DEADLINE=$((NOW+4*HOUR)) # The mediation deadline, four hours from now.\n", + "\n", + "echo \"PAYMENT_DEADLINE = $PAYMENT_DEADLINE POSIX milliseconds = $(date -d @$((PAYMENT_DEADLINE / SECOND)))\"\n", + "echo \"COMPLAINT_DEADLINE = $COMPLAINT_DEADLINE POSIX milliseconds = $(date -d @$((COMPLAINT_DEADLINE / SECOND)))\"\n", + "echo \"DISPUTE_DEADLINE = $DISPUTE_DEADLINE POSIX milliseconds = $(date -d @$((DISPUTE_DEADLINE / SECOND)))\"\n", + "echo \"MEDIATION_DEADLINE = $MEDIATION_DEADLINE POSIX milliseconds = $(date -d @$((MEDIATION_DEADLINE / SECOND)))\"" + ] + }, + { + "cell_type": "markdown", + "id": "67bb8476-28d1-4bea-9a4e-d979a3b753c0", + "metadata": {}, + "source": [ + "Now create the JSON file for the contract, `zcb-contract.json`." + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "efec81d2-4cd2-4b72-8fab-82a6e60741c7", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "marlowe-cli template escrow \\\n", + " --minimum-ada \"$MIN_LOVELACE\" \\\n", + " --price \"$PRICE\" \\\n", + " --seller Seller \\\n", + " --buyer Buyer \\\n", + " --mediator Mediator \\\n", + " --payment-deadline \"$PAYMENT_DEADLINE\" \\\n", + " --complaint-deadline \"$COMPLAINT_DEADLINE\" \\\n", + " --dispute-deadline \"$DISPUTE_DEADLINE\" \\\n", + " --mediation-deadline \"$MEDIATION_DEADLINE\" \\\n", + " --out-contract-file escrow-contract.json \\\n", + " --out-state-file /dev/null" + ] + }, + { + "cell_type": "markdown", + "id": "ec5de5c3-848a-417c-aebd-276f10bbce8d", + "metadata": {}, + "source": [ + "The various command-line options are described by the help system." + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "4b7754a1-3e13-4d54-81a3-9b98be4c87c9", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Usage: marlowe-cli template escrow --minimum-ada INTEGER --price INTEGER\n", + " --seller PARTY --buyer PARTY --mediator PARTY\n", + " --payment-deadline TIMEOUT\n", + " --complaint-deadline TIMEOUT\n", + " --dispute-deadline TIMEOUT\n", + " --mediation-deadline TIMEOUT\n", + "\n", + " Create an escrow contract.\n", + "\n", + "Available options:\n", + " --minimum-ada INTEGER Lovelace in the initial state.\n", + " --price INTEGER The price of the sale, in lovelace.\n", + " --seller PARTY The seller.\n", + " --buyer PARTY The buyer.\n", + " --mediator PARTY The mediator.\n", + " --payment-deadline TIMEOUT\n", + " The deadline for the buyer to pay. POSIX milliseconds\n", + " or duration: `INTEGER[s|m|d|w|h]`.\n", + " --complaint-deadline TIMEOUT\n", + " The deadline for the buyer to complain. POSIX\n", + " milliseconds or duration: `INTEGER[s|m|d|w|h]`.\n", + " --dispute-deadline TIMEOUT\n", + " The deadline for the seller to dispute a complaint.\n", + " POSIX milliseconds or duration: `INTEGER[s|m|d|w|h]`.\n", + " --mediation-deadline TIMEOUT\n", + " The deadline for the mediator to decide. POSIX\n", + " milliseconds or duration: `INTEGER[s|m|d|w|h]`.\n", + " -h,--help Show this help text\n" + ] + } + ], + "source": [ + "marlowe-cli template escrow --help" + ] + }, + { + "cell_type": "markdown", + "id": "b158c36f-c316-4a08-8db5-8464645f2466", + "metadata": {}, + "source": [ + "## Examine the contract\n", + "\n", + "View the contract file as YAML." + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "58855a22-decd-4730-bac7-800d0f766034", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "timeout: 1679004384000\n", + "timeout_continuation: close\n", + "when:\n", + "- case:\n", + " deposits: 75000000\n", + " into_account:\n", + " role_token: Seller\n", + " of_token:\n", + " currency_symbol: ''\n", + " token_name: ''\n", + " party:\n", + " role_token: Buyer\n", + " then:\n", + " timeout: 1679007984000\n", + " timeout_continuation: close\n", + " when:\n", + " - case:\n", + " choose_between:\n", + " - from: 0\n", + " to: 0\n", + " for_choice:\n", + " choice_name: Everything is alright\n", + " choice_owner:\n", + " role_token: Buyer\n", + " then: close\n", + " - case:\n", + " choose_between:\n", + " - from: 1\n", + " to: 1\n", + " for_choice:\n", + " choice_name: Report problem\n", + " choice_owner:\n", + " role_token: Buyer\n", + " then:\n", + " from_account:\n", + " role_token: Seller\n", + " pay: 75000000\n", + " then:\n", + " timeout: 1679011584000\n", + " timeout_continuation: close\n", + " when:\n", + " - case:\n", + " choose_between:\n", + " - from: 1\n", + " to: 1\n", + " for_choice:\n", + " choice_name: Confirm problem\n", + " choice_owner:\n", + " role_token: Seller\n", + " then: close\n", + " - case:\n", + " choose_between:\n", + " - from: 0\n", + " to: 0\n", + " for_choice:\n", + " choice_name: Dispute problem\n", + " choice_owner:\n", + " role_token: Seller\n", + " then:\n", + " timeout: 1679015184000\n", + " timeout_continuation: close\n", + " when:\n", + " - case:\n", + " choose_between:\n", + " - from: 0\n", + " to: 0\n", + " for_choice:\n", + " choice_name: Dismiss claim\n", + " choice_owner:\n", + " role_token: Mediator\n", + " then:\n", + " from_account:\n", + " role_token: Buyer\n", + " pay: 75000000\n", + " then: close\n", + " to:\n", + " account:\n", + " role_token: Seller\n", + " token:\n", + " currency_symbol: ''\n", + " token_name: ''\n", + " - case:\n", + " choose_between:\n", + " - from: 1\n", + " to: 1\n", + " for_choice:\n", + " choice_name: Confirm claim\n", + " choice_owner:\n", + " role_token: Mediator\n", + " then: close\n", + " to:\n", + " account:\n", + " role_token: Buyer\n", + " token:\n", + " currency_symbol: ''\n", + " token_name: ''\n" + ] + } + ], + "source": [ + "json2yaml escrow-contract.json" + ] + }, + { + "cell_type": "markdown", + "id": "4c4c1547-2bb6-4517-ba71-bf1ff35ad973", + "metadata": {}, + "source": [ + "### \\[Optional\\] Check the safety of the contract\n", + "\n", + "If we were running the contract on the Cardano `mainnet`, then we\\'d want to check its safety before creating it, so that there is no chance that we might lose funds.\n", + "\n", + "Here are the steps for checking the safety of a contract:\n", + "\n", + "1. Understand the [Marlowe Language](https://marlowe-finance.io/).\n", + "2. Understand Cardano\\'s [Extended UTxO Model](https://docs.cardano.org/learn/eutxo-explainer).\n", + "3. Read and understand the [Marlowe Best Practices Guide](https://github.com/input-output-hk/marlowe-cardano/blob/main/marlowe/best-practices.md).\n", + "4. Read and understand the [Marlowe Security Guide](https://github.com/input-output-hk/marlowe-cardano/blob/main/marlowe/security.md).\n", + "5. Use [Marlowe Playground](https://play.marlowe-finance.io/) to flag warnings, perform static analysis, and simulate the contract.\n", + "6. Use [Marlowe CLI\\'s](https://github.com/input-output-hk/marlowe-cardano/blob/main/marlowe-cli/ReadMe.md) `marlowe-cli run analyze` tool to study whether the contract can run on a Cardano network.\n", + "7. Run *all execution paths* of the contract on a [Cardano testnet](https://docs.cardano.org/cardano-testnet/overview).\n", + "\n", + "See [Lesson 1](../01-runtime-cli/ReadMe.ipynb) for an example of performing step 6." + ] + }, + { + "cell_type": "markdown", + "id": "87bb70c0-a8ed-4a9a-b0b7-732c40f0cad6", + "metadata": {}, + "source": [ + "## Transaction 1: Mediator Creates Escrow Contract with Initial ADA\n", + "\n", + "A `HTTP` `POST` request to Marlowe Runtime\\'s `/contracts` endpoint will build the creation transaction for a Marlowe contract. We provide it the JSON file containing the contract and tell it the `MIN_LOVELACE` value that we previously chose. Anyone could create the contract, but in this example the lender will be doing so, so we provide their address to fund the transaction and to receive the change from it.\n", + "\n", + "First we create the JSON body of the request to build the creation transaction." + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "4314ece0-462f-4df8-b739-f9db58cbc6a9", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{\"contract\":{\"timeout\":1679004384000,\"timeout_continuation\":\"close\",\"when\":[{\"case\":{\"deposits\":75000000,\"into_account\":{\"role_token\":\"Seller\"},\"of_token\":{\"currency_symbol\":\"\",\"token_name\":\"\"},\"party\":{\"role_token\":\"Buyer\"}},\"then\":{\"timeout\":1679007984000,\"timeout_continuation\":\"close\",\"when\":[{\"case\":{\"choose_between\":[{\"from\":0,\"to\":0}],\"for_choice\":{\"choice_name\":\"Everything is alright\",\"choice_owner\":{\"role_token\":\"Buyer\"}}},\"then\":\"close\"},{\"case\":{\"choose_between\":[{\"from\":1,\"to\":1}],\"for_choice\":{\"choice_name\":\"Report problem\",\"choice_owner\":{\"role_token\":\"Buyer\"}}},\"then\":{\"from_account\":{\"role_token\":\"Seller\"},\"pay\":75000000,\"then\":{\"timeout\":1679011584000,\"timeout_continuation\":\"close\",\"when\":[{\"case\":{\"choose_between\":[{\"from\":1,\"to\":1}],\"for_choice\":{\"choice_name\":\"Confirm problem\",\"choice_owner\":{\"role_token\":\"Seller\"}}},\"then\":\"close\"},{\"case\":{\"choose_between\":[{\"from\":0,\"to\":0}],\"for_choice\":{\"choice_name\":\"Dispute problem\",\"choice_owner\":{\"role_token\":\"Seller\"}}},\"then\":{\"timeout\":1679015184000,\"timeout_continuation\":\"close\",\"when\":[{\"case\":{\"choose_between\":[{\"from\":0,\"to\":0}],\"for_choice\":{\"choice_name\":\"Dismiss claim\",\"choice_owner\":{\"role_token\":\"Mediator\"}}},\"then\":{\"from_account\":{\"role_token\":\"Buyer\"},\"pay\":75000000,\"then\":\"close\",\"to\":{\"account\":{\"role_token\":\"Seller\"}},\"token\":{\"currency_symbol\":\"\",\"token_name\":\"\"}}},{\"case\":{\"choose_between\":[{\"from\":1,\"to\":1}],\"for_choice\":{\"choice_name\":\"Confirm claim\",\"choice_owner\":{\"role_token\":\"Mediator\"}}},\"then\":\"close\"}]}}]},\"to\":{\"account\":{\"role_token\":\"Buyer\"}},\"token\":{\"currency_symbol\":\"\",\"token_name\":\"\"}}}]}}]},\"metadata\":{},\"minUTxODeposit\":2000000,\"roles\":{\"Buyer\":\"addr_test1vpy4n4peh4suv0y55yptur0066j5kds8r4ncnuzm0vpzfgg0dhz6d\",\"Mediator\":\"addr_test1vr6tytqs3x8qgewhw89m3xrz58t3tqu2hfsecw0u06lf3hg052wsv\",\"Seller\":\"addr_test1vqd3yrtjyx49uld43lvwqaf7z4k03su8gf2x4yr7syzvckgfzm4ck\"},\"tags\":{},\"version\":\"v1\"}\n" + ] + } + ], + "source": [ + "yaml2json << EOI > request-1.json\n", + "version: v1\n", + "contract: $(cat escrow-contract.json)\n", + "roles:\n", + " Seller: $SELLER_ADDR\n", + " Buyer: $BUYER_ADDR\n", + " Mediator: $MEDIATOR_ADDR\n", + "minUTxODeposit: $MIN_LOVELACE\n", + "metadata: {}\n", + "tags: {}\n", + "EOI\n", + "cat request-1.json" + ] + }, + { + "cell_type": "markdown", + "id": "6b04626a-20d3-4b72-9cf0-0465e818311b", + "metadata": {}, + "source": [ + "Next we post the request and view the response." + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "5843b85f-f87e-46d2-a6e8-2550328bb6c6", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "links:\n", + " contract: contracts/3376c0eae5aa40e75e5d1d2264faa1a30a314a3d8ca9b6da99c5c04de9349a20%231\n", + "resource:\n", + " contractId: 3376c0eae5aa40e75e5d1d2264faa1a30a314a3d8ca9b6da99c5c04de9349a20#1\n", + " txBody:\n", + " cborHex: 86a80081825820b32eab58a670cc0164c9c2c615c81b40dc9229ab8d899db8f232bbede0984107040d81825820b32eab58a670cc0164c9c2c615c81b40dc9229ab8d899db8f232bbede0984107040185a200581d60f4b22c10898e0465d771cbb89862a1d715838aba619c39fc7ebe98dd011a3b45a132a300581d702ed2631dbb277c84334453c5c437b86325d371f0835a28b910a91a6e011a001e8480028200582016d16bfee2695ec0e03c08ec1ca21e1493640130a0cbfcc9a15f2ff181f25a49a200581d604959d439bd61c63c94a102be0defd6a54b36071d6789f05b7b0224a101821a000fb7caa1581cbf35f1fb673d65bd7fc65e90e52213e7c70ceadfab633e9765be060ba145427579657201a200581d60f4b22c10898e0465d771cbb89862a1d715838aba619c39fc7ebe98dd01821a000fea4ca1581cbf35f1fb673d65bd7fc65e90e52213e7c70ceadfab633e9765be060ba1484d65646961746f7201a200581d601b120d7221aa5e7db58fd8e0753e156cf8c38742546a907e8104cc5901821a000fc8a0a1581cbf35f1fb673d65bd7fc65e90e52213e7c70ceadfab633e9765be060ba14653656c6c65720110a200581d60f4b22c10898e0465d771cbb89862a1d715838aba619c39fc7ebe98dd011a3b8ff39c111a000ad664021a0007399809a1581cbf35f1fb673d65bd7fc65e90e52213e7c70ceadfab633e9765be060ba345427579657201484d65646961746f72014653656c6c6572010b5820316e1ce5dfbb2b39b951bdb9fd205124acad9f03f48d446f01168d57ef8dd6029f8202590ddd590dda01000033323233223232323232332232323232323232323322323232323232323233322232323232323232322223223232325335001102813263202d33573892010350543500028323232533500313300b49010b4275726e206661696c656400323235004223335530101200132335012223335003220020020013500122001123300101b02e2350012222533530080032103210323500222222222222200a3200135503322533500115021221350022253353301700200713502600113006003300f0021335502c300b49010b4d696e74206661696c656400330163232323500322222222222233355301b120013233501d2233350032200200200135001220011233001225335002103b100103825335333573466e3c03cd400488d4008880080e40e04ccd5cd19b8700e35001223500222001039038103800c3500b220013500a22002500133010335502c33555017237246ecccdd2a400066ae80dd398170009bb102f3355501725335333355300d1200133500e22230033002001200122533500121350032235003223500222350295335333573466e3c0080180cc0c84cd540eccd540ec008cdc0000802801899aa81d80499a81c80200189a81119aa81a001281999919191919191919118011803800990009aa81d11299a800898011801a81d110a99a800880111098031803802990009aa81c91299a8008a81c910a99a800880191099a81e198038020011803000990009aa81c111299a8010800910a99a8018802110a999a99806002001099a81e00219803801802899a81e00119803803000899a81e002198038018029a8019110009a8011110011a80091100199918008009119091a990919980091a801911180180211a801911180100211a8019111800802091a98018021a8020008009801001091111998021299a80089a80a89119801281c800910a99a80089a80b89119801002800910a999a998050020010999803001119a81d80280080089998038011a80c891198010030008008999803001119a81d802800800911299a800899a81c19a81c0018011803281c910a999a99805002801099a81d19a81d0028021804001899980380119a81d002802000899a81d19a81d002802180400191119299a80109800a4c442a666a6601600c004266600e0044600c66a07800e002002260069309998038011180319a81e003800800919a81c98019a80c0911980100300098038011919111a801111a80191912999a999a80d8048028018999a80d8040020008a8010a8010999a80c80380180099999999a80a11199ab9a3370e00400205a05844a66a666ae68cdc3801000816816080c8a99a999ab9a3371200400205a058202e203044666ae68cdc400100081681611199ab9a3371200400205a05844666ae68cdc480100081601691199ab9a3371000400205805a44a66a666ae68cdc48010008168160800880111299a999ab9a3371200400205a0582004200266666666a02602244a66a666ae68cdc7801000816015880c0a99a999ab9a33722004002058056202c202e44666ae68cdc800100081601591199ab9a3372200400205805644666ae68cdc880100081581611199ab9a3372000400205605844a66a666ae68cdc88010008160158800880111299a999ab9a3372200400205805620042002002a03e426a0024466a0660040022a062400266aa05866aaa02e644a66a002420022004a06066aaa02e646446004002640026aa06644a66a0022a0424426a00444a66a6602e00400e26a04c0022600c006601e00466aaa02e400246a002444444444444010a00201426a002440046666ae68cdc39aab9d5003480008cc8848cc00400c008c8c8c8c8c8c8c8c8c8c8c8c8c8cccd5cd19b8735573aa018900011999999999999111111111110919999999999980080680600580500480400380300280200180119a8128131aba1500c33502502635742a01666a04a04e6ae854028ccd540a5d728141aba150093335502975ca0506ae854020cd40940c0d5d0a803999aa814818bad35742a00c6464646666ae68cdc39aab9d5002480008cc8848cc00400c008c8c8c8cccd5cd19b8735573aa004900011991091980080180119a81dbad35742a00460786ae84d5d1280111931902219ab9c04003f042135573ca00226ea8004d5d0a8011919191999ab9a3370e6aae754009200023322123300100300233503b75a6ae854008c0f0d5d09aba2500223263204433573808007e08426aae7940044dd50009aba135744a004464c6408066ae700f00ec0f84d55cf280089baa00135742a00a66a04aeb8d5d0a802199aa81481690009aba150033335502975c40026ae854008c0bcd5d09aba2500223263203c33573807006e07426ae8940044d5d1280089aba25001135744a00226ae8940044d5d1280089aba25001135744a00226ae8940044d5d1280089aab9e5001137540026ae85400cc07cd5d09aba2500323263202e3357380540520586666ae68cdc3a80224004424400446666ae68cdc3a802a40004244002464c6405c66ae700a80a40b00ac4d55cf280089baa001135573a6ea8004894cd400440804cd5ce00100f990009aa8131108911299a80089a80191000910999a802910011802001199aa98038900080280200089109198008018010919a800a811281191a800911999a80091931901219ab9c4901024c680001f20012326320243357389201024c680001f2326320243357389201024c680001f22333573466e3c00800406c06848d40048888888801c48888888848cccccccc00402402001c01801401000c008488800c48880084888004894cd400840044050444888c00cc00800448c88c008dd6000990009aa80d911999aab9f0012501c233501b30043574200460066ae880080548c8c8cccd5cd19b8735573aa004900011991091980080180118061aba150023005357426ae8940088c98c8068cd5ce00b00a80c09aab9e5001137540024646464646666ae68cdc39aab9d5004480008cccc888848cccc00401401000c008c8c8c8cccd5cd19b8735573aa0049000119910919800801801180a9aba1500233500d014357426ae8940088c98c807ccd5ce00d80d00e89aab9e5001137540026ae854010ccd54021d728039aba150033232323333573466e1d4005200423212223002004357426aae79400c8cccd5cd19b875002480088c84888c004010dd71aba135573ca00846666ae68cdc3a801a400042444006464c6404266ae7007407007c0780744d55cea80089baa00135742a00466a012eb8d5d09aba2500223263201b33573802e02c03226ae8940044d5d1280089aab9e500113754002266aa002eb9d6889119118011bab00132001355018223233335573e0044a034466a03266aa036600c6aae754008c014d55cf280118021aba200301313574200224464646666ae68cdc3a800a400046a00e600a6ae84d55cf280191999ab9a3370ea00490011280391931900c19ab9c014013016015135573aa00226ea800448488c00800c44880048c8c8cccd5cd19b875001480188c848888c010014c01cd5d09aab9e500323333573466e1d400920042321222230020053009357426aae7940108cccd5cd19b875003480088c848888c004014c01cd5d09aab9e500523333573466e1d40112000232122223003005375c6ae84d55cf280311931900b19ab9c012011014013012011135573aa00226ea80048c8c8cccd5cd19b8735573aa004900011991091980080180118029aba15002375a6ae84d5d1280111931900919ab9c00e00d010135573ca00226ea80048c8cccd5cd19b8735573aa002900011bae357426aae7940088c98c8040cd5ce00600580709baa001232323232323333573466e1d4005200c21222222200323333573466e1d4009200a21222222200423333573466e1d400d2008233221222222233001009008375c6ae854014dd69aba135744a00a46666ae68cdc3a8022400c4664424444444660040120106eb8d5d0a8039bae357426ae89401c8cccd5cd19b875005480108cc8848888888cc018024020c030d5d0a8049bae357426ae8940248cccd5cd19b875006480088c848888888c01c020c034d5d09aab9e500b23333573466e1d401d2000232122222223005008300e357426aae7940308c98c8064cd5ce00a80a00b80b00a80a00980900889aab9d5004135573ca00626aae7940084d55cf280089baa0012323232323333573466e1d400520022333222122333001005004003375a6ae854010dd69aba15003375a6ae84d5d1280191999ab9a3370ea0049000119091180100198041aba135573ca00c464c6402466ae7003803404003c4d55cea80189aba25001135573ca00226ea80048c8c8cccd5cd19b875001480088c8488c00400cdd71aba135573ca00646666ae68cdc3a8012400046424460040066eb8d5d09aab9e500423263200f33573801601401a01826aae7540044dd500089119191999ab9a3370ea00290021091100091999ab9a3370ea00490011190911180180218031aba135573ca00846666ae68cdc3a801a400042444004464c6402066ae7003002c0380340304d55cea80089baa0012323333573466e1d40052002200523333573466e1d40092000200523263200c33573801000e01401226aae74dd500089100109100089000a481035054310011223002001320013550052253350011376200644266ae80d400888cdd2a400066ae80dd480119aba037500026ec401cc010005261122002122122330010040031122123300100300211232300100122330033002002001489207381bb21e6e7729681dfb5620376b3b4be92c5b83fce8ccb647dc75b624a17e5003351223300248920b32eab58a670cc0164c9c2c615c81b40dc9229ab8d899db8f232bbede098410700480208848cc00400c0088005ff81d8799fd8799f581cbf35f1fb673d65bd7fc65e90e52213e7c70ceadfab633e9765be060bffd8799fa1d8799fd8799fd87980d8799fd8799f581cf4b22c10898e0465d771cbb89862a1d715838aba619c39fc7ebe98ddffd87a80ffffd8799f4040ffff1a001e8480a0a000ffd87c9f9fd8799fd8799fd87a9f4653656c6c6572ffd87a9f454275796572ffd8799f4040ffd87a9f1a047868c0ffffd87c9f9fd8799fd87a9fd8799f5545766572797468696e6720697320616c7269676874d87a9f454275796572ffff9fd8799f0000ffffffd87980ffd8799fd87a9fd8799f4e5265706f72742070726f626c656dd87a9f454275796572ffff9fd8799f0101ffffffd87a9fd87a9f4653656c6c6572ffd8799fd87a9f454275796572ffffd8799f4040ffd87a9f1a047868c0ffd87c9f9fd8799fd87a9fd8799f4f436f6e6669726d2070726f626c656dd87a9f4653656c6c6572ffff9fd8799f0101ffffffd87980ffd8799fd87a9fd8799f4f446973707574652070726f626c656dd87a9f4653656c6c6572ffff9fd8799f0000ffffffd87c9f9fd8799fd87a9fd8799f4d4469736d69737320636c61696dd87a9f484d65646961746f72ffff9fd8799f0000ffffffd87a9fd87a9f454275796572ffd8799fd87a9f4653656c6c6572ffffd8799f4040ffd87a9f1a047868c0ffd87980ffffd8799fd87a9fd8799f4d436f6e6669726d20636c61696dd87a9f484d65646961746f72ffff9fd8799f0101ffffffd87980ffff1b00000186ed1a8680d87980ffffff1b00000186ece39800d87980ffffffff1b00000186ecaca980d87980ffffff1b00000186ec75bb00d87980ffff81840100d87980821a001275ca1a16b619d7f5f6\n", + " description: ''\n", + " type: TxBodyBabbage\n" + ] + } + ], + "source": [ + "curl \"$MARLOWE_RT_WEBSERVER_URL/contracts\" \\\n", + " -X POST \\\n", + " -H 'Content-Type: application/json' \\\n", + " -H \"X-Change-Address: $MEDIATOR_ADDR\" \\\n", + " -d @request-1.json \\\n", + " -o response-1.json \\\n", + " -sS\n", + "json2yaml response-1.json" + ] + }, + { + "cell_type": "markdown", + "id": "fde4adcb-8e68-4cae-bc3a-c3ef077ff47c", + "metadata": {}, + "source": [ + "The identifier for the contract is embedded in the response." + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "2e882a2e-07a0-4bf7-891d-cf99651c8c5a", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CONTRACT_ID = 3376c0eae5aa40e75e5d1d2264faa1a30a314a3d8ca9b6da99c5c04de9349a20#1\n" + ] + } + ], + "source": [ + "CONTRACT_ID=\"$(jq -r '.resource.contractId' response-1.json)\"\n", + "echo \"CONTRACT_ID = $CONTRACT_ID\"" + ] + }, + { + "cell_type": "markdown", + "id": "c1be0970-cd75-484d-a745-6e88208b612a", + "metadata": {}, + "source": [ + "The CBOR serialization (in text-envelope format) is also embedded in the response." + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "fb237371-071c-4b70-baca-c67f0751ac3e", + "metadata": {}, + "outputs": [], + "source": [ + "jq '.resource.txBody' response-1.json > tx-1.unsigned" + ] + }, + { + "cell_type": "markdown", + "id": "a59332a1-b1a0-4264-a84e-6b613eb20d72", + "metadata": {}, + "source": [ + "There are many ways to sign and submit Cardano transactions:\n", + "- `cardano-cli` at the command line\n", + "- `cardano-wallet` at the command line or as a REST service\n", + "- `cardano-hw-cli` for a hardware wallet at the command line\n", + "- a Babbage-compatible CIP-30 wallet in a web browser\n", + "- `marlowe-cli` at the command line\n", + "\n", + "For convenience, here we use `marlowe-cli transaction submit`. One may have to wait a minute or so for the transactions to be confirmed on the blockchain." + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "89bb49ae-2353-4d85-9ae5-ad805061f2cd", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "TX_1 = 3376c0eae5aa40e75e5d1d2264faa1a30a314a3d8ca9b6da99c5c04de9349a20\n" + ] + } + ], + "source": [ + "TX_1=$(\n", + "marlowe-cli transaction submit \\\n", + " --tx-body-file tx-1.unsigned \\\n", + " --required-signer \"$MEDIATOR_SKEY\" \\\n", + " --timeout 600 \\\n", + "| sed -e 's/^TxId \"\\(.*\\)\"$/\\1/' \\\n", + ")\n", + "echo \"TX_1 = $TX_1\"" + ] + }, + { + "cell_type": "markdown", + "id": "df082e87-eeaf-4924-b55b-94a4ba50c327", + "metadata": {}, + "source": [ + "One can view the transaction on a Cardano explorer and see that the contract has been created and the parties have received their role tokens. It sometimes takes thirty seconds or so for the transaction to be visible in an explorer." + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "006ca411-2088-439f-b735-b49892de22e8", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "https://preprod.cardanoscan.io/transaction/3376c0eae5aa40e75e5d1d2264faa1a30a314a3d8ca9b6da99c5c04de9349a20?tab=utxo\n" + ] + } + ], + "source": [ + "echo \"$EXPLORER_URL/transaction/$TX_1?tab=utxo\"" + ] + }, + { + "cell_type": "markdown", + "id": "9a1f44ce-de67-4b87-95d8-c1e052cc308a", + "metadata": {}, + "source": [ + "In particular, we see that the Marlowe contract holds the 2 ada that was set as `MINIMUM_LOVELACE`." + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "bc7b2078-d23c-47f4-9f12-697de8469ce1", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " TxHash TxIx Amount\n", + "--------------------------------------------------------------------------------------\n", + "3376c0eae5aa40e75e5d1d2264faa1a30a314a3d8ca9b6da99c5c04de9349a20 1 2000000 lovelace + TxOutDatumHash ScriptDataInBabbageEra \"16d16bfee2695ec0e03c08ec1ca21e1493640130a0cbfcc9a15f2ff181f25a49\"\n" + ] + } + ], + "source": [ + "cardano-cli query utxo --testnet-magic \"$CARDANO_TESTNET_MAGIC\" --tx-in \"$CONTRACT_ID\"" + ] + }, + { + "cell_type": "markdown", + "id": "9ce2b5b3-4c0b-4c53-ab6d-a1373499097c", + "metadata": {}, + "source": [ + "One can see that the seller, buyer, and mediator have received their role tokens. Note that `4c656e646572 = Seller`, `4275796572 = Buyer`, and `4d65646961746f72 = Mediator` in hexadecimal notation." + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "613f0751-3bc5-4ca7-b208-ef5830eef61d", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " TxHash TxIx Amount\n", + "--------------------------------------------------------------------------------------\n", + "3376c0eae5aa40e75e5d1d2264faa1a30a314a3d8ca9b6da99c5c04de9349a20 4 1034400 lovelace + 1 bf35f1fb673d65bd7fc65e90e52213e7c70ceadfab633e9765be060b.53656c6c6572 + TxOutDatumNone\n", + "b32eab58a670cc0164c9c2c615c81b40dc9229ab8d899db8f232bbede0984107 2 1000000000 lovelace + TxOutDatumNone\n" + ] + } + ], + "source": [ + "cardano-cli query utxo --testnet-magic \"$CARDANO_TESTNET_MAGIC\" --address \"$SELLER_ADDR\"" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "7f6d2b5e-86c2-4f53-ba20-8f95b43c3145", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " TxHash TxIx Amount\n", + "--------------------------------------------------------------------------------------\n", + "3376c0eae5aa40e75e5d1d2264faa1a30a314a3d8ca9b6da99c5c04de9349a20 2 1030090 lovelace + 1 bf35f1fb673d65bd7fc65e90e52213e7c70ceadfab633e9765be060b.4275796572 + TxOutDatumNone\n", + "b32eab58a670cc0164c9c2c615c81b40dc9229ab8d899db8f232bbede0984107 3 1000000000 lovelace + TxOutDatumNone\n" + ] + } + ], + "source": [ + "cardano-cli query utxo --testnet-magic \"$CARDANO_TESTNET_MAGIC\" --address \"$BUYER_ADDR\"" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "cbfab192-5a28-4595-b3ef-aa8bfdcee154", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " TxHash TxIx Amount\n", + "--------------------------------------------------------------------------------------\n", + "3376c0eae5aa40e75e5d1d2264faa1a30a314a3d8ca9b6da99c5c04de9349a20 0 994418994 lovelace + TxOutDatumNone\n", + "3376c0eae5aa40e75e5d1d2264faa1a30a314a3d8ca9b6da99c5c04de9349a20 3 1043020 lovelace + 1 bf35f1fb673d65bd7fc65e90e52213e7c70ceadfab633e9765be060b.4d65646961746f72 + TxOutDatumNone\n" + ] + } + ], + "source": [ + "cardano-cli query utxo --testnet-magic \"$CARDANO_TESTNET_MAGIC\" --address \"$MEDIATOR_ADDR\"" + ] + }, + { + "cell_type": "markdown", + "id": "3a7f985a-dba3-4b5f-aab8-8418270c5dda", + "metadata": {}, + "source": [ + "## View the details of the contract on the blockchain\n", + "\n", + "Marlowe Runtime\\'s `HTTP` `GET` endpoint `/contracts/{contractId}` can fetch a contract from the blockchain and return information about it." + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "id": "8328b458-43fb-4e53-8060-1740d25cf93b", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CONTRACT_URL = http://127.0.0.1:3780/contracts/3376c0eae5aa40e75e5d1d2264faa1a30a314a3d8ca9b6da99c5c04de9349a20%231\n" + ] + } + ], + "source": [ + "CONTRACT_URL=\"$MARLOWE_RT_WEBSERVER_URL/$(jq -r '.links.contract' response-1.json)\"\n", + "echo \"CONTRACT_URL = $CONTRACT_URL\"" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "id": "e805f893-bcd8-4169-a2da-90f1cfa080b2", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "links:\n", + " transactions: contracts/3376c0eae5aa40e75e5d1d2264faa1a30a314a3d8ca9b6da99c5c04de9349a20%231/transactions\n", + "resource:\n", + " block:\n", + " blockHeaderHash: ac573deefb3e0762732f5b25d0d1c676d1d0b566c03b447223c882df2c55ba06\n", + " blockNo: 732030\n", + " slotNo: 23317627\n", + " continuations: null\n", + " contractId: 3376c0eae5aa40e75e5d1d2264faa1a30a314a3d8ca9b6da99c5c04de9349a20#1\n", + " currentContract:\n", + " timeout: 1679004384000\n", + " timeout_continuation: close\n", + " when:\n", + " - case:\n", + " deposits: 75000000\n", + " into_account:\n", + " role_token: Seller\n", + " of_token:\n", + " currency_symbol: ''\n", + " token_name: ''\n", + " party:\n", + " role_token: Buyer\n", + " then:\n", + " timeout: 1679007984000\n", + " timeout_continuation: close\n", + " when:\n", + " - case:\n", + " choose_between:\n", + " - from: 0\n", + " to: 0\n", + " for_choice:\n", + " choice_name: Everything is alright\n", + " choice_owner:\n", + " role_token: Buyer\n", + " then: close\n", + " - case:\n", + " choose_between:\n", + " - from: 1\n", + " to: 1\n", + " for_choice:\n", + " choice_name: Report problem\n", + " choice_owner:\n", + " role_token: Buyer\n", + " then:\n", + " from_account:\n", + " role_token: Seller\n", + " pay: 75000000\n", + " then:\n", + " timeout: 1679011584000\n", + " timeout_continuation: close\n", + " when:\n", + " - case:\n", + " choose_between:\n", + " - from: 1\n", + " to: 1\n", + " for_choice:\n", + " choice_name: Confirm problem\n", + " choice_owner:\n", + " role_token: Seller\n", + " then: close\n", + " - case:\n", + " choose_between:\n", + " - from: 0\n", + " to: 0\n", + " for_choice:\n", + " choice_name: Dispute problem\n", + " choice_owner:\n", + " role_token: Seller\n", + " then:\n", + " timeout: 1679015184000\n", + " timeout_continuation: close\n", + " when:\n", + " - case:\n", + " choose_between:\n", + " - from: 0\n", + " to: 0\n", + " for_choice:\n", + " choice_name: Dismiss claim\n", + " choice_owner:\n", + " role_token: Mediator\n", + " then:\n", + " from_account:\n", + " role_token: Buyer\n", + " pay: 75000000\n", + " then: close\n", + " to:\n", + " account:\n", + " role_token: Seller\n", + " token:\n", + " currency_symbol: ''\n", + " token_name: ''\n", + " - case:\n", + " choose_between:\n", + " - from: 1\n", + " to: 1\n", + " for_choice:\n", + " choice_name: Confirm claim\n", + " choice_owner:\n", + " role_token: Mediator\n", + " then: close\n", + " to:\n", + " account:\n", + " role_token: Buyer\n", + " token:\n", + " currency_symbol: ''\n", + " token_name: ''\n", + " initialContract:\n", + " timeout: 1679004384000\n", + " timeout_continuation: close\n", + " when:\n", + " - case:\n", + " deposits: 75000000\n", + " into_account:\n", + " role_token: Seller\n", + " of_token:\n", + " currency_symbol: ''\n", + " token_name: ''\n", + " party:\n", + " role_token: Buyer\n", + " then:\n", + " timeout: 1679007984000\n", + " timeout_continuation: close\n", + " when:\n", + " - case:\n", + " choose_between:\n", + " - from: 0\n", + " to: 0\n", + " for_choice:\n", + " choice_name: Everything is alright\n", + " choice_owner:\n", + " role_token: Buyer\n", + " then: close\n", + " - case:\n", + " choose_between:\n", + " - from: 1\n", + " to: 1\n", + " for_choice:\n", + " choice_name: Report problem\n", + " choice_owner:\n", + " role_token: Buyer\n", + " then:\n", + " from_account:\n", + " role_token: Seller\n", + " pay: 75000000\n", + " then:\n", + " timeout: 1679011584000\n", + " timeout_continuation: close\n", + " when:\n", + " - case:\n", + " choose_between:\n", + " - from: 1\n", + " to: 1\n", + " for_choice:\n", + " choice_name: Confirm problem\n", + " choice_owner:\n", + " role_token: Seller\n", + " then: close\n", + " - case:\n", + " choose_between:\n", + " - from: 0\n", + " to: 0\n", + " for_choice:\n", + " choice_name: Dispute problem\n", + " choice_owner:\n", + " role_token: Seller\n", + " then:\n", + " timeout: 1679015184000\n", + " timeout_continuation: close\n", + " when:\n", + " - case:\n", + " choose_between:\n", + " - from: 0\n", + " to: 0\n", + " for_choice:\n", + " choice_name: Dismiss claim\n", + " choice_owner:\n", + " role_token: Mediator\n", + " then:\n", + " from_account:\n", + " role_token: Buyer\n", + " pay: 75000000\n", + " then: close\n", + " to:\n", + " account:\n", + " role_token: Seller\n", + " token:\n", + " currency_symbol: ''\n", + " token_name: ''\n", + " - case:\n", + " choose_between:\n", + " - from: 1\n", + " to: 1\n", + " for_choice:\n", + " choice_name: Confirm claim\n", + " choice_owner:\n", + " role_token: Mediator\n", + " then: close\n", + " to:\n", + " account:\n", + " role_token: Buyer\n", + " token:\n", + " currency_symbol: ''\n", + " token_name: ''\n", + " metadata: {}\n", + " roleTokenMintingPolicyId: bf35f1fb673d65bd7fc65e90e52213e7c70ceadfab633e9765be060b\n", + " state:\n", + " accounts:\n", + " - - - address: addr_test1vr6tytqs3x8qgewhw89m3xrz58t3tqu2hfsecw0u06lf3hg052wsv\n", + " - currency_symbol: ''\n", + " token_name: ''\n", + " - 2000000\n", + " boundValues: []\n", + " choices: []\n", + " minTime: 0\n", + " status: confirmed\n", + " tags: {}\n", + " txBody: null\n", + " utxo: 3376c0eae5aa40e75e5d1d2264faa1a30a314a3d8ca9b6da99c5c04de9349a20#1\n", + " version: v1\n" + ] + } + ], + "source": [ + "curl -sS \"$CONTRACT_URL\" | json2yaml" + ] + }, + { + "cell_type": "markdown", + "id": "e2166e0c-108b-40e5-b720-00043d697e1a", + "metadata": {}, + "source": [ + "## Transaction 2: Buyer Deposits Funds into Seller’s Account\n", + "\n", + "The buyer deposits their 75 ada into the contract using Marlowe Runtime\\'s `HTTP` `POST` `/contract/{contractId}/transactions` endpoint. The buyer is providing the funding for and receiving the change from this transaction, so we provide their address.\n", + "\n", + "The deposit is represented as JSON input to the contract. The `marlowe-cli input deposit` tool conveniently formats the correct JSON for a deposit." + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "id": "1fbf5b90-ba80-44b9-83f5-791a7a10b2ab", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Usage: marlowe-cli input deposit --deposit-account PARTY --deposit-party PARTY \n", + " [--deposit-token TOKEN]\n", + " --deposit-amount INTEGER \n", + " [--out-file OUTPUT_FILE]\n", + "\n", + " Create Marlowe input for a deposit.\n", + "\n", + "Available options:\n", + " --deposit-account PARTY The account for the deposit.\n", + " --deposit-party PARTY The party making the deposit.\n", + " --deposit-token TOKEN The token being deposited, if not Ada.\n", + " --deposit-amount INTEGER The amount of token being deposited.\n", + " --out-file OUTPUT_FILE JSON output file for contract input.\n", + " -h,--help Show this help text\n" + ] + } + ], + "source": [ + "marlowe-cli input deposit --help" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "id": "3c8a6076-f342-489c-939c-e9c017b6b445", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "input_from_party:\n", + " role_token: Buyer\n", + "into_account:\n", + " role_token: Seller\n", + "of_token:\n", + " currency_symbol: ''\n", + " token_name: ''\n", + "that_deposits: 75000000\n" + ] + } + ], + "source": [ + "marlowe-cli input deposit \\\n", + " --deposit-party Buyer \\\n", + " --deposit-account Seller \\\n", + " --deposit-amount \"$PRICE\" \\\n", + " --out-file input-2.json\n", + "json2yaml input-2.json" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "id": "4fc16b02-358c-438f-9e5b-7d709da7eac5", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{\"inputs\":[{\"input_from_party\":{\"role_token\":\"Buyer\"},\"into_account\":{\"role_token\":\"Seller\"},\"of_token\":{\"currency_symbol\":\"\",\"token_name\":\"\"},\"that_deposits\":75000000}],\"metadata\":{},\"tags\":{},\"version\":\"v1\"}\n" + ] + } + ], + "source": [ + "yaml2json << EOI > request-2.json\n", + "version: v1\n", + "inputs: [$(cat input-2.json)]\n", + "metadata: {}\n", + "tags: {}\n", + "EOI\n", + "cat request-2.json" + ] + }, + { + "cell_type": "markdown", + "id": "7f66252b-23fc-47e3-825d-7aba51a86368", + "metadata": {}, + "source": [ + "Next we post the request and store the response." + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "id": "465152a1-eaaa-4dab-9035-aa306c0022fa", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "links:\n", + " transaction: contracts/3376c0eae5aa40e75e5d1d2264faa1a30a314a3d8ca9b6da99c5c04de9349a20%231/transactions/a3e9a21f95ebf3df23e2e5c3de14dc02b8a87cf4578aa6afefec92a7e526e0e8\n", + "resource:\n", + " contractId: 3376c0eae5aa40e75e5d1d2264faa1a30a314a3d8ca9b6da99c5c04de9349a20#1\n", + " transactionId: a3e9a21f95ebf3df23e2e5c3de14dc02b8a87cf4578aa6afefec92a7e526e0e8\n", + " txBody:\n", + " cborHex: 86aa00838258203376c0eae5aa40e75e5d1d2264faa1a30a314a3d8ca9b6da99c5c04de9349a20018258203376c0eae5aa40e75e5d1d2264faa1a30a314a3d8ca9b6da99c5c04de9349a2002825820b32eab58a670cc0164c9c2c615c81b40dc9229ab8d899db8f232bbede0984107030d81825820b32eab58a670cc0164c9c2c615c81b40dc9229ab8d899db8f232bbede09841070312818258209a8a6f387a3330b4141e1cb019380b9ac5c72151c0abc52aa4266245d3c555cd010183a200581d604959d439bd61c63c94a102be0defd6a54b36071d6789f05b7b0224a1011a3716a88ea300581d702ed2631dbb277c84334453c5c437b86325d371f0835a28b910a91a6e011a0496ed4002820058200655c39786c393d64a5eacdbf20396a43c166a4882ae57d1ac02daa450e2f620a200581d604959d439bd61c63c94a102be0defd6a54b36071d6789f05b7b0224a101821a000fb7caa1581cbf35f1fb673d65bd7fc65e90e52213e7c70ceadfab633e9765be060ba14542757965720110a200581d604959d439bd61c63c94a102be0defd6a54b36071d6789f05b7b0224a1011a3b8934f5111a0011950b021a000bb8b2031a0163da60081a0163cc950b582025da31acd2181f5a9cdb2ab984ef98e9f891f5543eae8a0439d9b5c83eb07bd29fff82d8799fd8799f581cbf35f1fb673d65bd7fc65e90e52213e7c70ceadfab633e9765be060bffd8799fa2d8799fd8799fd87980d8799fd8799f581cf4b22c10898e0465d771cbb89862a1d715838aba619c39fc7ebe98ddffd87a80ffffd8799f4040ffff1a001e8480d8799fd87a9f4653656c6c6572ffd8799f4040ffff1a047868c0a0a01b00000186ec3fda08ffd87c9f9fd8799fd87a9fd8799f5545766572797468696e6720697320616c7269676874d87a9f454275796572ffff9fd8799f0000ffffffd87980ffd8799fd87a9fd8799f4e5265706f72742070726f626c656dd87a9f454275796572ffff9fd8799f0101ffffffd87a9fd87a9f4653656c6c6572ffd8799fd87a9f454275796572ffffd8799f4040ffd87a9f1a047868c0ffd87c9f9fd8799fd87a9fd8799f4f436f6e6669726d2070726f626c656dd87a9f4653656c6c6572ffff9fd8799f0101ffffffd87980ffd8799fd87a9fd8799f4f446973707574652070726f626c656dd87a9f4653656c6c6572ffff9fd8799f0000ffffffd87c9f9fd8799fd87a9fd8799f4d4469736d69737320636c61696dd87a9f484d65646961746f72ffff9fd8799f0000ffffffd87a9fd87a9f454275796572ffd8799fd87a9f4653656c6c6572ffffd8799f4040ffd87a9f1a047868c0ffd87980ffffd8799fd87a9fd8799f4d436f6e6669726d20636c61696dd87a9f484d65646961746f72ffff9fd8799f0101ffffffd87980ffff1b00000186ed1a8680d87980ffffff1b00000186ece39800d87980ffffffff1b00000186ecaca980d87980ffffd8799fd8799f581cbf35f1fb673d65bd7fc65e90e52213e7c70ceadfab633e9765be060bffd8799fa1d8799fd8799fd87980d8799fd8799f581cf4b22c10898e0465d771cbb89862a1d715838aba619c39fc7ebe98ddffd87a80ffffd8799f4040ffff1a001e8480a0a000ffd87c9f9fd8799fd8799fd87a9f4653656c6c6572ffd87a9f454275796572ffd8799f4040ffd87a9f1a047868c0ffffd87c9f9fd8799fd87a9fd8799f5545766572797468696e6720697320616c7269676874d87a9f454275796572ffff9fd8799f0000ffffffd87980ffd8799fd87a9fd8799f4e5265706f72742070726f626c656dd87a9f454275796572ffff9fd8799f0101ffffffd87a9fd87a9f4653656c6c6572ffd8799fd87a9f454275796572ffffd8799f4040ffd87a9f1a047868c0ffd87c9f9fd8799fd87a9fd8799f4f436f6e6669726d2070726f626c656dd87a9f4653656c6c6572ffff9fd8799f0101ffffffd87980ffd8799fd87a9fd8799f4f446973707574652070726f626c656dd87a9f4653656c6c6572ffff9fd8799f0000ffffffd87c9f9fd8799fd87a9fd8799f4d4469736d69737320636c61696dd87a9f484d65646961746f72ffff9fd8799f0000ffffffd87a9fd87a9f454275796572ffd8799fd87a9f4653656c6c6572ffffd8799f4040ffd87a9f1a047868c0ffd87980ffffd8799fd87a9fd8799f4d436f6e6669726d20636c61696dd87a9f484d65646961746f72ffff9fd8799f0101ffffffd87980ffff1b00000186ed1a8680d87980ffffff1b00000186ece39800d87980ffffffff1b00000186ecaca980d87980ffffff1b00000186ec75bb00d87980ffff818400009fd8799fd8799fd87a9f4653656c6c6572ffd87a9f454275796572ffd8799f4040ff1a047868c0ffffff821a006736961a6bf49e10f5f6\n", + " description: ''\n", + " type: TxBodyBabbage\n" + ] + } + ], + "source": [ + "curl \"$CONTRACT_URL/transactions\" \\\n", + " -X POST \\\n", + " -H 'Content-Type: application/json' \\\n", + " -H \"X-Change-Address: $BUYER_ADDR\" \\\n", + " -d @request-2.json \\\n", + " -o response-2.json \\\n", + " -sS\n", + "json2yaml response-2.json" + ] + }, + { + "cell_type": "markdown", + "id": "69e4024a-c61f-4e5a-8272-d1f958f82a15", + "metadata": {}, + "source": [ + "Once again, use `marlowe-cli` to submit the transaction and then wait for confirmation." + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "id": "6fb5d4c0-c158-434b-8dac-b2160f426e01", + "metadata": {}, + "outputs": [], + "source": [ + "jq '.resource.txBody' response-2.json > tx-2.unsigned" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "id": "b2aa2f81-d6b7-4994-b90b-0812d5fb3fca", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "TX_2 = a3e9a21f95ebf3df23e2e5c3de14dc02b8a87cf4578aa6afefec92a7e526e0e8\n" + ] + } + ], + "source": [ + "TX_2=$(\n", + "marlowe-cli transaction submit \\\n", + " --tx-body-file tx-2.unsigned \\\n", + " --required-signer \"$BUYER_SKEY\" \\\n", + " --timeout 600 \\\n", + "| sed -e 's/^TxId \"\\(.*\\)\"$/\\1/' \\\n", + ")\n", + "echo \"TX_2 = $TX_2\"" + ] + }, + { + "cell_type": "markdown", + "id": "b7d1ac41-f3c3-47b0-b192-e0f8ad53fdfa", + "metadata": {}, + "source": [ + "One can view the transaction on a Cardano explorer. It sometimes takes thirty seconds or so for the transaction to be visible in an explorer." + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "id": "9b994073-d1b9-44a4-8149-9b307a69a4e4", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "https://preprod.cardanoscan.io/transaction/a3e9a21f95ebf3df23e2e5c3de14dc02b8a87cf4578aa6afefec92a7e526e0e8?tab=utxo\n" + ] + } + ], + "source": [ + "echo \"$EXPLORER_URL/transaction/$TX_2?tab=utxo\"" + ] + }, + { + "cell_type": "markdown", + "id": "664d2826-7d6c-4564-9ef9-6b12e3e76f53", + "metadata": {}, + "source": [ + "One can see that the buyer has approximately 75 ada less than originally." + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "id": "b45dc15d-f54f-49cb-a36d-0524f47fd70e", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " TxHash TxIx Amount\n", + "--------------------------------------------------------------------------------------\n", + "a3e9a21f95ebf3df23e2e5c3de14dc02b8a87cf4578aa6afefec92a7e526e0e8 0 924231822 lovelace + TxOutDatumNone\n", + "a3e9a21f95ebf3df23e2e5c3de14dc02b8a87cf4578aa6afefec92a7e526e0e8 2 1030090 lovelace + 1 bf35f1fb673d65bd7fc65e90e52213e7c70ceadfab633e9765be060b.4275796572 + TxOutDatumNone\n" + ] + } + ], + "source": [ + "cardano-cli query utxo --testnet-magic \"$CARDANO_TESTNET_MAGIC\" --address \"$BUYER_ADDR\"" + ] + }, + { + "cell_type": "markdown", + "id": "4d2574d2-587f-46f7-8129-431694172296", + "metadata": {}, + "source": [ + "The Marlowe contract still has the 2 ada from its creation and an additional 75 ada." + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "id": "6485d605-dec4-4bab-86f6-81bf002041ed", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " TxHash TxIx Amount\n", + "--------------------------------------------------------------------------------------\n", + "a3e9a21f95ebf3df23e2e5c3de14dc02b8a87cf4578aa6afefec92a7e526e0e8 1 77000000 lovelace + TxOutDatumHash ScriptDataInBabbageEra \"0655c39786c393d64a5eacdbf20396a43c166a4882ae57d1ac02daa450e2f620\"\n" + ] + } + ], + "source": [ + "cardano-cli query utxo --testnet-magic \"$CARDANO_TESTNET_MAGIC\" --tx-in \"$TX_2#1\"" + ] + }, + { + "cell_type": "markdown", + "id": "2bbf4214-ecf6-4d4f-a8ea-acdb6ff8bcb7", + "metadata": {}, + "source": [ + "## View the further progress of the contract on the blockchain\n", + "\n", + "Marlowe Runtime\\'s `HTTP` `GET` endpoint `/contracts/{contractId}/transactions/{transactionId}` can fetch a contract from the blockchain and return information about it." + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "id": "e0461725-7f2b-4256-ac83-8e681ecb3e35", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "links: {}\n", + "resource:\n", + " block:\n", + " blockHeaderHash: 139a50cd367cf8e04c1cadf4729cf9d3c8b03ae8456a33ab2198eceac72ea4d2\n", + " blockNo: 732033\n", + " slotNo: 23317666\n", + " consumingTx: null\n", + " continuations: null\n", + " contractId: 3376c0eae5aa40e75e5d1d2264faa1a30a314a3d8ca9b6da99c5c04de9349a20#1\n", + " inputUtxo: 3376c0eae5aa40e75e5d1d2264faa1a30a314a3d8ca9b6da99c5c04de9349a20#1\n", + " inputs:\n", + " - input_from_party:\n", + " role_token: Buyer\n", + " into_account:\n", + " role_token: Seller\n", + " of_token:\n", + " currency_symbol: ''\n", + " token_name: ''\n", + " that_deposits: 75000000\n", + " invalidBefore: 2023-03-16T21:07:33Z\n", + " invalidHereafter: 2023-03-16T22:06:24Z\n", + " metadata: {}\n", + " outputContract:\n", + " timeout: 1679007984000\n", + " timeout_continuation: close\n", + " when:\n", + " - case:\n", + " choose_between:\n", + " - from: 0\n", + " to: 0\n", + " for_choice:\n", + " choice_name: Everything is alright\n", + " choice_owner:\n", + " role_token: Buyer\n", + " then: close\n", + " - case:\n", + " choose_between:\n", + " - from: 1\n", + " to: 1\n", + " for_choice:\n", + " choice_name: Report problem\n", + " choice_owner:\n", + " role_token: Buyer\n", + " then:\n", + " from_account:\n", + " role_token: Seller\n", + " pay: 75000000\n", + " then:\n", + " timeout: 1679011584000\n", + " timeout_continuation: close\n", + " when:\n", + " - case:\n", + " choose_between:\n", + " - from: 1\n", + " to: 1\n", + " for_choice:\n", + " choice_name: Confirm problem\n", + " choice_owner:\n", + " role_token: Seller\n", + " then: close\n", + " - case:\n", + " choose_between:\n", + " - from: 0\n", + " to: 0\n", + " for_choice:\n", + " choice_name: Dispute problem\n", + " choice_owner:\n", + " role_token: Seller\n", + " then:\n", + " timeout: 1679015184000\n", + " timeout_continuation: close\n", + " when:\n", + " - case:\n", + " choose_between:\n", + " - from: 0\n", + " to: 0\n", + " for_choice:\n", + " choice_name: Dismiss claim\n", + " choice_owner:\n", + " role_token: Mediator\n", + " then:\n", + " from_account:\n", + " role_token: Buyer\n", + " pay: 75000000\n", + " then: close\n", + " to:\n", + " account:\n", + " role_token: Seller\n", + " token:\n", + " currency_symbol: ''\n", + " token_name: ''\n", + " - case:\n", + " choose_between:\n", + " - from: 1\n", + " to: 1\n", + " for_choice:\n", + " choice_name: Confirm claim\n", + " choice_owner:\n", + " role_token: Mediator\n", + " then: close\n", + " to:\n", + " account:\n", + " role_token: Buyer\n", + " token:\n", + " currency_symbol: ''\n", + " token_name: ''\n", + " outputState:\n", + " accounts:\n", + " - - - address: addr_test1vr6tytqs3x8qgewhw89m3xrz58t3tqu2hfsecw0u06lf3hg052wsv\n", + " - currency_symbol: ''\n", + " token_name: ''\n", + " - 2000000\n", + " - - - role_token: Seller\n", + " - currency_symbol: ''\n", + " token_name: ''\n", + " - 75000000\n", + " boundValues: []\n", + " choices: []\n", + " minTime: 1679000853000\n", + " outputUtxo: a3e9a21f95ebf3df23e2e5c3de14dc02b8a87cf4578aa6afefec92a7e526e0e8#1\n", + " status: confirmed\n", + " tags: {}\n", + " transactionId: a3e9a21f95ebf3df23e2e5c3de14dc02b8a87cf4578aa6afefec92a7e526e0e8\n", + " txBody: null\n" + ] + } + ], + "source": [ + "curl -sS \"$CONTRACT_URL/transactions/$TX_2\" | json2yaml" + ] + }, + { + "cell_type": "markdown", + "id": "1a416c81-4ccb-4964-aab8-e2d76fc4512a", + "metadata": {}, + "source": [ + "## Transaction 3: The Buyer Reports That There is a Problem\n", + "\n", + "The buyer chooses to report a problem with the merchandise.\n", + "\n", + "The choice is represented as JSON input to the contract. The `marlowe-cli input choose` tool conveniently formats the correct JSON for a choice." + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "id": "b8a4045e-ceca-4272-90dc-72747e5329ab", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Usage: marlowe-cli input choose --choice-name NAME --choice-party PARTY\n", + " --choice-number INTEGER [--out-file OUTPUT_FILE]\n", + "\n", + " Create Marlowe input for a choice.\n", + "\n", + "Available options:\n", + " --choice-name NAME The name of the choice made.\n", + " --choice-party PARTY The party making the choice.\n", + " --choice-number INTEGER The number chosen.\n", + " --out-file OUTPUT_FILE JSON output file for contract input.\n", + " -h,--help Show this help text\n" + ] + } + ], + "source": [ + "marlowe-cli input choose --help" + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "id": "42aeee88-13e1-4170-b18a-727cd5cde877", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "for_choice_id:\n", + " choice_name: Report problem\n", + " choice_owner:\n", + " role_token: Buyer\n", + "input_that_chooses_num: 1\n" + ] + } + ], + "source": [ + "marlowe-cli input choose \\\n", + " --choice-name \"Report problem\" \\\n", + " --choice-party Buyer \\\n", + " --choice-number 1 \\\n", + " --out-file input-3.json\n", + "json2yaml input-3.json" + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "id": "3fee1c9b-c4d9-4ab4-9b47-061db363d31f", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{\"inputs\":[{\"for_choice_id\":{\"choice_name\":\"Report problem\",\"choice_owner\":{\"role_token\":\"Buyer\"}},\"input_that_chooses_num\":1}],\"metadata\":{},\"tags\":{},\"version\":\"v1\"}\n" + ] + } + ], + "source": [ + "yaml2json << EOI > request-3.json\n", + "version: v1\n", + "inputs: [$(cat input-3.json)]\n", + "metadata: {}\n", + "tags: {}\n", + "EOI\n", + "cat request-3.json" + ] + }, + { + "cell_type": "markdown", + "id": "8787ec8b-f045-4fbc-adfd-f68bc88303b4", + "metadata": {}, + "source": [ + "Next we post the request and store the response." + ] + }, + { + "cell_type": "code", + "execution_count": 44, + "id": "387362e6-8cb8-4a46-9222-4a065d964167", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "links:\n", + " transaction: contracts/3376c0eae5aa40e75e5d1d2264faa1a30a314a3d8ca9b6da99c5c04de9349a20%231/transactions/5a448f6b4861e36a984e880c6e46a7dacd8513de0fa27daf46f9c1d0ccac50af\n", + "resource:\n", + " contractId: 3376c0eae5aa40e75e5d1d2264faa1a30a314a3d8ca9b6da99c5c04de9349a20#1\n", + " transactionId: 5a448f6b4861e36a984e880c6e46a7dacd8513de0fa27daf46f9c1d0ccac50af\n", + " txBody:\n", + " cborHex: 86aa0083825820a3e9a21f95ebf3df23e2e5c3de14dc02b8a87cf4578aa6afefec92a7e526e0e800825820a3e9a21f95ebf3df23e2e5c3de14dc02b8a87cf4578aa6afefec92a7e526e0e801825820a3e9a21f95ebf3df23e2e5c3de14dc02b8a87cf4578aa6afefec92a7e526e0e8020d81825820a3e9a21f95ebf3df23e2e5c3de14dc02b8a87cf4578aa6afefec92a7e526e0e80012818258209a8a6f387a3330b4141e1cb019380b9ac5c72151c0abc52aa4266245d3c555cd010183a200581d604959d439bd61c63c94a102be0defd6a54b36071d6789f05b7b0224a1011a370a9baea300581d702ed2631dbb277c84334453c5c437b86325d371f0835a28b910a91a6e011a0496ed400282005820c384ef66cdc894120d0f71b03aaa114fe3731b70f0c7155d9352a04a0aaec264a200581d604959d439bd61c63c94a102be0defd6a54b36071d6789f05b7b0224a101821a000fb7caa1581cbf35f1fb673d65bd7fc65e90e52213e7c70ceadfab633e9765be060ba14542757965720110a200581d604959d439bd61c63c94a102be0defd6a54b36071d6789f05b7b0224a1011a3704953e111a00121350021a000c0ce0031a0163e870081a0163cca80b5820e83b04a449aadd0103a5c8e626f03a3e073cede8dec800cfa30bcafcee7ca3a39fff82d8799fd8799f581cbf35f1fb673d65bd7fc65e90e52213e7c70ceadfab633e9765be060bffd8799fa2d8799fd8799fd87980d8799fd8799f581cf4b22c10898e0465d771cbb89862a1d715838aba619c39fc7ebe98ddffd87a80ffffd8799f4040ffff1a001e8480d8799fd87a9f4653656c6c6572ffd8799f4040ffff1a047868c0a0a01b00000186ec3fda08ffd87c9f9fd8799fd87a9fd8799f5545766572797468696e6720697320616c7269676874d87a9f454275796572ffff9fd8799f0000ffffffd87980ffd8799fd87a9fd8799f4e5265706f72742070726f626c656dd87a9f454275796572ffff9fd8799f0101ffffffd87a9fd87a9f4653656c6c6572ffd8799fd87a9f454275796572ffffd8799f4040ffd87a9f1a047868c0ffd87c9f9fd8799fd87a9fd8799f4f436f6e6669726d2070726f626c656dd87a9f4653656c6c6572ffff9fd8799f0101ffffffd87980ffd8799fd87a9fd8799f4f446973707574652070726f626c656dd87a9f4653656c6c6572ffff9fd8799f0000ffffffd87c9f9fd8799fd87a9fd8799f4d4469736d69737320636c61696dd87a9f484d65646961746f72ffff9fd8799f0000ffffffd87a9fd87a9f454275796572ffd8799fd87a9f4653656c6c6572ffffd8799f4040ffd87a9f1a047868c0ffd87980ffffd8799fd87a9fd8799f4d436f6e6669726d20636c61696dd87a9f484d65646961746f72ffff9fd8799f0101ffffffd87980ffff1b00000186ed1a8680d87980ffffff1b00000186ece39800d87980ffffffff1b00000186ecaca980d87980ffffd8799fd8799f581cbf35f1fb673d65bd7fc65e90e52213e7c70ceadfab633e9765be060bffd8799fa2d8799fd8799fd87980d8799fd8799f581cf4b22c10898e0465d771cbb89862a1d715838aba619c39fc7ebe98ddffd87a80ffffd8799f4040ffff1a001e8480d8799fd87a9f454275796572ffd8799f4040ffff1a047868c0a1d8799f4e5265706f72742070726f626c656dd87a9f454275796572ffff01a01b00000186ec402440ffd87c9f9fd8799fd87a9fd8799f4f436f6e6669726d2070726f626c656dd87a9f4653656c6c6572ffff9fd8799f0101ffffffd87980ffd8799fd87a9fd8799f4f446973707574652070726f626c656dd87a9f4653656c6c6572ffff9fd8799f0000ffffffd87c9f9fd8799fd87a9fd8799f4d4469736d69737320636c61696dd87a9f484d65646961746f72ffff9fd8799f0000ffffffd87a9fd87a9f454275796572ffd8799fd87a9f4653656c6c6572ffffd8799f4040ffd87a9f1a047868c0ffd87980ffffd8799fd87a9fd8799f4d436f6e6669726d20636c61696dd87a9f484d65646961746f72ffff9fd8799f0101ffffffd87980ffff1b00000186ed1a8680d87980ffffff1b00000186ece39800d87980ffff818400019fd8799fd87a9fd8799f4e5265706f72742070726f626c656dd87a9f454275796572ffff01ffffff821a006d3cae1a70de7f55f5f6\n", + " description: ''\n", + " type: TxBodyBabbage\n" + ] + } + ], + "source": [ + "curl \"$CONTRACT_URL/transactions\" \\\n", + " -X POST \\\n", + " -H 'Content-Type: application/json' \\\n", + " -H \"X-Change-Address: $BUYER_ADDR\" \\\n", + " -d @request-3.json \\\n", + " -o response-3.json \\\n", + " -sS\n", + "json2yaml response-3.json" + ] + }, + { + "cell_type": "markdown", + "id": "29fe4142-1525-47ef-8270-571c3a5744fc", + "metadata": {}, + "source": [ + "Once again, use `marlowe-cli` to submit the transaction and then wait for confirmation." + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "id": "57490822-4650-481c-b2a3-beb73075ae6b", + "metadata": {}, + "outputs": [], + "source": [ + "jq '.resource.txBody' response-3.json > tx-3.unsigned" + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "id": "61733dd3-cac6-4ef3-bee8-9cb7ec4362ff", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "TX_3 = 5a448f6b4861e36a984e880c6e46a7dacd8513de0fa27daf46f9c1d0ccac50af\n" + ] + } + ], + "source": [ + "TX_3=$(\n", + "marlowe-cli transaction submit \\\n", + " --tx-body-file tx-3.unsigned \\\n", + " --required-signer \"$BUYER_SKEY\" \\\n", + " --timeout 600 \\\n", + "| sed -e 's/^TxId \"\\(.*\\)\"$/\\1/' \\\n", + ")\n", + "echo \"TX_3 = $TX_3\"" + ] + }, + { + "cell_type": "markdown", + "id": "5aa0221d-485b-4c7f-b711-3dc2773d616d", + "metadata": {}, + "source": [ + "One can view the transaction on a Cardano explorer. It sometimes takes thirty seconds or so for the transaction to be visible in an explorer." + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "id": "b7424735-4fba-433d-99ee-ae9b5ec91ab2", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "https://preprod.cardanoscan.io/transaction/5a448f6b4861e36a984e880c6e46a7dacd8513de0fa27daf46f9c1d0ccac50af?tab=utxo\n" + ] + } + ], + "source": [ + "echo \"$EXPLORER_URL/transaction/$TX_3?tab=utxo\"" + ] + }, + { + "cell_type": "markdown", + "id": "39055157-6c46-4b48-94ea-42fa54ec2fb5", + "metadata": {}, + "source": [ + "One can see that the buyer still has approximately 75 ada less than originally." + ] + }, + { + "cell_type": "code", + "execution_count": 48, + "id": "1f831ae4-36e9-4fb6-9c7b-c6a19e6f249f", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " TxHash TxIx Amount\n", + "--------------------------------------------------------------------------------------\n", + "5a448f6b4861e36a984e880c6e46a7dacd8513de0fa27daf46f9c1d0ccac50af 0 923442094 lovelace + TxOutDatumNone\n", + "5a448f6b4861e36a984e880c6e46a7dacd8513de0fa27daf46f9c1d0ccac50af 2 1030090 lovelace + 1 bf35f1fb673d65bd7fc65e90e52213e7c70ceadfab633e9765be060b.4275796572 + TxOutDatumNone\n" + ] + } + ], + "source": [ + "cardano-cli query utxo --testnet-magic \"$CARDANO_TESTNET_MAGIC\" --address \"$BUYER_ADDR\"" + ] + }, + { + "cell_type": "markdown", + "id": "3b092c43-548e-4ee4-8e0b-8898296d5cf5", + "metadata": {}, + "source": [ + "The Marlowe contract still has the 77 ada." + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "id": "0020850f-5700-4a2e-a1b6-f3486ab9eb14", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " TxHash TxIx Amount\n", + "--------------------------------------------------------------------------------------\n", + "5a448f6b4861e36a984e880c6e46a7dacd8513de0fa27daf46f9c1d0ccac50af 1 77000000 lovelace + TxOutDatumHash ScriptDataInBabbageEra \"c384ef66cdc894120d0f71b03aaa114fe3731b70f0c7155d9352a04a0aaec264\"\n" + ] + } + ], + "source": [ + "cardano-cli query utxo --testnet-magic \"$CARDANO_TESTNET_MAGIC\" --tx-in \"$TX_3#1\"" + ] + }, + { + "cell_type": "markdown", + "id": "4a2e8aac-9a19-48b9-97c7-5b0dc82e75c9", + "metadata": {}, + "source": [ + "## View the further progress of the contract on the blockchain\n", + "\n", + "Marlowe Runtime\\'s `HTTP` `GET` endpoint `/contracts/{contractId}/transactions/{transactionId}` can fetch a contract from the blockchain and return information about it." + ] + }, + { + "cell_type": "code", + "execution_count": 50, + "id": "b91dc7ca-2cf8-4d8d-81a7-3d0880aafd90", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "links:\n", + " previous: contracts/3376c0eae5aa40e75e5d1d2264faa1a30a314a3d8ca9b6da99c5c04de9349a20%231/transactions/a3e9a21f95ebf3df23e2e5c3de14dc02b8a87cf4578aa6afefec92a7e526e0e8\n", + "resource:\n", + " block:\n", + " blockHeaderHash: c58f330e1c27404c9643dd27694dd027301191b4c8fa8eca0960db85f1a70615\n", + " blockNo: 732035\n", + " slotNo: 23317702\n", + " consumingTx: null\n", + " continuations: null\n", + " contractId: 3376c0eae5aa40e75e5d1d2264faa1a30a314a3d8ca9b6da99c5c04de9349a20#1\n", + " inputUtxo: a3e9a21f95ebf3df23e2e5c3de14dc02b8a87cf4578aa6afefec92a7e526e0e8#1\n", + " inputs:\n", + " - for_choice_id:\n", + " choice_name: Report problem\n", + " choice_owner:\n", + " role_token: Buyer\n", + " input_that_chooses_num: 1\n", + " invalidBefore: 2023-03-16T21:07:52Z\n", + " invalidHereafter: 2023-03-16T23:06:24Z\n", + " metadata: {}\n", + " outputContract:\n", + " timeout: 1679011584000\n", + " timeout_continuation: close\n", + " when:\n", + " - case:\n", + " choose_between:\n", + " - from: 1\n", + " to: 1\n", + " for_choice:\n", + " choice_name: Confirm problem\n", + " choice_owner:\n", + " role_token: Seller\n", + " then: close\n", + " - case:\n", + " choose_between:\n", + " - from: 0\n", + " to: 0\n", + " for_choice:\n", + " choice_name: Dispute problem\n", + " choice_owner:\n", + " role_token: Seller\n", + " then:\n", + " timeout: 1679015184000\n", + " timeout_continuation: close\n", + " when:\n", + " - case:\n", + " choose_between:\n", + " - from: 0\n", + " to: 0\n", + " for_choice:\n", + " choice_name: Dismiss claim\n", + " choice_owner:\n", + " role_token: Mediator\n", + " then:\n", + " from_account:\n", + " role_token: Buyer\n", + " pay: 75000000\n", + " then: close\n", + " to:\n", + " account:\n", + " role_token: Seller\n", + " token:\n", + " currency_symbol: ''\n", + " token_name: ''\n", + " - case:\n", + " choose_between:\n", + " - from: 1\n", + " to: 1\n", + " for_choice:\n", + " choice_name: Confirm claim\n", + " choice_owner:\n", + " role_token: Mediator\n", + " then: close\n", + " outputState:\n", + " accounts:\n", + " - - - address: addr_test1vr6tytqs3x8qgewhw89m3xrz58t3tqu2hfsecw0u06lf3hg052wsv\n", + " - currency_symbol: ''\n", + " token_name: ''\n", + " - 2000000\n", + " - - - role_token: Buyer\n", + " - currency_symbol: ''\n", + " token_name: ''\n", + " - 75000000\n", + " boundValues: []\n", + " choices:\n", + " - - choice_name: Report problem\n", + " choice_owner:\n", + " role_token: Buyer\n", + " - 1\n", + " minTime: 1679000872000\n", + " outputUtxo: 5a448f6b4861e36a984e880c6e46a7dacd8513de0fa27daf46f9c1d0ccac50af#1\n", + " status: confirmed\n", + " tags: {}\n", + " transactionId: 5a448f6b4861e36a984e880c6e46a7dacd8513de0fa27daf46f9c1d0ccac50af\n", + " txBody: null\n" + ] + } + ], + "source": [ + "curl -sS \"$CONTRACT_URL/transactions/$TX_3\" | json2yaml" + ] + }, + { + "cell_type": "markdown", + "id": "6429ba4f-da3b-485f-9515-fc4fd0fc8e05", + "metadata": {}, + "source": [ + "## Transaction 4: The Seller Disputes that There is a Problem\n", + "\n", + "Now the seller chooses to dispute that there is a problem with the merchandise." + ] + }, + { + "cell_type": "code", + "execution_count": 51, + "id": "f726d751-dee2-46e3-8d95-066fbb3c4a8f", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "for_choice_id:\n", + " choice_name: Dispute problem\n", + " choice_owner:\n", + " role_token: Seller\n", + "input_that_chooses_num: 0\n" + ] + } + ], + "source": [ + "marlowe-cli input choose \\\n", + " --choice-name \"Dispute problem\" \\\n", + " --choice-party Seller \\\n", + " --choice-number 0 \\\n", + " --out-file input-4.json\n", + "json2yaml input-4.json" + ] + }, + { + "cell_type": "code", + "execution_count": 52, + "id": "10fe530d-ba44-4ef8-bc8f-a4fa9f301c1f", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{\"inputs\":[{\"for_choice_id\":{\"choice_name\":\"Dispute problem\",\"choice_owner\":{\"role_token\":\"Seller\"}},\"input_that_chooses_num\":0}],\"metadata\":{},\"tags\":{},\"version\":\"v1\"}\n" + ] + } + ], + "source": [ + "yaml2json << EOI > request-4.json\n", + "version: v1\n", + "inputs: [$(cat input-4.json)]\n", + "metadata: {}\n", + "tags: {}\n", + "EOI\n", + "cat request-4.json" + ] + }, + { + "cell_type": "markdown", + "id": "9566de68-290f-4f24-a9f7-a160aea60d17", + "metadata": {}, + "source": [ + "Next we post the request and store the response." + ] + }, + { + "cell_type": "code", + "execution_count": 53, + "id": "f430a724-b919-432b-a06d-1d179a746f7d", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "links:\n", + " transaction: contracts/3376c0eae5aa40e75e5d1d2264faa1a30a314a3d8ca9b6da99c5c04de9349a20%231/transactions/0f40ff5e41521e03a15837f3f1ee1436103ed64a1b55c5698bdd8a8db6ab043c\n", + "resource:\n", + " contractId: 3376c0eae5aa40e75e5d1d2264faa1a30a314a3d8ca9b6da99c5c04de9349a20#1\n", + " transactionId: 0f40ff5e41521e03a15837f3f1ee1436103ed64a1b55c5698bdd8a8db6ab043c\n", + " txBody:\n", + " cborHex: 86aa00838258203376c0eae5aa40e75e5d1d2264faa1a30a314a3d8ca9b6da99c5c04de9349a20048258205a448f6b4861e36a984e880c6e46a7dacd8513de0fa27daf46f9c1d0ccac50af01825820b32eab58a670cc0164c9c2c615c81b40dc9229ab8d899db8f232bbede0984107020d81825820b32eab58a670cc0164c9c2c615c81b40dc9229ab8d899db8f232bbede09841070212818258209a8a6f387a3330b4141e1cb019380b9ac5c72151c0abc52aa4266245d3c555cd010183a200581d601b120d7221aa5e7db58fd8e0753e156cf8c38742546a907e8104cc59011a3b9025c2a300581d702ed2631dbb277c84334453c5c437b86325d371f0835a28b910a91a6e011a0496ed4002820058203431d4dd22e93ac8a724511fd960b137d98905a2aad7b59ee299790f9c9f7f2ca200581d601b120d7221aa5e7db58fd8e0753e156cf8c38742546a907e8104cc5901821a000fc8a0a1581cbf35f1fb673d65bd7fc65e90e52213e7c70ceadfab633e9765be060ba14653656c6c65720110a200581d601b120d7221aa5e7db58fd8e0753e156cf8c38742546a907e8104cc59011a3b8ad3a3111a000ff65d021a000aa43e031a0163f680081a0163ccc90b58207d8c2b031e4986d6400c5957fa3d3f3208d07830146098b46a9b5f7515642cb59fff82d8799fd8799f581cbf35f1fb673d65bd7fc65e90e52213e7c70ceadfab633e9765be060bffd8799fa2d8799fd8799fd87980d8799fd8799f581cf4b22c10898e0465d771cbb89862a1d715838aba619c39fc7ebe98ddffd87a80ffffd8799f4040ffff1a001e8480d8799fd87a9f454275796572ffd8799f4040ffff1a047868c0a2d8799f4e5265706f72742070726f626c656dd87a9f454275796572ffff01d8799f4f446973707574652070726f626c656dd87a9f4653656c6c6572ffff00a01b00000186ec40a528ffd87c9f9fd8799fd87a9fd8799f4d4469736d69737320636c61696dd87a9f484d65646961746f72ffff9fd8799f0000ffffffd87a9fd87a9f454275796572ffd8799fd87a9f4653656c6c6572ffffd8799f4040ffd87a9f1a047868c0ffd87980ffffd8799fd87a9fd8799f4d436f6e6669726d20636c61696dd87a9f484d65646961746f72ffff9fd8799f0101ffffffd87980ffff1b00000186ed1a8680d87980ffffd8799fd8799f581cbf35f1fb673d65bd7fc65e90e52213e7c70ceadfab633e9765be060bffd8799fa2d8799fd8799fd87980d8799fd8799f581cf4b22c10898e0465d771cbb89862a1d715838aba619c39fc7ebe98ddffd87a80ffffd8799f4040ffff1a001e8480d8799fd87a9f454275796572ffd8799f4040ffff1a047868c0a1d8799f4e5265706f72742070726f626c656dd87a9f454275796572ffff01a01b00000186ec402440ffd87c9f9fd8799fd87a9fd8799f4f436f6e6669726d2070726f626c656dd87a9f4653656c6c6572ffff9fd8799f0101ffffffd87980ffd8799fd87a9fd8799f4f446973707574652070726f626c656dd87a9f4653656c6c6572ffff9fd8799f0000ffffffd87c9f9fd8799fd87a9fd8799f4d4469736d69737320636c61696dd87a9f484d65646961746f72ffff9fd8799f0000ffffffd87a9fd87a9f454275796572ffd8799fd87a9f4653656c6c6572ffffd8799f4040ffd87a9f1a047868c0ffd87980ffffd8799fd87a9fd8799f4d436f6e6669726d20636c61696dd87a9f484d65646961746f72ffff9fd8799f0101ffffffd87980ffff1b00000186ed1a8680d87980ffffff1b00000186ece39800d87980ffff818400019fd8799fd87a9fd8799f4f446973707574652070726f626c656dd87a9f4653656c6c6572ffff00ffffff821a005cded61a5f755401f5f6\n", + " description: ''\n", + " type: TxBodyBabbage\n" + ] + } + ], + "source": [ + "curl \"$CONTRACT_URL/transactions\" \\\n", + " -X POST \\\n", + " -H 'Content-Type: application/json' \\\n", + " -H \"X-Change-Address: $SELLER_ADDR\" \\\n", + " -d @request-4.json \\\n", + " -o response-4.json \\\n", + " -sS\n", + "json2yaml response-4.json" + ] + }, + { + "cell_type": "markdown", + "id": "28044680-041a-453b-8447-e4f210d8813d", + "metadata": {}, + "source": [ + "Once again, use `marlowe-cli` to submit the transaction and then wait for confirmation." + ] + }, + { + "cell_type": "code", + "execution_count": 54, + "id": "b6a98bfc-6ffd-4d4b-97a0-89e380f23f15", + "metadata": {}, + "outputs": [], + "source": [ + "jq '.resource.txBody' response-4.json > tx-4.unsigned" + ] + }, + { + "cell_type": "code", + "execution_count": 55, + "id": "01de4b62-c225-4675-8945-97292798286b", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "TX_4 = 0f40ff5e41521e03a15837f3f1ee1436103ed64a1b55c5698bdd8a8db6ab043c\n" + ] + } + ], + "source": [ + "TX_4=$(\n", + "marlowe-cli transaction submit \\\n", + " --tx-body-file tx-4.unsigned \\\n", + " --required-signer \"$SELLER_SKEY\" \\\n", + " --timeout 600 \\\n", + "| sed -e 's/^TxId \"\\(.*\\)\"$/\\1/' \\\n", + ")\n", + "echo \"TX_4 = $TX_4\"" + ] + }, + { + "cell_type": "markdown", + "id": "75f2da2a-27b4-42c4-9215-c793a4501d85", + "metadata": {}, + "source": [ + "One can view the transaction on a Cardano explorer. It sometimes takes thirty seconds or so for the transaction to be visible in an explorer." + ] + }, + { + "cell_type": "code", + "execution_count": 56, + "id": "3bc43634-af98-43a7-bcd1-0d2bc8ab6a88", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "https://preprod.cardanoscan.io/transaction/0f40ff5e41521e03a15837f3f1ee1436103ed64a1b55c5698bdd8a8db6ab043c?tab=utxo\n" + ] + } + ], + "source": [ + "echo \"$EXPLORER_URL/transaction/$TX_4?tab=utxo\"" + ] + }, + { + "cell_type": "markdown", + "id": "fb5a46df-5530-4e8e-9684-05d228cc4a25", + "metadata": {}, + "source": [ + "One can see that the seller still has approximately their original balance." + ] + }, + { + "cell_type": "code", + "execution_count": 57, + "id": "99a542df-cd08-4cc3-b835-24498d673969", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " TxHash TxIx Amount\n", + "--------------------------------------------------------------------------------------\n", + "0f40ff5e41521e03a15837f3f1ee1436103ed64a1b55c5698bdd8a8db6ab043c 0 999302594 lovelace + TxOutDatumNone\n", + "0f40ff5e41521e03a15837f3f1ee1436103ed64a1b55c5698bdd8a8db6ab043c 2 1034400 lovelace + 1 bf35f1fb673d65bd7fc65e90e52213e7c70ceadfab633e9765be060b.53656c6c6572 + TxOutDatumNone\n" + ] + } + ], + "source": [ + "cardano-cli query utxo --testnet-magic \"$CARDANO_TESTNET_MAGIC\" --address \"$SELLER_ADDR\"" + ] + }, + { + "cell_type": "markdown", + "id": "d94596e2-757a-4ead-b81f-89187f481908", + "metadata": {}, + "source": [ + "The Marlowe contract still has the 77 ada." + ] + }, + { + "cell_type": "code", + "execution_count": 58, + "id": "4d076dc7-1768-4a3d-b11f-61ed2c5f1318", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " TxHash TxIx Amount\n", + "--------------------------------------------------------------------------------------\n", + "0f40ff5e41521e03a15837f3f1ee1436103ed64a1b55c5698bdd8a8db6ab043c 1 77000000 lovelace + TxOutDatumHash ScriptDataInBabbageEra \"3431d4dd22e93ac8a724511fd960b137d98905a2aad7b59ee299790f9c9f7f2c\"\n" + ] + } + ], + "source": [ + "cardano-cli query utxo --testnet-magic \"$CARDANO_TESTNET_MAGIC\" --tx-in \"$TX_4#1\"" + ] + }, + { + "cell_type": "markdown", + "id": "2dba77ee-2f74-4d31-a825-39383a6cd1c7", + "metadata": {}, + "source": [ + "## View the further progress of the contract on the blockchain\n", + "\n", + "Marlowe Runtime\\'s `HTTP` `GET` endpoint `/contracts/{contractId}/transactions/{transactionId}` can fetch a contract from the blockchain and return information about it." + ] + }, + { + "cell_type": "code", + "execution_count": 59, + "id": "92f51247-9285-45a4-93b9-1d561425a4cf", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "links:\n", + " previous: contracts/3376c0eae5aa40e75e5d1d2264faa1a30a314a3d8ca9b6da99c5c04de9349a20%231/transactions/5a448f6b4861e36a984e880c6e46a7dacd8513de0fa27daf46f9c1d0ccac50af\n", + "resource:\n", + " block:\n", + " blockHeaderHash: d46d1d6a3554c29d439fd818cec68a8deb0c46f31efdc17c7161a2287fe15103\n", + " blockNo: 732037\n", + " slotNo: 23317731\n", + " consumingTx: null\n", + " continuations: null\n", + " contractId: 3376c0eae5aa40e75e5d1d2264faa1a30a314a3d8ca9b6da99c5c04de9349a20#1\n", + " inputUtxo: 5a448f6b4861e36a984e880c6e46a7dacd8513de0fa27daf46f9c1d0ccac50af#1\n", + " inputs:\n", + " - for_choice_id:\n", + " choice_name: Dispute problem\n", + " choice_owner:\n", + " role_token: Seller\n", + " input_that_chooses_num: 0\n", + " invalidBefore: 2023-03-16T21:08:25Z\n", + " invalidHereafter: 2023-03-17T00:06:24Z\n", + " metadata: {}\n", + " outputContract:\n", + " timeout: 1679015184000\n", + " timeout_continuation: close\n", + " when:\n", + " - case:\n", + " choose_between:\n", + " - from: 0\n", + " to: 0\n", + " for_choice:\n", + " choice_name: Dismiss claim\n", + " choice_owner:\n", + " role_token: Mediator\n", + " then:\n", + " from_account:\n", + " role_token: Buyer\n", + " pay: 75000000\n", + " then: close\n", + " to:\n", + " account:\n", + " role_token: Seller\n", + " token:\n", + " currency_symbol: ''\n", + " token_name: ''\n", + " - case:\n", + " choose_between:\n", + " - from: 1\n", + " to: 1\n", + " for_choice:\n", + " choice_name: Confirm claim\n", + " choice_owner:\n", + " role_token: Mediator\n", + " then: close\n", + " outputState:\n", + " accounts:\n", + " - - - address: addr_test1vr6tytqs3x8qgewhw89m3xrz58t3tqu2hfsecw0u06lf3hg052wsv\n", + " - currency_symbol: ''\n", + " token_name: ''\n", + " - 2000000\n", + " - - - role_token: Buyer\n", + " - currency_symbol: ''\n", + " token_name: ''\n", + " - 75000000\n", + " boundValues: []\n", + " choices:\n", + " - - choice_name: Report problem\n", + " choice_owner:\n", + " role_token: Buyer\n", + " - 1\n", + " - - choice_name: Dispute problem\n", + " choice_owner:\n", + " role_token: Seller\n", + " - 0\n", + " minTime: 1679000905000\n", + " outputUtxo: 0f40ff5e41521e03a15837f3f1ee1436103ed64a1b55c5698bdd8a8db6ab043c#1\n", + " status: confirmed\n", + " tags: {}\n", + " transactionId: 0f40ff5e41521e03a15837f3f1ee1436103ed64a1b55c5698bdd8a8db6ab043c\n", + " txBody: null\n" + ] + } + ], + "source": [ + "curl -sS \"$CONTRACT_URL/transactions/$TX_4\" | json2yaml" + ] + }, + { + "cell_type": "markdown", + "id": "29edde4f-b562-4310-8ffb-0f083fe5d247", + "metadata": {}, + "source": [ + "## Transaction 5: The Mediator Dismisses the Claim\n", + "\n", + "The mediator rules in favor or the seller and dismisses the buyer's claim." + ] + }, + { + "cell_type": "code", + "execution_count": 60, + "id": "3b6ea2d9-22f3-4cf8-a6c2-f4f4acadad70", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "for_choice_id:\n", + " choice_name: Dismiss claim\n", + " choice_owner:\n", + " role_token: Mediator\n", + "input_that_chooses_num: 0\n" + ] + } + ], + "source": [ + "marlowe-cli input choose \\\n", + " --choice-name \"Dismiss claim\" \\\n", + " --choice-party Mediator \\\n", + " --choice-number 0 \\\n", + " --out-file input-5.json\n", + "json2yaml input-5.json" + ] + }, + { + "cell_type": "code", + "execution_count": 61, + "id": "91be787b-0a96-4ea9-8f50-e942abb381b8", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{\"inputs\":[{\"for_choice_id\":{\"choice_name\":\"Dismiss claim\",\"choice_owner\":{\"role_token\":\"Mediator\"}},\"input_that_chooses_num\":0}],\"metadata\":{},\"tags\":{},\"version\":\"v1\"}\n" + ] + } + ], + "source": [ + "yaml2json << EOI > request-5.json\n", + "version: v1\n", + "inputs: [$(cat input-5.json)]\n", + "metadata: {}\n", + "tags: {}\n", + "EOI\n", + "cat request-5.json" + ] + }, + { + "cell_type": "markdown", + "id": "a9f003fb-7d2b-4f4b-bf4b-ed1b7821d84e", + "metadata": {}, + "source": [ + "Next we post the request and store the response." + ] + }, + { + "cell_type": "code", + "execution_count": 62, + "id": "e5d6e036-aa13-4b93-9d9d-499787d05341", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "links:\n", + " transaction: contracts/3376c0eae5aa40e75e5d1d2264faa1a30a314a3d8ca9b6da99c5c04de9349a20%231/transactions/182a53706d9eedb1b66d8e86d54351ba8a7822fc2361e1cdb6a129f265d22040\n", + "resource:\n", + " contractId: 3376c0eae5aa40e75e5d1d2264faa1a30a314a3d8ca9b6da99c5c04de9349a20#1\n", + " transactionId: 182a53706d9eedb1b66d8e86d54351ba8a7822fc2361e1cdb6a129f265d22040\n", + " txBody:\n", + " cborHex: 86aa00838258200f40ff5e41521e03a15837f3f1ee1436103ed64a1b55c5698bdd8a8db6ab043c018258203376c0eae5aa40e75e5d1d2264faa1a30a314a3d8ca9b6da99c5c04de9349a20008258203376c0eae5aa40e75e5d1d2264faa1a30a314a3d8ca9b6da99c5c04de9349a20030d818258203376c0eae5aa40e75e5d1d2264faa1a30a314a3d8ca9b6da99c5c04de9349a200012818258209a8a6f387a3330b4141e1cb019380b9ac5c72151c0abc52aa4266245d3c555cd010184a200581d60f4b22c10898e0465d771cbb89862a1d715838aba619c39fc7ebe98dd011a3b39ea31a200581d60f4b22c10898e0465d771cbb89862a1d715838aba619c39fc7ebe98dd01821a000fea4ca1581cbf35f1fb673d65bd7fc65e90e52213e7c70ceadfab633e9765be060ba1484d65646961746f7201a300581d70e165610232235bbbbeff5b998b233daae42979dec92a6722d9cda989011a047868c002820058201fc22e57cbb141ffcba4d63f002e03cb55031186880e32e5448e526044eaacd5a200581d60f4b22c10898e0465d771cbb89862a1d715838aba619c39fc7ebe98dd011a001e848010a200581d60f4b22c10898e0465d771cbb89862a1d715838aba619c39fc7ebe98dd011a3b340eb0111a00119282021a000bb701031a01640490081a0163cce30b5820795ec7b34bc6976b470472b6f6baa2715f9e0b08b71f9a28ff1d4a3700f30e0c9fff82d8799f581cbf35f1fb673d65bd7fc65e90e52213e7c70ceadfab633e9765be060b4653656c6c6572ffd8799fd8799f581cbf35f1fb673d65bd7fc65e90e52213e7c70ceadfab633e9765be060bffd8799fa2d8799fd8799fd87980d8799fd8799f581cf4b22c10898e0465d771cbb89862a1d715838aba619c39fc7ebe98ddffd87a80ffffd8799f4040ffff1a001e8480d8799fd87a9f454275796572ffd8799f4040ffff1a047868c0a2d8799f4e5265706f72742070726f626c656dd87a9f454275796572ffff01d8799f4f446973707574652070726f626c656dd87a9f4653656c6c6572ffff00a01b00000186ec40a528ffd87c9f9fd8799fd87a9fd8799f4d4469736d69737320636c61696dd87a9f484d65646961746f72ffff9fd8799f0000ffffffd87a9fd87a9f454275796572ffd8799fd87a9f4653656c6c6572ffffd8799f4040ffd87a9f1a047868c0ffd87980ffffd8799fd87a9fd8799f4d436f6e6669726d20636c61696dd87a9f484d65646961746f72ffff9fd8799f0101ffffffd87980ffff1b00000186ed1a8680d87980ffff818400009fd8799fd87a9fd8799f4d4469736d69737320636c61696dd87a9f484d65646961746f72ffff00ffffff821a006eb82c1a6f28ce7df5f6\n", + " description: ''\n", + " type: TxBodyBabbage\n" + ] + } + ], + "source": [ + "curl \"$CONTRACT_URL/transactions\" \\\n", + " -X POST \\\n", + " -H 'Content-Type: application/json' \\\n", + " -H \"X-Change-Address: $MEDIATOR_ADDR\" \\\n", + " -d @request-5.json \\\n", + " -o response-5.json \\\n", + " -sS\n", + "json2yaml response-5.json" + ] + }, + { + "cell_type": "markdown", + "id": "e013214d-0294-467b-a13f-9b80eb837b4e", + "metadata": {}, + "source": [ + "Once again, use `marlowe-cli` to submit the transaction and then wait for confirmation." + ] + }, + { + "cell_type": "code", + "execution_count": 63, + "id": "6f48a296-9751-4496-9d4b-e9278104b437", + "metadata": {}, + "outputs": [], + "source": [ + "jq '.resource.txBody' response-5.json > tx-5.unsigned" + ] + }, + { + "cell_type": "code", + "execution_count": 64, + "id": "6c725733-bc6a-4903-a5cd-60766b258a40", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "TX_5 = 182a53706d9eedb1b66d8e86d54351ba8a7822fc2361e1cdb6a129f265d22040\n" + ] + } + ], + "source": [ + "TX_5=$(\n", + "marlowe-cli transaction submit \\\n", + " --tx-body-file tx-5.unsigned \\\n", + " --required-signer \"$MEDIATOR_SKEY\" \\\n", + " --timeout 600 \\\n", + "| sed -e 's/^TxId \"\\(.*\\)\"$/\\1/' \\\n", + ")\n", + "echo \"TX_5 = $TX_5\"" + ] + }, + { + "cell_type": "markdown", + "id": "69c913d9-8a05-4cbc-b229-b0e0ec22e0ee", + "metadata": {}, + "source": [ + "One can view the transaction on a Cardano explorer. It sometimes takes thirty seconds or so for the transaction to be visible in an explorer." + ] + }, + { + "cell_type": "code", + "execution_count": 65, + "id": "05eaf50a-f7c9-4af8-9bd1-fdc72c6e3cd2", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "https://preprod.cardanoscan.io/transaction/182a53706d9eedb1b66d8e86d54351ba8a7822fc2361e1cdb6a129f265d22040?tab=utxo\n" + ] + } + ], + "source": [ + "echo \"$EXPLORER_URL/transaction/$TX_5?tab=utxo\"" + ] + }, + { + "cell_type": "markdown", + "id": "dffff587-c8c3-43d2-b08c-cc881153234b", + "metadata": {}, + "source": [ + "One can see that the mediator still has approximately their original balance, which includes the 2 ada they just received, refunding the 2 ada they used to create the contract." + ] + }, + { + "cell_type": "code", + "execution_count": 66, + "id": "ee3f2e7f-0268-4c4a-84fe-bfc5ca2cf297", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " TxHash TxIx Amount\n", + "--------------------------------------------------------------------------------------\n", + "182a53706d9eedb1b66d8e86d54351ba8a7822fc2361e1cdb6a129f265d22040 0 993651249 lovelace + TxOutDatumNone\n", + "182a53706d9eedb1b66d8e86d54351ba8a7822fc2361e1cdb6a129f265d22040 1 1043020 lovelace + 1 bf35f1fb673d65bd7fc65e90e52213e7c70ceadfab633e9765be060b.4d65646961746f72 + TxOutDatumNone\n", + "182a53706d9eedb1b66d8e86d54351ba8a7822fc2361e1cdb6a129f265d22040 3 2000000 lovelace + TxOutDatumNone\n" + ] + } + ], + "source": [ + "cardano-cli query utxo --testnet-magic \"$CARDANO_TESTNET_MAGIC\" --address \"$MEDIATOR_ADDR\"" + ] + }, + { + "cell_type": "markdown", + "id": "ff85a692-9d89-40c2-a8bd-76f5b5eedcad", + "metadata": {}, + "source": [ + "The Marlowe contract is closed, but the role-payout address has the 75 ada for the benefit of the seller." + ] + }, + { + "cell_type": "code", + "execution_count": 67, + "id": "de0b22dd-6563-4376-a9f7-fda2dd58939f", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " TxHash TxIx Amount\n", + "--------------------------------------------------------------------------------------\n", + "182a53706d9eedb1b66d8e86d54351ba8a7822fc2361e1cdb6a129f265d22040 2 75000000 lovelace + TxOutDatumHash ScriptDataInBabbageEra \"1fc22e57cbb141ffcba4d63f002e03cb55031186880e32e5448e526044eaacd5\"\n" + ] + } + ], + "source": [ + "cardano-cli query utxo --testnet-magic \"$CARDANO_TESTNET_MAGIC\" --tx-in \"$TX_5#2\"" + ] + }, + { + "cell_type": "markdown", + "id": "55eab573-dd77-4a93-ac7f-53db59265233", + "metadata": {}, + "source": [ + "## View the further progress of the contract on the blockchain\n", + "\n", + "Marlowe Runtime\\'s `HTTP` `GET` endpoint `/contracts/{contractId}/transactions/{transactionId}` can fetch a contract from the blockchain and return information about it." + ] + }, + { + "cell_type": "code", + "execution_count": 68, + "id": "6c5841e6-f94b-4f62-9a9e-efab8b427aa2", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "links:\n", + " previous: contracts/3376c0eae5aa40e75e5d1d2264faa1a30a314a3d8ca9b6da99c5c04de9349a20%231/transactions/0f40ff5e41521e03a15837f3f1ee1436103ed64a1b55c5698bdd8a8db6ab043c\n", + "resource:\n", + " block:\n", + " blockHeaderHash: 23a80ec90982f747cba7f17992e673572a3d4b06d94bbfa13e1a62f3c9054396\n", + " blockNo: 732038\n", + " slotNo: 23317766\n", + " consumingTx: null\n", + " continuations: null\n", + " contractId: 3376c0eae5aa40e75e5d1d2264faa1a30a314a3d8ca9b6da99c5c04de9349a20#1\n", + " inputUtxo: 0f40ff5e41521e03a15837f3f1ee1436103ed64a1b55c5698bdd8a8db6ab043c#1\n", + " inputs:\n", + " - for_choice_id:\n", + " choice_name: Dismiss claim\n", + " choice_owner:\n", + " role_token: Mediator\n", + " input_that_chooses_num: 0\n", + " invalidBefore: 2023-03-16T21:08:51Z\n", + " invalidHereafter: 2023-03-17T01:06:24Z\n", + " metadata: {}\n", + " outputContract: null\n", + " outputState: null\n", + " outputUtxo: null\n", + " status: confirmed\n", + " tags: {}\n", + " transactionId: 182a53706d9eedb1b66d8e86d54351ba8a7822fc2361e1cdb6a129f265d22040\n", + " txBody: null\n" + ] + } + ], + "source": [ + "curl -sS \"$CONTRACT_URL/transactions/$TX_5\" | json2yaml" + ] + }, + { + "cell_type": "markdown", + "id": "1111ac65-fd60-429a-811f-dfe3440e6b95", + "metadata": {}, + "source": [ + "## Transaction 6: The Seller Withdraws Their Funds\n", + "\n", + "The price of 75 ada is held at Marlowe's role-payout address for the benefit of the seller. The seller can withdraw these funds at any time. The contract ID and role name are included in the request body for a withdrawal." + ] + }, + { + "cell_type": "code", + "execution_count": 69, + "id": "223cd7b7-30d5-4e7d-b99d-76a5926ff737", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{\"contractId\":\"3376c0eae5aa40e75e5d1d2264faa1a30a314a3d8ca9b6da99c5c04de9349a20#1\",\"role\":\"Seller\"}\n" + ] + } + ], + "source": [ + "yaml2json << EOI > request-6.json\n", + "contractId: \"$CONTRACT_ID\"\n", + "role: Seller\n", + "EOI\n", + "cat request-6.json" + ] + }, + { + "cell_type": "markdown", + "id": "7b3c9b1f-b55a-4a09-b0da-6a33ec67fb2c", + "metadata": {}, + "source": [ + "Next we post the request and store the response." + ] + }, + { + "cell_type": "code", + "execution_count": 70, + "id": "fae22f06-a0b5-4366-88c1-4926948dfb50", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "links:\n", + " withdrawal: withdrawals/850e4ce20d1c1b07f05c28d7d6c9d961597d1c29b90d6cf57f35f4629461ab5a\n", + "resource:\n", + " txBody:\n", + " cborHex: 86a800838258200f40ff5e41521e03a15837f3f1ee1436103ed64a1b55c5698bdd8a8db6ab043c008258200f40ff5e41521e03a15837f3f1ee1436103ed64a1b55c5698bdd8a8db6ab043c02825820182a53706d9eedb1b66d8e86d54351ba8a7822fc2361e1cdb6a129f265d22040020d818258200f40ff5e41521e03a15837f3f1ee1436103ed64a1b55c5698bdd8a8db6ab043c0012818258209a8a6f387a3330b4141e1cb019380b9ac5c72151c0abc52aa4266245d3c555cd020182a200581d601b120d7221aa5e7db58fd8e0753e156cf8c38742546a907e8104cc59011a40037f60a200581d601b120d7221aa5e7db58fd8e0753e156cf8c38742546a907e8104cc5901821a000fc8a0a1581cbf35f1fb673d65bd7fc65e90e52213e7c70ceadfab633e9765be060ba14653656c6c65720110a200581d601b120d7221aa5e7db58fd8e0753e156cf8c38742546a907e8104cc59011a3b888f0f111a000796b3021a00050f220b5820eb4a2171f8674f1256d443350ae57c518900b0398bdd259564e6935869d5c35e9fff81d8799f581cbf35f1fb673d65bd7fc65e90e52213e7c70ceadfab633e9765be060b4653656c6c6572ff81840002d87980821a001b8ea21a1df5686ff5f6\n", + " description: ''\n", + " type: TxBodyBabbage\n", + " withdrawalId: 850e4ce20d1c1b07f05c28d7d6c9d961597d1c29b90d6cf57f35f4629461ab5a\n" + ] + } + ], + "source": [ + "curl \"$MARLOWE_RT_WEBSERVER_URL/withdrawals\" \\\n", + " -X POST \\\n", + " -H 'Content-Type: application/json' \\\n", + " -H \"X-Change-Address: $SELLER_ADDR\" \\\n", + " -d @request-6.json \\\n", + " -o response-6.json \\\n", + " -sS\n", + "json2yaml response-6.json" + ] + }, + { + "cell_type": "markdown", + "id": "afefec57-7bba-4c88-82db-6a0f429bf6bb", + "metadata": {}, + "source": [ + "Once again, use `marlowe-cli` to submit the transaction and then wait for confirmation." + ] + }, + { + "cell_type": "code", + "execution_count": 71, + "id": "e5d6f45f-89cf-402b-8a17-520a85d9f757", + "metadata": {}, + "outputs": [], + "source": [ + "jq '.resource.txBody' response-6.json > tx-6.unsigned" + ] + }, + { + "cell_type": "code", + "execution_count": 72, + "id": "c7fa907d-07d8-46b2-9ece-a6f52320e628", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "TX_6 = 850e4ce20d1c1b07f05c28d7d6c9d961597d1c29b90d6cf57f35f4629461ab5a\n" + ] + } + ], + "source": [ + "TX_6=$(\n", + "marlowe-cli transaction submit \\\n", + " --tx-body-file tx-6.unsigned \\\n", + " --required-signer \"$SELLER_SKEY\" \\\n", + " --timeout 600 \\\n", + "| sed -e 's/^TxId \"\\(.*\\)\"$/\\1/' \\\n", + ")\n", + "echo \"TX_6 = $TX_6\"" + ] + }, + { + "cell_type": "markdown", + "id": "89158154-d547-4378-806b-de1d7662503e", + "metadata": {}, + "source": [ + "On can view the transaction on a Cardano explorer. It sometimes takes thirty seconds or so for the transaction to be visible in an explorer." + ] + }, + { + "cell_type": "code", + "execution_count": 73, + "id": "331d652b-e7fa-4eb0-96a3-e5cfa565b1b9", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "https://preprod.cardanoscan.io/transaction/850e4ce20d1c1b07f05c28d7d6c9d961597d1c29b90d6cf57f35f4629461ab5a?tab=utxo\n" + ] + } + ], + "source": [ + "echo \"$EXPLORER_URL/transaction/$TX_6?tab=utxo\"" + ] + }, + { + "cell_type": "markdown", + "id": "2dfa5c8a-938f-4d0d-a806-ca65b688ae32", + "metadata": {}, + "source": [ + "The seller now has about an additional 75 ada." + ] + }, + { + "cell_type": "code", + "execution_count": 74, + "id": "18fabe44-1bd2-40ba-8764-f0b384fb5739", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " TxHash TxIx Amount\n", + "--------------------------------------------------------------------------------------\n", + "850e4ce20d1c1b07f05c28d7d6c9d961597d1c29b90d6cf57f35f4629461ab5a 0 1073971040 lovelace + TxOutDatumNone\n", + "850e4ce20d1c1b07f05c28d7d6c9d961597d1c29b90d6cf57f35f4629461ab5a 1 1034400 lovelace + 1 bf35f1fb673d65bd7fc65e90e52213e7c70ceadfab633e9765be060b.53656c6c6572 + TxOutDatumNone\n" + ] + } + ], + "source": [ + "cardano-cli query utxo --testnet-magic \"$CARDANO_TESTNET_MAGIC\" --address \"$SELLER_ADDR\"" + ] + }, + { + "cell_type": "markdown", + "id": "97b64a91-527f-4456-9798-c214a8a795b8", + "metadata": {}, + "source": [ + "## View the withdrawal\n", + "\n", + "Marlowe Runtime\\'s `HTTP` `GET` endpoint `/withdrawals/{transactionId}` can fetch a withdrawal from the blockchain and return information about it." + ] + }, + { + "cell_type": "code", + "execution_count": 75, + "id": "72ca3c23-4074-4581-ac08-30f46fca17b4", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "block:\n", + " blockHeaderHash: 4dfa1ea56ce98d4f8a476e808ce5f5c2803ffd76d4b8ba3ee83f57ec816d9f66\n", + " blockNo: 732039\n", + " slotNo: 23317779\n", + "payouts:\n", + "- contractId: 3376c0eae5aa40e75e5d1d2264faa1a30a314a3d8ca9b6da99c5c04de9349a20#1\n", + " payout: 182a53706d9eedb1b66d8e86d54351ba8a7822fc2361e1cdb6a129f265d22040#2\n", + " role: Seller\n", + " roleTokenMintingPolicyId: bf35f1fb673d65bd7fc65e90e52213e7c70ceadfab633e9765be060b\n", + "status: confirmed\n", + "withdrawalId: 850e4ce20d1c1b07f05c28d7d6c9d961597d1c29b90d6cf57f35f4629461ab5a\n" + ] + } + ], + "source": [ + "curl -sS \"$MARLOWE_RT_WEBSERVER_URL/withdrawals/$TX_6\" | json2yaml" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Bash with Marlowe Tools", + "language": "bash", + "name": "bash-minimal" + }, + "language_info": { + "codemirror_mode": "shell", + "file_extension": ".sh", + "mimetype": "text/x-sh", + "name": "bash" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/04-escrow-rest/dismiss-claim.svg b/04-escrow-rest/dismiss-claim.svg new file mode 100644 index 0000000..e58576a --- /dev/null +++ b/04-escrow-rest/dismiss-claim.svg @@ -0,0 +1,113 @@ + + + + + + +escrow + + + +minAda + +Mediator deposits minimum ADA. + + + +deposit + +Buyer deposits funds. + + + +minAda->deposit + + + + + +problem + +Does the buyer +report a problem? + + + +deposit->problem + + + + + +dispute + +Does the seller dispute +that there is a problem? + + + +problem->dispute + + +Report problem. + + + +sale + +Seller receives purchase price. +Mediator receives minimum ADA. + + + +problem->sale + + +Everything is alright. + + + +mediate + +Mediator decides. + + + +dispute->mediate + + +Dispute problem. + + + +refund + +Buyer receives refund. +Mediator receives minimum ADA. + + + +dispute->refund + + +Confirm problem. + + + +mediate->sale + + +Dismiss claim. + + + +mediate->refund + + +Confirm claim. + + + diff --git a/ReadMe.md b/ReadMe.md index 9314195..736acf0 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -6,7 +6,8 @@ - [1. ZCB using the Marlowe Runtime command-line client](01-runtime-cli/ReadMe.ipynb) - [2. ZCB using the Marlowe Runtime REST API](02-runtime-rest/ReadMe.ipynb) - [3. ZCB using the Marlowe command-line tool](03-marlowe-cli/ReadMe.ipynb) -- Additional Information + - [4. Escrow using Marlow Runtime REST API](04-escrow-rest/ReadMe.ipynb) +- [Additional Information](#additional-information) - [Overview of Marlowe Tools](#marlowe-tools) - [Overview of Marlowe Runtime](#marlowe-runtime) - [Using Marlowe Safely](#using-marlowe-safely) @@ -29,7 +30,7 @@ If you are unfamiliar with the Marlowe smart-contract language or with the Carda - [Lesson 1. Marlowe Runtime's Command-Line Interface](01-runtime-cli/ReadMe.ipynb): This lesson shows how to use Marlowe Runtime to execute a zero-coupon bond contract using the command line for a Cardano testnet. - [Lesson 2. Marlowe Runtime's REST Interface](02-runtime-rest/ReadMe.ipynb): This lesson shows how to use the REST API for Marlowe Runtime to execute a zero-coupon bond contract on a Cardano testnet. - [Lesson 3. Marlowe CLI](03-marlowe-cli/ReadMe.ipynb): This lesson shows how to use the Marlowe CLI without Marlowe Runtime to execute a zero-coupon bond contract on a Cardano testnet. - +- [Lesson 4. Escrow](04-escrow-rest/ReadMe.ipynb): This lessons shows how to use the REST API of Marlowe Runtime to execute an escrow contract on a Cardano testnet. ## Additional Information @@ -61,7 +62,7 @@ If one plans to run a Marlowe contract on the Cardano `mainnet`, then one should Here are the steps for checking the safety of a contract: -1. Understand the [Marlowe Language](https://marlowe-finance.io/) +1. Understand the [Marlowe Language](https://marlowe-finance.io/). 2. Understand Cardano\'s [Extended UTxO Model](https://docs.cardano.org/learn/eutxo-explainer). 3. Read and understand the [Marlowe Best Practices Guide](https://github.com/input-output-hk/marlowe-cardano/blob/main/marlowe/best-practices.md). 4. Read and understand the [Marlowe Security Guide](https://github.com/input-output-hk/marlowe-cardano/blob/main/marlowe/security.md). diff --git a/images/escrow-playground.png b/images/escrow-playground.png new file mode 100644 index 0000000..5bd1016 Binary files /dev/null and b/images/escrow-playground.png differ diff --git a/images/escrow-simulation.png b/images/escrow-simulation.png new file mode 100644 index 0000000..08594be Binary files /dev/null and b/images/escrow-simulation.png differ