Skip to content

Commit 0fc8941

Browse files
committed
Add support for CIS-6 Track and Trace
Fixes #1
1 parent 30da0b0 commit 0fc8941

File tree

2 files changed

+173
-2
lines changed

2 files changed

+173
-2
lines changed

ccdexplorer_fundamentals/cis.py

+79-1
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,8 @@ class StandardIdentifiers(Enum):
139139
CIS_2 = "CIS-2"
140140
CIS_3 = "CIS-3"
141141
CIS_4 = "CIS-4"
142+
CIS_5 = "CIS-5"
143+
CIS_6 = "CIS-6"
142144

143145

144146
class LoggedEvents(Enum):
@@ -240,6 +242,20 @@ class tokenMetadataEvent(BaseModel):
240242
metadata: MetadataUrl
241243

242244

245+
class itemCreatedEvent(BaseModel):
246+
tag: int
247+
item_id: str
248+
metadata: MetadataUrl
249+
initial_status: str
250+
251+
252+
class itemStatusChangedEvent(BaseModel):
253+
tag: int
254+
item_id: str
255+
new_status: str
256+
additional_data: bytes
257+
258+
243259
class nonceEvent(BaseModel):
244260
tag: int
245261
nonce: Optional[int] = None
@@ -705,7 +721,7 @@ def support_result(self, bs: io.BytesIO):
705721
def supports_response(self, res: bytes):
706722
bs = io.BytesIO(bytes.fromhex(res.decode()))
707723
if bs.getbuffer().nbytes > 0:
708-
n = int.from_bytes(bs.read(2), byteorder="big")
724+
n = int.from_bytes(bs.read(2), byteorder="little")
709725
responses = []
710726
for _ in range(n):
711727
responses.append(self.support_result(bs))
@@ -970,6 +986,13 @@ def token_id(self, bs: io.BytesIO):
970986
n = int.from_bytes(bs.read(1), byteorder="little")
971987
return bytes.hex(bs.read(n))
972988

989+
def item_id(self, bs: io.BytesIO):
990+
n = int.from_bytes(bs.read(1), byteorder="little")
991+
return bytes.hex(bs.read(n))
992+
993+
def status(self, bs: io.BytesIO):
994+
return bytes.hex(bs.read(1))
995+
973996
def nonce(self, bs: io.BytesIO):
974997
return bytes.hex(bs.read(8))
975998

@@ -1246,6 +1269,61 @@ def revocationKeyEvent(self, hexParameter: str):
12461269
}
12471270
)
12481271

1272+
def ItemCreatedEvent(self, hexParameter: str):
1273+
bs = io.BytesIO(bytes.fromhex(hexParameter))
1274+
1275+
tag_ = int.from_bytes(bs.read(1), byteorder="little")
1276+
1277+
item_id_ = self.item_id(bs)
1278+
metadata_ = self.metadataUrl(bs)
1279+
initial_status_ = self.status(bs)
1280+
1281+
return itemCreatedEvent(
1282+
**{
1283+
"tag": tag_,
1284+
"item_id": item_id_,
1285+
"metadata": metadata_,
1286+
"initial_status": initial_status_,
1287+
}
1288+
)
1289+
1290+
def ItemStatusChangedEvent(self, hexParameter: str):
1291+
bs = io.BytesIO(bytes.fromhex(hexParameter))
1292+
1293+
tag_ = int.from_bytes(bs.read(1), byteorder="little")
1294+
1295+
item_id_ = self.item_id(bs)
1296+
new_status_ = self.status(bs)
1297+
additional_data_ = self.additionalData(bs)
1298+
1299+
return itemStatusChangedEvent(
1300+
**{
1301+
"tag": tag_,
1302+
"item_id": item_id_,
1303+
"new_status": new_status_,
1304+
"additional_data": additional_data_,
1305+
}
1306+
)
1307+
1308+
def process_tnt_log_event(self, hexParameter: str):
1309+
bs = io.BytesIO(bytes.fromhex(hexParameter))
1310+
1311+
tag_ = int.from_bytes(bs.read(1), byteorder="little")
1312+
if tag_ == 237:
1313+
try:
1314+
event = self.ItemCreatedEvent(hexParameter)
1315+
return tag_, event
1316+
except: # noqa: E722
1317+
return tag_, None
1318+
elif tag_ == 236:
1319+
try:
1320+
event = self.ItemStatusChangedEvent(hexParameter)
1321+
return tag_, event
1322+
except: # noqa: E722
1323+
return tag_, None
1324+
else:
1325+
return tag_, f"Custom even with tag={tag_}."
1326+
12491327
def process_log_events(self, hexParameter: str):
12501328
bs = io.BytesIO(bytes.fromhex(hexParameter))
12511329

tests/cis/test_cis.py

