From d8bf9962754937f20f3f4f2005e32ad5607196c7 Mon Sep 17 00:00:00 2001 From: "mariacarmina.cretu" Date: Wed, 31 May 2023 13:50:53 +0000 Subject: [PATCH] GITBOOK-375: change request with no subject merged in GitBook --- developers/ocean.py/technical-details.md | 885 ++++++++++++++++++++++- 1 file changed, 874 insertions(+), 11 deletions(-) diff --git a/developers/ocean.py/technical-details.md b/developers/ocean.py/technical-details.md index bbbdab73..e8b27f3d 100644 --- a/developers/ocean.py/technical-details.md +++ b/developers/ocean.py/technical-details.md @@ -362,10 +362,525 @@ As parameters: ### Ocean Assets +
+ocean.assets.create_url_asset( self, name: str, url: str, publisher_wallet, wait_for_aqua: bool = True ) -> tuple + +It is the most used functions in all the READMEs. + +Creates asset of type "dataset", having `UrlFiles`, with good defaults. + +It can be called after instantiating Ocean object. + +Params: + +1. `name` - name of the asset, `string` +2. `url` - url that is stored in the asset, `string` +3. `publisher_wallet` - wallet of the asset publisher/owner, `Brownie account` +4. `wait_for_aqua` - boolean value which default is `True`, waiting for aquarius to fetch the asset takes additional time, but if you want to be sure that your asset is indexed, keep the default value. + +Return: + +A tuple which contains the data NFT, datatoken and the data asset. + +{% code overflow="wrap" %} +```python + @enforce_types + def create_url_asset( + self, name: str, url: str, publisher_wallet, wait_for_aqua: bool = True + ) -> tuple: + """Create asset of type "data", having UrlFiles, with good defaults""" + metadata = self._default_metadata(name, publisher_wallet) + files = [UrlFile(url)] + return self._create_1dt(metadata, files, publisher_wallet, wait_for_aqua) +``` +{% endcode %} + +
+ +
+ +ocean.assets.create_algo_asset( self, name: str, url: str, publisher_wallet, image: str = "oceanprotocol/algo_dockers", tag: str = "python-branin", checksum: str = "sha256:8221d20c1c16491d7d56b9657ea09082c0ee4a8ab1a6621fa720da58b09580e4", wait_for_aqua: bool = True) -> tuple + +Create asset of type "algorithm", having `UrlFiles`, with good defaults + +It can be called after instantiating Ocean object. + +Params: + +1. `name` - name of the asset, `string` +2. `url` - url that is stored in the asset, `string` +3. `publisher_wallet` - wallet of the asset publisher/owner, `Brownie account` +4. `image` - docker image of that algorithm, `string` +5. `tag` - docker tag for that algorithm image, `string` +6. `checksum` - docker checksum for algorithm's image, `string` +7. `wait_for_aqua` - boolean value which default is `True`, waiting for aquarius to fetch the asset takes additional time, but if you want to be sure that your asset is indexed, keep the default value. + +Return: + +A tuple which contains the algorithm NFT, algorithm datatoken and the algorithm asset. + +{% code overflow="wrap" %} +```python +@enforce_types + def create_algo_asset( + self, + name: str, + url: str, + publisher_wallet, + image: str = "oceanprotocol/algo_dockers", + tag: str = "python-branin", + checksum: str = "sha256:8221d20c1c16491d7d56b9657ea09082c0ee4a8ab1a6621fa720da58b09580e4", + wait_for_aqua: bool = True, + ) -> tuple: + """Create asset of type "algorithm", having UrlFiles, with good defaults""" + + if image == "oceanprotocol/algo_dockers" or tag == "python-branin": + assert image == "oceanprotocol/algo_dockers" and tag == "python-branin" + + metadata = self._default_metadata(name, publisher_wallet, "algorithm") + metadata["algorithm"] = { + "language": "python", + "format": "docker-image", + "version": "0.1", + "container": { + "entrypoint": "python $ALGO", + "image": image, + "tag": tag, + "checksum": checksum, + }, + } + + files = [UrlFile(url)] + return self._create_1dt(metadata, files, publisher_wallet, wait_for_aqua) +``` +{% endcode %} + +
+ +
+ +ocean.assets.create_arweave_asset( self, name: str, transaction_id: str, publisher_wallet, wait_for_aqua: bool = True) -> tuple + +Creates asset of type "data", having `ArweaveFile`, with good defaults. + +It can be called after instantiating Ocean object. + +Params: + +1. `name` - name of the asset, `string` +2. `transaction_id` - transaction id from the arweave file, `string` +3. `publisher_wallet` - wallet of the asset publisher/owner, `Brownie account` +4. `wait_for_aqua` - boolean value which default is `True`, waiting for aquarius to fetch the asset takes additional time, but if you want to be sure that your asset is indexed, keep the default value. + +Return: + +A tuple which contains the data NFT, datatoken and the data asset. + +{% code overflow="wrap" %} +```python +@enforce_types + def create_arweave_asset( + self, + name: str, + transaction_id: str, + publisher_wallet, + wait_for_aqua: bool = True, + ) -> tuple: + """Create asset of type "data", having ArweaveFiles, with good defaults""" + metadata = self._default_metadata(name, publisher_wallet) + files = [ArweaveFile(transaction_id)] + return self._create_1dt(metadata, files, publisher_wallet, wait_for_aqua) +``` +{% endcode %} + +
+ +
+ +ocean.assets.create_graphql_asset( self, name: str, url: str, query: str, publisher_wallet, wait_for_aqua: bool = True, ) -> tuple + +Creates asset of type "data", having `GraphqlQuery` files, with good defaults. + +It can be called after instantiating Ocean object. + +Params: + +1. `name` - name of the asset, `string` +2. `url` - url of subgraph that you are using, `string` +3. `query` - GraphQL query, `string` +4. `publisher_wallet` - wallet of the asset publisher/owner, `Brownie account` +5. `wait_for_aqua` - boolean value which default is `True`, waiting for aquarius to fetch the asset takes additional time, but if you want to be sure that your asset is indexed, keep the default value. + +Return: + +A tuple which contains the data NFT, datatoken and the data asset. + +{% code overflow="wrap" %} +```python +@enforce_types + def create_graphql_asset( + self, + name: str, + url: str, + query: str, + publisher_wallet, + wait_for_aqua: bool = True, + ) -> tuple: + """Create asset of type "data", having GraphqlQuery files, w good defaults""" + metadata = self._default_metadata(name, publisher_wallet) + files = [GraphqlQuery(url, query)] + return self._create_1dt(metadata, files, publisher_wallet, wait_for_aqua) +``` +{% endcode %} + +
+ +
+ +ocean.assets.create_onchain_asset( self, name: str, contract_address: str, contract_abi: dict, publisher_wallet, wait_for_aqua: bool = True ) -> tuple + +Creates asset of type "data", having `SmartContractCall` files, with good defaults. + +It can be called after instantiating Ocean object. + +Params: + +1. `name` - name of the asset, `string` +2. `contract_address` - contract address that should be stored in the asset, `string` +3. `contract_abi` - ABI of functions presented in the contract, `string` +4. `publisher_wallet` - wallet of the asset publisher/owner, `Brownie account` +5. `wait_for_aqua` - boolean value which default is `True`, waiting for aquarius to fetch the asset takes additional time, but if you want to be sure that your asset is indexed, keep the default value. + +Return: + +A tuple which contains the data NFT, datatoken and the data asset. + +{% code overflow="wrap" %} +```python +@enforce_types + def create_onchain_asset( + self, + name: str, + contract_address: str, + contract_abi: dict, + publisher_wallet, + wait_for_aqua: bool = True, + ) -> tuple: + """Create asset of type "data", having SmartContractCall files, w defaults""" + chain_id = self._chain_id + onchain_data = SmartContractCall(contract_address, chain_id, contract_abi) + files = [onchain_data] + metadata = self._default_metadata(name, publisher_wallet) + return self._create_1dt(metadata, files, publisher_wallet, wait_for_aqua) +``` +{% endcode %} + +
+ +
+ +ocean.assets.create( self, metadata: dict, publisher_wallet, credentials: Optional[dict] = None, data_nft_address: Optional[str] = None, data_nft_args: Optional[DataNFTArguments] = None, deployed_datatokens: Optional[List[Datatoken]] = None, services: Optional[list] = None, datatoken_args: Optional[List["DatatokenArguments"]] = None, encrypt_flag: Optional[bool] = True, compress_flag: Optional[bool] = True, wait_for_aqua: bool = True, ) -> Optional[DDO] + + + +Register an asset on-chain. Asset = {data\_NFT, >=0 datatokens, DDO} + +Creating/deploying a DataNFT contract and in the Metadata store (Aquarius). + +Params: + +* `metadata`: `dictionary` conforming to the Metadata accepted by Ocean Protocol. +* `publisher_wallet`- `Brownie account` of the publisher registering this asset. +* `credentials` - credentials `dictionary` necessary for the asset, which establish who can consume the asset and who cannot. +* `data_nft_address`- hex string, the address of the data NFT. The new asset will be associated with this data NFT address. +* `data_nft_args`- object of DataNFTArguments type if creating a new one. +* `deployed_datatokens`- list of datatokens which are already deployed. +* `services` - list of `Service` objects if you want to run multiple services for a datatoken or you have multiple datatokens with a single service each. +* `datatoken_args` - list of objects of `DatatokenArguments` type if creating a new datatokens. +* `encrypt_flag`- bool for encryption of the DDO. +* `compress_flag`- bool for compression of the DDO. +* `wait_for_aqua`- bool for spending time waiting for DDO to be updated in Aquarius. + +Return: + +A tuple which contains the data NFT, datatoken and the data asset. + +{% code overflow="wrap" %} +```python +def create( + self, + metadata: dict, + publisher_wallet, + credentials: Optional[dict] = None, + data_nft_address: Optional[str] = None, + data_nft_args: Optional[DataNFTArguments] = None, + deployed_datatokens: Optional[List[Datatoken]] = None, + services: Optional[list] = None, + datatoken_args: Optional[List["DatatokenArguments"]] = None, + encrypt_flag: Optional[bool] = True, + compress_flag: Optional[bool] = True, + wait_for_aqua: bool = True, + ) -> Optional[DDO]: + + self._assert_ddo_metadata(metadata) + + provider_uri = DataServiceProvider.get_url(self._config_dict) + + if not data_nft_address: + data_nft_args = data_nft_args or DataNFTArguments( + metadata["name"], metadata["name"] + ) + data_nft = data_nft_args.deploy_contract( + self._config_dict, publisher_wallet + ) + # register on-chain + if not data_nft: + logger.warning("Creating new NFT failed.") + return None, None, None + logger.info(f"Successfully created NFT with address {data_nft.address}.") + else: + data_nft = DataNFT(self._config_dict, data_nft_address) + + # Create DDO object + ddo = DDO() + + # Generate the did, add it to the ddo. + ddo.did = data_nft.calculate_did() + # Check if it's already registered first! + if self._aquarius.ddo_exists(ddo.did): + raise AquariusError( + f"Asset id {ddo.did} is already registered to another asset." + ) + ddo.chain_id = self._chain_id + ddo.metadata = metadata + + ddo.credentials = credentials if credentials else {"allow": [], "deny": []} + + ddo.nft_address = data_nft.address + datatokens = [] + + if not deployed_datatokens: + services = [] + for datatoken_arg in datatoken_args: + new_dt = datatoken_arg.create_datatoken( + data_nft, publisher_wallet, with_services=True + ) + datatokens.append(new_dt) + + services.extend(datatoken_arg.services) + + for service in services: + ddo.add_service(service) + else: + if not services: + logger.warning("services required with deployed_datatokens.") + return None, None, None + + datatokens = deployed_datatokens + dt_addresses = [] + for datatoken in datatokens: + if deployed_datatokens[0].address not in data_nft.getTokensList(): + logger.warning( + "some deployed_datatokens don't belong to the given data nft." + ) + return None, None, None + + dt_addresses.append(datatoken.address) + + for service in services: + if service.datatoken not in dt_addresses: + logger.warning("Datatoken services mismatch.") + return None, None, None + + ddo.add_service(service) + + # Validation by Aquarius + _, proof = self.validate(ddo) + proof = ( + proof["publicKey"], + proof["v"], + proof["r"][0], + proof["s"][0], + ) + + document, flags, ddo_hash = self._encrypt_ddo( + ddo, provider_uri, encrypt_flag, compress_flag + ) + + data_nft.setMetaData( + 0, + provider_uri, + Web3.toChecksumAddress(publisher_wallet.address.lower()).encode("utf-8"), + flags, + document, + ddo_hash, + [proof], + {"from": publisher_wallet}, + ) + + # Fetch the ddo on chain + if wait_for_aqua: + ddo = self._aquarius.wait_for_ddo(ddo.did) + + return (data_nft, datatokens, ddo) +``` +{% endcode %} + + + +
+ +
+ +ocean.assets.update( self, ddo: DDO, publisher_wallet, provider_uri: Optional[str] = None, encrypt_flag: Optional[bool] = True, compress_flag: Optional[bool] = True, ) -> Optional[DDO] + +Updates a ddo on-chain. + +Params: + +* `ddo` - DDO to update +* `publisher_wallet` - who published this DDO +* `provider_uri` - URL of service provider. This will be used as base to construct the serviceEndpoint for the `access` (download) service. +* `encrypt_flag` - boolean value for encryption the DDO +* `compress_flag` - boolean value for compression the DDO + +Return: + +The updated DDO, or `None` if updated DDO not found in Aquarius. + +{% code overflow="wrap" %} +```python +@enforce_types + def update( + self, + ddo: DDO, + publisher_wallet, + provider_uri: Optional[str] = None, + encrypt_flag: Optional[bool] = True, + compress_flag: Optional[bool] = True, + ) -> Optional[DDO]: + + self._assert_ddo_metadata(ddo.metadata) + + if not provider_uri: + provider_uri = DataServiceProvider.get_url(self._config_dict) + + assert ddo.nft_address, "need nft address to update a ddo" + data_nft = DataNFT(self._config_dict, ddo.nft_address) + + assert ddo.chain_id == self._chain_id + + for service in ddo.services: + service.encrypt_files(ddo.nft_address) + + # Validation by Aquarius + validation_result, errors_or_proof = self.validate(ddo) + if not validation_result: + msg = f"DDO has validation errors: {errors_or_proof}" + logger.error(msg) + raise ValueError(msg) + + document, flags, ddo_hash = self._encrypt_ddo( + ddo, provider_uri, encrypt_flag, compress_flag + ) + + proof = ( + errors_or_proof["publicKey"], + errors_or_proof["v"], + errors_or_proof["r"][0], + errors_or_proof["s"][0], + ) + + tx_result = data_nft.setMetaData( + 0, + provider_uri, + Web3.toChecksumAddress(publisher_wallet.address.lower()).encode("utf-8"), + flags, + document, + ddo_hash, + [proof], + {"from": publisher_wallet}, + ) + + ddo = self._aquarius.wait_for_ddo_update(ddo, tx_result.txid) + + return ddo +``` +{% endcode %} + +
+ +
+ +ocean.assets.resolve(self, did: str) -> "DDO" + +Resolves the asset from Metadata Cache store (Aquarius). + +Param: + +* did - identifier of the DDO to be searched & resolved in Aquarius + +Return: + +Returns DDO instance. + +```python +@enforce_types + def resolve(self, did: str) -> "DDO": + return self._aquarius.get_ddo(did) +``` + +
+ +
+ +ocean.assets.search(self, text: str) -> list + +Searches a DDO by a specific text. + + + +
+ +
+ +ocean.assets.query(self, query: dict) -> list + + + +
+ +
+ +ocean.assets.download_asset( self, ddo: DDO, consumer_wallet, destination: str, order_tx_id: Union[str, bytes], service: Optional[Service] = None, index: Optional[int] = None, userdata: Optional[dict] = None, ) -> str + + + +
+ +
+ +ocean.assets.pay_for_access_service( self, ddo: DDO, wallet, service: Optional[Service] = None, consume_market_fees: Optional[TokenFeeInfo] = None, consumer_address: Optional[str] = None, userdata: Optional[dict] = None, ) + + + +
+ +
+ +ocean.assets.pay_for_compute_service( self, datasets: List[ComputeInput], algorithm_data: Union[ComputeInput, AlgorithmMetadata], compute_environment: str, valid_until: int, consume_market_order_fee_address: str, wallet, consumer_address: Optional[str] = None, ) + + + +
+ +### Ocean Compute ### Datatoken Interface +Dispenser utils: +
datatoken.create_dispenser(self, tx_dict: dict, max_tokens: Optional[Union[int, str]] = None, max_balance: Optional[Union[int, str]] = None, with_mint: Optional[bool] = True) @@ -376,9 +891,9 @@ It is implemented in DatatokenBase, inherited by Datatoken2, so it can be called Each parameter has the following meaning: -1. `tx_dict` - is the configuration for that specific transaction. Usually for `development` we include just the `from` wallet, but for remote networks, you can provide gas fees, required confirmations for that block etc. For more info, check [Brownie docs](https://eth-brownie.readthedocs.io/en/stable/). -2. `max_tokens` - maximum amount of tokens to dispense in wei -3. `max_balance` - maximum balance of requester in wei +1. `tx_dict` - is the configuration `dictionary` for that specific transaction. Usually for `development` we include just the `from` wallet, but for remote networks, you can provide gas fees, required confirmations for that block etc. For more info, check [Brownie docs](https://eth-brownie.readthedocs.io/en/stable/). +2. `max_tokens` - maximum amount of tokens to dispense in wei. The default is a large number. +3. `max_balance` - maximum balance of requester in wei. The default is a large number. 4. `with_mint` - boolean, `true` if we want to allow the dispenser to be a minter as default value Return value is a hex string which denotes the transaction hash of dispenser deployment. @@ -436,14 +951,14 @@ Return value is a hex string which denotes the transaction hash of dispenser dep datatoken.dispense(self, amount: Union[int, str], tx_dict: dict) -This function is used to retrieve funds or datatokens for an user who wants to access an asset. +This function is used to retrieve funds or datatokens for an user who wants to start an order. It is implemented in DatatokenBase, so it can be called within Datatoken class. Each parameter has the following meaning: 1. `amount` - amount of datatokens to be dispensed in wei (int or string format) -2. `tx_dict` - is the configuration for that specific transaction. Usually for `development` we include just the `from` wallet, but for remote networks, you can provide gas fees, required confirmations for that block etc. For more info, check [Brownie docs](https://eth-brownie.readthedocs.io/en/stable/). +2. `tx_dict` - is the configuration `dictionary` for that specific transaction. Usually for `development` we include just the `from` wallet, but for remote networks, you can provide gas fees, required confirmations for that block etc. For more info, check [Brownie docs](https://eth-brownie.readthedocs.io/en/stable/). Return value is a hex string which denotes the transaction hash of dispensed datatokens, like a proof. @@ -478,21 +993,369 @@ Return value is a hex string which denotes the transaction hash of dispensed dat datatoken.dispense_and_order(self, consumer: str, service_index: int, provider_fees: dict, transaction_parameters: dict, consume_market_fees=None) -This function is used to retrieve funds or datatokens for an user who wants to access an asset. +This function is used to retrieve funds or datatokens for an user who wants to start an order. It is implemented in Datatoken2, so it can be called within Datatoken2 class (using the enterprise template). Each parameter has the following meaning: -1. `amount` - amount of datatokens to be dispensed in wei (int or string format) -2. `tx_dict` - is the configuration for that specific transaction. Usually for `development` we include just the `from` wallet, but for remote networks, you can provide gas fees, required confirmations for that block etc. For more info, check [Brownie docs](https://eth-brownie.readthedocs.io/en/stable/). +1. `consumer` - address of the consumer wallet that needs funding +2. `service_index` - service index as int for identifying the service that you want to further call [`start_order`](https://github.com/oceanprotocol/ocean.py/blob/4aa12afd8a933d64bc2ed68d1e5359d0b9ae62f9/ocean\_lib/models/datatoken.py#LL169C5-L197C10). +3. `transaction_parameters` - is the configuration `dictionary` for that specific transaction. Usually for `development` we include just the `from` wallet, but for remote networks, you can provide gas fees, required confirmations for that block etc. For more info, check [Brownie docs](https://eth-brownie.readthedocs.io/en/stable/). +4. `consume_market_fees` - [`TokenInfo` ](https://github.com/oceanprotocol/ocean.py/blob/4aa12afd8a933d64bc2ed68d1e5359d0b9ae62f9/ocean\_lib/models/datatoken.py#L31)object which contains the consume market fee amount, address & token address. If it is not explicitly specified, by default it has an empty `TokenInfo` object. -Return value is a hex string which denotes the transaction hash of dispensed datatokens, like a proof. +Return value is a hex string which denotes the transaction hash of dispensed datatokens, like a proof of starting order. + +```python +def dispense_and_order( + self, + consumer: str, + service_index: int, + provider_fees: dict, + transaction_parameters: dict, + consume_market_fees=None, + ) -> str: + if not consume_market_fees: + consume_market_fees = TokenFeeInfo() + + buyer_addr = ( + transaction_parameters["from"].address + if hasattr(transaction_parameters["from"], "address") + else transaction_parameters["from"] + ) + + bal = from_wei(self.balanceOf(buyer_addr)) + if bal < 1.0: + dispenser_addr = get_address_of_type(self.config_dict, "Dispenser") + from ocean_lib.models.dispenser import Dispenser # isort: skip + + dispenser = Dispenser(self.config_dict, dispenser_addr) + + # catch key failure modes + st = dispenser.status(self.address) + active, allowedSwapper = st[0], st[6] + if not active: + raise ValueError("No active dispenser for datatoken") + if allowedSwapper not in [ZERO_ADDRESS, buyer_addr]: + raise ValueError(f"Not allowed. allowedSwapper={allowedSwapper}") + + # Try to dispense. If other issues, they'll pop out + dispenser.dispense( + self.address, "1 ether", buyer_addr, transaction_parameters + ) + + return self.start_order( + consumer=ContractBase.to_checksum_address(consumer), + service_index=service_index, + provider_fees=provider_fees, + consume_market_fees=consume_market_fees, + transaction_parameters=transaction_parameters, + ) +```
-### Fixed Rate Exchange +
+datatoken.dispenser_status(self) -> DispenserStatus +Returns a `DispenserStatus` object returned from `Dispenser.sol::status(dt_addr)` which is composed of: + +* bool active +* address owner +* bool isMinter +* uint256 maxTokens +* uint256 maxBalance +* uint256 balance +* address allowedSwapper + +These are Solidity return values & types, but `uint256` means int in Python and `address` is a `string` instance. + +For tips & tricks, check [this section](https://github.com/oceanprotocol/ocean.py/blob/4aa12afd8a933d64bc2ed68d1e5359d0b9ae62f9/READMEs/main-flow.md#faucet-tips--tricks) from the [README](https://github.com/oceanprotocol/ocean.py/blob/4aa12afd8a933d64bc2ed68d1e5359d0b9ae62f9/READMEs/main-flow.md). + +It is implemented in DatatokenBase, inherited by Datatoken2, so it can be called within both instances. + +```python +@enforce_types + def dispenser_status(self): + """:return: DispenserStatus object""" + # import here to avoid circular import + from ocean_lib.models.dispenser import DispenserStatus + + status_tup = self._ocean_dispenser().status(self.address) + return DispenserStatus(status_tup) +``` + +
+ +Fixed Rate Exchange utils: + +
+ +datatoken.create_exchange(self, rate: Union[int, str], base_token_addr: str, tx_dict: dict, owner_addr: Optional[str] = None, publish_market_fee_collector: Optional[str] = None, publish_market_fee: Union[int, str] = 0, with_mint: bool = False, allowed_swapper: str = ZERO_ADDRESS, full_info: bool = False) -> Union[OneExchange, tuple] + +It is implemented in DatatokenBase, inherited by Datatoken2, so it can be called within both instances. + +For this datatoken, create a single fixed-rate exchange (OneExchange). + +This wraps the smart contract method `Datatoken.createFixedRate()` with a simpler interface. + +Main params: + +* `rate` - how many base tokens does 1 datatoken cost? In wei or string +* `base_token_addr` - e.g. OCEAN address +* `tx_dict` - is the configuration `dictionary` for that specific transaction. Usually for `development` we include just the `from` wallet, but for remote networks, you can provide gas fees, required confirmations for that block etc. For more info, check [Brownie docs](https://eth-brownie.readthedocs.io/en/stable/). + +Optional params, with good defaults: + +* `owner_addr` - owner of the datatoken +* `publish_market_fee_collector` - fee going to publish market address +* `publish_market_fee` - in wei or string, e.g. `int(1e15)` or `"0.001 ether"` +* `with_mint` - should the exchange mint datatokens as needed (`True`), or do they need to be supplied/allowed by participants like base token (`False`)? +* `allowed_swapper` - if `ZERO_ADDRESS`, anyone can swap +* `full_info` - return just `OneExchange`, or `(OneExchange, )` + +Return + +* `exchange` - OneExchange +* (maybe) `tx_receipt` + +{% code overflow="wrap" %} +```python +@enforce_types + def create_exchange( + self, + rate: Union[int, str], + base_token_addr: str, + tx_dict: dict, + owner_addr: Optional[str] = None, + publish_market_fee_collector: Optional[str] = None, + publish_market_fee: Union[int, str] = 0, + with_mint: bool = False, + allowed_swapper: str = ZERO_ADDRESS, + full_info: bool = False, + ) -> Union[OneExchange, tuple]: + + # import now, to avoid circular import + from ocean_lib.models.fixed_rate_exchange import OneExchange + + FRE_addr = get_address_of_type(self.config_dict, "FixedPrice") + from_addr = ( + tx_dict["from"].address + if hasattr(tx_dict["from"], "address") + else tx_dict["from"] + ) + BT = Datatoken(self.config_dict, base_token_addr) + owner_addr = owner_addr or from_addr + publish_market_fee_collector = publish_market_fee_collector or from_addr + + tx = self.contract.createFixedRate( + checksum_addr(FRE_addr), + [ + checksum_addr(BT.address), + checksum_addr(owner_addr), + checksum_addr(publish_market_fee_collector), + checksum_addr(allowed_swapper), + ], + [ + BT.decimals(), + self.decimals(), + rate, + publish_market_fee, + with_mint, + ], + tx_dict, + ) + + exchange_id = tx.events["NewFixedRate"]["exchangeId"] + FRE = self._FRE() + exchange = OneExchange(FRE, exchange_id) + if full_info: + return (exchange, tx) + return exchange +``` +{% endcode %} + +
+ +
+ +datatoken.buy_DT_and_order(self, consumer: str, service_index: int, provider_fees: dict, exchange: Any, transaction_parameters: dict, consume_market_fees=None, ) -> str: + +This function is used to retrieve funds or datatokens for an user who wants to start an order. + +It is implemented in Datatoken class and it is also inherited in Datatoken2 class. + +Each parameter has the following meaning: + +1. `consumer` - address of the consumer wallet that needs funding +2. `service_index` - service index as int for identifying the service that you want to further call [`start_order`](https://github.com/oceanprotocol/ocean.py/blob/4aa12afd8a933d64bc2ed68d1e5359d0b9ae62f9/ocean\_lib/models/datatoken.py#LL169C5-L197C10). +3. `transaction_parameters` - is the configuration `dictionary` for that specific transaction. Usually for `development` we include just the `from` wallet, but for remote networks, you can provide gas fees, required confirmations for that block etc. For more info, check [Brownie docs](https://eth-brownie.readthedocs.io/en/stable/). +4. `consume_market_fees` - [`TokenInfo` ](https://github.com/oceanprotocol/ocean.py/blob/4aa12afd8a933d64bc2ed68d1e5359d0b9ae62f9/ocean\_lib/models/datatoken.py#L31)object which contains the consume market fee amount, address & token address. If it is not explicitly specified, by default it has an empty `TokenInfo` object. + +Return value is a hex string for transaction hash which denotes the proof of starting order. + +```python + @enforce_types + def buy_DT_and_order( + self, + consumer: str, + service_index: int, + provider_fees: dict, + exchange: Any, + transaction_parameters: dict, + consume_market_fees=None, + ) -> str: + fre_address = get_address_of_type(self.config_dict, "FixedPrice") + + # import now, to avoid circular import + from ocean_lib.models.fixed_rate_exchange import OneExchange + + if not consume_market_fees: + consume_market_fees = TokenFeeInfo() + + if not isinstance(exchange, OneExchange): + exchange = OneExchange(fre_address, exchange) + + exchange.buy_DT( + datatoken_amt=to_wei(1), + consume_market_fee_addr=consume_market_fees.address, + consume_market_fee=consume_market_fees.amount, + tx_dict=transaction_parameters, + ) + + return self.start_order( + consumer=ContractBase.to_checksum_address(consumer), + service_index=service_index, + provider_fees=provider_fees, + consume_market_fees=consume_market_fees, + transaction_parameters=transaction_parameters, + ) +``` + +
+ +
+ +datatoken.get_exchanges(self) -> list + +Returns `List[OneExchange]` - all the exchanges for this datatoken. + +It is implemented in DatatokenBase, inherited by Datatoken2, so it can be called within both instances. + +{% code overflow="wrap" %} +```python +@enforce_types + def get_exchanges(self) -> list: + """return List[OneExchange] - all the exchanges for this datatoken""" + # import now, to avoid circular import + from ocean_lib.models.fixed_rate_exchange import OneExchange + + FRE = self._FRE() + addrs_and_exchange_ids = self.getFixedRates() + exchanges = [ + OneExchange(FRE, exchange_id) for _, exchange_id in addrs_and_exchange_ids + ] + return exchanges + +``` +{% endcode %} + +
+ +Orders: + +
+ +datatoken.start_order( self, consumer: str, service_index: int, provider_fees: dict, transaction_parameters: dict, consume_market_fees=None, ) -> str + +Starting order of a certain datatoken. + +It is implemented in Datatoken class and it is also inherited in Datatoken2 class. + +Each parameter has the following meaning: + +1. `consumer` - address of the consumer wallet that needs funding +2. `service_index` - service index as int for identifying the service that you want to apply `start_order`. +3. `provider_fees` - dictionary which includes provider fees generated when `initialize` endpoint from `Provider` was called. +4. `transaction_parameters` - is the configuration `dictionary` for that specific transaction. Usually for `development` we include just the `from` wallet, but for remote networks, you can provide gas fees, required confirmations for that block etc. For more info, check [Brownie docs](https://eth-brownie.readthedocs.io/en/stable/). +5. `consume_market_fees` - [`TokenInfo` ](https://github.com/oceanprotocol/ocean.py/blob/4aa12afd8a933d64bc2ed68d1e5359d0b9ae62f9/ocean\_lib/models/datatoken.py#L31)object which contains the consume market fee amount, address & token address. If it is not explicitly specified, by default it has an empty `TokenInfo` object. + +Return value is a hex string for transaction hash which denotes the proof of starting order. + +```python +@enforce_types + def start_order( + self, + consumer: str, + service_index: int, + provider_fees: dict, + transaction_parameters: dict, + consume_market_fees=None, + ) -> str: + + if not consume_market_fees: + consume_market_fees = TokenFeeInfo() + + return self.contract.startOrder( + checksum_addr(consumer), + service_index, + ( + checksum_addr(provider_fees["providerFeeAddress"]), + checksum_addr(provider_fees["providerFeeToken"]), + int(provider_fees["providerFeeAmount"]), + provider_fees["v"], + provider_fees["r"], + provider_fees["s"], + provider_fees["validUntil"], + provider_fees["providerData"], + ), + consume_market_fees.to_tuple(), + transaction_parameters, + ) +``` + +
+ +
+ +datatoken.reuse_order(self, order_tx_id: Union[str, bytes], provider_fees: dict, transaction_parameters: dict) -> str + +Reusing an order from a certain datatoken. + +It is implemented in Datatoken class and it is also inherited in Datatoken2 class. + +Each parameter has the following meaning: + +1. `order_tx_id` - transaction hash of a previous order, string or bytes format. +2. `provider_fees` - dictionary which includes provider fees generated when `initialize` endpoint from `Provider` was called. +3. `transaction_parameters` - is the configuration `dictionary` for that specific transaction. Usually for `development` we include just the `from` wallet, but for remote networks, you can provide gas fees, required confirmations for that block etc. For more info, check [Brownie docs](https://eth-brownie.readthedocs.io/en/stable/). + +Return value is a hex string for transaction hash which denotes the proof of reusing order. + +```python + @enforce_types + def reuse_order( + self, + order_tx_id: Union[str, bytes], + provider_fees: dict, + transaction_parameters: dict, + ) -> str: + return self.contract.reuseOrder( + order_tx_id, + ( + checksum_addr(provider_fees["providerFeeAddress"]), + checksum_addr(provider_fees["providerFeeToken"]), + int(provider_fees["providerFeeAmount"]), + provider_fees["v"], + provider_fees["r"], + provider_fees["s"], + provider_fees["validUntil"], + provider_fees["providerData"], + ), + transaction_parameters, + ) +``` + +
-### Dispenser