From 5555f36351283195031d4ae2ff2197a000fc8fdc Mon Sep 17 00:00:00 2001 From: George Danezis Date: Wed, 5 Jun 2024 13:27:26 +0100 Subject: [PATCH 01/15] Simple python example --- examples/python/hello_walrus.py | 67 +++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 examples/python/hello_walrus.py diff --git a/examples/python/hello_walrus.py b/examples/python/hello_walrus.py new file mode 100644 index 00000000..495a4061 --- /dev/null +++ b/examples/python/hello_walrus.py @@ -0,0 +1,67 @@ +# Example of uploading and downloading a file to / from the Walrus service +# +# Prerequisites: +# +# - Configure Sui Client to connect to testnet, and some testnet Sui tokens +# see: https://docs.sui.io/guides/developer/getting-started/connect +# +# - Configure Walrus +# see: TODO +# +# - Run the Walrus client in daemon mode: +# $ walrus --config working_dir/client_config.yaml daemon -b 127.0.0.1:8899 +# + +# Std lib imports +import os +import time + +# External requests HTTP library +import requests + +ADDRESS = "127.0.0.1:8899" +EPOCHS = "5" + +# Helper functions to upload a blob +def upload_blob(ADDRESS, EPOCHS, data): + + # Upload the data to the Walrus service using a PUT request + store_url = f"http://{ADDRESS}/v1/store?epochs={EPOCHS}" + response = requests.put(store_url, data=random_data) + + # Assert the response status code + assert response.status_code == 200 + blob_id = response.text + return blob_id + +# Helper functions to download a blob +def download_blob(ADDRESS, blob_id): + + # Now read the same resource using the blob-id + read_url = f"http://{ADDRESS}/v1/{blob_id}" + response = requests.get(read_url) + + # Assert the response status code + assert response.status_code == 200 + return response.content + +# Upload a random 1MB string then download it, and check it matches +if __name__ == "__main__": + + # Generate a 1MB blob of random data + random_data = os.urandom(1024 * 1024) + + # Upload the blob to the Walrus service + start_time = time.time() + blob_id = upload_blob(ADDRESS, EPOCHS, random_data) + upload_time = time.time() + + # Now download the same blob using the blob-id + data = download_blob(ADDRESS, blob_id) + assert data == random_data + download_time = time.time() + + # Print some information about the blob + print(f"Blob ID: {blob_id} Size {len(random_data)} bytes") + print(f"Upload time: {upload_time - start_time:.2f}s") + print(f"Download time: {download_time - upload_time:.2f}s") From 61c7fa7073d209f02853142f11193d96d51fc9d7 Mon Sep 17 00:00:00 2001 From: George Danezis Date: Thu, 6 Jun 2024 11:41:01 +0100 Subject: [PATCH 02/15] New ignore --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 9dd8f184..ce040ba7 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,6 @@ build/ config.yml working_dir *.log + +# Walrus binary +./examples/CONFIG/bin/walrus \ No newline at end of file From 3022f91417f7f6293ebdd55a104239ead89c8e8e Mon Sep 17 00:00:00 2001 From: George Danezis Date: Thu, 6 Jun 2024 11:41:25 +0100 Subject: [PATCH 03/15] More python examples --- examples/python/hello_walrus_jsonapi.py | 106 ++++++++++++++++++ ...hello_walrus.py => hello_walrus_webapi.py} | 3 +- examples/python/utils.py | 17 +++ 3 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 examples/python/hello_walrus_jsonapi.py rename examples/python/{hello_walrus.py => hello_walrus_webapi.py} (95%) create mode 100644 examples/python/utils.py diff --git a/examples/python/hello_walrus_jsonapi.py b/examples/python/hello_walrus_jsonapi.py new file mode 100644 index 00000000..ec0f28ee --- /dev/null +++ b/examples/python/hello_walrus_jsonapi.py @@ -0,0 +1,106 @@ +# Example of uploading and downloading a file to / from the Walrus service +# Using the walrus client json input & output facilities. +# +# Prerequisites: +# +# - Configure Sui Client to connect to testnet, and some testnet Sui tokens +# see: https://docs.sui.io/guides/developer/getting-started/connect +# +# - Configure Walrus +# see: TODO +# +# - Update the paths PATH_TO_WALRUS and PATH_TO_WALRUS_CONFIG below +# + +# Std lib imports +import os +import subprocess +import json +import tempfile +import base64 + +import requests + +from utils import num_to_blob_id + +PATH_TO_WALRUS = "../CONFIG/bin/walrus" +PATH_TO_WALRUS_CONFIG = "../CONFIG/working_dir/client_config.yaml" + +try: + + # Create a 1MB file of random data + random_data = os.urandom(1024 * 1024) + tmp = tempfile.NamedTemporaryFile(delete=False) + tmp.write(random_data) + tmp.close() + + # Part 1. Upload the file to the Walrus service + store_json_command = f"""{{ "config" : "{PATH_TO_WALRUS_CONFIG}", + "command" : {{ "store" : + {{ "file" : "{tmp.name}", "epochs" : 2 }}}} + }}""" + result = subprocess.run( + [PATH_TO_WALRUS, "json"], + text=True, + capture_output=True, + input=store_json_command) + assert result.returncode == 0 + + # Parse the response and display key information + json_result_dict = json.loads(result.stdout.strip()) + print(f"Upload Blob ID: {json_result_dict['blob_id']} Size {len(random_data)} bytes") + sui_object_id = json_result_dict['sui_object_id'] + blob_id = json_result_dict['blob_id'] + print(f"Certificate in Object ID: {sui_object_id}") + + # Part 2. Download the file from the Walrus service + read_json_command = f"""{{ "config" : "{PATH_TO_WALRUS_CONFIG}", + "command" : {{ "read" : + {{ "blob_id" : "{json_result_dict['blob_id']}" }}}} + }}""" + result = subprocess.run( + [PATH_TO_WALRUS, "json"], + text=True, + capture_output=True, + input=read_json_command) + assert result.returncode == 0 + + # Parse the response and display key information + json_result_dict = json.loads(result.stdout.strip()) + downloaded_data = base64.b64decode(json_result_dict['blob']) + assert downloaded_data == random_data + + print(f"Download Blob ID: {json_result_dict['blob_id']} Size {len(downloaded_data)} bytes") + + # Part 3. Check the availability of the blob + request = { + "jsonrpc": "2.0", + "id": 1, + "method": "sui_getObject", + "params": [ + sui_object_id, + { + "showType": True, + "showOwner": False, + "showPreviousTransaction": True, + "showDisplay": False, + "showContent": True, + "showBcs": False, + "showStorageRebate": False + } + ] + } + response = requests.post("https://fullnode.testnet.sui.io:443", json=request) + object_content = response.json()["result"]["data"]["content"] + print("Object content:") + print(json.dumps(object_content, indent=4)) + + # Check that the blob ID matches the one we uploaded + blob_id_downloaded = int(object_content["fields"]["blob_id"]) + if num_to_blob_id(blob_id_downloaded) == blob_id: + print("Blob ID matches certificate!") + else: + print("Blob ID does not match") + +finally: + os.unlink(tmp.name) diff --git a/examples/python/hello_walrus.py b/examples/python/hello_walrus_webapi.py similarity index 95% rename from examples/python/hello_walrus.py rename to examples/python/hello_walrus_webapi.py index 495a4061..680a2fdd 100644 --- a/examples/python/hello_walrus.py +++ b/examples/python/hello_walrus_webapi.py @@ -1,4 +1,5 @@ # Example of uploading and downloading a file to / from the Walrus service +# Using the walrus client web API facilities. # # Prerequisites: # @@ -27,7 +28,7 @@ def upload_blob(ADDRESS, EPOCHS, data): # Upload the data to the Walrus service using a PUT request store_url = f"http://{ADDRESS}/v1/store?epochs={EPOCHS}" - response = requests.put(store_url, data=random_data) + response = requests.put(store_url, data=data) # Assert the response status code assert response.status_code == 200 diff --git a/examples/python/utils.py b/examples/python/utils.py new file mode 100644 index 00000000..f7a866d1 --- /dev/null +++ b/examples/python/utils.py @@ -0,0 +1,17 @@ +import base64 + +# Convert a numeric (u256) blob_id to a base64 encoded Blob ID +def num_to_blob_id(blob_id_num): + extracted_bytes = [] + for i in range(32): + extracted_bytes += [ blob_id_num & 0xff ] + blob_id_num = blob_id_num >> 8 + assert blob_id_num == 0 + blob_id_bytes = bytes(extracted_bytes) + encoded = base64.urlsafe_b64encode(blob_id_bytes) + return encoded.decode("ascii").strip("=") + +if __name__ == "__main__": + blob_id_num = 46269954626831698189342469164469112511517843773769981308926739591706762839432 + blob_id_base64 = "iIWkkUTzPZx-d1E_A7LqUynnYFD-ztk39_tP8MLdS2Y" + assert num_to_blob_id(blob_id_num) == blob_id_base64 From dcead3da537706241ab29357e50630b5825dc93e Mon Sep 17 00:00:00 2001 From: George Danezis Date: Thu, 6 Jun 2024 11:41:40 +0100 Subject: [PATCH 04/15] fix ignore --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index ce040ba7..750e099b 100644 --- a/.gitignore +++ b/.gitignore @@ -20,4 +20,4 @@ working_dir *.log # Walrus binary -./examples/CONFIG/bin/walrus \ No newline at end of file +examples/CONFIG/bin/walrus \ No newline at end of file From 52a68bdfbad378c33de143181aca4edd70eba0b8 Mon Sep 17 00:00:00 2001 From: George Danezis Date: Thu, 6 Jun 2024 12:13:26 +0100 Subject: [PATCH 05/15] Clean up and system object script --- .gitignore | 4 ++ examples/CONFIG/config_dir/client_config.yaml | 34 ++++++++++++++ examples/python/hello_walrus_jsonapi.py | 2 +- examples/python/hello_walrus_sui_system.py | 45 +++++++++++++++++++ examples/python/hello_walrus_webapi.py | 2 +- 5 files changed, 85 insertions(+), 2 deletions(-) create mode 100644 examples/CONFIG/config_dir/client_config.yaml create mode 100644 examples/python/hello_walrus_sui_system.py diff --git a/.gitignore b/.gitignore index 750e099b..0e834423 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,10 @@ # mdBook build/ +# Python +__pycache__/ +*.pyc + # Misc *.key .env diff --git a/examples/CONFIG/config_dir/client_config.yaml b/examples/CONFIG/config_dir/client_config.yaml new file mode 100644 index 00000000..85393f07 --- /dev/null +++ b/examples/CONFIG/config_dir/client_config.yaml @@ -0,0 +1,34 @@ +system_pkg: 0x17108fb344dbea0d315e6f44cdd3af12a028cd568bafcbfb7f7a7b152719d15d +system_object: 0x3fb18e675ad41158f59acbdb7f574136a198cbd83be9b968c0fdeaa139c312f9 +wallet_config: null + +# Default values for the client are commented out. +# +# There is no risk in playing aroud with these values. +# Worst case, you may not be able to store/read from Walrus. + +# communication_config: +# max_concurrent_writes: null +# max_concurrent_sliver_reads: null +# max_concurrent_metadata_reads: 3 +# reqwest_config: +# total_timeout: +# secs: 180 +# nanos: 0 +# pool_idle_timeout: null +# http2_keep_alive_timeout: +# secs: 5 +# nanos: 0 +# http2_keep_alive_interval: +# secs: 30 +# nanos: 0 +# http2_keep_alive_while_idle: true +# request_rate_config: +# max_node_connections: 10 +# max_retries: 5 +# min_backoff: +# secs: 2 +# nanos: 0 +# max_backoff: +# secs: 60 +# nanos: 0 diff --git a/examples/python/hello_walrus_jsonapi.py b/examples/python/hello_walrus_jsonapi.py index ec0f28ee..a52b7954 100644 --- a/examples/python/hello_walrus_jsonapi.py +++ b/examples/python/hello_walrus_jsonapi.py @@ -24,7 +24,7 @@ from utils import num_to_blob_id PATH_TO_WALRUS = "../CONFIG/bin/walrus" -PATH_TO_WALRUS_CONFIG = "../CONFIG/working_dir/client_config.yaml" +PATH_TO_WALRUS_CONFIG = "../CONFIG/config_dir/client_config.yaml" try: diff --git a/examples/python/hello_walrus_sui_system.py b/examples/python/hello_walrus_sui_system.py new file mode 100644 index 00000000..bab048d6 --- /dev/null +++ b/examples/python/hello_walrus_sui_system.py @@ -0,0 +1,45 @@ +# Example of querying the Walrus system object on Sui +# +# Prerequisites: +# +# - Configure Walrus +# see: TODO +# +# - Update the paths PATH_TO_WALRUS_CONFIG below +# + +# Std lib imports +import requests +import re + +PATH_TO_WALRUS_CONFIG = "../CONFIG/config_dir/client_config.yaml" + +system_object_id = re.findall(r"system_object:[ ]*(.*)", open(PATH_TO_WALRUS_CONFIG).read())[0] +print(f'System object ID: {system_object_id}') + # Part 3. Check the availability of the blob +request = { +"jsonrpc": "2.0", +"id": 1, +"method": "sui_getObject", +"params": [ + system_object_id, + { + "showType": True, + "showOwner": False, + "showPreviousTransaction": True, + "showDisplay": False, + "showContent": True, + "showBcs": False, + "showStorageRebate": False + } +] +} +response = requests.post("https://fullnode.testnet.sui.io:443", json=request) +system_object_content = response.json()["result"]["data"]["content"]["fields"] +committee = system_object_content["current_committee"]["fields"]["bls_committee"]["fields"] + +print(f'Current walrus epoch: {system_object_content["current_committee"]["fields"]["epoch"]}') +print(f'Number of members: {len(committee["members"])} Number of shards: {committee["n_shards"]}') +print(f'Price per unit size: {system_object_content["price_per_unit_size"]} MIST') +print(f'Total capacity size: {system_object_content["total_capacity_size"]} bytes') +print(f'Used capacity size: {system_object_content["used_capacity_size"]} bytes') \ No newline at end of file diff --git a/examples/python/hello_walrus_webapi.py b/examples/python/hello_walrus_webapi.py index 680a2fdd..22582604 100644 --- a/examples/python/hello_walrus_webapi.py +++ b/examples/python/hello_walrus_webapi.py @@ -10,7 +10,7 @@ # see: TODO # # - Run the Walrus client in daemon mode: -# $ walrus --config working_dir/client_config.yaml daemon -b 127.0.0.1:8899 +# $ walrus --config config_dir/client_config.yaml daemon -b 127.0.0.1:8899 # # Std lib imports From 1deef299feead0bf7392da431d8011e9481cb349 Mon Sep 17 00:00:00 2001 From: George Danezis Date: Thu, 6 Jun 2024 12:14:22 +0100 Subject: [PATCH 06/15] Added info --- examples/CONFIG/bin/README.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 examples/CONFIG/bin/README.md diff --git a/examples/CONFIG/bin/README.md b/examples/CONFIG/bin/README.md new file mode 100644 index 00000000..64c30e0a --- /dev/null +++ b/examples/CONFIG/bin/README.md @@ -0,0 +1,3 @@ +# Congiration + +Place the 'walrus' client binary for your system in this directory. \ No newline at end of file From 5afe212e812063ad3f18b86112e2abe438b4f389 Mon Sep 17 00:00:00 2001 From: George Danezis Date: Thu, 6 Jun 2024 12:17:58 +0100 Subject: [PATCH 07/15] fix lints --- .gitignore | 2 +- examples/CONFIG/bin/README.md | 4 ++-- examples/CONFIG/config_dir/client_config.yaml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 0e834423..642125d0 100644 --- a/.gitignore +++ b/.gitignore @@ -24,4 +24,4 @@ working_dir *.log # Walrus binary -examples/CONFIG/bin/walrus \ No newline at end of file +examples/CONFIG/bin/walrus diff --git a/examples/CONFIG/bin/README.md b/examples/CONFIG/bin/README.md index 64c30e0a..44f07856 100644 --- a/examples/CONFIG/bin/README.md +++ b/examples/CONFIG/bin/README.md @@ -1,3 +1,3 @@ -# Congiration +# Configuration -Place the 'walrus' client binary for your system in this directory. \ No newline at end of file +Place the 'walrus' client binary for your system in this directory. diff --git a/examples/CONFIG/config_dir/client_config.yaml b/examples/CONFIG/config_dir/client_config.yaml index 85393f07..626ab41b 100644 --- a/examples/CONFIG/config_dir/client_config.yaml +++ b/examples/CONFIG/config_dir/client_config.yaml @@ -4,7 +4,7 @@ wallet_config: null # Default values for the client are commented out. # -# There is no risk in playing aroud with these values. +# There is no risk in playing around with these values. # Worst case, you may not be able to store/read from Walrus. # communication_config: From 6c2af1acb45e1c4e646518d6a733d801b82f22af Mon Sep 17 00:00:00 2001 From: George Danezis Date: Thu, 6 Jun 2024 12:19:57 +0100 Subject: [PATCH 08/15] Fix comment --- examples/python/hello_walrus_sui_system.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/examples/python/hello_walrus_sui_system.py b/examples/python/hello_walrus_sui_system.py index bab048d6..e1ca9b64 100644 --- a/examples/python/hello_walrus_sui_system.py +++ b/examples/python/hello_walrus_sui_system.py @@ -16,7 +16,8 @@ system_object_id = re.findall(r"system_object:[ ]*(.*)", open(PATH_TO_WALRUS_CONFIG).read())[0] print(f'System object ID: {system_object_id}') - # Part 3. Check the availability of the blob + +# Query the Walrus system object on Sui request = { "jsonrpc": "2.0", "id": 1, @@ -35,6 +36,8 @@ ] } response = requests.post("https://fullnode.testnet.sui.io:443", json=request) +assert response.status_code == 200 + system_object_content = response.json()["result"]["data"]["content"]["fields"] committee = system_object_content["current_committee"]["fields"]["bls_committee"]["fields"] From 45d809393e4dd3841046ddaa6767faf16f15588d Mon Sep 17 00:00:00 2001 From: George Danezis Date: Thu, 6 Jun 2024 12:23:00 +0100 Subject: [PATCH 09/15] Add requirements --- examples/python/requirements.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 examples/python/requirements.txt diff --git a/examples/python/requirements.txt b/examples/python/requirements.txt new file mode 100644 index 00000000..e000c3a7 --- /dev/null +++ b/examples/python/requirements.txt @@ -0,0 +1 @@ +requests>=2.22.0 \ No newline at end of file From 2b01f8fa019fa744dce382af13331a5c5a1c0795 Mon Sep 17 00:00:00 2001 From: George Danezis Date: Thu, 6 Jun 2024 12:26:23 +0100 Subject: [PATCH 10/15] Add new line to requirements file --- examples/python/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/python/requirements.txt b/examples/python/requirements.txt index e000c3a7..d5c2bc9c 100644 --- a/examples/python/requirements.txt +++ b/examples/python/requirements.txt @@ -1 +1 @@ -requests>=2.22.0 \ No newline at end of file +requests>=2.22.0 From ae092fef8a1eace8717b784edd7e8a251caddf69 Mon Sep 17 00:00:00 2001 From: George Danezis Date: Thu, 6 Jun 2024 12:26:35 +0100 Subject: [PATCH 11/15] New line --- examples/python/hello_walrus_sui_system.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/python/hello_walrus_sui_system.py b/examples/python/hello_walrus_sui_system.py index e1ca9b64..115241c5 100644 --- a/examples/python/hello_walrus_sui_system.py +++ b/examples/python/hello_walrus_sui_system.py @@ -45,4 +45,4 @@ print(f'Number of members: {len(committee["members"])} Number of shards: {committee["n_shards"]}') print(f'Price per unit size: {system_object_content["price_per_unit_size"]} MIST') print(f'Total capacity size: {system_object_content["total_capacity_size"]} bytes') -print(f'Used capacity size: {system_object_content["used_capacity_size"]} bytes') \ No newline at end of file +print(f'Used capacity size: {system_object_content["used_capacity_size"]} bytes') From 5207c4c0a3e5073a00b437ff21d9ca9587c82079 Mon Sep 17 00:00:00 2001 From: George Danezis Date: Thu, 6 Jun 2024 12:29:47 +0100 Subject: [PATCH 12/15] Added issue number to TODO --- examples/python/hello_walrus_jsonapi.py | 2 +- examples/python/hello_walrus_sui_system.py | 2 +- examples/python/hello_walrus_webapi.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/python/hello_walrus_jsonapi.py b/examples/python/hello_walrus_jsonapi.py index a52b7954..25ddc51c 100644 --- a/examples/python/hello_walrus_jsonapi.py +++ b/examples/python/hello_walrus_jsonapi.py @@ -7,7 +7,7 @@ # see: https://docs.sui.io/guides/developer/getting-started/connect # # - Configure Walrus -# see: TODO +# see: TODO(#12) # # - Update the paths PATH_TO_WALRUS and PATH_TO_WALRUS_CONFIG below # diff --git a/examples/python/hello_walrus_sui_system.py b/examples/python/hello_walrus_sui_system.py index 115241c5..0e179957 100644 --- a/examples/python/hello_walrus_sui_system.py +++ b/examples/python/hello_walrus_sui_system.py @@ -3,7 +3,7 @@ # Prerequisites: # # - Configure Walrus -# see: TODO +# see: TODO(#12) # # - Update the paths PATH_TO_WALRUS_CONFIG below # diff --git a/examples/python/hello_walrus_webapi.py b/examples/python/hello_walrus_webapi.py index 22582604..89dd630c 100644 --- a/examples/python/hello_walrus_webapi.py +++ b/examples/python/hello_walrus_webapi.py @@ -7,7 +7,7 @@ # see: https://docs.sui.io/guides/developer/getting-started/connect # # - Configure Walrus -# see: TODO +# see: TODO(#12) # # - Run the Walrus client in daemon mode: # $ walrus --config config_dir/client_config.yaml daemon -b 127.0.0.1:8899 From 58940cb3e75fcb5fb75b6c7fe189c1473cdc2016 Mon Sep 17 00:00:00 2001 From: George Danezis Date: Fri, 7 Jun 2024 12:13:49 +0100 Subject: [PATCH 13/15] Integrate review comments --- .gitignore | 1 + examples/CONFIG/config_dir/client_config.yaml | 4 ++ examples/python/README.md | 16 +++++ examples/python/hello_walrus_jsonapi.py | 69 ++++++++----------- examples/python/hello_walrus_sui_system.py | 58 ++++++++-------- examples/python/hello_walrus_webapi.py | 17 ++--- examples/python/utils.py | 14 +++- 7 files changed, 98 insertions(+), 81 deletions(-) create mode 100644 examples/python/README.md diff --git a/.gitignore b/.gitignore index 642125d0..18c94f47 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,7 @@ build/ # Python __pycache__/ +.venv/ *.pyc # Misc diff --git a/examples/CONFIG/config_dir/client_config.yaml b/examples/CONFIG/config_dir/client_config.yaml index 626ab41b..9210fb0d 100644 --- a/examples/CONFIG/config_dir/client_config.yaml +++ b/examples/CONFIG/config_dir/client_config.yaml @@ -1,5 +1,9 @@ system_pkg: 0x17108fb344dbea0d315e6f44cdd3af12a028cd568bafcbfb7f7a7b152719d15d system_object: 0x3fb18e675ad41158f59acbdb7f574136a198cbd83be9b968c0fdeaa139c312f9 + +# You can define a custom path to your Sui wallet configuration here. If this is unset or `null`, +# the wallet is configured from `./client.yaml`, `./sui_config.yaml` (both relative to your current +# working directory), or `~/.sui/sui_config/client.yaml` in this order. wallet_config: null # Default values for the client are commented out. diff --git a/examples/python/README.md b/examples/python/README.md new file mode 100644 index 00000000..8a10bbe4 --- /dev/null +++ b/examples/python/README.md @@ -0,0 +1,16 @@ +# Walrus Python Examples + + + +## Prerequisites: + + - Configure Sui Client to connect to testnet, and some testnet Sui tokens + see: https://docs.sui.io/guides/developer/getting-started/connect + - Configure Walrus + see: TODO(#12) + - Update the paths PATH_TO_WALRUS and PATH_TO_WALRUS_CONFIG and other + constant in 'utils.py' + +## Index of examples + + - ... diff --git a/examples/python/hello_walrus_jsonapi.py b/examples/python/hello_walrus_jsonapi.py index 25ddc51c..6beb3acb 100644 --- a/examples/python/hello_walrus_jsonapi.py +++ b/examples/python/hello_walrus_jsonapi.py @@ -1,16 +1,5 @@ # Example of uploading and downloading a file to / from the Walrus service # Using the walrus client json input & output facilities. -# -# Prerequisites: -# -# - Configure Sui Client to connect to testnet, and some testnet Sui tokens -# see: https://docs.sui.io/guides/developer/getting-started/connect -# -# - Configure Walrus -# see: TODO(#12) -# -# - Update the paths PATH_TO_WALRUS and PATH_TO_WALRUS_CONFIG below -# # Std lib imports import os @@ -21,13 +10,9 @@ import requests -from utils import num_to_blob_id - -PATH_TO_WALRUS = "../CONFIG/bin/walrus" -PATH_TO_WALRUS_CONFIG = "../CONFIG/config_dir/client_config.yaml" +from utils import num_to_blob_id, PATH_TO_WALRUS, PATH_TO_WALRUS_CONFIG, FULL_NODE_URL try: - # Create a 1MB file of random data random_data = os.urandom(1024 * 1024) tmp = tempfile.NamedTemporaryFile(delete=False) @@ -43,14 +28,17 @@ [PATH_TO_WALRUS, "json"], text=True, capture_output=True, - input=store_json_command) + input=store_json_command, + ) assert result.returncode == 0 # Parse the response and display key information json_result_dict = json.loads(result.stdout.strip()) - print(f"Upload Blob ID: {json_result_dict['blob_id']} Size {len(random_data)} bytes") - sui_object_id = json_result_dict['sui_object_id'] - blob_id = json_result_dict['blob_id'] + print( + f"Upload Blob ID: {json_result_dict['blob_id']} Size {len(random_data)} bytes" + ) + sui_object_id = json_result_dict["sui_object_id"] + blob_id = json_result_dict["blob_id"] print(f"Certificate in Object ID: {sui_object_id}") # Part 2. Download the file from the Walrus service @@ -62,35 +50,38 @@ [PATH_TO_WALRUS, "json"], text=True, capture_output=True, - input=read_json_command) + input=read_json_command, + ) assert result.returncode == 0 # Parse the response and display key information json_result_dict = json.loads(result.stdout.strip()) - downloaded_data = base64.b64decode(json_result_dict['blob']) + downloaded_data = base64.b64decode(json_result_dict["blob"]) assert downloaded_data == random_data - print(f"Download Blob ID: {json_result_dict['blob_id']} Size {len(downloaded_data)} bytes") + print( + f"Download Blob ID: {json_result_dict['blob_id']} Size {len(downloaded_data)} bytes" + ) # Part 3. Check the availability of the blob request = { - "jsonrpc": "2.0", - "id": 1, - "method": "sui_getObject", - "params": [ - sui_object_id, - { - "showType": True, - "showOwner": False, - "showPreviousTransaction": True, - "showDisplay": False, - "showContent": True, - "showBcs": False, - "showStorageRebate": False - } - ] + "jsonrpc": "2.0", + "id": 1, + "method": "sui_getObject", + "params": [ + sui_object_id, + { + "showType": True, + "showOwner": False, + "showPreviousTransaction": True, + "showDisplay": False, + "showContent": True, + "showBcs": False, + "showStorageRebate": False, + }, + ], } - response = requests.post("https://fullnode.testnet.sui.io:443", json=request) + response = requests.post(FULL_NODE_URL, json=request) object_content = response.json()["result"]["data"]["content"] print("Object content:") print(json.dumps(object_content, indent=4)) diff --git a/examples/python/hello_walrus_sui_system.py b/examples/python/hello_walrus_sui_system.py index 0e179957..75702df8 100644 --- a/examples/python/hello_walrus_sui_system.py +++ b/examples/python/hello_walrus_sui_system.py @@ -1,48 +1,48 @@ # Example of querying the Walrus system object on Sui -# -# Prerequisites: -# -# - Configure Walrus -# see: TODO(#12) -# -# - Update the paths PATH_TO_WALRUS_CONFIG below -# # Std lib imports import requests import re -PATH_TO_WALRUS_CONFIG = "../CONFIG/config_dir/client_config.yaml" +from utils import PATH_TO_WALRUS_CONFIG -system_object_id = re.findall(r"system_object:[ ]*(.*)", open(PATH_TO_WALRUS_CONFIG).read())[0] -print(f'System object ID: {system_object_id}') +system_object_id = re.findall( + r"system_object:[ ]*(.*)", open(PATH_TO_WALRUS_CONFIG).read() +)[0] +print(f"System object ID: {system_object_id}") # Query the Walrus system object on Sui request = { -"jsonrpc": "2.0", -"id": 1, -"method": "sui_getObject", -"params": [ - system_object_id, - { - "showType": True, - "showOwner": False, - "showPreviousTransaction": True, - "showDisplay": False, - "showContent": True, - "showBcs": False, - "showStorageRebate": False - } -] + "jsonrpc": "2.0", + "id": 1, + "method": "sui_getObject", + "params": [ + system_object_id, + { + "showType": True, + "showOwner": False, + "showPreviousTransaction": True, + "showDisplay": False, + "showContent": True, + "showBcs": False, + "showStorageRebate": False, + }, + ], } response = requests.post("https://fullnode.testnet.sui.io:443", json=request) assert response.status_code == 200 system_object_content = response.json()["result"]["data"]["content"]["fields"] -committee = system_object_content["current_committee"]["fields"]["bls_committee"]["fields"] +committee = system_object_content["current_committee"]["fields"]["bls_committee"][ + "fields" +] -print(f'Current walrus epoch: {system_object_content["current_committee"]["fields"]["epoch"]}') -print(f'Number of members: {len(committee["members"])} Number of shards: {committee["n_shards"]}') +print( + f'Current walrus epoch: {system_object_content["current_committee"]["fields"]["epoch"]}' +) +print( + f'Number of members: {len(committee["members"])} Number of shards: {committee["n_shards"]}' +) print(f'Price per unit size: {system_object_content["price_per_unit_size"]} MIST') print(f'Total capacity size: {system_object_content["total_capacity_size"]} bytes') print(f'Used capacity size: {system_object_content["used_capacity_size"]} bytes') diff --git a/examples/python/hello_walrus_webapi.py b/examples/python/hello_walrus_webapi.py index 89dd630c..0991c608 100644 --- a/examples/python/hello_walrus_webapi.py +++ b/examples/python/hello_walrus_webapi.py @@ -3,14 +3,8 @@ # # Prerequisites: # -# - Configure Sui Client to connect to testnet, and some testnet Sui tokens -# see: https://docs.sui.io/guides/developer/getting-started/connect -# -# - Configure Walrus -# see: TODO(#12) -# # - Run the Walrus client in daemon mode: -# $ walrus --config config_dir/client_config.yaml daemon -b 127.0.0.1:8899 +# $ ../CONFIG/bin/walrus --config ../CONFIG/config_dir/client_config.yaml daemon -b 127.0.0.1:8899 # # Std lib imports @@ -23,9 +17,9 @@ ADDRESS = "127.0.0.1:8899" EPOCHS = "5" + # Helper functions to upload a blob def upload_blob(ADDRESS, EPOCHS, data): - # Upload the data to the Walrus service using a PUT request store_url = f"http://{ADDRESS}/v1/store?epochs={EPOCHS}" response = requests.put(store_url, data=data) @@ -35,9 +29,9 @@ def upload_blob(ADDRESS, EPOCHS, data): blob_id = response.text return blob_id + # Helper functions to download a blob def download_blob(ADDRESS, blob_id): - # Now read the same resource using the blob-id read_url = f"http://{ADDRESS}/v1/{blob_id}" response = requests.get(read_url) @@ -46,9 +40,9 @@ def download_blob(ADDRESS, blob_id): assert response.status_code == 200 return response.content + # Upload a random 1MB string then download it, and check it matches if __name__ == "__main__": - # Generate a 1MB blob of random data random_data = os.urandom(1024 * 1024) @@ -63,6 +57,7 @@ def download_blob(ADDRESS, blob_id): download_time = time.time() # Print some information about the blob - print(f"Blob ID: {blob_id} Size {len(random_data)} bytes") + print(f"Blob ID: {blob_id}") + print(f"Size {len(random_data)} bytes") print(f"Upload time: {upload_time - start_time:.2f}s") print(f"Download time: {download_time - upload_time:.2f}s") diff --git a/examples/python/utils.py b/examples/python/utils.py index f7a866d1..fad7c7d1 100644 --- a/examples/python/utils.py +++ b/examples/python/utils.py @@ -1,17 +1,27 @@ import base64 +# Configure these paths to match your system +FULL_NODE_URL = "https://fullnode.testnet.sui.io:443" +PATH_TO_WALRUS = "../CONFIG/bin/walrus" +PATH_TO_WALRUS_CONFIG = "../CONFIG/config_dir/client_config.yaml" + + # Convert a numeric (u256) blob_id to a base64 encoded Blob ID def num_to_blob_id(blob_id_num): extracted_bytes = [] for i in range(32): - extracted_bytes += [ blob_id_num & 0xff ] + extracted_bytes += [blob_id_num & 0xFF] blob_id_num = blob_id_num >> 8 assert blob_id_num == 0 blob_id_bytes = bytes(extracted_bytes) encoded = base64.urlsafe_b64encode(blob_id_bytes) return encoded.decode("ascii").strip("=") + if __name__ == "__main__": - blob_id_num = 46269954626831698189342469164469112511517843773769981308926739591706762839432 + # A test case for the num_to_blob_id function + blob_id_num = ( + 46269954626831698189342469164469112511517843773769981308926739591706762839432 + ) blob_id_base64 = "iIWkkUTzPZx-d1E_A7LqUynnYFD-ztk39_tP8MLdS2Y" assert num_to_blob_id(blob_id_num) == blob_id_base64 From 7aaaf7b604ad28e682c1114219e5b10ed36cf706 Mon Sep 17 00:00:00 2001 From: George Danezis Date: Fri, 7 Jun 2024 12:16:43 +0100 Subject: [PATCH 14/15] Md linter --- examples/python/README.md | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/examples/python/README.md b/examples/python/README.md index 8a10bbe4..61a388fe 100644 --- a/examples/python/README.md +++ b/examples/python/README.md @@ -1,16 +1,12 @@ # Walrus Python Examples - - -## Prerequisites: - - - Configure Sui Client to connect to testnet, and some testnet Sui tokens - see: https://docs.sui.io/guides/developer/getting-started/connect - - Configure Walrus - see: TODO(#12) - - Update the paths PATH_TO_WALRUS and PATH_TO_WALRUS_CONFIG and other - constant in 'utils.py' +## Prerequisites +- Configure Sui Client to connect to testnet, and some testnet Sui tokens + see: https://docs.sui.io/guides/developer/getting-started/connect +- Configure Walrus + see: TODO(#12) +- Update the paths PATH_TO_WALRUS and PATH_TO_WALRUS_CONFIG and other + constant in 'utils.py' ## Index of examples - - - ... +- ... From e99b983cf3c869440f8c4fcc2a6fc3bbe4ea278a Mon Sep 17 00:00:00 2001 From: George Danezis Date: Fri, 7 Jun 2024 12:19:54 +0100 Subject: [PATCH 15/15] More md lints --- examples/python/README.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/examples/python/README.md b/examples/python/README.md index 61a388fe..e7cc7d1c 100644 --- a/examples/python/README.md +++ b/examples/python/README.md @@ -1,12 +1,13 @@ # Walrus Python Examples ## Prerequisites -- Configure Sui Client to connect to testnet, and some testnet Sui tokens - see: https://docs.sui.io/guides/developer/getting-started/connect -- Configure Walrus - see: TODO(#12) + +- [Configure Sui Client](https://docs.sui.io/guides/developer/getting-started/connect) to connect + to testnet, and some testnet Sui tokens. +- Configure Walrus TODO(#12). - Update the paths PATH_TO_WALRUS and PATH_TO_WALRUS_CONFIG and other - constant in 'utils.py' + constant in `utils.py`. ## Index of examples + - ...