+94-1
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,35 @@
22
import sys
33
import os
44

5-
sys.path.append(os.path.dirname("ccdefundamentals"))
5+
6+
sys.path.append(os.path.dirname("ccdexplorer_fundamentals"))
67
from ccdexplorer_fundamentals.GRPCClient import GRPCClient
78
from rich import print
89
from ccdexplorer_fundamentals.enums import NET
10+
from ccdexplorer_fundamentals.mongodb import MongoDB, Collections
11+
from ccdexplorer_schema_parser.Schema import Schema
912
from ccdexplorer_fundamentals.cis import (
1013
CIS,
1114
registerCredentialEvent,
1215
revokeCredentialEvent,
1316
transferEvent,
1417
tokenMetadataEvent,
18+
itemCreatedEvent,
19+
itemStatusChangedEvent,
1520
)
21+
from ccdexplorer_fundamentals.GRPCClient.CCD_Types import CCD_ContractAddress
1622

1723

1824
@pytest.fixture
1925
def grpcclient():
2026
return GRPCClient()
2127

2228

29+
@pytest.fixture
30+
def mongodb():
31+
return MongoDB(tooter=None)
32+
33+
2334
def tx_at_index_from(
2435
tx_index: int,
2536
block_hash: str,
@@ -151,3 +162,85 @@ def test_checksum_other2(grpcclient: GRPCClient):
151162
assert tag == 251
152163
assert result.token_id == "25"
153164
assert result.metadata.checksum is None
165+
166+
167+
def get_schema_from_source(
168+
contract_address: CCD_ContractAddress,
169+
mongodb: MongoDB,
170+
grpcclient: GRPCClient,
171+
net: NET,
172+
):
173+
result = mongodb.testnet[Collections.instances].find_one(
174+
{"_id": contract_address.to_str()}
175+
)
176+
module_ref = (
177+
result["v1"]["source_module"]
178+
if result.get("v1")
179+
else result["v0"]["source_module"]
180+
)
181+
source_module_name = (
182+
result["v1"]["name"][5:] if result.get("v1") else result["v0"]["name"][5:]
183+
)
184+
ms = grpcclient.get_module_source_original_classes(
185+
module_ref, "last_final", net=net
186+
)
187+
schema = Schema(ms.v1.value, 1) if ms.v1 else Schema(ms.v0.value, 0)
188+
189+
return schema, source_module_name
190+
191+
192+
def test_cis_6_create_item(
193+
grpcclient: GRPCClient,
194+
mongodb: MongoDB,
195+
):
196+
net = NET.TESTNET
197+
block_hash = grpcclient.get_finalized_block_at_height(13753259, net).hash
198+
tx = tx_at_index_from(0, block_hash, grpcclient, net)
199+
# print(tx)
200+
contract_address = CCD_ContractAddress(index=8901, subindex=0)
201+
schema, source_module_name = get_schema_from_source(
202+
contract_address, mongodb, grpcclient, net
203+
)
204+
ci = CIS(grpcclient, contract_address.index, contract_address.subindex, "", net)
205+
206+
event = tx.account_transaction.effects.contract_update_issued.effects[0]
207+
tag, result = ci.process_tnt_log_event(event.updated.events[0])
208+
209+
if tag == 237:
210+
event_json = schema.event_to_json(
211+
source_module_name,
212+
bytes.fromhex(event.updated.events[0]),
213+
)
214+
215+
result: itemCreatedEvent
216+
result.initial_status = list(
217+
event_json["ItemCreated"][0]["initial_status"].keys()
218+
)[0]
219+
print(result)
220+
221+
222+
def test_cis_6_status_changed_item(grpcclient: GRPCClient, mongodb: MongoDB):
223+
net = NET.TESTNET
224+
block_hash = grpcclient.get_finalized_block_at_height(13757068, net).hash
225+
tx = tx_at_index_from(0, block_hash, grpcclient, net)
226+
# print(tx)
227+
contract_address = CCD_ContractAddress(index=8901, subindex=0)
228+
schema, source_module_name = get_schema_from_source(
229+
contract_address, mongodb, grpcclient, net
230+
)
231+
ci = CIS(grpcclient, contract_address.index, contract_address.subindex, "", net)
232+
233+
event = tx.account_transaction.effects.contract_update_issued.effects[0]
234+
tag, result = ci.process_tnt_log_event(event.updated.events[0])
235+
236+
if tag == 236:
237+
event_json = schema.event_to_json(
238+
source_module_name,
239+
bytes.fromhex(event.updated.events[0]),
240+
)
241+
242+
result: itemStatusChangedEvent
243+
result.new_status = list(
244+
event_json["ItemStatusChanged"][0]["new_status"].keys()
245+
)[0]
246+
print(result)

0 commit comments

Comments
 (0)