Skip to content

Commit 19b60f0

Browse files
authored
feat: add pilFlavor to generate license terms (#177)
* feat: introduce PILFlavor class for managing programmable IP license terms * feat: enhance PILFlavor class with camelCase to snake_case conversion and improve error messages for clarity * feat: add unit tests for PILFlavor class to validate non-commercial and commercial use cases * feat: refactor License class to utilize PILFlavor for license terms management and enhance validation logic * feat: enhance License class tests by integrating PILFlavorError for improved validation and error handling * feat: enhance PILFlavor class with new method for converting camelCase to snake_case license terms and update return types for license terms methods * refactor: the pil_flavor class * feat: update License class to use LicenseTermsInput for license terms management and enhance deprecation messages for clarity * feat: add unit tests for various PILFlavor registration scenarios, including non-commercial and commercial use cases * feat: enhance IPAsset and License classes with camelCase conversion for license terms and improve validation logic * refactor: replace Web3 checksum address validation with a dedicated validate_address function and update related unit tests * feat: integrate ModuleRegistryClient into IPAsset and update licensing configuration validation logic * fix: update hookData handling in LicensingConfigData to use text conversion and adjust related tests for consistency * refactor: remove LicenseTerms class and integrate LicensingConfigData into Group and IPAsset for improved licensing configuration management * feat: add comprehensive tests for various licensing configurations in IPAsset, including commercial remix and non-commercial terms * refactor: improve deprecation messages in License class methods to clarify future usage of register_pil_terms * docs: update parameter descriptions in License and PILFlavor classes for improved clarity and consistency * test: add unit tests for snake_to_camel and convert_dict_keys_to_camel_case functions * feat: enhance IPAsset validation by adding checks for whitelisted royalty policies and currencies, along with corresponding unit tests * refactor: streamline currency whitelisting check in IPAsset validation logic for improved readability * refactor: enhance License class by utilizing replace for commercial revenue share calculation and streamline address validation in DerivativeData class
1 parent 9210dae commit 19b60f0

22 files changed

+1762
-631
lines changed

src/story_protocol_python_sdk/__init__.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@
3030
RegistrationWithRoyaltyVaultAndLicenseTermsResponse,
3131
RegistrationWithRoyaltyVaultResponse,
3232
)
33-
from .types.resource.License import LicenseTermsInput
34-
from .types.resource.Royalty import RoyaltyShareInput
33+
from .types.resource.License import LicenseTermsInput, LicenseTermsOverride
34+
from .types.resource.Royalty import NativeRoyaltyPolicy, RoyaltyShareInput
3535
from .utils.constants import (
3636
DEFAULT_FUNCTION_SELECTOR,
3737
MAX_ROYALTY_TOKEN,
@@ -45,6 +45,7 @@
4545
from .utils.derivative_data import DerivativeDataInput
4646
from .utils.ip_metadata import IPMetadataInput
4747
from .utils.licensing_config_data import LicensingConfig
48+
from .utils.pil_flavor import PILFlavor, PILFlavorError
4849

4950
__all__ = [
5051
"StoryClient",
@@ -73,7 +74,9 @@
7374
"LicensingConfig",
7475
"RegisterPILTermsAndAttachResponse",
7576
"RoyaltyShareInput",
77+
"NativeRoyaltyPolicy",
7678
"LicenseTermsInput",
79+
"LicenseTermsOverride",
7780
"MintNFT",
7881
"MintedNFT",
7982
"RegisterIpAssetResponse",
@@ -88,4 +91,7 @@
8891
"DEFAULT_FUNCTION_SELECTOR",
8992
"MAX_ROYALTY_TOKEN",
9093
"WIP_TOKEN_ADDRESS",
94+
# utils
95+
"PILFlavor",
96+
"PILFlavorError",
9197
]

src/story_protocol_python_sdk/resources/Group.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@
2222
from story_protocol_python_sdk.abi.LicensingModule.LicensingModule_client import (
2323
LicensingModuleClient,
2424
)
25+
from story_protocol_python_sdk.abi.ModuleRegistry.ModuleRegistry_client import (
26+
ModuleRegistryClient,
27+
)
2528
from story_protocol_python_sdk.abi.PILicenseTemplate.PILicenseTemplate_client import (
2629
PILicenseTemplateClient,
2730
)
@@ -32,7 +35,7 @@
3235
CollectRoyaltiesResponse,
3336
)
3437
from story_protocol_python_sdk.utils.constants import ZERO_ADDRESS, ZERO_HASH
35-
from story_protocol_python_sdk.utils.license_terms import LicenseTerms
38+
from story_protocol_python_sdk.utils.licensing_config_data import LicensingConfigData
3639
from story_protocol_python_sdk.utils.sign import Sign
3740
from story_protocol_python_sdk.utils.transaction_utils import build_and_send_transaction
3841
from story_protocol_python_sdk.utils.validation import get_revenue_share
@@ -59,8 +62,7 @@ def __init__(self, web3: Web3, account, chain_id: int):
5962
self.licensing_module_client = LicensingModuleClient(web3)
6063
self.license_registry_client = LicenseRegistryClient(web3)
6164
self.pi_license_template_client = PILicenseTemplateClient(web3)
62-
63-
self.license_terms_util = LicenseTerms(web3)
65+
self.module_registry_client = ModuleRegistryClient(web3)
6466
self.sign_util = Sign(web3, self.chain_id, self.account)
6567

