Skip to content

Commit 8107042

Browse files
feat(Group): add add_ips_to_group and remove_ips_from_group
- GroupingModule client: add removeIp and build_removeIp_transaction - Group: add add_ips_to_group(group_ip_id, ip_ids, max_allowed_reward_share_percentage=100, tx_options) - Group: add remove_ips_from_group(group_ip_id, ip_ids, tx_options) - Unit tests for both methods (invalid args, success, default/zero reward share, tx failure) - Integration tests: add_ips_to_group, remove_ips_from_group, add then remove
1 parent 0e6b2d8 commit 8107042

File tree

4 files changed

+396
-0
lines changed

4 files changed

+396
-0
lines changed

src/story_protocol_python_sdk/abi/GroupingModule/GroupingModule_client.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,14 @@ def build_addIp_transaction(
4343
groupIpId, ipIds, maxAllowedRewardShare
4444
).build_transaction(tx_params)
4545

46+
def removeIp(self, groupIpId, ipIds):
47+
return self.contract.functions.removeIp(groupIpId, ipIds).transact()
48+
49+
def build_removeIp_transaction(self, groupIpId, ipIds, tx_params):
50+
return self.contract.functions.removeIp(
51+
groupIpId, ipIds
52+
).build_transaction(tx_params)
53+
4654
def claimReward(self, groupId, token, ipIds):
4755
return self.contract.functions.claimReward(groupId, token, ipIds).transact()
4856

src/story_protocol_python_sdk/resources/Group.py

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,86 @@ def register_group_and_attach_license_and_add_ips(
453453
f"Failed to register group and attach license and add IPs: {str(e)}"
454454
)
455455

