Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CU-86dtu92vq - Include how to test smart contract events using boa test constructor #1268

Merged
merged 2 commits into from
Jun 20, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions docs/source/testing-and-debugging.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,3 +135,52 @@ 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 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):
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_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)

# 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.from_script_hash)
self.assertEqual(self.genesis.script_hash, transfer_event.to_script_hash)
self.assertEqual(amount_gas, transfer_event.amount)
```
Loading