6668
def register_group(self, group_pool: str, tx_options: dict | None = None) -> dict:
@@ -707,8 +709,8 @@ def _get_license_data(self, license_data: list) -> list:
707709
processed_item = {
708710
"licenseTemplate": license_template,
709711
"licenseTermsId": item["license_terms_id"],
710-
"licensingConfig": self.license_terms_util.validate_licensing_config(
711-
item.get("licensing_config", {})
712+
"licensingConfig": LicensingConfigData.validate_license_config(
713+
self.module_registry_client, item.get("licensing_config", {})
712714
),
713715
}
714716

src/story_protocol_python_sdk/resources/IPAsset.py

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"""Module for handling IP Account operations and transactions."""
22

3-
from dataclasses import asdict, is_dataclass
3+
from dataclasses import asdict, is_dataclass, replace
44
from typing import cast
55

66
from ens.ens import Address, HexStr
@@ -37,6 +37,9 @@
3737
from story_protocol_python_sdk.abi.LicensingModule.LicensingModule_client import (
3838
LicensingModuleClient,
3939
)
40+
from story_protocol_python_sdk.abi.ModuleRegistry.ModuleRegistry_client import (
41+
ModuleRegistryClient,
42+
)
4043
from story_protocol_python_sdk.abi.Multicall3.Multicall3_client import Multicall3Client
4144
from story_protocol_python_sdk.abi.PILicenseTemplate.PILicenseTemplate_client import (
4245
PILicenseTemplateClient,
@@ -69,6 +72,7 @@
6972
RegistrationWithRoyaltyVaultAndLicenseTermsResponse,
7073
RegistrationWithRoyaltyVaultResponse,
7174
)
75+
from story_protocol_python_sdk.types.resource.License import LicenseTermsInput
7276
from story_protocol_python_sdk.types.resource.Royalty import RoyaltyShareInput
7377
from story_protocol_python_sdk.utils.constants import (
7478
DEADLINE,
@@ -87,11 +91,14 @@
8791
get_ip_metadata_dict,
8892
is_initial_ip_metadata,
8993
)
90-
from story_protocol_python_sdk.utils.license_terms import LicenseTerms
94+
from story_protocol_python_sdk.utils.licensing_config_data import LicensingConfigData
95+
from story_protocol_python_sdk.utils.pil_flavor import PILFlavor
9196
from story_protocol_python_sdk.utils.royalty import get_royalty_shares
9297
from story_protocol_python_sdk.utils.sign import Sign
9398
from story_protocol_python_sdk.utils.transaction_utils import build_and_send_transaction
99+
from story_protocol_python_sdk.utils.util import convert_dict_keys_to_camel_case
94100
from story_protocol_python_sdk.utils.validation import (
101+
get_revenue_share,
95102
validate_address,
96103
validate_max_rts,
97104
)
@@ -129,8 +136,8 @@ def __init__(self, web3: Web3, account, chain_id: int):
129136
)
130137
self.royalty_module_client = RoyaltyModuleClient(web3)
131138
self.multicall3_client = Multicall3Client(web3)
132-
self.license_terms_util = LicenseTerms(web3)
133139
self.sign_util = Sign(web3, self.chain_id, self.account)
140+
self.module_registry_client = ModuleRegistryClient(web3)
134141

135142
def mint(
136143
self,
@@ -755,7 +762,6 @@ def register_ip_and_attach_pil_terms(
755762
f"The NFT with id {token_id} is already registered as IP."
756763
)
757764
license_terms = self._validate_license_terms_data(license_terms_data)
758-
759765
calculated_deadline = self.sign_util.get_deadline(deadline=deadline)
760766

761767
# Get permission signature for all required permissions
@@ -1399,7 +1405,6 @@ def register_ip_and_attach_pil_terms_and_distribute_royalty_tokens(
13991405
license_terms = self._validate_license_terms_data(license_terms_data)
14001406
calculated_deadline = self.sign_util.get_deadline(deadline=deadline)
14011407
royalty_shares_obj = get_royalty_shares(royalty_shares)
1402-
14031408
signature_response = self.sign_util.get_permission_signature(
14041409
ip_id=ip_id,
14051410
deadline=calculated_deadline,
@@ -2251,11 +2256,34 @@ def _validate_license_terms_data(
22512256
terms_dict = term["terms"]
22522257
licensing_config_dict = term["licensing_config"]
22532258

2259+
license_terms = PILFlavor.validate_license_terms(
2260+
LicenseTermsInput(**terms_dict)
2261+
)
2262+
license_terms = replace(
2263+
license_terms,
2264+
commercial_rev_share=get_revenue_share(
2265+
license_terms.commercial_rev_share
2266+
),
2267+
)
2268+
if license_terms.royalty_policy != ZERO_ADDRESS:
2269+
is_whitelisted = self.royalty_module_client.isWhitelistedRoyaltyPolicy(
2270+
license_terms.royalty_policy
2271+
)
2272+
if not is_whitelisted:
2273+
raise ValueError("The royalty_policy is not whitelisted.")
2274+
2275+
if license_terms.currency != ZERO_ADDRESS:
2276+
is_whitelisted = self.royalty_module_client.isWhitelistedRoyaltyToken(
2277+
license_terms.currency
2278+
)
2279+
if not is_whitelisted:
2280+
raise ValueError("The currency is not whitelisted.")
2281+
22542282
validated_license_terms_data.append(
22552283
{
2256-
"terms": self.license_terms_util.validate_license_terms(terms_dict),
2257-
"licensingConfig": self.license_terms_util.validate_licensing_config(
2258-
licensing_config_dict
2284+
"terms": convert_dict_keys_to_camel_case(asdict(license_terms)),
2285+
"licensingConfig": LicensingConfigData.validate_license_config(
2286+
self.module_registry_client, licensing_config_dict
22592287
),
22602288
}
22612289
)

0 commit comments

Comments
 (0)