Skip to content

Commit 2f2312a

Browse files
authored
Merge pull request #133 from Virtual-Protocol/feat/percentage-fee-notification
Percentage fee for payable delivery & notification
2 parents 648f484 + 97fd29d commit 2f2312a

3 files changed

Lines changed: 54 additions & 41 deletions

File tree

examples/acp_base/funds_transfer_v2/trading/seller.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,8 @@ def handle_task_transaction(job: ACPJob):
237237
logger.info(f"Returning swapped token: {swapped_amount}")
238238
job.deliver_payable(
239239
f"Return swapped token {job.requirement.get('toSymbol', 'VIRTUAL')}",
240-
swapped_amount
240+
swapped_amount,
241+
True # skip fee to return swapped tokens
241242
)
242243
logger.info("Swapped token returned")
243244

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "virtuals-acp"
3-
version = "0.3.15"
3+
version = "0.3.16"
44
description = "Agent Commerce Protocol Python SDK by Virtuals"
55
authors = ["Steven Lee Soon Fatt <steven@virtuals.io>"]
66
readme = "README.md"

virtuals_acp/job.py

Lines changed: 51 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ def model_post_init(self, __context: Any) -> None:
8181
self._name = content_obj.service_name or content_obj.name
8282
self._price_type = content_obj.price_type or PriceType.FIXED
8383
self._price_value = content_obj.price_value or self.price
84+
return None
8485

8586
@property
8687
def requirement(self) -> Optional[Union[str, Dict[str, Any]]]:
@@ -174,11 +175,11 @@ def create_requirement(self, content: str) -> str | None:
174175

175176
operations.append(
176177
self.acp_contract_client.create_memo(
177-
self.id,
178-
content,
179-
MemoType.MESSAGE,
180-
False,
181-
ACPJobPhase.TRANSACTION,
178+
job_id=self.id,
179+
content=content,
180+
memo_type=MemoType.MESSAGE,
181+
is_secured=False,
182+
next_phase=ACPJobPhase.TRANSACTION,
182183
)
183184
)
184185

@@ -214,16 +215,16 @@ def create_payable_requirement(
214215

215216
operations.append(
216217
self.acp_contract_client.create_payable_memo(
217-
self.id,
218-
content,
219-
amount.amount,
220-
recipient,
221-
fee_amount,
222-
fee_type,
223-
ACPJobPhase.TRANSACTION,
224-
type,
225-
expired_at,
226-
amount.fare.contract_address,
218+
job_id=self.id,
219+
content=content,
220+
amount_base_unit=amount.amount,
221+
recipient=recipient,
222+
fee_amount_base_unit=fee_amount,
223+
fee_type=fee_type,
224+
next_phase=ACPJobPhase.TRANSACTION,
225+
memo_type=type,
226+
expired_at=expired_at,
227+
token=amount.fare.contract_address,
227228
)
228229
)
229230

@@ -241,11 +242,10 @@ def pay_and_accept_requirement(self, reason: Optional[str] = "") -> str | None:
241242
operations: List[OperationPayload] = []
242243
base_fare_amount = FareAmount(self.price, self.base_fare)
243244

244-
base_fare_amount = FareAmount(self.price, self.base_fare)
245245
if memo.payable_details:
246246
transfer_amount = FareAmountBase.from_contract_address(
247-
memo.payable_details["amount"],
248-
memo.payable_details["token"],
247+
memo.payable_details.get("amount"),
248+
memo.payable_details.get("token"),
249249
self.config,
250250
)
251251
else:
@@ -285,11 +285,11 @@ def pay_and_accept_requirement(self, reason: Optional[str] = "") -> str | None:
285285

286286
operations.append(
287287
self.acp_contract_client.create_memo(
288-
self.id,
289-
f"Payment made. {reason or ''}".strip(),
290-
MemoType.MESSAGE,
291-
True,
292-
ACPJobPhase.EVALUATION,
288+
job_id=self.id,
289+
content=f"Payment made. {reason or ''}".strip(),
290+
memo_type=MemoType.MESSAGE,
291+
is_secured=True,
292+
next_phase=ACPJobPhase.EVALUATION,
293293
)
294294
)
295295

@@ -321,11 +321,11 @@ def reject(self, reason: Optional[str] = None) -> str | None:
321321

322322
operations.append(
323323
self.acp_contract_client.create_memo(
324-
self.id,
325-
memo_content,
326-
MemoType.MESSAGE,
327-
True,
328-
ACPJobPhase.REJECTED
324+
job_id=self.id,
325+
content=memo_content,
326+
memo_type=MemoType.MESSAGE,
327+
is_secured=True,
328+
next_phase=ACPJobPhase.REJECTED
329329
)
330330
)
331331

@@ -418,11 +418,11 @@ def deliver(self, deliverable: DeliverablePayload) -> str | None:
418418

419419
operations.append(
420420
self.acp_contract_client.create_memo(
421-
self.id,
422-
prepare_payload(deliverable),
423-
MemoType.MESSAGE,
424-
True,
425-
ACPJobPhase.COMPLETED,
421+
job_id=self.id,
422+
content=prepare_payload(deliverable),
423+
memo_type=MemoType.MESSAGE,
424+
is_secured=True,
425+
next_phase=ACPJobPhase.COMPLETED,
426426
)
427427
)
428428

@@ -433,6 +433,7 @@ def deliver_payable(
433433
self,
434434
deliverable: DeliverablePayload,
435435
amount: FareAmountBase,
436+
skip_fee: bool = False,
436437
expired_at: Optional[datetime] = None,
437438
) -> str | None:
438439
if expired_at is None:
@@ -452,16 +453,21 @@ def deliver_payable(
452453
)
453454
)
454455

