From 0766c22182114f351700bae2720fad24f59a741a Mon Sep 17 00:00:00 2001 From: Adam Majmudar Date: Mon, 10 Jul 2023 18:34:52 -0400 Subject: [PATCH 1/9] Update storage to use api key --- thirdweb/core/classes/contract_deployer.py | 6 +++--- thirdweb/core/classes/factory.py | 6 +++--- thirdweb/core/classes/ipfs_storage.py | 23 +++++++--------------- thirdweb/core/sdk.py | 10 ++++++++-- thirdweb/types/sdk.py | 1 + 5 files changed, 22 insertions(+), 24 deletions(-) diff --git a/thirdweb/core/classes/contract_deployer.py b/thirdweb/core/classes/contract_deployer.py index c5ad0f4c..c4d8f57b 100644 --- a/thirdweb/core/classes/contract_deployer.py +++ b/thirdweb/core/classes/contract_deployer.py @@ -30,9 +30,9 @@ class ContractDeployer(ProviderHandler): def __init__( self, provider: Web3, - signer: Optional[LocalAccount] = None, - options: SDKOptions = SDKOptions(), - storage: IpfsStorage = IpfsStorage(), + signer: Optional[LocalAccount], + options: SDKOptions, + storage: IpfsStorage, ): super().__init__(provider, signer, options) self._storage = storage diff --git a/thirdweb/core/classes/factory.py b/thirdweb/core/classes/factory.py index e230a84d..c089e8af 100644 --- a/thirdweb/core/classes/factory.py +++ b/thirdweb/core/classes/factory.py @@ -44,9 +44,9 @@ def __init__( self, factory_address: str, provider: Web3, - signer: Optional[LocalAccount] = None, - options: SDKOptions = SDKOptions(), - storage: IpfsStorage = IpfsStorage(), + signer: Optional[LocalAccount], + options: SDKOptions, + storage: IpfsStorage, ): abi = TWFactory(provider, factory_address) super().__init__(abi, provider, signer, options) diff --git a/thirdweb/core/classes/ipfs_storage.py b/thirdweb/core/classes/ipfs_storage.py index d7cb9105..3b69b262 100644 --- a/thirdweb/core/classes/ipfs_storage.py +++ b/thirdweb/core/classes/ipfs_storage.py @@ -41,8 +41,10 @@ class IpfsStorage(ABC): """ _gateway_url: str + _api_key: str - def __init__(self, gateway_url=DEFAULT_IPFS_GATEWAY): + def __init__(self, api_key: str, gateway_url=DEFAULT_IPFS_GATEWAY): + self._api_key = api_key self._gateway_url = re.sub(r"\/$", "", gateway_url) + "/" def get(self, hash: str) -> Any: @@ -63,7 +65,7 @@ def get(self, hash: str) -> Any: except: return res.text - def get_upload_token(self, contract_address: str) -> str: + def get_upload_token(self) -> str: """ Gets an upload token for a given contract address. @@ -74,7 +76,7 @@ def get_upload_token(self, contract_address: str) -> str: res = get( f"{TW_IPFS_SERVER_URL}/grant", headers={ - "X-App-Name": f"CONSOLE-PYTHON-SDK-{contract_address}", + "Authorization": f"Bearer {self._api_key}", }, ) @@ -234,21 +236,10 @@ def _build_file_properties_map( def _upload_batch_with_cid( self, files: Sequence[Union[TextIO, BinaryIO, str, Dict[str, Any]]], - file_start_number: int = 0, - contract_address: str = "", - signer_address: str = "", + file_start_number: int = 0 ) -> CidWithFileName: - token = self.get_upload_token(contract_address) - - metadata = { - "name": f"CONSOLE-PYTHON-SDK-{contract_address}", - "keyvalues": { - "sdk": "python", - "contractAddress": contract_address, - "signerAddress": signer_address, - }, - } + token = self.get_upload_token() form: List[Any] = [] file_names: List[str] = [] diff --git a/thirdweb/core/sdk.py b/thirdweb/core/sdk.py index c4528403..0fa6e17c 100644 --- a/thirdweb/core/sdk.py +++ b/thirdweb/core/sdk.py @@ -56,8 +56,8 @@ def __init__( self, network: str, signer: Optional[LocalAccount] = None, - options: SDKOptions = SDKOptions(), - storage: IpfsStorage = IpfsStorage(), + options: SDKOptions = None, + storage: IpfsStorage = None, ): """ Initialize the thirdweb SDK. @@ -68,6 +68,12 @@ def __init__( :param storage: optional IPFS storage instance to use for storing data """ + if options is None: + options = SDKOptions() + + if storage is None: + storage = IpfsStorage(options.api_key) + provider = get_provider_for_network(network) super().__init__(provider, signer, options) diff --git a/thirdweb/types/sdk.py b/thirdweb/types/sdk.py index ac1ef5b2..2a98b1a3 100644 --- a/thirdweb/types/sdk.py +++ b/thirdweb/types/sdk.py @@ -46,5 +46,6 @@ class SDKOptions(object): :param gas_settings: gas settings """ + api_key: str = "" read_only_settings: Optional[ReadOnlySettings] = None gas_settings: GasSettings = GasSettings() From 24ac7932d6738c089b862a27eaac951eae9294b1 Mon Sep 17 00:00:00 2001 From: Adam Majmudar Date: Mon, 10 Jul 2023 18:38:38 -0400 Subject: [PATCH 2/9] Remove contract address and signer address from parameters --- thirdweb/core/classes/ipfs_storage.py | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/thirdweb/core/classes/ipfs_storage.py b/thirdweb/core/classes/ipfs_storage.py index 3b69b262..9f315c95 100644 --- a/thirdweb/core/classes/ipfs_storage.py +++ b/thirdweb/core/classes/ipfs_storage.py @@ -88,8 +88,6 @@ def get_upload_token(self) -> str: def upload( self, data: Union[TextIO, BinaryIO, str], - contract_address: str = "", - signer_address: str = "", ) -> str: """ Uploads data to IPFS and returns the hash of the data. @@ -100,15 +98,13 @@ def upload( :returns: hash of the data. """ - cid = self.upload_batch([data], 0, contract_address, signer_address) + cid = self.upload_batch([data], 0) return f"{cid}0" def upload_batch( self, files: Sequence[Union[TextIO, BinaryIO, str, Dict[str, Any]]], file_start_number: int = 0, - contract_address: str = "", - signer_address: str = "", ) -> str: """ Uploads a list of files to IPFS and returns the hash. @@ -123,8 +119,6 @@ def upload_batch( cid_with_filename = self._upload_batch_with_cid( files, file_start_number, - contract_address, - signer_address, ) return f"ipfs://{cid_with_filename.cid}" @@ -132,8 +126,6 @@ def upload_batch( def upload_metadata( self, metadata: Dict[str, Any], - contract_address: str = "", - signer_address: str = "", ) -> str: """ Uploads metadata to IPFS and returns the hash of the metadata. @@ -145,7 +137,7 @@ def upload_metadata( """ uri_with_metadata = self.upload_metadata_batch( - [metadata], 0, contract_address, signer_address + [metadata], 0 ) return uri_with_metadata.metadata_uris[0] @@ -154,8 +146,6 @@ def upload_metadata_batch( self, metadatas: Sequence[Dict[str, Any]], file_start_number: int = 0, - contract_address: str = "", - signer_address: str = "", ) -> UriWithMetadata: """ Uploads a list of metadata to IPFS and returns the hash. @@ -169,7 +159,7 @@ def upload_metadata_batch( metadata_to_upload = self._batch_upload_properties(metadatas) cid_with_filename = self._upload_batch_with_cid( - metadata_to_upload, file_start_number, contract_address, signer_address + metadata_to_upload, file_start_number ) base_uri = f"ipfs://{cid_with_filename.cid}/" From 23de26e5668b55e2f24753250334936682b142d0 Mon Sep 17 00:00:00 2001 From: Adam Majmudar Date: Mon, 10 Jul 2023 18:48:23 -0400 Subject: [PATCH 3/9] Add X-App-Name header back --- thirdweb/core/classes/ipfs_storage.py | 1 + 1 file changed, 1 insertion(+) diff --git a/thirdweb/core/classes/ipfs_storage.py b/thirdweb/core/classes/ipfs_storage.py index 9f315c95..a199b02b 100644 --- a/thirdweb/core/classes/ipfs_storage.py +++ b/thirdweb/core/classes/ipfs_storage.py @@ -77,6 +77,7 @@ def get_upload_token(self) -> str: f"{TW_IPFS_SERVER_URL}/grant", headers={ "Authorization": f"Bearer {self._api_key}", + "X-App-Name": "Python SDK" }, ) From 7370d330d088a5ea0578331c4b6f1180c0cab3ee Mon Sep 17 00:00:00 2001 From: Adam Majmudar Date: Mon, 10 Jul 2023 19:13:35 -0400 Subject: [PATCH 4/9] Fix test cases --- tests/test_ipfs.py | 2 +- thirdweb/core/classes/factory.py | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/tests/test_ipfs.py b/tests/test_ipfs.py index b7e7d0a7..caf7e2d4 100644 --- a/tests/test_ipfs.py +++ b/tests/test_ipfs.py @@ -117,7 +117,7 @@ def test_replace_gateway_urls(storage: IpfsStorage): } ) - other_storage = IpfsStorage(gateway_url="https://ipfs.thirdweb.com/ipfs/") + other_storage = IpfsStorage(api_key="", gateway_url="https://ipfs.thirdweb.com/ipfs/") downloaded = other_storage.get(upload) assert downloaded["svg"].startswith("https://ipfs.thirdweb.com/ipfs/") diff --git a/thirdweb/core/classes/factory.py b/thirdweb/core/classes/factory.py index c089e8af..03c04e89 100644 --- a/thirdweb/core/classes/factory.py +++ b/thirdweb/core/classes/factory.py @@ -57,9 +57,7 @@ def deploy( ) -> str: # First, we upload the contract metadata to IPFS contract_uri = self._storage.upload_metadata( - contract_metadata, - self._contract_abi.contract_address, - self.get_signer_address(), + contract_metadata ) # Then, we get setup the contract interface for the contract we want to deploy From 8cf360fe19ccaafa04cf43dc7a78c999ea9a0090 Mon Sep 17 00:00:00 2001 From: Adam Majmudar Date: Mon, 17 Jul 2023 22:28:30 +0200 Subject: [PATCH 5/9] Update to accept secret_key --- tests/fixtures/sdk.py | 9 ++++- thirdweb/common/keys.py | 5 +++ thirdweb/constants/urls.py | 32 +++++++++-------- thirdweb/core/classes/ipfs_storage.py | 52 ++++++++++----------------- thirdweb/core/sdk.py | 6 ++-- thirdweb/types/sdk.py | 2 +- 6 files changed, 53 insertions(+), 53 deletions(-) create mode 100644 thirdweb/common/keys.py diff --git a/tests/fixtures/sdk.py b/tests/fixtures/sdk.py index c59fcd77..861133d1 100644 --- a/tests/fixtures/sdk.py +++ b/tests/fixtures/sdk.py @@ -1,6 +1,7 @@ from thirdweb.core.classes.ipfs_storage import IpfsStorage from thirdweb.core.classes.registry import ContractRegistry from thirdweb.core.classes.factory import ContractFactory +from thirdweb.types.sdk import SDKOptions from web3.middleware import geth_poa_middleware from thirdweb.core.sdk import ThirdwebSDK from eth_account import Account @@ -16,5 +17,11 @@ @pytest.fixture(scope="session") def sdk(primary_account): signer = primary_account - sdk = ThirdwebSDK("http://localhost:8545", signer) + sdk = ThirdwebSDK( + "http://localhost:8545", + signer, + SDKOptions( + secret_key=os.getenv("THIRDWEB_SECRET_KEY") + ) + ) return sdk diff --git a/thirdweb/common/keys.py b/thirdweb/common/keys.py new file mode 100644 index 00000000..80f1df10 --- /dev/null +++ b/thirdweb/common/keys.py @@ -0,0 +1,5 @@ +import hashlib + +def derive_client_id_from_secret_key(secret_key: str) -> str: + hashed = hashlib.sha256(secret_key.encode()).hexdigest() + return hashed[:32] \ No newline at end of file diff --git a/thirdweb/constants/urls.py b/thirdweb/constants/urls.py index 42a72bab..a63ceee5 100644 --- a/thirdweb/constants/urls.py +++ b/thirdweb/constants/urls.py @@ -1,43 +1,45 @@ +from typing import Optional from web3 import Web3 -DEFAULT_IPFS_GATEWAY = "https://gateway.ipfscdn.io/ipfs/" +DEFAULT_IPFS_GATEWAY = "https://ipfs.io/ipfs/" TW_IPFS_SERVER_URL = "https://upload.nftlabs.co" -PINATA_IPFS_URL = "https://api.pinata.cloud/pinning/pinFileToIPFS" +TW_STORAGE_SERVER_URL = "https://storage.staging.thirdweb.com" DEFAULT_API_KEY = "39a3c037d7a88e6692c6681bccfd1f1cf36370324c4051a83acd0edcffb20708" -def get_rpc_url(network: str) -> str: - return f"https://{network}.rpc.thirdweb.com/{DEFAULT_API_KEY}" +def get_rpc_url(network: str, client_id: Optional[str]) -> str: + api_key = client_id if client_id is not None else DEFAULT_API_KEY + return f"https://{network}.rpc.thirdweb.com/{api_key}" -def get_provider_for_network(network: str) -> Web3: +def get_provider_for_network(network: str, client_id: str) -> Web3: """ Returns a web3 provider instance for the given network. """ rpc_url = "" if network == "mainnet" or network == "ethereum": - rpc_url = get_rpc_url("ethereum") + rpc_url = get_rpc_url("ethereum", client_id) elif network == "goerli": - rpc_url = get_rpc_url("goerli") + rpc_url = get_rpc_url("goerli", client_id) elif network == "polygon": - rpc_url = get_rpc_url("polygon") + rpc_url = get_rpc_url("polygon", client_id) elif network == "mumbai": - rpc_url = get_rpc_url("mumbai") + rpc_url = get_rpc_url("mumbai", client_id) elif network == "optimism": - rpc_url = getRpcUrl("optimism"); + rpc_url = get_rpc_url("optimism", client_id) elif network == "optimism-goerli": - rpc_url = getRpcUrl("optimism-goerli"); + rpc_url = get_rpc_url("optimism-goerli", client_id) elif network == "arbitrum": - rpc_url = getRpcUrl("arbitrum"); + rpc_url = get_rpc_url("arbitrum", client_id) elif network == "arbitrum-goerli": - rpc_url = getRpcUrl("arbitrum-goerli"); + rpc_url = get_rpc_url("arbitrum-goerli", client_id) elif network == "fantom": - rpc_url = get_rpc_url("fantom") + rpc_url = get_rpc_url("fantom", client_id) elif network == "avalanche": - rpc_url = get_rpc_url("avalanche") + rpc_url = get_rpc_url("avalanche", client_id) else: if network.startswith("http"): rpc_url = network diff --git a/thirdweb/core/classes/ipfs_storage.py b/thirdweb/core/classes/ipfs_storage.py index a199b02b..0119e8a2 100644 --- a/thirdweb/core/classes/ipfs_storage.py +++ b/thirdweb/core/classes/ipfs_storage.py @@ -3,16 +3,16 @@ import re import json from requests import get, Response, post -from typing import Any, Dict, List, Sequence, TextIO, BinaryIO, Union, cast +from typing import Any, Dict, List, Optional, Sequence, TextIO, BinaryIO, Union, cast from thirdweb.common.error import ( DuplicateFileNameException, FetchException, UploadException, ) +from thirdweb.common.keys import derive_client_id_from_secret_key from thirdweb.constants.urls import ( DEFAULT_IPFS_GATEWAY, - PINATA_IPFS_URL, - TW_IPFS_SERVER_URL, + TW_STORAGE_SERVER_URL, ) from thirdweb.core.helpers.storage import ( replace_file_properties_with_hashes, @@ -41,11 +41,18 @@ class IpfsStorage(ABC): """ _gateway_url: str - _api_key: str + _secret_key: Optional[str] - def __init__(self, api_key: str, gateway_url=DEFAULT_IPFS_GATEWAY): - self._api_key = api_key - self._gateway_url = re.sub(r"\/$", "", gateway_url) + "/" + def __init__(self, secret_key: Optional[str], gateway_url: Optional[str] = None): + self._secret_key = secret_key + + if gateway_url is not None: + self._gateway_url = re.sub(r"\/$", "", gateway_url) + "/" + elif secret_key is not None: + client_id = derive_client_id_from_secret_key(self._secret_key) + self._gateway_url = f"https://{client_id}.thirdwebstorage-staging.com/ipfs/" + else: + self._gateway_url = DEFAULT_IPFS_GATEWAY def get(self, hash: str) -> Any: """ @@ -65,27 +72,6 @@ def get(self, hash: str) -> Any: except: return res.text - def get_upload_token(self) -> str: - """ - Gets an upload token for a given contract address. - - :param contract_address: address of the contract to get the token for. - :returns: upload token. - """ - - res = get( - f"{TW_IPFS_SERVER_URL}/grant", - headers={ - "Authorization": f"Bearer {self._api_key}", - "X-App-Name": "Python SDK" - }, - ) - - if not res.ok: - raise FetchException("Failed to upload token") - - return res.text - def upload( self, data: Union[TextIO, BinaryIO, str], @@ -176,7 +162,8 @@ def upload_metadata_batch( def _get(self, hash: str) -> Response: hash = resolve_gateway_url(hash, "ipfs://", self._gateway_url) - res = get(hash) + headers = { "x-secret-key": self._secret_key } if ".thirdwebstorage-staging.com" in self._gateway_url else {} + res = get(hash, headers=headers) if not res.ok: raise FetchException(f"Could not get {hash}") @@ -229,9 +216,6 @@ def _upload_batch_with_cid( files: Sequence[Union[TextIO, BinaryIO, str, Dict[str, Any]]], file_start_number: int = 0 ) -> CidWithFileName: - - token = self.get_upload_token() - form: List[Any] = [] file_names: List[str] = [] @@ -265,10 +249,10 @@ def _upload_batch_with_cid( # form.append(("pinataMetadata", metadata)) res = post( - PINATA_IPFS_URL, + f"{TW_STORAGE_SERVER_URL}/ipfs/upload", files=form, headers={ - "Authorization": f"Bearer {token}", + "x-secret-key": self._secret_key, }, ) body = res.json() diff --git a/thirdweb/core/sdk.py b/thirdweb/core/sdk.py index 0fa6e17c..43bbc2c6 100644 --- a/thirdweb/core/sdk.py +++ b/thirdweb/core/sdk.py @@ -2,6 +2,7 @@ from thirdweb.common.feature_detection import ( fetch_contract_metadata_from_address, ) +from thirdweb.common.keys import derive_client_id_from_secret_key from thirdweb.constants.urls import get_provider_for_network from thirdweb.contracts import Marketplace from thirdweb.contracts.custom import CustomContract @@ -72,9 +73,10 @@ def __init__( options = SDKOptions() if storage is None: - storage = IpfsStorage(options.api_key) + storage = IpfsStorage(options.secret_key) - provider = get_provider_for_network(network) + client_id = derive_client_id_from_secret_key(options.secret_key) if options.secret_key is not None else None + provider = get_provider_for_network(network, client_id) super().__init__(provider, signer, options) self.auth = WalletAuthenticator(provider, signer, options) diff --git a/thirdweb/types/sdk.py b/thirdweb/types/sdk.py index 2a98b1a3..f8bcba04 100644 --- a/thirdweb/types/sdk.py +++ b/thirdweb/types/sdk.py @@ -46,6 +46,6 @@ class SDKOptions(object): :param gas_settings: gas settings """ - api_key: str = "" + secret_key: Optional[str] = None read_only_settings: Optional[ReadOnlySettings] = None gas_settings: GasSettings = GasSettings() From a25f633f17e43f9e0bb30609e28670e8feeae467 Mon Sep 17 00:00:00 2001 From: Adam Majmudar Date: Mon, 17 Jul 2023 22:29:30 +0200 Subject: [PATCH 6/9] Update ipfs test case --- tests/test_ipfs.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_ipfs.py b/tests/test_ipfs.py index caf7e2d4..7a0020c1 100644 --- a/tests/test_ipfs.py +++ b/tests/test_ipfs.py @@ -117,7 +117,7 @@ def test_replace_gateway_urls(storage: IpfsStorage): } ) - other_storage = IpfsStorage(api_key="", gateway_url="https://ipfs.thirdweb.com/ipfs/") + other_storage = IpfsStorage(api_key="", gateway_url="https://ipfs.io/ipfs/") downloaded = other_storage.get(upload) - assert downloaded["svg"].startswith("https://ipfs.thirdweb.com/ipfs/") + assert downloaded["svg"].startswith("https://ipfs.io/ipfs/") From a2ad0d97db459833151817f5fbe45685fbb20a5a Mon Sep 17 00:00:00 2001 From: Adam Majmudar Date: Mon, 17 Jul 2023 22:30:56 +0200 Subject: [PATCH 7/9] Update to production URLs --- thirdweb/constants/urls.py | 2 +- thirdweb/core/classes/ipfs_storage.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/thirdweb/constants/urls.py b/thirdweb/constants/urls.py index a63ceee5..23eb2d73 100644 --- a/thirdweb/constants/urls.py +++ b/thirdweb/constants/urls.py @@ -6,7 +6,7 @@ TW_IPFS_SERVER_URL = "https://upload.nftlabs.co" -TW_STORAGE_SERVER_URL = "https://storage.staging.thirdweb.com" +TW_STORAGE_SERVER_URL = "https://storage.thirdweb.com" DEFAULT_API_KEY = "39a3c037d7a88e6692c6681bccfd1f1cf36370324c4051a83acd0edcffb20708" diff --git a/thirdweb/core/classes/ipfs_storage.py b/thirdweb/core/classes/ipfs_storage.py index 0119e8a2..8b796fd5 100644 --- a/thirdweb/core/classes/ipfs_storage.py +++ b/thirdweb/core/classes/ipfs_storage.py @@ -50,7 +50,7 @@ def __init__(self, secret_key: Optional[str], gateway_url: Optional[str] = None) self._gateway_url = re.sub(r"\/$", "", gateway_url) + "/" elif secret_key is not None: client_id = derive_client_id_from_secret_key(self._secret_key) - self._gateway_url = f"https://{client_id}.thirdwebstorage-staging.com/ipfs/" + self._gateway_url = f"https://{client_id}.ipfscdn.io/ipfs/" else: self._gateway_url = DEFAULT_IPFS_GATEWAY @@ -162,7 +162,7 @@ def upload_metadata_batch( def _get(self, hash: str) -> Response: hash = resolve_gateway_url(hash, "ipfs://", self._gateway_url) - headers = { "x-secret-key": self._secret_key } if ".thirdwebstorage-staging.com" in self._gateway_url else {} + headers = { "x-secret-key": self._secret_key } if ".ipfscdn.io" in self._gateway_url else {} res = get(hash, headers=headers) if not res.ok: From ec40aa3619e92b847adcc164dc06fe06136f4c34 Mon Sep 17 00:00:00 2001 From: Adam Majmudar Date: Mon, 17 Jul 2023 22:35:54 +0200 Subject: [PATCH 8/9] Update to replace gateway urls --- tests/test_ipfs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_ipfs.py b/tests/test_ipfs.py index 7a0020c1..c6115d0e 100644 --- a/tests/test_ipfs.py +++ b/tests/test_ipfs.py @@ -117,7 +117,7 @@ def test_replace_gateway_urls(storage: IpfsStorage): } ) - other_storage = IpfsStorage(api_key="", gateway_url="https://ipfs.io/ipfs/") + other_storage = IpfsStorage(secret_key=None, gateway_url="https://ipfs.io/ipfs/") downloaded = other_storage.get(upload) assert downloaded["svg"].startswith("https://ipfs.io/ipfs/") From 2e523283634ec6e8fce9463a8132905269b79147 Mon Sep 17 00:00:00 2001 From: Adam Majmudar Date: Tue, 18 Jul 2023 20:50:21 +0200 Subject: [PATCH 9/9] Update documentation --- README.md | 20 ++++++++++++++------ docs/common/index.md | 15 +++++++++++---- thirdweb/contracts/custom.py | 8 ++++++-- thirdweb/contracts/edition.py | 8 ++++++-- thirdweb/contracts/edition_drop.py | 8 ++++++-- thirdweb/contracts/marketplace.py | 8 ++++++-- thirdweb/contracts/multiwrap.py | 8 ++++++-- thirdweb/contracts/nft_collection.py | 8 ++++++-- thirdweb/contracts/nft_drop.py | 8 ++++++-- thirdweb/contracts/token.py | 8 ++++++-- 10 files changed, 73 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 1897b28b..3150de07 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ pip install thirdweb-sdk ## Getting Started -To start using this SDK, you just need to pass in a provider configuration. +To start using this SDK, you just need to pass in a provider configuration. It's also strongly recommended that you use your thirdweb API keys with the SDK in order to get the best infrastructure performance (across RPCs, IPFS, etc.) - you can learn more about creating and using API keys [here](https://portal.thirdweb.com/api-keys). ### Instantiating the SDK @@ -29,9 +29,13 @@ Once you have all the necessary dependencies, you can follow the following setup ```python from thirdweb import ThirdwebSDK +from thirdweb.types import SDKOptions -# You can create a new instance of the SDK to use by just passing in a network name -sdk = ThirdwebSDK("mumbai") +# Get your secret key from the thirdweb api keys dashboard +SECRET_KEY = "..." + +# You can create a new instance of the SDK to use by passing in a network name and your api key +sdk = ThirdwebSDK("mumbai", options=SDKOptions(secret_key=SECRET_KEY)) ``` The SDK supports the `mainnet`, `rinkeby`, `goerli`, `polygon`, `mumbai`, `fantom`, and `avalanche` networks. @@ -73,12 +77,16 @@ Meanwhile, if you want to use write functions as well and connect a signer, you ```python from thirdweb import ThirdwebSDK from thirdweb.types.nft import NFTMetadataInput +import os + +# Get your secret key from the thirdweb api keys dashboard +SECRET_KEY = "..." -# Learn more about securely accessing your private key: https://portal.thirdweb.com/web3-sdk/set-up-the-sdk/securing-your-private-key -PRIVATE_KEY = "", +# This PRIVATE KEY is coming from your environment variables. Make sure to never put it in a tracked file or share it with anyone. +PRIVATE_KEY = os.environ.get("PRIVATE_KEY") # Now you can create a new instance of the SDK with your private key -sdk = ThirdwebSDK.from_private_key(PRIVATE_KEY, "mumbai") +sdk = ThirdwebSDK.from_private_key(PRIVATE_KEY, "mumbai", options=SDKOptions(secret_key=SECRET_KEY)) # Instantiate a new NFT Collection contract as described above. NFT_COLLECTION_ADDRESS = "0x.." diff --git a/docs/common/index.md b/docs/common/index.md index db0c9ac9..adea401d 100644 --- a/docs/common/index.md +++ b/docs/common/index.md @@ -21,16 +21,21 @@ pip install thirdweb-sdk ## Getting Started -To start using this SDK, you just need to pass in a provider configuration. +To start using this SDK, you just need to pass in a provider configuration. It's also strongly recommended that you use your thirdweb API keys with the SDK in order to get the best infrastructure performance (across RPCs, IPFS, etc.) - you can learn more about creating and using API keys [here](https://portal.thirdweb.com/api-keys). + ### Instantiating the SDK Once you have all the necessary dependencies, you can follow the following setup steps to get started with the SDK read-only functions: ```python from thirdweb import ThirdwebSDK +from thirdweb.types import SDKOptions + +# Get your secret key from the thirdweb api keys dashboard +SECRET_KEY = "..." -# You can create a new instance of the SDK to use by just passing in a network name -sdk = ThirdwebSDK("mumbai") +# You can create a new instance of the SDK to use by passing in a network name and your api key +sdk = ThirdwebSDK("mumbai", options=SDKOptions(secret_key=SECRET_KEY)) ``` The SDK supports the `mainnet`, `rinkeby`, `goerli`, `polygon`, `mumbai`, `fantom`, and `avalanche` networks. @@ -74,12 +79,14 @@ from thirdweb import ThirdwebSDK from thirdweb.types.nft import NFTMetadataInput import os +# Get your secret key from the thirdweb api keys dashboard +SECRET_KEY = "..." # This PRIVATE KEY is coming from your environment variables. Make sure to never put it in a tracked file or share it with anyone. PRIVATE_KEY = os.environ.get("PRIVATE_KEY") # Now you can create a new instance of the SDK with your private key -sdk = ThirdwebSDK.from_private_key(PRIVATE_KEY, "mumbai") +sdk = ThirdwebSDK.from_private_key(PRIVATE_KEY, "mumbai", options=SDKOptions(secret_key=SECRET_KEY)) # Instantiate a new NFT Collection contract as described above. NFT_COLLECTION_ADDRESS = "0x.." diff --git a/thirdweb/contracts/custom.py b/thirdweb/contracts/custom.py index f42bf0c4..eb0511f8 100644 --- a/thirdweb/contracts/custom.py +++ b/thirdweb/contracts/custom.py @@ -42,15 +42,19 @@ class CustomContract(BaseContract[Any]): ```python from thirdweb import ThirdwebSDK + from thirdweb.types import SDKOptions + + # Get your secret key from the thirdweb api keys dashboard + secret_key = "..." # You can customize this to a supported network or your own RPC URL network = "mumbai" # Now we can create a new instance of the SDK - sdk = ThirdwebSDK(network) + sdk = ThirdwebSDK(network, options=SDKOptions(secret_key=secret_key)) # If you want to send transactions, you can instantiate the SDK with a private key instead: - # sdk = ThirdwebSDK.from_private_key(PRIVATE_KEY, network) + # sdk = ThirdwebSDK.from_private_key(PRIVATE_KEY, network, options=SDKOptions(secret_key=secret_key)) contract = sdk.get_contract("{{contract_address}}") diff --git a/thirdweb/contracts/edition.py b/thirdweb/contracts/edition.py index 540175ef..ba8614ba 100644 --- a/thirdweb/contracts/edition.py +++ b/thirdweb/contracts/edition.py @@ -33,15 +33,19 @@ class Edition(ERC1155Standard[TokenERC1155]): ```python from thirdweb import ThirdwebSDK + from thirdweb.types import SDKOptions + + # Get your secret key from the thirdweb api keys dashboard + secret_key = "..." # You can customize this to a supported network or your own RPC URL network = "mumbai" # Now we can create a new instance of the SDK - sdk = ThirdwebSDK(network) + sdk = ThirdwebSDK(network, options=SDKOptions(secret_key=secret_key)) # If you want to send transactions, you can instantiate the SDK with a private key instead: - # sdk = ThirdwebSDK.from_private_key(PRIVATE_KEY, network) + # sdk = ThirdwebSDK.from_private_key(PRIVATE_KEY, network, options=SDKOptions(secret_key=secret_key)) contract = sdk.get_edition("{{contract_address}}") ``` diff --git a/thirdweb/contracts/edition_drop.py b/thirdweb/contracts/edition_drop.py index e12acc3b..6a77a832 100644 --- a/thirdweb/contracts/edition_drop.py +++ b/thirdweb/contracts/edition_drop.py @@ -30,15 +30,19 @@ class EditionDrop(ERC1155Standard[DropERC1155]): ```python from thirdweb import ThirdwebSDK + from thirdweb.types import SDKOptions + + # Get your secret key from the thirdweb api keys dashboard + secret_key = "..." # You can customize this to a supported network or your own RPC URL network = "mumbai" # Now we can create a new instance of the SDK - sdk = ThirdwebSDK(network) + sdk = ThirdwebSDK(network, options=SDKOptions(secret_key=secret_key)) # If you want to send transactions, you can instantiate the SDK with a private key instead: - # sdk = ThirdwebSDK.from_private_key(PRIVATE_KEY, network) + # sdk = ThirdwebSDK.from_private_key(PRIVATE_KEY, network, options=SDKOptions(secret_key=secret_key)) contract = sdk.get_edition_drop("{{contract_address}}") ``` diff --git a/thirdweb/contracts/marketplace.py b/thirdweb/contracts/marketplace.py index 3a23da1a..e3f44e57 100644 --- a/thirdweb/contracts/marketplace.py +++ b/thirdweb/contracts/marketplace.py @@ -36,15 +36,19 @@ class Marketplace(BaseContract[MarketplaceABI]): ```python from thirdweb import ThirdwebSDK + from thirdweb.types import SDKOptions + + # Get your secret key from the thirdweb api keys dashboard + secret_key = "..." # You can customize this to a supported network or your own RPC URL network = "mumbai" # Now we can create a new instance of the SDK - sdk = ThirdwebSDK(network) + sdk = ThirdwebSDK(network, options=SDKOptions(secret_key=secret_key)) # If you want to send transactions, you can instantiate the SDK with a private key instead: - # sdk = ThirdwebSDK.from_private_key(PRIVATE_KEY, network) + # sdk = ThirdwebSDK.from_private_key(PRIVATE_KEY, network, options=SDKOptions(secret_key=secret_key)) contract = sdk.get_marketplace("{{contract_address}}") ``` diff --git a/thirdweb/contracts/multiwrap.py b/thirdweb/contracts/multiwrap.py index 0522da6b..e668fb91 100644 --- a/thirdweb/contracts/multiwrap.py +++ b/thirdweb/contracts/multiwrap.py @@ -42,15 +42,19 @@ class Multiwrap(ERC721Standard[MultiwrapABI]): ```python from thirdweb import ThirdwebSDK + from thirdweb.types import SDKOptions + + # Get your secret key from the thirdweb api keys dashboard + secret_key = "..." # You can customize this to a supported network or your own RPC URL network = "mumbai" # Now we can create a new instance of the SDK - sdk = ThirdwebSDK(network) + sdk = ThirdwebSDK(network, options=SDKOptions(secret_key=secret_key)) # If you want to send transactions, you can instantiate the SDK with a private key instead: - # sdk = ThirdwebSDK.from_private_key(PRIVATE_KEY, network) + # sdk = ThirdwebSDK.from_private_key(PRIVATE_KEY, network, options=SDKOptions(secret_key=secret_key)) contract = sdk.get_multiwrap("{{contract_address}}") ``` diff --git a/thirdweb/contracts/nft_collection.py b/thirdweb/contracts/nft_collection.py index 33d863b6..5b916d74 100644 --- a/thirdweb/contracts/nft_collection.py +++ b/thirdweb/contracts/nft_collection.py @@ -31,15 +31,19 @@ class NFTCollection(ERC721Standard[TokenERC721]): ```python from thirdweb import ThirdwebSDK + from thirdweb.types import SDKOptions + + # Get your secret key from the thirdweb api keys dashboard + secret_key = "..." # You can customize this to a supported network or your own RPC URL network = "mumbai" # Now we can create a new instance of the SDK - sdk = ThirdwebSDK(network) + sdk = ThirdwebSDK(network, options=SDKOptions(secret_key=secret_key)) # If you want to send transactions, you can instantiate the SDK with a private key instead: - # sdk = ThirdwebSDK.from_private_key(PRIVATE_KEY, network) + # sdk = ThirdwebSDK.from_private_key(PRIVATE_KEY, network, options=SDKOptions(secret_key=secret_key)) contract = sdk.get_nft_collection("{{contract_address}}") ``` diff --git a/thirdweb/contracts/nft_drop.py b/thirdweb/contracts/nft_drop.py index 7b56ee31..3dbad558 100644 --- a/thirdweb/contracts/nft_drop.py +++ b/thirdweb/contracts/nft_drop.py @@ -33,15 +33,19 @@ class NFTDrop(ERC721Standard[DropERC721]): ```python from thirdweb import ThirdwebSDK + from thirdweb.types import SDKOptions + + # Get your secret key from the thirdweb api keys dashboard + secret_key = "..." # You can customize this to a supported network or your own RPC URL network = "mumbai" # Now we can create a new instance of the SDK - sdk = ThirdwebSDK(network) + sdk = ThirdwebSDK(network, options=SDKOptions(secret_key=secret_key)) # If you want to send transactions, you can instantiate the SDK with a private key instead: - # sdk = ThirdwebSDK.from_private_key(PRIVATE_KEY, network) + # sdk = ThirdwebSDK.from_private_key(PRIVATE_KEY, network, options=SDKOptions(secret_key=secret_key)) contract = sdk.get_nft_drop("{{contract_address}}") ``` diff --git a/thirdweb/contracts/token.py b/thirdweb/contracts/token.py index 3ec00910..e343679d 100644 --- a/thirdweb/contracts/token.py +++ b/thirdweb/contracts/token.py @@ -28,15 +28,19 @@ class Token(ERC20Standard): ```python from thirdweb import ThirdwebSDK + from thirdweb.types import SDKOptions + + # Get your secret key from the thirdweb api keys dashboard + secret_key = "..." # You can customize this to a supported network or your own RPC URL network = "mumbai" # Now we can create a new instance of the SDK - sdk = ThirdwebSDK(network) + sdk = ThirdwebSDK(network, options=SDKOptions(secret_key=secret_key)) # If you want to send transactions, you can instantiate the SDK with a private key instead: - # sdk = ThirdwebSDK.from_private_key(PRIVATE_KEY, network) + # sdk = ThirdwebSDK.from_private_key(PRIVATE_KEY, network, options=SDKOptions(secret_key=secret_key)) contract = sdk.get_token("{{contract_address}}") ```