Skip to content

Commit 109b1e6

Browse files
draft: moving towards new arkiv node specs
1 parent 7d482bc commit 109b1e6

File tree

7 files changed

+130
-9
lines changed

7 files changed

+130
-9
lines changed

src/arkiv/contract.py

Lines changed: 86 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,28 +15,44 @@
1515
)
1616

1717

18-
CREATED_EVENT: Final[str] = "GolemBaseStorageEntityCreated"
19-
UPDATED_EVENT: Final[str] = "GolemBaseStorageEntityUpdated"
20-
EXTENDED_EVENT: Final[str] = "GolemBaseStorageEntityBTLExtended"
21-
DELETED_EVENT: Final[str] = "GolemBaseStorageEntityDeleted"
18+
CREATED_EVENT_LEGACY: Final[str] = "GolemBaseStorageEntityCreated"
19+
UPDATED_EVENT_LEGACY: Final[str] = "GolemBaseStorageEntityUpdated"
20+
EXTENDED_EVENT_LEGACY: Final[str] = "GolemBaseStorageEntityBTLExtended"
21+
DELETED_EVENT_LEGACY: Final[str] = "GolemBaseStorageEntityDeleted"
22+
23+
CREATED_EVENT: Final[str] = "ArkivEntityCreated"
24+
UPDATED_EVENT: Final[str] = "ArkivEntityUpdated"
25+
DELETED_EVENT: Final[str] = "ArkivEntityDeleted"
26+
EXPIRED_EVENT: Final[str] = "ArkivEntityExpired"
27+
EXTENDED_EVENT: Final[str] = "ArkivEntityBTLExtended"
28+
OWNER_CHANGED_EVENT: Final[str] = "ArkivEntityOwnerChanged"
29+
2230

2331
EVENTS: dict[str, str] = {
32+
"created_legacy": CREATED_EVENT_LEGACY,
33+
"updated_legacy": UPDATED_EVENT_LEGACY,
34+
"extended_legacy": EXTENDED_EVENT_LEGACY,
35+
"deleted_legacy": DELETED_EVENT_LEGACY,
2436
"created": CREATED_EVENT,
2537
"updated": UPDATED_EVENT,
2638
"extended": EXTENDED_EVENT,
2739
"deleted": DELETED_EVENT,
40+
"expired": EXPIRED_EVENT,
41+
"owner_changed": OWNER_CHANGED_EVENT,
2842
}
2943