456+
def add_ips_to_group(
457+
self,
458+
group_ip_id: str,
459+
ip_ids: list,
460+
max_allowed_reward_share_percentage: int = 100,
461+
tx_options: dict | None = None,
462+
) -> dict:
463+
"""
464+
Add IPs to an existing group IP.
465+
466+
:param group_ip_id str: The ID of the group IP.
467+
:param ip_ids list: List of IP IDs to add to the group.
468+
:param max_allowed_reward_share_percentage int: [Optional] Maximum allowed reward share percentage (0-100). Default is 100.
469+
:param tx_options dict: [Optional] The transaction options.
470+
:return dict: A dictionary with the transaction hash.
471+
"""
472+
try:
473+
if not self.web3.is_address(group_ip_id):
474+
raise ValueError(f'Group IP ID "{group_ip_id}" is invalid.')
475+
476+
for ip_id in ip_ids:
477+
if not self.web3.is_address(ip_id):
478+
raise ValueError(f'IP ID "{ip_id}" is invalid.')
479+
480+
max_allowed_reward_share = get_revenue_share(
481+
max_allowed_reward_share_percentage,
482+
type=RevShareType.MAX_ALLOWED_REWARD_SHARE,
483+
)
484+
485+
response = build_and_send_transaction(
486+
self.web3,
487+
self.account,
488+
self.grouping_module_client.build_addIp_transaction,
489+
group_ip_id,
490+
ip_ids,
491+
max_allowed_reward_share,
492+
tx_options=tx_options,
493+
)
494+
495+
return {"tx_hash": response["tx_hash"]}
496+
497+
except Exception as e:
498+
raise ValueError(f"Failed to add IP to group: {str(e)}")
499+
500+
def remove_ips_from_group(
501+
self,
502+
group_ip_id: str,
503+
ip_ids: list,
504+
tx_options: dict | None = None,
505+
) -> dict:
506+
"""
507+
Remove IPs from a group IP.
508+
509+
:param group_ip_id str: The ID of the group IP.
510+
:param ip_ids list: List of IP IDs to remove from the group.
511+
:param tx_options dict: [Optional] The transaction options.
512+
:return dict: A dictionary with the transaction hash.
513+
"""
514+
try:
515+
if not self.web3.is_address(group_ip_id):
516+
raise ValueError(f'Group IP ID "{group_ip_id}" is invalid.')
517+
518+
for ip_id in ip_ids:
519+
if not self.web3.is_address(ip_id):
520+
raise ValueError(f'IP ID "{ip_id}" is invalid.')
521+
522+
response = build_and_send_transaction(
523+
self.web3,
524+
self.account,
525+
self.grouping_module_client.build_removeIp_transaction,
526+
group_ip_id,
527+
ip_ids,
528+
tx_options=tx_options,
529+
)
530+
531+
return {"tx_hash": response["tx_hash"]}
532+
533+
except Exception as e:
534+
raise ValueError(f"Failed to remove IPs from group: {str(e)}")
535+
456536
def collect_and_distribute_group_royalties(
457537
self,
458538
group_ip_id: str,

tests/integration/test_integration_group.py

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,3 +366,133 @@ def test_get_claimable_reward(
366366
assert len(claimable_rewards) == 2
367367
assert claimable_rewards[0] == 10
368368
assert claimable_rewards[1] == 10
369+
370+
371+
class TestAddIpsToGroupAndRemoveIpsFromGroup:
372+
"""Integration tests for add_ips_to_group and remove_ips_from_group."""
373+
374+
def test_add_ips_to_group(
375+
self, story_client: StoryClient, nft_collection: Address
376+
):
377+
"""Test adding IPs to an existing group."""
378+
# Register two IPs with PIL terms
379+
result1 = GroupTestHelper.mint_and_register_ip_asset_with_pil_terms(
380+
story_client, nft_collection
381+
)
382+
result2 = GroupTestHelper.mint_and_register_ip_asset_with_pil_terms(
383+
story_client, nft_collection
384+
)
385+
ip_id1 = result1["ip_id"]
386+
ip_id2 = result2["ip_id"]
387+
license_terms_id = result1["license_terms_id"]
388+
389+
# Register group with only the first IP
390+
group_ip_id = GroupTestHelper.register_group_and_attach_license(
391+
story_client, license_terms_id, [ip_id1]
392+
)
393+
394+
# Add the second IP to the group
395+
result = story_client.Group.add_ips_to_group(
396+
group_ip_id=group_ip_id,
397+
ip_ids=[ip_id2],
398+
)
399+
400+
assert "tx_hash" in result
401+
assert isinstance(result["tx_hash"], str)
402+
assert len(result["tx_hash"]) > 0
403+
404+
def test_add_ips_to_group_with_max_reward_share(
405+
self, story_client: StoryClient, nft_collection: Address
406+
):
407+
"""Test adding IPs to group with custom max_allowed_reward_share_percentage."""
408+
result1 = GroupTestHelper.mint_and_register_ip_asset_with_pil_terms(
409+
story_client, nft_collection
410+
)
411+
result2 = GroupTestHelper.mint_and_register_ip_asset_with_pil_terms(
412+
story_client, nft_collection
413+
)
414+
ip_id1 = result1["ip_id"]
415+
ip_id2 = result2["ip_id"]
416+
license_terms_id = result1["license_terms_id"]
417+
418+
group_ip_id = GroupTestHelper.register_group_and_attach_license(
419+
story_client, license_terms_id, [ip_id1]
420+
)
421+
422+
result = story_client.Group.add_ips_to_group(
423+
group_ip_id=group_ip_id,
424+
ip_ids=[ip_id2],
425+
max_allowed_reward_share_percentage=50,
426+
)
427+
428+
assert "tx_hash" in result
429+
assert isinstance(result["tx_hash"], str)
430+
431+
def test_remove_ips_from_group(
432+
self, story_client: StoryClient, nft_collection: Address
433+
):
434+
"""Test removing IPs from a group."""
435+
# Register two IPs with PIL terms
436+
result1 = GroupTestHelper.mint_and_register_ip_asset_with_pil_terms(
437+
story_client, nft_collection
438+
)
439+
result2 = GroupTestHelper.mint_and_register_ip_asset_with_pil_terms(
440+
story_client, nft_collection
441+
)
442+
ip_id1 = result1["ip_id"]
443+
ip_id2 = result2["ip_id"]
444+
license_terms_id = result1["license_terms_id"]
445+
446+
# Register group with both IPs
447+
group_ip_id = GroupTestHelper.register_group_and_attach_license(
448+
story_client, license_terms_id, [ip_id1, ip_id2]
449+
)
450+
451+
# Remove the second IP from the group
452+
result = story_client.Group.remove_ips_from_group(
453+
group_ip_id=group_ip_id,
454+
ip_ids=[ip_id2],
455+
)
456+
457+
assert "tx_hash" in result
458+
assert isinstance(result["tx_hash"], str)
459+
assert len(result["tx_hash"]) > 0
460+
461+
def test_add_then_remove_ips_from_group(
462+
self, story_client: StoryClient, nft_collection: Address
463+
):
464+
"""Test add_ips_to_group then remove_ips_from_group in sequence."""
465+
result1 = GroupTestHelper.mint_and_register_ip_asset_with_pil_terms(
466+
story_client, nft_collection
467+
)
468+
result2 = GroupTestHelper.mint_and_register_ip_asset_with_pil_terms(
469+
story_client, nft_collection
470+
)
471+
result3 = GroupTestHelper.mint_and_register_ip_asset_with_pil_terms(
472+
story_client, nft_collection
473+
)
474+
ip_id1 = result1["ip_id"]
475+
ip_id2 = result2["ip_id"]
476+
ip_id3 = result3["ip_id"]
477+
license_terms_id = result1["license_terms_id"]
478+
479+
# Register group with first IP only
480+
group_ip_id = GroupTestHelper.register_group_and_attach_license(
481+
story_client, license_terms_id, [ip_id1]
482+
)
483+
484+
# Add ip_id2 and ip_id3
485+
add_result = story_client.Group.add_ips_to_group(
486+
group_ip_id=group_ip_id,
487+
ip_ids=[ip_id2, ip_id3],
488+
)
489+
assert "tx_hash" in add_result
490+
assert isinstance(add_result["tx_hash"], str)
491+
492+
# Remove ip_id2
493+
remove_result = story_client.Group.remove_ips_from_group(
494+
group_ip_id=group_ip_id,
495+
ip_ids=[ip_id2],
496+
)
497+
assert "tx_hash" in remove_result
498+
assert isinstance(remove_result["tx_hash"], str)

0 commit comments

Comments
 (0)