From 12e442ecd3c7087413d927eb10aa0ed439f9f199 Mon Sep 17 00:00:00 2001 From: luc10921 Date: Tue, 18 Jun 2024 11:10:23 -0300 Subject: [PATCH 1/2] CU-86dtu92vq - Include how to test smart contract events using boa test constructor --- docs/source/testing-and-debugging.md | 32 ++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/docs/source/testing-and-debugging.md b/docs/source/testing-and-debugging.md index 4cb68c55..f8b8f6b8 100644 --- a/docs/source/testing-and-debugging.md +++ b/docs/source/testing-and-debugging.md @@ -135,3 +135,35 @@ of the transaction. result, _ = await self.call("get_message", return_type=str) self.assertEqual(new_message, result) ``` + +#### Accessing Events + +If you want to test events, you'll get all the notifications that were emitted on the transaction from the second return +value of the `call` method. The resulting stack of every notification is a list of stack items, so it's best you unwrap +them using [neo-mamba unwrapping methods](https://dojo.coz.io/neo3/mamba/api/neo3/api/helpers/unwrap.html). In this +example, we are testing the "Transfer" event, so we can use the `Nep17TransferEvent` class from `boaconstructor`. If you +plan to test other events, it's best you also create a class or method that will help you unwrap the stack results. +Check out [`Nep17TransferEvent`](https://github.com/CityOfZion/boa-test-constructor/blob/20a45755767b3d919bf7a594cfff6bff78cb72ac/boaconstructor/__init__.py#L302-L314) +implementation for reference. + +```python + # inside the HelloWorldWithDeployTest class + async def test_gas_transfer_event(self): + # the amount of GAS tokens to transfer, since we will be invoking the transfer method, it's necessary to multiply by the decimals + amount = 1 * 10**8 + # calling the transfer method to emit a 'Transfer' event + result, notifications = await self.call( + "transfer", [self.user1.script_hash, self.genesis.script_hash, amount, None], + return_type=bool, target_contract=GAS, signing_accounts=[self.user1] + ) + self.assertEqual(True, result) + self.assertEqual(1, len(notifications)) + self.assertEqual("Transfer", notifications[0].event_name) + + from boaconstructor import Nep17TransferEvent + # we can use the Nep17TransferEvent class to unwrap the stack items + transfer_event = Nep17TransferEvent.from_notification(notifications[0]) + self.assertEqual(self.user1.script_hash, transfer_event.source) + self.assertEqual(self.genesis.script_hash, transfer_event.destination) + self.assertEqual(amount, transfer_event.amount) +``` From 7f2b3329556477ccc35de5baa31de0a28b986e5f Mon Sep 17 00:00:00 2001 From: luc10921 Date: Thu, 20 Jun 2024 09:54:49 -0300 Subject: [PATCH 2/2] 86dtu92vq - Include how to test smart contract events using boa test constructor --- docs/source/testing-and-debugging.md | 41 ++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/docs/source/testing-and-debugging.md b/docs/source/testing-and-debugging.md index f8b8f6b8..37f25e63 100644 --- a/docs/source/testing-and-debugging.md +++ b/docs/source/testing-and-debugging.md @@ -140,30 +140,47 @@ of the transaction. If you want to test events, you'll get all the notifications that were emitted on the transaction from the second return value of the `call` method. The resulting stack of every notification is a list of stack items, so it's best you unwrap -them using [neo-mamba unwrapping methods](https://dojo.coz.io/neo3/mamba/api/neo3/api/helpers/unwrap.html). In this -example, we are testing the "Transfer" event, so we can use the `Nep17TransferEvent` class from `boaconstructor`. If you -plan to test other events, it's best you also create a class or method that will help you unwrap the stack results. -Check out [`Nep17TransferEvent`](https://github.com/CityOfZion/boa-test-constructor/blob/20a45755767b3d919bf7a594cfff6bff78cb72ac/boaconstructor/__init__.py#L302-L314) -implementation for reference. +them using [neo-mamba unwrapping methods](https://dojo.coz.io/neo3/mamba/api/neo3/api/helpers/unwrap.html). In this +example, we are testing the "Transfer" event from the GAS token smart contract, so we can create a `Nep17TransferEvent` +class that is compliant with the event being emitted. If you plan to test other events, it's best you also create a +class or method that will help you unwrap the stack results. ```python # inside the HelloWorldWithDeployTest class async def test_gas_transfer_event(self): - # the amount of GAS tokens to transfer, since we will be invoking the transfer method, it's necessary to multiply by the decimals - amount = 1 * 10**8 + from dataclasses import dataclass + from neo3.api import noderpc, StackItemType + + # the dataclass decorator will automatically generate the __init__ method among other things + @dataclass + class Nep17TransferEvent: + # the Transfer event has 3 parameters: from, to, and amount + from_script_hash: types.UInt160 | None + to_script_hash: types.UInt160 | None + amount: int + + @classmethod + def from_notification(cls, n: noderpc.Notification): + stack = n.state.as_list() + from_script_hash = stack[0].as_uint160() if not stack[0].type == StackItemType.ANY else None + to_script_hash = stack[1].as_uint160() if not stack[1].type == StackItemType.ANY else None + amount = stack[2].as_int() + return cls(from_script_hash, to_script_hash, amount) + + # the amount of GAS tokens to transfer, since we will be invoking the transfer method, it's necessary to multiply by the decimals + amount_gas = 1 * 10 ** 8 # calling the transfer method to emit a 'Transfer' event result, notifications = await self.call( - "transfer", [self.user1.script_hash, self.genesis.script_hash, amount, None], + "transfer", [self.user1.script_hash, self.genesis.script_hash, amount_gas, None], return_type=bool, target_contract=GAS, signing_accounts=[self.user1] ) self.assertEqual(True, result) self.assertEqual(1, len(notifications)) self.assertEqual("Transfer", notifications[0].event_name) - from boaconstructor import Nep17TransferEvent # we can use the Nep17TransferEvent class to unwrap the stack items transfer_event = Nep17TransferEvent.from_notification(notifications[0]) - self.assertEqual(self.user1.script_hash, transfer_event.source) - self.assertEqual(self.genesis.script_hash, transfer_event.destination) - self.assertEqual(amount, transfer_event.amount) + self.assertEqual(self.user1.script_hash, transfer_event.from_script_hash) + self.assertEqual(self.genesis.script_hash, transfer_event.to_script_hash) + self.assertEqual(amount_gas, transfer_event.amount) ```