3044
TYPE_EVENT = "event"
3145
TYPE_UINT = "uint256"
46+
TYPE_ADDRESS = "address"
47+
3248
EVENTS_ABI: Final[Sequence[dict[str, Any]]] = [
3349
{
3450
"anonymous": False,
3551
"inputs": [
3652
{"indexed": True, "name": "entityKey", "type": TYPE_UINT},
3753
{"indexed": False, "name": "expirationBlock", "type": TYPE_UINT},
3854
],
39-
"name": CREATED_EVENT,
55+
"name": CREATED_EVENT_LEGACY,
4056
"type": TYPE_EVENT,
4157
},
4258
{
@@ -45,25 +61,88 @@
4561
{"indexed": True, "name": "entityKey", "type": TYPE_UINT},
4662
{"indexed": False, "name": "expirationBlock", "type": TYPE_UINT},
4763
],
48-
"name": UPDATED_EVENT,
64+
"name": UPDATED_EVENT_LEGACY,
4965
"type": TYPE_EVENT,
5066
},
5167
{
5268
"anonymous": False,
5369
"inputs": [{"indexed": True, "name": "entityKey", "type": TYPE_UINT}],
54-
"name": DELETED_EVENT,
70+
"name": DELETED_EVENT_LEGACY,
71+
"type": TYPE_EVENT,
72+
},
73+
{
74+
"anonymous": False,
75+
"inputs": [
76+
{"indexed": True, "name": "entityKey", "type": TYPE_UINT},
77+
{"indexed": False, "name": "oldExpirationBlock", "type": TYPE_UINT},
78+
{"indexed": False, "name": "newExpirationBlock", "type": TYPE_UINT},
79+
],
80+
"name": EXTENDED_EVENT_LEGACY,
81+
"type": TYPE_EVENT,
82+
},
83+
{
84+
"anonymous": False,
85+
"inputs": [
86+
{"indexed": True, "name": "entityKey", "type": TYPE_UINT},
87+
{"indexed": True, "name": "ownerAddress", "type": TYPE_ADDRESS},
88+
{"indexed": False, "name": "expirationBlock", "type": TYPE_UINT},
89+
{"indexed": False, "name": "cost", "type": TYPE_UINT},
90+
],
91+
"name": CREATED_EVENT,
5592
"type": TYPE_EVENT,
5693
},
5794
{
5895
"anonymous": False,
5996
"inputs": [
6097
{"indexed": True, "name": "entityKey", "type": TYPE_UINT},
98+
{"indexed": True, "name": "ownerAddress", "type": TYPE_ADDRESS},
6199
{"indexed": False, "name": "oldExpirationBlock", "type": TYPE_UINT},
62100
{"indexed": False, "name": "newExpirationBlock", "type": TYPE_UINT},
101+
{"indexed": False, "name": "cost", "type": TYPE_UINT},
102+
],
103+
"name": UPDATED_EVENT,
104+
"type": TYPE_EVENT,
105+
},
106+
{
107+
"anonymous": False,
108+
"inputs": [
109+
{"indexed": True, "name": "entityKey", "type": TYPE_UINT},
110+
{"indexed": True, "name": "ownerAddress", "type": TYPE_ADDRESS},
111+
],
112+
"name": DELETED_EVENT,
113+
"type": TYPE_EVENT,
114+
},
115+
{
116+
"anonymous": False,
117+
"inputs": [
118+
{"indexed": True, "name": "entityKey", "type": TYPE_UINT},
119+
{"indexed": True, "name": "ownerAddress", "type": TYPE_ADDRESS},
63120
],
64121
"name": EXTENDED_EVENT,
65122
"type": TYPE_EVENT,
66123
},
124+
{
125+
"anonymous": False,
126+
"inputs": [
127+
{"indexed": True, "name": "entityKey", "type": TYPE_UINT},
128+
{"indexed": True, "name": "ownerAddress", "type": TYPE_ADDRESS},
129+
{"indexed": False, "name": "oldExpirationBlock", "type": TYPE_UINT},
130+
{"indexed": False, "name": "newExpirationBlock", "type": TYPE_UINT},
131+
{"indexed": False, "name": "cost", "type": TYPE_UINT},
132+
],
133+
"name": EXPIRED_EVENT,
134+
"type": TYPE_EVENT,
135+
},
136+
{
137+
"anonymous": False,
138+
"inputs": [
139+
{"indexed": True, "name": "entityKey", "type": TYPE_UINT},
140+
{"indexed": True, "name": "oldOwnerAddress", "type": TYPE_ADDRESS},
141+
{"indexed": True, "name": "newOwnerAddress", "type": TYPE_ADDRESS},
142+
],
143+
"name": OWNER_CHANGED_EVENT,
144+
"type": TYPE_EVENT,
145+
},
67146
]
68147

69148

src/arkiv/events_base.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,8 @@ def _extract_tx_hash(self, event_data: EventData) -> TxHash:
130130
tx_hash_hex = f"0x{tx_hash_hex}"
131131
return TxHash(HexStr(tx_hash_hex))
132132

133+
# TODO (1) check/match against utils.py::to_receipt
134+
# TODO (2) update to new log/event definition in contract.py
133135
def _parse_event_data(self, event_data: EventData) -> tuple[EventObject, TxHash]:
134136
"""
135137
Parse event data and create appropriate event object.

src/arkiv/module.py

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,10 @@ def get_entity(self, entity_key: EntityKey, fields: int = ALL) -> Entity:
295295
"""
296296
# Gather the requested data
297297
owner: ChecksumAddress | None = None
298+
created_at_block: int | None = None
299+
last_modified_at_block: int | None = None
300+
transaction_index: int | None = None
301+
operation_index: int | None = None
298302
expires_at_block: int | None = None
299303
payload: bytes | None = None
300304
annotations: Annotations | None = None
@@ -308,11 +312,28 @@ def get_entity(self, entity_key: EntityKey, fields: int = ALL) -> Entity:
308312
# get and decode annotations and/or metadata if requested
309313
if fields & METADATA or fields & ANNOTATIONS:
310314
metadata_all = self._get_entity_metadata(entity_key)
315+
logger.info(
316+
f"Fetched metadata for entity[{entity_key}]: {metadata_all}"
317+
)
311318