455-
fee_amount = FareAmount(0, self.acp_contract_client.config.base_fare)
456+
if self._price_type == PriceType.PERCENTAGE and not skip_fee:
457+
fee_amount = int(self.price_value * 10000)
458+
fee_type = FeeType.PERCENTAGE_FEE
459+
else:
460+
fee_amount = (FareAmount(0, self.base_fare)).amount
461+
fee_type = FeeType.NO_FEE
456462

457463
operations.append(
458464
self.acp_contract_client.create_payable_memo(
459465
job_id=self.id,
460466
content=prepare_payload(deliverable),
461467
amount_base_unit=amount.amount,
462468
recipient=self.client_address,
463-
fee_amount_base_unit=fee_amount.amount,
464-
fee_type=FeeType.NO_FEE,
469+
fee_amount_base_unit=fee_amount,
470+
fee_type=fee_type,
465471
next_phase=ACPJobPhase.COMPLETED,
466472
memo_type=MemoType.PAYABLE_TRANSFER,
467473
expired_at=expired_at,
@@ -504,6 +510,7 @@ def create_payable_notification(
504510
self,
505511
content: str,
506512
amount: FareAmountBase,
513+
skip_fee: bool = False,
507514
expired_at: Optional[datetime] = None,
508515
):
509516
operations: List[OperationPayload] = []
@@ -518,16 +525,21 @@ def create_payable_notification(
518525
)
519526
)
520527

521-
fee_amount = FareAmount(0, self.acp_contract_client.config.base_fare)
528+
if self._price_type == PriceType.PERCENTAGE and not skip_fee:
529+
fee_amount = int(self.price_value * 10000)
530+
fee_type = FeeType.PERCENTAGE_FEE
531+
else:
532+
fee_amount = (FareAmount(0, self.base_fare)).amount
533+
fee_type = FeeType.NO_FEE
522534

523535
operations.append(
524536
self.acp_contract_client.create_payable_memo(
525537
job_id=self.id,
526538
content=content,
527539
amount_base_unit=amount.amount,
528540
recipient=self.client_address,
529-
fee_amount_base_unit=fee_amount.amount,
530-
fee_type=FeeType.NO_FEE,
541+
fee_amount_base_unit=fee_amount,
542+
fee_type=fee_type,
531543
next_phase=ACPJobPhase.COMPLETED,
532544
memo_type=MemoType.PAYABLE_NOTIFICATION,
533545
expired_at=expired_at,

0 commit comments

Comments
 (0)