diff --git a/docs/cli/index.md b/docs/cli/index.md index 25e81232b..923151700 100644 --- a/docs/cli/index.md +++ b/docs/cli/index.md @@ -729,7 +729,7 @@ algokit task [OPTIONS] COMMAND [ARGS]... ### ipfs -Upload files to IPFS using Web3 Storage provider. +Upload files to IPFS using Pinata provider. ```shell algokit task ipfs [OPTIONS] COMMAND [ARGS]... @@ -737,7 +737,7 @@ algokit task ipfs [OPTIONS] COMMAND [ARGS]... #### login -Login to web3 storage ipfs provider. +Login to Pinata ipfs provider. You will be prompted for your JWT. ```shell algokit task ipfs login [OPTIONS] @@ -745,7 +745,7 @@ algokit task ipfs login [OPTIONS] #### logout -Logout of web3 storage ipfs provider. +Logout of Pinata ipfs provider. ```shell algokit task ipfs logout [OPTIONS] @@ -753,7 +753,7 @@ algokit task ipfs logout [OPTIONS] #### upload -Upload a file to web3 storage ipfs provider. Please note, max file size is 100MB. +Upload a file to Pinata ipfs provider. Please note, max file size is 100MB. ```shell algokit task ipfs upload [OPTIONS] diff --git a/docs/features/tasks/ipfs.md b/docs/features/tasks/ipfs.md index b82994164..638038be3 100644 --- a/docs/features/tasks/ipfs.md +++ b/docs/features/tasks/ipfs.md @@ -1,6 +1,6 @@ # AlgoKit Task IPFS -The AlgoKit IPFS feature allows you to interact with the IPFS [InterPlanetary File System](https://ipfs.tech/) using the [Web3 Storage provider](https://web3.storage/). This feature supports logging in and out of the Web3 Storage provider, and uploading files to IPFS. +The AlgoKit IPFS feature allows you to interact with the IPFS [InterPlanetary File System](https://ipfs.tech/) using the [Piñata provider](https://www.pinata.cloud/). This feature supports logging in and out of the Piñata provider, and uploading files to IPFS. ## Usage @@ -10,7 +10,7 @@ Available commands and possible usage as follows: $ ~ algokit task ipfs Usage: algokit task ipfs [OPTIONS] -Upload files to IPFS using Web3 Storage provider. +Upload files to IPFS using Pinata provider. Options: -f, --file PATH Path to the file to upload. [required] @@ -25,17 +25,17 @@ Options: ## Prerequisites -Before you can use this feature, you need to ensure that you have signed up for a Web3 Storage account and have an API token. You can sign up for a Web3 Storage account by reading [quickstart](https://web3.storage/docs/intro/#quickstart). +Before you can use this feature, you need to ensure that you have signed up for a Piñata account and have a JWT. You can sign up for a Piñata account by reading [quickstart](https://docs.pinata.cloud/docs/getting-started). ## Login -Please note, you need to login to the Web3 Storage provider before you can upload files. You can do this using the `login` command: +Please note, you need to login to the Piñata provider before you can upload files. You can do this using the `login` command: ```bash $ algokit task ipfs login ``` -This will prompt you to enter your Web3 Storage API token. Once you are logged in, you can upload files to IPFS. +This will prompt you to enter your Piñata JWT. Once you are logged in, you can upload files to IPFS. ## Upload @@ -45,17 +45,17 @@ To upload a file to IPFS, you can use the `ipfs` command as follows: $ algokit task ipfs --file {PATH_TO_YOUR_FILE} ``` -This will upload the file to IPFS using the Web3 Storage provider and return the CID (Content Identifier) of the uploaded file. +This will upload the file to IPFS using the Piñata provider and return the CID (Content Identifier) of the uploaded file. ## Logout -If you want to logout from the Web3 Storage provider, you can use the `logout` command: +If you want to logout from the Piñata provider, you can use the `logout` command: ```bash $ algokit task ipfs logout ``` -This will remove your Web3 Storage API token from the keyring. +This will remove your Piñata JWT from the keyring. ## File Size Limit diff --git a/docs/features/tasks/mint.md b/docs/features/tasks/mint.md index b6cba77f7..5fabda32b 100644 --- a/docs/features/tasks/mint.md +++ b/docs/features/tasks/mint.md @@ -1,6 +1,6 @@ # AlgoKit Task Mint -The AlgoKit Mint feature allows you to mint new fungible or non-fungible assets on the Algorand blockchain. This feature supports the creation of assets, validation of asset parameters, and uploading of asset metadata and image to IPFS using the Web3 Storage provider. Immutable assets are compliant with [ARC3](https://arc.algorand.foundation/ARCs/arc-0003), while mutable are based using [ARC19](https://arc.algorand.foundation/ARCs/arc-0019) standard. +The AlgoKit Mint feature allows you to mint new fungible or non-fungible assets on the Algorand blockchain. This feature supports the creation of assets, validation of asset parameters, and uploading of asset metadata and image to IPFS using the Piñata provider. Immutable assets are compliant with [ARC3](https://arc.algorand.foundation/ARCs/arc-0003), while mutable are based using [ARC19](https://arc.algorand.foundation/ARCs/arc-0019) standard. ## Usage @@ -51,7 +51,7 @@ To mint a new asset in interactive mode, you can use the mint command as follows $ algokit task mint ``` -This will interactively prompt you for the required information, upload the asset image and metadata to IPFS using the Web3 Storage provider and mint a new asset on the Algorand blockchain. The [asset's metadata](https://arc.algorand.foundation/ARCs/arc-0003#json-metadata-file-schema) will be generated automatically based on the provided asset name, decimals, and image. +This will interactively prompt you for the required information, upload the asset image and metadata to IPFS using the Piñata provider and mint a new asset on the Algorand blockchain. The [asset's metadata](https://arc.algorand.foundation/ARCs/arc-0003#json-metadata-file-schema) will be generated automatically based on the provided asset name, decimals, and image. If you want to provide a custom metadata file, you can use the --metadata flag: diff --git a/poetry.lock b/poetry.lock index 36e1372ee..495089026 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1308,16 +1308,6 @@ files = [ {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac"}, {file = "MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"}, {file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f698de3fd0c4e6972b92290a45bd9b1536bffe8c6759c62471efaa8acb4c37bc"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aa57bd9cf8ae831a362185ee444e15a93ecb2e344c8e52e4d721ea3ab6ef1823"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffcc3f7c66b5f5b7931a5aa68fc9cecc51e685ef90282f4a82f0f5e9b704ad11"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47d4f1c5f80fc62fdd7777d0d40a2e9dda0a05883ab11374334f6c4de38adffd"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1f67c7038d560d92149c060157d623c542173016c4babc0c1913cca0564b9939"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9aad3c1755095ce347e26488214ef77e0485a3c34a50c5a5e2471dff60b9dd9c"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:14ff806850827afd6b07a5f32bd917fb7f45b046ba40c57abdb636674a8b559c"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8f9293864fe09b8149f0cc42ce56e3f0e54de883a9de90cd427f191c346eb2e1"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-win32.whl", hash = "sha256:715d3562f79d540f251b99ebd6d8baa547118974341db04f5ad06d5ea3eb8007"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-win_amd64.whl", hash = "sha256:1b8dd8c3fd14349433c79fa8abeb573a55fc0fdd769133baac1f5e07abf54aeb"}, {file = "MarkupSafe-2.1.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2"}, {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b"}, {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707"}, @@ -2455,7 +2445,6 @@ files = [ {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, - {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, @@ -2463,15 +2452,8 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, - {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, - {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, - {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, - {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, - {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, - {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, @@ -2488,7 +2470,6 @@ files = [ {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, - {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, @@ -2496,7 +2477,6 @@ files = [ {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, - {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, @@ -2942,6 +2922,20 @@ sphinx = "*" unify = "*" yapf = "*" +[[package]] +name = "termcolor" +version = "2.4.0" +description = "ANSI color formatting for output in terminal" +optional = false +python-versions = ">=3.8" +files = [ + {file = "termcolor-2.4.0-py3-none-any.whl", hash = "sha256:9297c0df9c99445c2412e832e882a7884038a25617c60cea2ad69488d4040d63"}, + {file = "termcolor-2.4.0.tar.gz", hash = "sha256:aab9e56047c8ac41ed798fa36d892a37aca6b3e9159f3e0c24bc64a9b3ac7b7a"}, +] + +[package.extras] +tests = ["pytest", "pytest-cov"] + [[package]] name = "toml" version = "0.10.2" @@ -3326,6 +3320,20 @@ files = [ idna = ">=2.0" multidict = ">=4.0" +[[package]] +name = "yaspin" +version = "3.0.1" +description = "Yet Another Terminal Spinner" +optional = false +python-versions = ">=3.9,<4.0" +files = [ + {file = "yaspin-3.0.1-py3-none-any.whl", hash = "sha256:c4b5d2ca23ae664b87a5cd53401c5107cef12668a71d9ee5ea5536045f364121"}, + {file = "yaspin-3.0.1.tar.gz", hash = "sha256:9c04aa69cce9be83e1ea3134a6712e749e6c0c9cd02599023713e6befd7bf369"}, +] + +[package.dependencies] +termcolor = ">=2.3,<3.0" + [[package]] name = "zipp" version = "3.16.2" @@ -3344,4 +3352,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" python-versions = "^3.10" -content-hash = "e1b4efdc3c33c9cf3eb984eaf168f5a337cb60c59093caa12698ccc42bbc49ed" +content-hash = "72fa0fc996fa246002366627fad86bb1eeda56bacf43e8d0dee5855c3ec82ab0" diff --git a/pyproject.toml b/pyproject.toml index 7eea20d41..5e6a83250 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -24,6 +24,7 @@ auth0-python = "^4.4.0" algokit-utils = "v2.1.0" multiformats = "^0.2.1" aiohttp = "3.9.1" +yaspin = "^3.0.1" [tool.poetry.group.dev.dependencies] pytest = "^7.2.0" diff --git a/src/algokit/cli/tasks/ipfs.py b/src/algokit/cli/tasks/ipfs.py index 6b124a95f..ee3517eb8 100644 --- a/src/algokit/cli/tasks/ipfs.py +++ b/src/algokit/cli/tasks/ipfs.py @@ -1,20 +1,19 @@ import logging -from collections.abc import Generator from pathlib import Path import click +from yaspin import yaspin # type: ignore # noqa: PGH003 from algokit.core.tasks.ipfs import ( - MAX_CHUNK_SIZE, MAX_FILE_SIZE, - Web3StorageBadRequestError, - Web3StorageForbiddenError, - Web3StorageHttpError, - Web3StorageInternalServerError, - Web3StorageUnauthorizedError, - get_web3_storage_api_key, - set_web3_storage_api_key, - upload_to_web3_storage, + PinataBadRequestError, + PinataForbiddenError, + PinataHttpError, + PinataInternalServerError, + PinataUnauthorizedError, + get_pinata_jwt, + set_pinata_jwt, + upload_to_pinata, ) logger = logging.getLogger(__name__) @@ -24,37 +23,36 @@ "ipfs", ) def ipfs_group() -> None: - """Upload files to IPFS using Web3 Storage provider.""" + """Upload files to IPFS using Pinata provider.""" -@ipfs_group.command("login", help="Login to web3 storage ipfs provider.") +@ipfs_group.command("login", help="Login to Pinata ipfs provider. You will be prompted for your JWT.") def login_command() -> None: - web3_storage_api_key = get_web3_storage_api_key() - if web3_storage_api_key: + pinata_jwt = get_pinata_jwt() + if pinata_jwt: logger.warning("You are already logged in!") return else: logger.info( - "Follow the instructions on https://web3.storage/docs/intro/#get-an-api-token " - "to create an account and obtain an API token." - ) - set_web3_storage_api_key( - click.prompt("Enter web3 storage API token", hide_input=True, confirmation_prompt=True, type=str) + "Follow the instructions on https://docs.pinata.cloud/docs/getting-started " + "to create an account and obtain a JWT." ) + set_pinata_jwt(click.prompt("Enter pinata JWT", hide_input=True, confirmation_prompt=True, type=str)) + logger.info("Login successful") -@ipfs_group.command("logout", help="Logout of web3 storage ipfs provider.") +@ipfs_group.command("logout", help="Logout of Pinata ipfs provider.") def logout_command() -> None: - web3_storage_api_key = get_web3_storage_api_key() - if web3_storage_api_key: - set_web3_storage_api_key(None) + pinata_jwt = get_pinata_jwt() + if pinata_jwt: + set_pinata_jwt(None) logger.info("Logout successful") return else: logger.warning("Already logged out") -@ipfs_group.command("upload", help="Upload a file to web3 storage ipfs provider. Please note, max file size is 100MB.") +@ipfs_group.command("upload", help="Upload a file to Pinata ipfs provider. Please note, max file size is 100MB.") @click.option( "--file", "-f", @@ -72,37 +70,31 @@ def logout_command() -> None: help="Human readable name for this upload, for use in file listings.", ) def upload(file_path: Path, name: str | None) -> None: - web3_storage_api_key = get_web3_storage_api_key() - if not web3_storage_api_key: + pinata_jwt = get_pinata_jwt() + if not pinata_jwt: raise click.ClickException("You are not logged in! Please login using `algokit ipfs login`.") try: - with file_path.open("rb") as file: - total = file_path.stat().st_size - - if total > MAX_FILE_SIZE: - raise click.ClickException("File size exceeds 100MB limit!") - - with click.progressbar(length=total, label="Uploading file") as bar: # type: ignore[var-annotated] + total = file_path.stat().st_size + if total > MAX_FILE_SIZE: + raise click.ClickException("File size exceeds 100MB limit!") - def read_file_in_chunks() -> Generator[bytes, None, None]: - while data := file.read(MAX_CHUNK_SIZE): - yield data - bar.update(len(data)) + with yaspin(text="Uploading", color="yellow") as spinner: + cid = upload_to_pinata(file_path, pinata_jwt, name) + spinner.ok("✅ ") + logger.info(f"File uploaded successfully!\nCID: {cid}") - cid = upload_to_web3_storage(file_path, web3_storage_api_key, name, read_file_in_chunks()) - logger.info(f"\nFile uploaded successfully!\nCID: {cid}") except click.ClickException as ex: raise ex except OSError as ex: logger.debug(ex) raise click.ClickException("Failed to open file!") from ex except ( - Web3StorageBadRequestError, - Web3StorageUnauthorizedError, - Web3StorageForbiddenError, - Web3StorageInternalServerError, - Web3StorageHttpError, + PinataBadRequestError, + PinataUnauthorizedError, + PinataForbiddenError, + PinataInternalServerError, + PinataHttpError, ) as ex: logger.debug(ex) raise click.ClickException(repr(ex)) from ex diff --git a/src/algokit/cli/tasks/mint.py b/src/algokit/cli/tasks/mint.py index 55d718f98..00e06e0d1 100644 --- a/src/algokit/cli/tasks/mint.py +++ b/src/algokit/cli/tasks/mint.py @@ -14,12 +14,12 @@ validate_balance, ) from algokit.core.tasks.ipfs import ( - Web3StorageBadRequestError, - Web3StorageForbiddenError, - Web3StorageHttpError, - Web3StorageInternalServerError, - Web3StorageUnauthorizedError, - get_web3_storage_api_key, + PinataBadRequestError, + PinataForbiddenError, + PinataHttpError, + PinataInternalServerError, + PinataUnauthorizedError, + get_pinata_jwt, ) from algokit.core.tasks.mint.mint import mint_token from algokit.core.tasks.mint.models import TokenMetadata @@ -205,8 +205,8 @@ def mint( # noqa: PLR0913 creator_account = get_account_with_private_key(creator) - web3_storage_api_key = get_web3_storage_api_key() - if not web3_storage_api_key: + pinata_jwt = get_pinata_jwt() + if not pinata_jwt: raise click.ClickException("You are not logged in! Please login using `algokit ipfs login`.") client = load_algod_client(network) @@ -224,7 +224,7 @@ def mint( # noqa: PLR0913 try: asset_id, txn_id = mint_token( client=client, - api_key=web3_storage_api_key, + jwt=pinata_jwt, creator_account=creator_account, token_metadata=token_metadata, image_path=image_path, @@ -238,11 +238,11 @@ def mint( # noqa: PLR0913 click.echo(f"Browse your asset at: {get_explorer_url(asset_id, network, ExplorerEntityType.ASSET)}") click.echo(f"Check transaction status at: {get_explorer_url(txn_id, network, ExplorerEntityType.TRANSACTION)}") except ( - Web3StorageBadRequestError, - Web3StorageUnauthorizedError, - Web3StorageForbiddenError, - Web3StorageInternalServerError, - Web3StorageHttpError, + PinataBadRequestError, + PinataUnauthorizedError, + PinataForbiddenError, + PinataInternalServerError, + PinataHttpError, ) as ex: logger.debug(ex) raise click.ClickException(repr(ex)) from ex diff --git a/src/algokit/core/tasks/ipfs.py b/src/algokit/core/tasks/ipfs.py index 0d59f01fe..f861a025f 100644 --- a/src/algokit/core/tasks/ipfs.py +++ b/src/algokit/core/tasks/ipfs.py @@ -1,5 +1,5 @@ +import json import logging -from collections.abc import Generator from pathlib import Path import httpx @@ -7,85 +7,91 @@ logger = logging.getLogger(__name__) -ALGOKIT_WEB3_STORAGE_NAMESPACE = "algokit_web3_storage" -ALGOKIT_WEB3_STORAGE_TOKEN_KEY = "algokit_web3_storage_access_token" +ALGOKIT_PINATA_NAMESPACE = "algokit_pinata" +ALGOKIT_PINATA_TOKEN_KEY = "algokit_pinata_access_token" MAX_FILE_SIZE = 100 * 1024 * 1024 # 100MB -MAX_CHUNK_SIZE = 1024 * 1024 # 1MB -DEFAULT_TIMEOUT = 10 +DEFAULT_TIMEOUT = 90 -class Web3StorageError(Exception): - """Base class for Web3 Storage errors.""" +class PinataError(Exception): + """Base class for Piñata errors.""" def __init__(self, response: httpx.Response): self.response = response - super().__init__(f"Web3 Storage error: {response.status_code}") + super().__init__(f"Pinata error: {response.status_code}") def __str__(self) -> str: - return f"Web3 Storage error: {self.response.status_code}. {self.response.text}" + return f"Pinata error: {self.response.status_code}. {self.response.text}" -class Web3StorageBadRequestError(Web3StorageError): +class PinataBadRequestError(PinataError): pass -class Web3StorageUnauthorizedError(Web3StorageError): +class PinataUnauthorizedError(PinataError): pass -class Web3StorageForbiddenError(Web3StorageError): +class PinataForbiddenError(PinataError): pass -class Web3StorageInternalServerError(Web3StorageError): +class PinataInternalServerError(PinataError): pass -class Web3StorageHttpError(Web3StorageError): +class PinataHttpError(PinataError): pass -def get_web3_storage_api_key() -> str | None: +def get_pinata_jwt() -> str | None: """ Retrieves a password from the keyring library using the - ALGOKIT_WEB3_STORAGE_NAMESPACE and ALGOKIT_WEB3_STORAGE_TOKEN_KEY variables. + ALGOKIT_PINATA_NAMESPACE and ALGOKIT_PINATA_TOKEN_KEY variables. Returns: str | None: The retrieved password from the keyring, or None if no password is found. """ - - return keyring.get_password(ALGOKIT_WEB3_STORAGE_NAMESPACE, ALGOKIT_WEB3_STORAGE_TOKEN_KEY) - - -def set_web3_storage_api_key(api_key: str | None) -> None: + try: + old_api_key = keyring.get_password("algokit_web3_storage", "algokit_web3_storage_access_token") + if old_api_key: + logger.warning( + "You are using the old Web3 Storage API key. Please login again using `algokit ipfs login` with Pinata " + "ipfs provider. Follow the instructions on https://docs.pinata.cloud/docs/getting-started " + "to create an account and obtain a JWT." + ) + keyring.delete_password("algokit_web3_storage", "algokit_web3_storage_access_token") + except Exception: + pass + return keyring.get_password(ALGOKIT_PINATA_NAMESPACE, ALGOKIT_PINATA_TOKEN_KEY) + + +def set_pinata_jwt(jwt: str | None) -> None: """ - Sets or deletes a password in the keyring library based on the provided API key. + Sets or deletes a password in the keyring library based on the provided JWT. Args: - api_key (str | None): The API key to be set in the keyring library. If None, the password will be deleted. + jwt (str | None): The JWT to be set in the keyring library. If None, the password will be deleted. Returns: None """ - if api_key: - keyring.set_password(ALGOKIT_WEB3_STORAGE_NAMESPACE, ALGOKIT_WEB3_STORAGE_TOKEN_KEY, api_key) + if jwt: + keyring.set_password(ALGOKIT_PINATA_NAMESPACE, ALGOKIT_PINATA_TOKEN_KEY, jwt) else: - keyring.delete_password(ALGOKIT_WEB3_STORAGE_NAMESPACE, ALGOKIT_WEB3_STORAGE_TOKEN_KEY) + keyring.delete_password(ALGOKIT_PINATA_NAMESPACE, ALGOKIT_PINATA_TOKEN_KEY) -def upload_to_web3_storage( - file_path: Path, api_key: str, name: str | None = None, content: Generator | None = None -) -> str: +def upload_to_pinata(file_path: Path, jwt: str, name: str | None = None) -> str: """ - Uploads a file to the Web3 Storage API. + Uploads a file to the Piñata API. Args: file_path (Path): The path to the file that needs to be uploaded. - api_key (str): The API key for accessing the Web3 Storage API. + jwt (str): The JWT for accessing the Piñata API. name (str | None, optional): The name to be assigned to the uploaded file. If not provided, the name of the file at `file_path` will be used. Defaults to None. - content (Generator | None, optional): A generator that yields the content of the file. If not provided, the content will be read from the file at `file_path`. Defaults to None. Returns: @@ -93,53 +99,54 @@ def upload_to_web3_storage( Raises: ValueError: If the CID is not a string. - Web3StorageBadRequestError: If there is a bad request error. - Web3StorageUnauthorizedError: If there is an unauthorized error. - Web3StorageForbiddenError: If there is a forbidden error. - Web3StorageInternalServerError: If there is an internal server error. - Web3StorageHttpError: If there is an HTTP error. + PinataBadRequestError: If there is a bad request error. + PinataUnauthorizedError: If there is an unauthorized error. + PinataForbiddenError: If there is a forbidden error. + PinataInternalServerError: If there is an internal server error. + PinataHttpError: If there is an HTTP error. Example Usage: file_path = Path("path/to/file.txt") - api_key = "your_api_key" + jwt = "your_jwt" name = "file.txt" - cid = upload_to_web3_storage(file_path, api_key, name) - print(cid) # e.g. "bafybeih6z7z2z3z4z5z6z7z8z9z0" + cid = upload_to_pinata(file_path, jwt, name) + print(cid) # e.g. "bafybeih6z7z2z3z4z5z6z7z8z9z0" """ with file_path.open("rb") as file: file_content = file.read() - num_chunks = file_path.stat().st_size // MAX_CHUNK_SIZE | 1 - timeout = DEFAULT_TIMEOUT * num_chunks - logger.debug(f"Timeout set to {timeout} seconds based on {num_chunks} chunks.") headers = { - "Authorization": f"Bearer {api_key}", - "Content-Type": "application/x-www-form-urlencoded", - "X-Name": name or file_path.name, + "accept": "application/json", + "Authorization": f"Bearer {jwt}", } + pinata_options = {"cidVersion": "1"} + data = {"pinataOptions": json.dumps(pinata_options)} + files = {"file": (name or file_path.name, file_content)} try: response = httpx.post( - "https://api.web3.storage/upload", + url="https://api.pinata.cloud/pinning/pinFileToIPFS", + data=data, + files=files, headers=headers, - timeout=timeout, - content=content or file_content, + timeout=DEFAULT_TIMEOUT, ) + response.raise_for_status() - cid = response.json().get("cid") + cid = response.json().get("IpfsHash") if not isinstance(cid, str): - raise ValueError("CID is not a string.") + raise ValueError("IpfsHash is not a string.") return cid except httpx.HTTPStatusError as ex: if ex.response.status_code == httpx.codes.BAD_REQUEST: - raise Web3StorageBadRequestError(ex.response) from ex + raise PinataBadRequestError(ex.response) from ex if ex.response.status_code == httpx.codes.UNAUTHORIZED: - raise Web3StorageUnauthorizedError(ex.response) from ex + raise PinataUnauthorizedError(ex.response) from ex if ex.response.status_code == httpx.codes.FORBIDDEN: - raise Web3StorageForbiddenError(ex.response) from ex + raise PinataForbiddenError(ex.response) from ex if ex.response.status_code == httpx.codes.INTERNAL_SERVER_ERROR: - raise Web3StorageInternalServerError(ex.response) from ex + raise PinataInternalServerError(ex.response) from ex - raise Web3StorageHttpError(ex.response) from ex + raise PinataHttpError(ex.response) from ex diff --git a/src/algokit/core/tasks/mint/mint.py b/src/algokit/core/tasks/mint/mint.py index 61bfd510e..0509343d8 100644 --- a/src/algokit/core/tasks/mint/mint.py +++ b/src/algokit/core/tasks/mint/mint.py @@ -13,7 +13,7 @@ from algosdk.v2client import algod from multiformats import CID -from algokit.core.tasks.ipfs import upload_to_web3_storage +from algokit.core.tasks.ipfs import upload_to_pinata from algokit.core.tasks.mint.models import AssetConfigTxnParams, TokenMetadata logger = logging.getLogger(__name__) @@ -144,7 +144,7 @@ def _create_asset_txn( def mint_token( # noqa: PLR0913 *, client: algod.AlgodClient, - api_key: str, + jwt: str, creator_account: Account, asset_name: str, unit_name: str, @@ -159,7 +159,7 @@ def mint_token( # noqa: PLR0913 Args: client (algod.AlgodClient): An instance of the `algod.AlgodClient` class representing the Algorand node. - api_key (str): A string representing the API key for accessing the Algorand network. + jwt (str): The JWT for accessing the Piñata API. creator_account (Account): An instance of the `Account` class representing the account that will create the token. asset_name (str): A string representing the name of the token. @@ -189,16 +189,16 @@ def mint_token( # noqa: PLR0913 if image_path: token_metadata.image_integrity = _file_integrity(image_path) token_metadata.image_mimetype = _file_mimetype(image_path) - logger.info("Uploading image to Web3 Storage...") - token_metadata.image = "ipfs://" + upload_to_web3_storage(image_path, api_key=api_key) - logger.info(f"Image uploaded to Web3 Storage: {token_metadata.image}") + logger.info("Uploading image to pinata...") + token_metadata.image = "ipfs://" + upload_to_pinata(image_path, jwt=jwt) + logger.info(f"Image uploaded to pinata: {token_metadata.image}") - logger.info("Uploading metadata to Web3 Storage...") - metadata_cid = upload_to_web3_storage( + logger.info("Uploading metadata to pinata...") + metadata_cid = upload_to_pinata( token_metadata.to_file_path(), - api_key=api_key, + jwt=jwt, ) - logger.info(f"Metadata uploaded to Web3 Storage: {metadata_cid}") + logger.info(f"Metadata uploaded to pinata: {metadata_cid}") asset_config_params = AssetConfigTxnParams( sender=creator_account.address, diff --git a/tests/tasks/TestIpfsLogin.test_ipfs_login_successful.approved.txt b/tests/tasks/TestIpfsLogin.test_ipfs_login_successful.approved.txt index 920112bc2..63e58406e 100644 --- a/tests/tasks/TestIpfsLogin.test_ipfs_login_successful.approved.txt +++ b/tests/tasks/TestIpfsLogin.test_ipfs_login_successful.approved.txt @@ -1,3 +1,4 @@ -Follow the instructions on https://web3.storage/docs/intro/#get-an-api-token to create an account and obtain an API token. -Enter web3 storage API token: +Follow the instructions on https://docs.pinata.cloud/docs/getting-started to create an account and obtain a JWT. +Enter pinata JWT: Repeat for confirmation: +Login successful diff --git a/tests/tasks/TestIpfsUpload.test_ipfs_upload_http_error.approved.txt b/tests/tasks/TestIpfsUpload.test_ipfs_upload_http_error.approved.txt index de6880331..9b2fc92e2 100644 --- a/tests/tasks/TestIpfsUpload.test_ipfs_upload_http_error.approved.txt +++ b/tests/tasks/TestIpfsUpload.test_ipfs_upload_http_error.approved.txt @@ -1,5 +1,8 @@ -Uploading file -DEBUG: Timeout set to 10 seconds based on 1 chunks. -DEBUG: HTTP Request: POST https://api.web3.storage/upload "HTTP/1.1 500 Internal Server Error" -DEBUG: Web3 Storage error: 500. {"ok": false, "cid": "test"} -Error: Web3StorageInternalServerError('Web3 Storage error: 500') + + + +⠋ UploadingDEBUG: HTTP Request: POST https://api.pinata.cloud/pinning/pinFileToIPFS "HTTP/1.1 500 Internal Server Error" + + +DEBUG: Pinata error: 500. {"ok": false, "cid": "test"} +Error: PinataInternalServerError('Pinata error: 500') diff --git a/tests/tasks/TestIpfsUpload.test_ipfs_upload_successful.approved.txt b/tests/tasks/TestIpfsUpload.test_ipfs_upload_successful.approved.txt index a9e7323ca..d2a54405b 100644 --- a/tests/tasks/TestIpfsUpload.test_ipfs_upload_successful.approved.txt +++ b/tests/tasks/TestIpfsUpload.test_ipfs_upload_successful.approved.txt @@ -1,6 +1,9 @@ -Uploading file -DEBUG: Timeout set to 10 seconds based on 1 chunks. -DEBUG: HTTP Request: POST https://api.web3.storage/upload "HTTP/1.1 200 OK" + + +⠋ UploadingDEBUG: HTTP Request: POST https://api.pinata.cloud/pinning/pinFileToIPFS "HTTP/1.1 200 OK" + + +✅ Uploading File uploaded successfully! CID: test diff --git a/tests/tasks/test_ipfs.py b/tests/tasks/test_ipfs.py index aa57dbbaa..6ec406c0d 100644 --- a/tests/tasks/test_ipfs.py +++ b/tests/tasks/test_ipfs.py @@ -1,5 +1,5 @@ import pytest -from algokit.core.tasks.ipfs import ALGOKIT_WEB3_STORAGE_TOKEN_KEY +from algokit.core.tasks.ipfs import ALGOKIT_PINATA_TOKEN_KEY from pytest_httpx import HTTPXMock from tests.utils.approvals import verify @@ -8,7 +8,7 @@ class TestIpfsLogin: def test_ipfs_login_exists(self, mock_keyring: dict[str, str]) -> None: - mock_keyring[ALGOKIT_WEB3_STORAGE_TOKEN_KEY] = "test" + mock_keyring[ALGOKIT_PINATA_TOKEN_KEY] = "test" result = invoke("task ipfs login", input="test\ntest") @@ -17,35 +17,35 @@ def test_ipfs_login_exists(self, mock_keyring: dict[str, str]) -> None: verify(result.output) def test_ipfs_login_successful(self, mock_keyring: dict[str, str | None]) -> None: - mock_keyring[ALGOKIT_WEB3_STORAGE_TOKEN_KEY] = None + mock_keyring[ALGOKIT_PINATA_TOKEN_KEY] = None result = invoke("task ipfs login", input="test\ntest") # Assert assert result.exit_code == 0 verify(result.output) - assert mock_keyring[ALGOKIT_WEB3_STORAGE_TOKEN_KEY] == "test" + assert mock_keyring[ALGOKIT_PINATA_TOKEN_KEY] == "test" class TestIpfsLogout: def test_ipfs_logout(self, mock_keyring: dict[str, str | None]) -> None: - mock_keyring[ALGOKIT_WEB3_STORAGE_TOKEN_KEY] = "test" + mock_keyring[ALGOKIT_PINATA_TOKEN_KEY] = "test" result = invoke("task ipfs logout") # Assert assert result.exit_code == 0 verify(result.output) - assert mock_keyring.get(ALGOKIT_WEB3_STORAGE_TOKEN_KEY) is None + assert mock_keyring.get(ALGOKIT_PINATA_TOKEN_KEY) is None class TestIpfsUpload: def test_ipfs_upload_successful( self, tmp_path_factory: pytest.TempPathFactory, httpx_mock: HTTPXMock, mock_keyring: dict[str, str | None] ) -> None: - mock_keyring[ALGOKIT_WEB3_STORAGE_TOKEN_KEY] = "test" + mock_keyring[ALGOKIT_PINATA_TOKEN_KEY] = "test" cwd = tmp_path_factory.mktemp("cwd") (cwd / "dummy.txt").write_text("dummy text to upload") - httpx_mock.add_response(status_code=200, json={"ok": True, "cid": "test"}) + httpx_mock.add_response(status_code=200, json={"ok": True, "IpfsHash": "test"}) result = invoke("task ipfs upload --file dummy.txt", cwd=cwd) # Assert @@ -55,7 +55,7 @@ def test_ipfs_upload_successful( def test_ipfs_not_logged_in( self, tmp_path_factory: pytest.TempPathFactory, mock_keyring: dict[str, str | None] ) -> None: - mock_keyring[ALGOKIT_WEB3_STORAGE_TOKEN_KEY] = None + mock_keyring[ALGOKIT_PINATA_TOKEN_KEY] = None cwd = tmp_path_factory.mktemp("cwd") (cwd / "dummy.txt").write_text("dummy text to upload") @@ -71,7 +71,7 @@ def test_ipfs_upload_http_error( httpx_mock: HTTPXMock, mock_keyring: dict[str, str | None], ) -> None: - mock_keyring[ALGOKIT_WEB3_STORAGE_TOKEN_KEY] = "test" + mock_keyring[ALGOKIT_PINATA_TOKEN_KEY] = "test" cwd = tmp_path_factory.mktemp("cwd") (cwd / "dummy.txt").write_text("dummy text to upload") diff --git a/tests/tasks/test_mint.py b/tests/tasks/test_mint.py index 8fa3d959e..6336be510 100644 --- a/tests/tasks/test_mint.py +++ b/tests/tasks/test_mint.py @@ -41,7 +41,7 @@ def test_mint_token_successful( (cwd / "image.png").touch() mocker.patch( - "algokit.core.tasks.mint.mint.upload_to_web3_storage", + "algokit.core.tasks.mint.mint.upload_to_pinata", side_effect=[ "bafkreifax6dswcxk4us2am3jxhd3swxew32oreaxzol7dnnqzhieepqg2y", "bafkreiftmc4on252dnckhv7jdqnhkxjkpvlrekpevjwm3gjszygxkus5oe", @@ -49,7 +49,7 @@ def test_mint_token_successful( ) mocker.patch("algokit.core.tasks.mint.mint.wait_for_confirmation", return_value={"asset-index": 123}) mocker.patch( - "algokit.cli.tasks.mint.get_web3_storage_api_key", + "algokit.cli.tasks.mint.get_pinata_jwt", return_value="dummy_key", ) mocker.patch( @@ -102,7 +102,7 @@ def test_mint_token_pure_fractional_nft_ft_validation( assert nft_result.exit_code == 1 -def test_mint_token_web3_storage_error( +def test_mint_token_pinata_error( mocker: MockerFixture, httpx_mock: HTTPXMock, tmp_path_factory: pytest.TempPathFactory, @@ -116,7 +116,7 @@ def test_mint_token_web3_storage_error( httpx_mock.add_response(status_code=403, json={"ok": False}) mocker.patch( - "algokit.cli.tasks.mint.get_web3_storage_api_key", + "algokit.cli.tasks.mint.get_pinata_jwt", return_value="dummy_key", ) mocker.patch( @@ -138,7 +138,7 @@ def test_mint_token_web3_storage_error( verify(result.output) -def test_mint_token_no_web3_token_error( +def test_mint_token_no_pinata_jwt_error( mocker: MockerFixture, tmp_path_factory: pytest.TempPathFactory, ) -> None: @@ -150,7 +150,7 @@ def test_mint_token_no_web3_token_error( (cwd / "image.png").touch() mocker.patch( - "algokit.cli.tasks.mint.get_web3_storage_api_key", + "algokit.cli.tasks.mint.get_pinata_jwt", return_value=None, ) # Act @@ -196,7 +196,7 @@ def test_mint_token_acfg_token_metadata_mismatch( ) mocker.patch( - "algokit.cli.tasks.mint.get_web3_storage_api_key", + "algokit.cli.tasks.mint.get_pinata_jwt", return_value="dummy_key", ) mocker.patch( diff --git a/tests/tasks/test_mint.test_mint_token_no_web3_token_error.approved.txt b/tests/tasks/test_mint.test_mint_token_no_pinata_jwt_error.approved.txt similarity index 100% rename from tests/tasks/test_mint.test_mint_token_no_web3_token_error.approved.txt rename to tests/tasks/test_mint.test_mint_token_no_pinata_jwt_error.approved.txt diff --git a/tests/tasks/test_mint.test_mint_token_pinata_error.approved.txt b/tests/tasks/test_mint.test_mint_token_pinata_error.approved.txt new file mode 100644 index 000000000..4c423e477 --- /dev/null +++ b/tests/tasks/test_mint.test_mint_token_pinata_error.approved.txt @@ -0,0 +1,5 @@ +Enter the mnemonic phrase (25 words separated by whitespace): +Uploading image to pinata... +DEBUG: HTTP Request: POST https://api.pinata.cloud/pinning/pinFileToIPFS "HTTP/1.1 403 Forbidden" +DEBUG: Pinata error: 403. {"ok": false} +Error: PinataForbiddenError('Pinata error: 403') diff --git a/tests/tasks/test_mint.test_mint_token_successful.address.False.localnet.approved.txt b/tests/tasks/test_mint.test_mint_token_successful.address.False.localnet.approved.txt index ebce19599..18ce73e4d 100644 --- a/tests/tasks/test_mint.test_mint_token_successful.address.False.localnet.approved.txt +++ b/tests/tasks/test_mint.test_mint_token_successful.address.False.localnet.approved.txt @@ -1,8 +1,8 @@ Enter the mnemonic phrase (25 words separated by whitespace): -Uploading image to Web3 Storage... -Image uploaded to Web3 Storage: ipfs://bafkreifax6dswcxk4us2am3jxhd3swxew32oreaxzol7dnnqzhieepqg2y -Uploading metadata to Web3 Storage... -Metadata uploaded to Web3 Storage: bafkreiftmc4on252dnckhv7jdqnhkxjkpvlrekpevjwm3gjszygxkus5oe +Uploading image to pinata... +Image uploaded to pinata: ipfs://bafkreifax6dswcxk4us2am3jxhd3swxew32oreaxzol7dnnqzhieepqg2y +Uploading metadata to pinata... +Metadata uploaded to pinata: bafkreiftmc4on252dnckhv7jdqnhkxjkpvlrekpevjwm3gjszygxkus5oe DEBUG: Asset config params: { "sender": "MW5E55FG7OHV7B2YB5JGFL6ONZSP7ABCMM77CIDGOT2GSBJEYUBOF3UYKA", "unit_name": "tst", diff --git a/tests/tasks/test_mint.test_mint_token_successful.address.False.mainnet.approved.txt b/tests/tasks/test_mint.test_mint_token_successful.address.False.mainnet.approved.txt index d4e49d40d..4cc2d6397 100644 --- a/tests/tasks/test_mint.test_mint_token_successful.address.False.mainnet.approved.txt +++ b/tests/tasks/test_mint.test_mint_token_successful.address.False.mainnet.approved.txt @@ -1,8 +1,8 @@ Enter the mnemonic phrase (25 words separated by whitespace): -Uploading image to Web3 Storage... -Image uploaded to Web3 Storage: ipfs://bafkreifax6dswcxk4us2am3jxhd3swxew32oreaxzol7dnnqzhieepqg2y -Uploading metadata to Web3 Storage... -Metadata uploaded to Web3 Storage: bafkreiftmc4on252dnckhv7jdqnhkxjkpvlrekpevjwm3gjszygxkus5oe +Uploading image to pinata... +Image uploaded to pinata: ipfs://bafkreifax6dswcxk4us2am3jxhd3swxew32oreaxzol7dnnqzhieepqg2y +Uploading metadata to pinata... +Metadata uploaded to pinata: bafkreiftmc4on252dnckhv7jdqnhkxjkpvlrekpevjwm3gjszygxkus5oe DEBUG: Asset config params: { "sender": "MW5E55FG7OHV7B2YB5JGFL6ONZSP7ABCMM77CIDGOT2GSBJEYUBOF3UYKA", "unit_name": "tst", diff --git a/tests/tasks/test_mint.test_mint_token_successful.address.False.testnet.approved.txt b/tests/tasks/test_mint.test_mint_token_successful.address.False.testnet.approved.txt index 0d6076b53..847966b91 100644 --- a/tests/tasks/test_mint.test_mint_token_successful.address.False.testnet.approved.txt +++ b/tests/tasks/test_mint.test_mint_token_successful.address.False.testnet.approved.txt @@ -1,8 +1,8 @@ Enter the mnemonic phrase (25 words separated by whitespace): -Uploading image to Web3 Storage... -Image uploaded to Web3 Storage: ipfs://bafkreifax6dswcxk4us2am3jxhd3swxew32oreaxzol7dnnqzhieepqg2y -Uploading metadata to Web3 Storage... -Metadata uploaded to Web3 Storage: bafkreiftmc4on252dnckhv7jdqnhkxjkpvlrekpevjwm3gjszygxkus5oe +Uploading image to pinata... +Image uploaded to pinata: ipfs://bafkreifax6dswcxk4us2am3jxhd3swxew32oreaxzol7dnnqzhieepqg2y +Uploading metadata to pinata... +Metadata uploaded to pinata: bafkreiftmc4on252dnckhv7jdqnhkxjkpvlrekpevjwm3gjszygxkus5oe DEBUG: Asset config params: { "sender": "MW5E55FG7OHV7B2YB5JGFL6ONZSP7ABCMM77CIDGOT2GSBJEYUBOF3UYKA", "unit_name": "tst", diff --git a/tests/tasks/test_mint.test_mint_token_successful.alias.True.localnet.approved.txt b/tests/tasks/test_mint.test_mint_token_successful.alias.True.localnet.approved.txt index 319c1c9d3..1a70d2cd5 100644 --- a/tests/tasks/test_mint.test_mint_token_successful.alias.True.localnet.approved.txt +++ b/tests/tasks/test_mint.test_mint_token_successful.alias.True.localnet.approved.txt @@ -1,7 +1,7 @@ -Uploading image to Web3 Storage... -Image uploaded to Web3 Storage: ipfs://bafkreifax6dswcxk4us2am3jxhd3swxew32oreaxzol7dnnqzhieepqg2y -Uploading metadata to Web3 Storage... -Metadata uploaded to Web3 Storage: bafkreiftmc4on252dnckhv7jdqnhkxjkpvlrekpevjwm3gjszygxkus5oe +Uploading image to pinata... +Image uploaded to pinata: ipfs://bafkreifax6dswcxk4us2am3jxhd3swxew32oreaxzol7dnnqzhieepqg2y +Uploading metadata to pinata... +Metadata uploaded to pinata: bafkreiftmc4on252dnckhv7jdqnhkxjkpvlrekpevjwm3gjszygxkus5oe DEBUG: Asset config params: { "sender": "MW5E55FG7OHV7B2YB5JGFL6ONZSP7ABCMM77CIDGOT2GSBJEYUBOF3UYKA", "unit_name": "tst", diff --git a/tests/tasks/test_mint.test_mint_token_successful.alias.True.mainnet.approved.txt b/tests/tasks/test_mint.test_mint_token_successful.alias.True.mainnet.approved.txt index c503157b4..f017ef9bf 100644 --- a/tests/tasks/test_mint.test_mint_token_successful.alias.True.mainnet.approved.txt +++ b/tests/tasks/test_mint.test_mint_token_successful.alias.True.mainnet.approved.txt @@ -1,7 +1,7 @@ -Uploading image to Web3 Storage... -Image uploaded to Web3 Storage: ipfs://bafkreifax6dswcxk4us2am3jxhd3swxew32oreaxzol7dnnqzhieepqg2y -Uploading metadata to Web3 Storage... -Metadata uploaded to Web3 Storage: bafkreiftmc4on252dnckhv7jdqnhkxjkpvlrekpevjwm3gjszygxkus5oe +Uploading image to pinata... +Image uploaded to pinata: ipfs://bafkreifax6dswcxk4us2am3jxhd3swxew32oreaxzol7dnnqzhieepqg2y +Uploading metadata to pinata... +Metadata uploaded to pinata: bafkreiftmc4on252dnckhv7jdqnhkxjkpvlrekpevjwm3gjszygxkus5oe DEBUG: Asset config params: { "sender": "MW5E55FG7OHV7B2YB5JGFL6ONZSP7ABCMM77CIDGOT2GSBJEYUBOF3UYKA", "unit_name": "tst", diff --git a/tests/tasks/test_mint.test_mint_token_successful.alias.True.testnet.approved.txt b/tests/tasks/test_mint.test_mint_token_successful.alias.True.testnet.approved.txt index 413d5a0e9..61b23dc75 100644 --- a/tests/tasks/test_mint.test_mint_token_successful.alias.True.testnet.approved.txt +++ b/tests/tasks/test_mint.test_mint_token_successful.alias.True.testnet.approved.txt @@ -1,7 +1,7 @@ -Uploading image to Web3 Storage... -Image uploaded to Web3 Storage: ipfs://bafkreifax6dswcxk4us2am3jxhd3swxew32oreaxzol7dnnqzhieepqg2y -Uploading metadata to Web3 Storage... -Metadata uploaded to Web3 Storage: bafkreiftmc4on252dnckhv7jdqnhkxjkpvlrekpevjwm3gjszygxkus5oe +Uploading image to pinata... +Image uploaded to pinata: ipfs://bafkreifax6dswcxk4us2am3jxhd3swxew32oreaxzol7dnnqzhieepqg2y +Uploading metadata to pinata... +Metadata uploaded to pinata: bafkreiftmc4on252dnckhv7jdqnhkxjkpvlrekpevjwm3gjszygxkus5oe DEBUG: Asset config params: { "sender": "MW5E55FG7OHV7B2YB5JGFL6ONZSP7ABCMM77CIDGOT2GSBJEYUBOF3UYKA", "unit_name": "tst", diff --git a/tests/tasks/test_mint.test_mint_token_web3_storage_error.approved.txt b/tests/tasks/test_mint.test_mint_token_web3_storage_error.approved.txt deleted file mode 100644 index 9071df5c0..000000000 --- a/tests/tasks/test_mint.test_mint_token_web3_storage_error.approved.txt +++ /dev/null @@ -1,6 +0,0 @@ -Enter the mnemonic phrase (25 words separated by whitespace): -Uploading image to Web3 Storage... -DEBUG: Timeout set to 10 seconds based on 1 chunks. -DEBUG: HTTP Request: POST https://api.web3.storage/upload "HTTP/1.1 403 Forbidden" -DEBUG: Web3 Storage error: 403. {"ok": false} -Error: Web3StorageForbiddenError('Web3 Storage error: 403')