312319
if fields & METADATA:
313320
# Convert owner address to checksummed format
314321
owner = self._get_owner(metadata_all)
315-
expires_at_block = self._get_expires_at_block(metadata_all)
322+
created_at_block = self._get_metadata_numeric_field(
323+
metadata_all, "createdAtBlock"
324+
)
325+
last_modified_at_block = self._get_metadata_numeric_field(
326+
metadata_all, "lastModifiedAtBlock"
327+
)
328+
expires_at_block = self._get_metadata_numeric_field(
329+
metadata_all, "expiresAtBlock"
330+
)
331+
transaction_index = self._get_metadata_numeric_field(
332+
metadata_all, "transactionIndex"
333+
)
334+
operation_index = self._get_metadata_numeric_field(
335+
metadata_all, "operationIndex"
336+
)
316337

317338
if fields & ANNOTATIONS:
318339
annotations = merge_annotations(
@@ -327,7 +348,11 @@ def get_entity(self, entity_key: EntityKey, fields: int = ALL) -> Entity:
327348
entity_key=entity_key,
328349
fields=fields,
329350
owner=owner,
351+
created_at_block=created_at_block,
352+
last_modified_at_block=last_modified_at_block,
330353
expires_at_block=expires_at_block,
354+
transaction_index=transaction_index,
355+
operation_index=operation_index,
331356
payload=payload,
332357
annotations=annotations,
333358
)

src/arkiv/module_base.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,15 @@ def _get_expires_at_block(self, metadata: dict[str, Any]) -> int:
133133
raise ValueError("Entity metadata missing required 'expiresAtBlock' field")
134134
return int(expires_at_block_metadata)
135135

136+
def _get_metadata_numeric_field(
137+
self, metadata: dict[str, Any], field_name: str
138+
) -> int:
139+
"""Get a numeric field from the entity metadata."""
140+
field_value = metadata.get(field_name)
141+
if field_value is None:
142+
raise ValueError(f"Entity metadata missing required '{field_name}' field")
143+
return int(field_value)
144+
136145
def _validate_query_entities_params(
137146
self,
138147
query: str | None,

src/arkiv/types.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,11 @@ class Entity:
6262

6363
# Populated when fields | METADATA returns true
6464
owner: ChecksumAddress | None
65+
created_at_block: int | None
66+
last_modified_at_block: int | None
6567
expires_at_block: int | None
68+
transaction_index: int | None
69+
operation_index: int | None
6670

6771
# Populated when fields | PAYLOAD returns true
6872
payload: bytes | None

tests/test_entity_create.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ def test_create_entity_simple(self, arkiv_client_http: Arkiv) -> None:
148148
check_tx_hash(label, tx_hash)
149149

150150
entity = arkiv_client_http.arkiv.get_entity(entity_key)
151-
logger.info(f"{label}: Retrieved entity: {entity}")
151+
logger.info(f"{label}: Retrieved entity:\n{entity}")
152152

153153
assert entity.entity_key == entity_key, f"{label}: Entity key should match"
154154
assert entity.payload == pl, f"{label}: Entity payload should match"

tests/test_entity_extend.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ def test_extend_entity_simple(self, arkiv_client_http: Arkiv) -> None:
3232

3333
# Get initial expiration block
3434
entity_before = arkiv_client_http.arkiv.get_entity(entity_key)
35+
logger.info(f"Entity before extension: {entity_before}")
3536
initial_expiration = entity_before.expires_at_block
3637
assert initial_expiration is not None, "Entity should have expiration block"
3738
logger.info(f"Initial expiration block: {initial_expiration}")
@@ -50,6 +51,7 @@ def test_extend_entity_simple(self, arkiv_client_http: Arkiv) -> None:
5051

5152
# Verify the entity still exists and expiration increased
5253
entity_after = arkiv_client_http.arkiv.get_entity(entity_key)
54+
logger.info(f"Entity after extension: {entity_after}")
5355
assert entity_after.expires_at_block == initial_expiration + number_of_blocks, (
5456
f"Expiration should increase by {number_of_blocks} blocks"
5557
)

0 commit comments

Comments
 (0)