Skip to content

Commit

Permalink
Merge pull request #1268 from CityOfZion/CU-86dtu92vq
Browse files Browse the repository at this point in the history
CU-86dtu92vq - Include how to test smart contract events using boa test constructor
  • Loading branch information
meevee98 authored Jun 20, 2024
2 parents 555a83d + 7f2b332 commit 7b9aa38
Showing 1 changed file with 49 additions and 0 deletions.
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)
```

0 comments on commit 7b9aa38

Please sign in to comment.