diff --git a/docs/golem_base_sdk.html b/docs/golem_base_sdk.html index 7eb4202..32d5fec 100644 --- a/docs/golem_base_sdk.html +++ b/docs/golem_base_sdk.html @@ -126,574 +126,571 @@
1#! /usr/bin/env python
+ 1"""GolemBase Python SDK"""
2
- 3"""GolemBase Python SDK"""
- 4
- 5import asyncio
- 6import base64
- 7import logging
- 8import logging.config
- 9import typing
- 10from typing import (
- 11 AsyncGenerator,
- 12 Awaitable,
- 13 Callable,
- 14 Iterable,
- 15 List,
- 16 Optional,
- 17 Sequence,
- 18 Set,
- 19)
- 20
- 21from eth_typing import ChecksumAddress, HexStr
- 22from web3 import AsyncWeb3, WebSocketProvider
- 23from web3.contract import AsyncContract
- 24from web3.exceptions import ProviderConnectionError
- 25from web3.method import Method, default_root_munger
- 26from web3.middleware import SignAndSendRawMiddlewareBuilder
- 27from web3.types import LogReceipt, RPCEndpoint, TxReceipt
- 28from web3.utils.subscriptions import (
- 29 LogsSubscription,
- 30 LogsSubscriptionContext,
- 31)
- 32
- 33from .constants import (
- 34 GOLEM_BASE_ABI,
- 35 STORAGE_ADDRESS,
- 36)
- 37from .types import (
- 38 Address,
- 39 Annotation,
- 40 CreateEntityReturnType,
- 41 EntityKey,
- 42 EntityMetadata,
- 43 ExtendEntityReturnType,
- 44 GenericBytes,
- 45 GolemBaseCreate,
- 46 GolemBaseDelete,
- 47 GolemBaseExtend,
- 48 GolemBaseTransaction,
- 49 GolemBaseTransactionReceipt,
- 50 GolemBaseUpdate,
- 51 QueryEntitiesResult,
- 52 UpdateEntityReturnType,
- 53)
- 54from .utils import parse_legacy_btl_extended_log, rlp_encode_transaction
+ 3import asyncio
+ 4import base64
+ 5import logging
+ 6import logging.config
+ 7import typing
+ 8from typing import (
+ 9 AsyncGenerator,
+ 10 Awaitable,
+ 11 Callable,
+ 12 List,
+ 13 Optional,
+ 14 Sequence,
+ 15 Set,
+ 16)
+ 17
+ 18from eth_typing import ChecksumAddress, HexStr
+ 19from web3 import AsyncWeb3, WebSocketProvider
+ 20from web3.contract import AsyncContract
+ 21from web3.exceptions import ProviderConnectionError
+ 22from web3.method import Method, default_root_munger
+ 23from web3.middleware import SignAndSendRawMiddlewareBuilder
+ 24from web3.types import LogReceipt, RPCEndpoint, TxReceipt
+ 25from web3.utils.subscriptions import (
+ 26 LogsSubscription,
+ 27 LogsSubscriptionContext,
+ 28)
+ 29
+ 30from .constants import (
+ 31 GOLEM_BASE_ABI,
+ 32 STORAGE_ADDRESS,
+ 33)
+ 34from .types import (
+ 35 Address,
+ 36 Annotation,
+ 37 CreateEntityReturnType,
+ 38 EntityKey,
+ 39 EntityMetadata,
+ 40 ExtendEntityReturnType,
+ 41 GenericBytes,
+ 42 GolemBaseCreate,
+ 43 GolemBaseDelete,
+ 44 GolemBaseExtend,
+ 45 GolemBaseTransaction,
+ 46 GolemBaseTransactionReceipt,
+ 47 GolemBaseUpdate,
+ 48 QueryEntitiesResult,
+ 49 UpdateEntityReturnType,
+ 50)
+ 51from .utils import parse_legacy_btl_extended_log, rlp_encode_transaction
+ 52
+ 53
+ 54__version__ = "0.0.2"
55
56
- 57__version__ = "0.0.2"
- 58
- 59
- 60logger = logging.getLogger(__name__)
- 61"""
- 62@private
- 63"""
- 64
- 65
- 66class GolemBaseClient:
- 67 """
- 68 The Golem Base client used to interact with Golem Base.
- 69 Many useful methods are implemented directly on this type, while more
- 70 generic ethereum methods can be accessed through the underlying
- 71 web3 client that you can access with the
- 72 `GolemBaseClient.http_client()`
- 73 method.
- 74 """
- 75
- 76 _http_client: AsyncWeb3
- 77 _ws_client: AsyncWeb3
- 78 _golem_base_contract: AsyncContract
- 79 _background_tasks: Set[asyncio.Task]
- 80
- 81 @staticmethod
- 82 async def create(
- 83 rpc_url: str, ws_url: str, private_key: Sequence[bytes]
- 84 ) -> "GolemBaseClient":
- 85 """
- 86 Static method to create a `GolemBaseClient` instance,
- 87 this is the preferred method to create an instance.
- 88 """
- 89 ws_client = await AsyncWeb3(WebSocketProvider(ws_url))
- 90 return GolemBaseClient(rpc_url, ws_client, private_key)
- 91
- 92 def __init__(
- 93 self, rpc_url: str, ws_client: AsyncWeb3, private_key: Sequence[bytes]
- 94 ) -> None:
- 95 self._http_client = GolemBaseClient._create_client(rpc_url)
- 96 self._ws_client = ws_client
- 97
- 98 # Keep references to async tasks we created
- 99 self._background_tasks = set()
-100
-101 def is_connected(client) -> Callable[[bool], Awaitable[bool]]:
-102 async def inner(show_traceback: bool) -> bool:
-103 try:
-104 logger.debug("Calling eth_blockNumber to test connectivity...")
-105 await client.eth.get_block_number()
-106 return True
-107 except (OSError, ProviderConnectionError) as e:
-108 logger.debug(
-109 "Problem connecting to provider", exc_info=show_traceback
-110 )
-111 if show_traceback:
-112 raise ProviderConnectionError(
-113 "Problem connecting to provider"
-114 ) from e
-115 return False
-116
-117 return inner
-118
-119 # The default is_connected method calls web3_clientVersion, but the web3
-120 # API is not enabled on all our nodes, so let's monkey patch this to call
-121 # eth_getBlockNumber instead.
-122 # The method on the provider is usually not called directly, instead you
-123 # can call the eponymous method on the client, which will delegate to the
-124 # provider.
-125 setattr(
-126 self.http_client().provider,
-127 "is_connected",
-128 is_connected(self.http_client()),
-129 )
-130
-131 # Allow caching of certain methods to improve performance
-132 self.http_client().provider.cache_allowed_requests = True
-133
-134 # Set up the ethereum account
-135 self.account = self.http_client().eth.account.from_key(private_key)
-136 # Inject a middleware that will sign transactions with the account that we created
-137 self.http_client().middleware_onion.inject(
-138 # pylint doesn't detect nested @curry annotations properly...
-139 # pylint: disable=no-value-for-parameter
-140 SignAndSendRawMiddlewareBuilder.build(self.account),
-141 layer=0,
-142 )
-143 # Set the account as the default, so we don't need to specify the from field
-144 # every time
-145 self.http_client().eth.default_account = self.account.address
-146 logger.debug("Using account: %s", self.account.address)
-147
-148 # https://github.com/pylint-dev/pylint/issues/3162
-149 # pylint: disable=no-member
-150 self.golem_base_contract = self.http_client().eth.contract(
-151 address=STORAGE_ADDRESS.as_address(),
-152 abi=GOLEM_BASE_ABI,
-153 )
-154 for event in self.golem_base_contract.all_events():
-155 logger.debug(
-156 "Registered event %s with hash %s", event.signature, event.topic
-157 )
-158
-159 @staticmethod
-160 def _create_client(rpc_url: str) -> AsyncWeb3:
-161 client = AsyncWeb3(
-162 AsyncWeb3.AsyncHTTPProvider(rpc_url, request_kwargs={"timeout": 60}),
-163 )
-164 client.eth.attach_methods(
-165 {
-166 "get_storage_value": Method(
-167 json_rpc_method=RPCEndpoint("golembase_getStorageValue"),
-168 mungers=[default_root_munger],
-169 ),
-170 "get_entity_metadata": Method(
-171 json_rpc_method=RPCEndpoint("golembase_getEntityMetaData"),
-172 mungers=[default_root_munger],
-173 ),
-174 "get_entities_to_expire_at_block": Method(
-175 json_rpc_method=RPCEndpoint("golembase_getEntitiesToExpireAtBlock"),
-176 mungers=[default_root_munger],
-177 ),
-178 "get_entity_count": Method(
-179 json_rpc_method=RPCEndpoint("golembase_getEntityCount"),
-180 mungers=[default_root_munger],
-181 ),
-182 "get_all_entity_keys": Method(
-183 json_rpc_method=RPCEndpoint("golembase_getAllEntityKeys"),
-184 mungers=[default_root_munger],
-185 ),
-186 "get_entities_of_owner": Method(
-187 json_rpc_method=RPCEndpoint("golembase_getEntitiesOfOwner"),
-188 mungers=[default_root_munger],
-189 ),
-190 "query_entities": Method(
-191 json_rpc_method=RPCEndpoint("golembase_queryEntities"),
-192 mungers=[default_root_munger],
-193 ),
-194 }
-195 )
-196 return client
-197
-198 def http_client(self):
-199 """
-200 Get the underlying web3 http client
-201 """
-202 return self._http_client
-203
-204 def ws_client(self) -> AsyncWeb3:
-205 """
-206 Get the underlying web3 websocket client
-207 """
-208 return self._ws_client
-209
-210 async def is_connected(self) -> bool:
-211 """
-212 Check whether the client's underlying http client is connected
-213 """
-214 return await self.http_client().is_connected()
-215
-216 async def disconnect(self) -> None:
-217 """
-218 Disconnect both the underlying http and ws clients and
-219 unsubscribe from all subscriptions
-220 """
-221 await self.http_client().provider.disconnect()
-222 await self.ws_client().subscription_manager.unsubscribe_all()
-223 await self.ws_client().provider.disconnect()
-224
-225 def get_account_address(self) -> ChecksumAddress:
-226 """
-227 Get the address associated with the private key that this client
-228 was created with
-229 """
-230 return self.account.address
-231
-232 async def get_storage_value(self, entity_key: EntityKey) -> bytes:
-233 """
-234 Get the storage value stored in the given entity
-235 """
-236 return base64.b64decode(
-237 await self.http_client().eth.get_storage_value(entity_key.as_hex_string())
-238 )
-239
-240 async def get_entity_metadata(self, entity_key: EntityKey) -> EntityMetadata:
-241 """
-242 Get the metadata of the given entity
-243 """
-244 metadata = await self.http_client().eth.get_entity_metadata(
-245 entity_key.as_hex_string()
-246 )
-247
-248 return EntityMetadata(
-249 entity_key=entity_key,
-250 owner=Address(GenericBytes.from_hex_string(metadata.owner)),
-251 expires_at_block=metadata.expiresAtBlock,
-252 string_annotations=list(
-253 map(
-254 lambda ann: Annotation(key=ann["key"], value=ann["value"]),
-255 metadata.stringAnnotations,
-256 )
-257 ),
-258 numeric_annotations=list(
-259 map(
-260 lambda ann: Annotation(key=ann["key"], value=ann["value"]),
-261 metadata.numericAnnotations,
-262 )
-263 ),
-264 )
-265
-266 async def get_entities_to_expire_at_block(
-267 self, block_number: int
-268 ) -> Iterable[EntityKey]:
-269 """
-270 Get all entities that will expire at the given block
-271 """
-272 return list(
-273 map(
-274 lambda e: EntityKey(GenericBytes.from_hex_string(e)),
-275 await self.http_client().eth.get_entities_to_expire_at_block(
-276 block_number
-277 ),
-278 )
-279 )
-280
-281 async def get_entity_count(self) -> int:
-282 """
-283 Get the total entity count in Golem Base
-284 """
-285 return await self.http_client().eth.get_entity_count()
-286
-287 async def get_all_entity_keys(self) -> Sequence[EntityKey]:
-288 """
-289 Get all entity keys in Golem Base
-290 """
-291 return list(
-292 map(
-293 lambda e: EntityKey(GenericBytes.from_hex_string(e)),
-294 await self.http_client().eth.get_all_entity_keys(),
-295 )
-296 )
-297
-298 async def get_entities_of_owner(self, owner: Address) -> Sequence[EntityKey]:
-299 """
-300 Get all the entities owned by the given address
-301 """
-302 return list(
-303 map(
-304 lambda e: EntityKey(GenericBytes.from_hex_string(e)),
-305 # https://github.com/pylint-dev/pylint/issues/3162
-306 # pylint: disable=no-member
-307 await self.http_client().eth.get_entities_of_owner(owner),
-308 )
-309 )
-310
-311 async def query_entities(self, query: str) -> Sequence[QueryEntitiesResult]:
-312 """
-313 Get all entities that satisfy the given Golem Base query
-314 """
-315 return list(
-316 map(
-317 lambda result: QueryEntitiesResult(
-318 entity_key=result.key, storage_value=base64.b64decode(result.value)
-319 ),
-320 await self.http_client().eth.query_entities(query),
-321 )
-322 )
-323
-324 async def create_entities(
-325 self,
-326 creates: Sequence[GolemBaseCreate],
-327 ) -> Iterable[CreateEntityReturnType]:
-328 """
-329 Create entities in Golem Base
-330 """
-331 return (await self.send_transaction(creates=creates)).creates
-332
-333 async def update_entities(
-334 self,
-335 updates: Sequence[GolemBaseUpdate],
-336 ) -> Iterable[UpdateEntityReturnType]:
-337 """
-338 Update entities in Golem Base
-339 """
-340 return (await self.send_transaction(updates=updates)).updates
-341
-342 async def delete_entities(
-343 self,
-344 deletes: Sequence[GolemBaseDelete],
-345 ) -> Iterable[EntityKey]:
-346 """
-347 Delete entities from Golem Base
-348 """
-349 return (await self.send_transaction(deletes=deletes)).deletes
-350
-351 async def extend_entities(
-352 self,
-353 extensions: Sequence[GolemBaseExtend],
-354 ) -> Iterable[ExtendEntityReturnType]:
-355 """
-356 Extend the BTL of entities in Golem Base
-357 """
-358 return (await self.send_transaction(extensions=extensions)).extensions
-359
-360 async def send_transaction(
-361 self,
-362 creates: Optional[Sequence[GolemBaseCreate]] = None,
-363 updates: Optional[Sequence[GolemBaseUpdate]] = None,
-364 deletes: Optional[Sequence[GolemBaseDelete]] = None,
-365 extensions: Optional[Sequence[GolemBaseExtend]] = None,
-366 ) -> GolemBaseTransactionReceipt:
-367 """
-368 Send a generic transaction to Golem Base.
-369 This transaction can contain multiple create, update, delete and
-370 extend operations
-371 """
-372 tx = GolemBaseTransaction(
-373 creates,
-374 updates,
-375 deletes,
-376 extensions,
-377 )
-378 return await self._send_gb_transaction(tx)
-379
-380 async def _process_golem_base_log_receipt(
-381 self,
-382 log_receipt: LogReceipt,
-383 ) -> GolemBaseTransactionReceipt:
-384 # Read the first entry of the topics array,
-385 # which is the hash of the event signature, identifying the event
-386 topic = AsyncWeb3.to_hex(log_receipt["topics"][0])
-387 # Look up the corresponding event
-388 # If there is no such event in the ABI, it probably needs to be added
-389 event = self.golem_base_contract.get_event_by_topic(topic)
-390 # Use the event to process the whole log
-391 event_data = event.process_log(log_receipt)
-392
-393 creates: List[CreateEntityReturnType] = []
-394 updates: List[UpdateEntityReturnType] = []
-395 deletes: List[EntityKey] = []
-396 extensions: List[ExtendEntityReturnType] = []
-397
-398 match event_data["event"]:
-399 case "GolemBaseStorageEntityCreated":
-400 creates.append(
-401 CreateEntityReturnType(
-402 expiration_block=event_data["args"]["expirationBlock"],
-403 entity_key=EntityKey(
-404 GenericBytes(
-405 event_data["args"]["entityKey"].to_bytes(32, "big")
-406 )
-407 ),
-408 )
-409 )
-410 case "GolemBaseStorageEntityUpdated":
-411 updates.append(
-412 UpdateEntityReturnType(
-413 expiration_block=event_data["args"]["expirationBlock"],
-414 entity_key=EntityKey(
-415 GenericBytes(
-416 event_data["args"]["entityKey"].to_bytes(32, "big")
-417 )
-418 ),
-419 )
-420 )
-421 case "GolemBaseStorageEntityDeleted":
-422 deletes.append(
-423 EntityKey(
-424 GenericBytes(
-425 event_data["args"]["entityKey"].to_bytes(32, "big")
-426 ),
-427 )
-428 )
-429 case "GolemBaseStorageEntityBTLExtended":
-430 extensions.append(
-431 ExtendEntityReturnType(
-432 old_expiration_block=event_data["args"]["old_expirationBlock"],
-433 new_expiration_block=event_data["args"]["new_expirationBlock"],
-434 entity_key=EntityKey(
-435 GenericBytes(
-436 event_data["args"]["entityKey"].to_bytes(32, "big")
-437 )
-438 ),
-439 )
-440 )
-441 # This is only here for backwards compatibility and can be removed
-442 # once we undeploy kaolin.
-443 case (
-444 "GolemBaseStorageEntityBTLExptended"
-445 | "GolemBaseStorageEntityTTLExptended"
-446 ):
-447 extensions.append(parse_legacy_btl_extended_log(log_receipt))
-448 case other:
-449 raise ValueError(f"Unknown event type: {other}")
-450
-451 return GolemBaseTransactionReceipt(
-452 creates=creates,
-453 updates=updates,
-454 deletes=deletes,
-455 extensions=extensions,
-456 )
-457
-458 async def _process_golem_base_receipt(
-459 self, receipt: TxReceipt
-460 ) -> GolemBaseTransactionReceipt:
-461 # There doesn't seem to be a method for this in the web3 lib.
-462 # The only option in the lib is to iterate over the events in the ABI
-463 # and call process_receipt on each of them to try and decode the logs.
-464 # This is inefficient though compared to reading the actual topic signature
-465 # and immediately selecting the right event from the ABI, which is what
-466 # we do here.
-467 async def process_receipt(
-468 receipt: TxReceipt,
-469 ) -> AsyncGenerator[GolemBaseTransactionReceipt, None]:
-470 for log in receipt["logs"]:
-471 yield await self._process_golem_base_log_receipt(log)
-472
-473 creates: List[CreateEntityReturnType] = []
-474 updates: List[UpdateEntityReturnType] = []
-475 deletes: List[EntityKey] = []
-476 extensions: List[ExtendEntityReturnType] = []
-477
-478 async for res in process_receipt(receipt):
-479 creates.extend(res.creates)
-480 updates.extend(res.updates)
-481 deletes.extend(res.deletes)
-482 extensions.extend(res.extensions)
-483
-484 return GolemBaseTransactionReceipt(
-485 creates=creates,
-486 updates=updates,
-487 deletes=deletes,
-488 extensions=extensions,
-489 )
-490
-491 async def _send_gb_transaction(
-492 self, tx: GolemBaseTransaction
-493 ) -> GolemBaseTransactionReceipt:
-494 txhash = await self.http_client().eth.send_transaction(
-495 {
-496 # https://github.com/pylint-dev/pylint/issues/3162
-497 # pylint: disable=no-member
-498 "to": STORAGE_ADDRESS.as_address(),
-499 "value": AsyncWeb3.to_wei(0, "ether"),
-500 "data": rlp_encode_transaction(tx),
-501 }
-502 )
-503 receipt = await self.http_client().eth.wait_for_transaction_receipt(txhash)
-504 return await self._process_golem_base_receipt(receipt)
-505
-506 async def watch_logs(
-507 self,
-508 create_callback: Callable[[CreateEntityReturnType], None],
-509 update_callback: Callable[[UpdateEntityReturnType], None],
-510 delete_callback: Callable[[EntityKey], None],
-511 extend_callback: Callable[[ExtendEntityReturnType], None],
-512 ) -> None:
-513 """
-514 Subscribe to events on Golem Base.
-515 You can pass in four different callbacks, and the right one will
-516 be invoked for every create, update, delete, and extend operation.
-517 """
-518
-519 async def log_handler(
-520 handler_context: LogsSubscriptionContext,
-521 ) -> None:
-522 # We only use this handler for log receipts
-523 # TypeDicts cannot be checked at runtime
-524 log_receipt = typing.cast(LogReceipt, handler_context.result)
-525 logger.debug("New log: %s", log_receipt)
-526 res = await self._process_golem_base_log_receipt(log_receipt)
-527
-528 for create in res.creates:
-529 create_callback(create)
-530 for update in res.updates:
-531 update_callback(update)
-532 for key in res.deletes:
-533 delete_callback(key)
-534 for extension in res.extensions:
-535 extend_callback(extension)
-536
-537 def create_subscription(topic: HexStr) -> LogsSubscription:
-538 return LogsSubscription(
-539 label=f"Golem Base subscription to topic {topic}",
-540 address=self.golem_base_contract.address,
-541 topics=[topic],
-542 handler=log_handler,
-543 # optional `handler_context` args to help parse a response
-544 handler_context={},
-545 )
-546
-547 async def handle_subscriptions() -> None:
-548 await self._ws_client.subscription_manager.subscribe(
-549 list(
-550 map(
-551 lambda event: create_subscription(event.topic),
-552 self.golem_base_contract.all_events(),
-553 )
-554 ),
-555 )
-556 # handle subscriptions via configured handlers:
-557 await self.ws_client().subscription_manager.handle_subscriptions()
-558
-559 # Create a long running task to handle subscriptions that we can run on
-560 # the asyncio event loop
-561 task = asyncio.create_task(handle_subscriptions())
-562 self._background_tasks.add(task)
-563
-564 def task_done(task: asyncio.Task) -> None:
-565 logger.info("Subscription background task done, removing...")
-566 self._background_tasks.discard(task)
-567
-568 task.add_done_callback(task_done)
+ 57logger = logging.getLogger(__name__)
+ 58"""
+ 59@private
+ 60"""
+ 61
+ 62
+ 63class GolemBaseClient:
+ 64 """
+ 65 The Golem Base client used to interact with Golem Base.
+ 66 Many useful methods are implemented directly on this type, while more
+ 67 generic ethereum methods can be accessed through the underlying
+ 68 web3 client that you can access with the
+ 69 `GolemBaseClient.http_client()`
+ 70 method.
+ 71 """
+ 72
+ 73 _http_client: AsyncWeb3
+ 74 _ws_client: AsyncWeb3
+ 75 _golem_base_contract: AsyncContract
+ 76 _background_tasks: Set[asyncio.Task]
+ 77
+ 78 @staticmethod
+ 79 async def create(
+ 80 rpc_url: str, ws_url: str, private_key: bytes
+ 81 ) -> "GolemBaseClient":
+ 82 """
+ 83 Static method to create a `GolemBaseClient` instance,
+ 84 this is the preferred method to create an instance.
+ 85 """
+ 86 ws_client = await AsyncWeb3(WebSocketProvider(ws_url))
+ 87 return GolemBaseClient(rpc_url, ws_client, private_key)
+ 88
+ 89 def __init__(self, rpc_url: str, ws_client: AsyncWeb3, private_key: bytes) -> None:
+ 90 self._http_client = GolemBaseClient._create_client(rpc_url)
+ 91 self._ws_client = ws_client
+ 92
+ 93 # Keep references to async tasks we created
+ 94 self._background_tasks = set()
+ 95
+ 96 def is_connected(client) -> Callable[[bool], Awaitable[bool]]:
+ 97 async def inner(show_traceback: bool) -> bool:
+ 98 try:
+ 99 logger.debug("Calling eth_blockNumber to test connectivity...")
+100 await client.eth.get_block_number()
+101 return True
+102 except (OSError, ProviderConnectionError) as e:
+103 logger.debug(
+104 "Problem connecting to provider", exc_info=show_traceback
+105 )
+106 if show_traceback:
+107 raise ProviderConnectionError(
+108 "Problem connecting to provider"
+109 ) from e
+110 return False
+111
+112 return inner
+113
+114 # The default is_connected method calls web3_clientVersion, but the web3
+115 # API is not enabled on all our nodes, so let's monkey patch this to call
+116 # eth_getBlockNumber instead.
+117 # The method on the provider is usually not called directly, instead you
+118 # can call the eponymous method on the client, which will delegate to the
+119 # provider.
+120 setattr(
+121 self.http_client().provider,
+122 "is_connected",
+123 is_connected(self.http_client()),
+124 )
+125
+126 # Allow caching of certain methods to improve performance
+127 self.http_client().provider.cache_allowed_requests = True
+128
+129 # Set up the ethereum account
+130 self.account = self.http_client().eth.account.from_key(private_key)
+131 # Inject a middleware that will sign transactions with the account that we created
+132 self.http_client().middleware_onion.inject(
+133 # pylint doesn't detect nested @curry annotations properly...
+134 # pylint: disable=no-value-for-parameter
+135 SignAndSendRawMiddlewareBuilder.build(self.account),
+136 layer=0,
+137 )
+138 # Set the account as the default, so we don't need to specify the from field
+139 # every time
+140 self.http_client().eth.default_account = self.account.address
+141 logger.debug("Using account: %s", self.account.address)
+142
+143 # https://github.com/pylint-dev/pylint/issues/3162
+144 # pylint: disable=no-member
+145 self.golem_base_contract = self.http_client().eth.contract(
+146 address=STORAGE_ADDRESS.as_address(),
+147 abi=GOLEM_BASE_ABI,
+148 )
+149 for event in self.golem_base_contract.all_events():
+150 logger.debug(
+151 "Registered event %s with hash %s", event.signature, event.topic
+152 )
+153
+154 @staticmethod
+155 def _create_client(rpc_url: str) -> AsyncWeb3:
+156 client = AsyncWeb3(
+157 AsyncWeb3.AsyncHTTPProvider(rpc_url, request_kwargs={"timeout": 60}),
+158 )
+159 client.eth.attach_methods(
+160 {
+161 "get_storage_value": Method(
+162 json_rpc_method=RPCEndpoint("golembase_getStorageValue"),
+163 mungers=[default_root_munger],
+164 ),
+165 "get_entity_metadata": Method(
+166 json_rpc_method=RPCEndpoint("golembase_getEntityMetaData"),
+167 mungers=[default_root_munger],
+168 ),
+169 "get_entities_to_expire_at_block": Method(
+170 json_rpc_method=RPCEndpoint("golembase_getEntitiesToExpireAtBlock"),
+171 mungers=[default_root_munger],
+172 ),
+173 "get_entity_count": Method(
+174 json_rpc_method=RPCEndpoint("golembase_getEntityCount"),
+175 mungers=[default_root_munger],
+176 ),
+177 "get_all_entity_keys": Method(
+178 json_rpc_method=RPCEndpoint("golembase_getAllEntityKeys"),
+179 mungers=[default_root_munger],
+180 ),
+181 "get_entities_of_owner": Method(
+182 json_rpc_method=RPCEndpoint("golembase_getEntitiesOfOwner"),
+183 mungers=[default_root_munger],
+184 ),
+185 "query_entities": Method(
+186 json_rpc_method=RPCEndpoint("golembase_queryEntities"),
+187 mungers=[default_root_munger],
+188 ),
+189 }
+190 )
+191 return client
+192
+193 def http_client(self):
+194 """
+195 Get the underlying web3 http client
+196 """
+197 return self._http_client
+198
+199 def ws_client(self) -> AsyncWeb3:
+200 """
+201 Get the underlying web3 websocket client
+202 """
+203 return self._ws_client
+204
+205 async def is_connected(self) -> bool:
+206 """
+207 Check whether the client's underlying http client is connected
+208 """
+209 return await self.http_client().is_connected()
+210
+211 async def disconnect(self) -> None:
+212 """
+213 Disconnect both the underlying http and ws clients and
+214 unsubscribe from all subscriptions
+215 """
+216 await self.http_client().provider.disconnect()
+217 await self.ws_client().subscription_manager.unsubscribe_all()
+218 await self.ws_client().provider.disconnect()
+219
+220 def get_account_address(self) -> ChecksumAddress:
+221 """
+222 Get the address associated with the private key that this client
+223 was created with
+224 """
+225 return self.account.address
+226
+227 async def get_storage_value(self, entity_key: EntityKey) -> bytes:
+228 """
+229 Get the storage value stored in the given entity
+230 """
+231 return base64.b64decode(
+232 await self.http_client().eth.get_storage_value(entity_key.as_hex_string())
+233 )
+234
+235 async def get_entity_metadata(self, entity_key: EntityKey) -> EntityMetadata:
+236 """
+237 Get the metadata of the given entity
+238 """
+239 metadata = await self.http_client().eth.get_entity_metadata(
+240 entity_key.as_hex_string()
+241 )
+242
+243 return EntityMetadata(
+244 entity_key=entity_key,
+245 owner=Address(GenericBytes.from_hex_string(metadata.owner)),
+246 expires_at_block=metadata.expiresAtBlock,
+247 string_annotations=list(
+248 map(
+249 lambda ann: Annotation(key=ann["key"], value=ann["value"]),
+250 metadata.stringAnnotations,
+251 )
+252 ),
+253 numeric_annotations=list(
+254 map(
+255 lambda ann: Annotation(key=ann["key"], value=ann["value"]),
+256 metadata.numericAnnotations,
+257 )
+258 ),
+259 )
+260
+261 async def get_entities_to_expire_at_block(
+262 self, block_number: int
+263 ) -> Sequence[EntityKey]:
+264 """
+265 Get all entities that will expire at the given block
+266 """
+267 return list(
+268 map(
+269 lambda e: EntityKey(GenericBytes.from_hex_string(e)),
+270 await self.http_client().eth.get_entities_to_expire_at_block(
+271 block_number
+272 ),
+273 )
+274 )
+275
+276 async def get_entity_count(self) -> int:
+277 """
+278 Get the total entity count in Golem Base
+279 """
+280 return await self.http_client().eth.get_entity_count()
+281
+282 async def get_all_entity_keys(self) -> Sequence[EntityKey]:
+283 """
+284 Get all entity keys in Golem Base
+285 """
+286 return list(
+287 map(
+288 lambda e: EntityKey(GenericBytes.from_hex_string(e)),
+289 await self.http_client().eth.get_all_entity_keys(),
+290 )
+291 )
+292
+293 async def get_entities_of_owner(
+294 self, owner: ChecksumAddress
+295 ) -> Sequence[EntityKey]:
+296 """
+297 Get all the entities owned by the given address
+298 """
+299 return list(
+300 map(
+301 lambda e: EntityKey(GenericBytes.from_hex_string(e)),
+302 # https://github.com/pylint-dev/pylint/issues/3162
+303 # pylint: disable=no-member
+304 await self.http_client().eth.get_entities_of_owner(owner),
+305 )
+306 )
+307
+308 async def query_entities(self, query: str) -> Sequence[QueryEntitiesResult]:
+309 """
+310 Get all entities that satisfy the given Golem Base query
+311 """
+312 return list(
+313 map(
+314 lambda result: QueryEntitiesResult(
+315 entity_key=result.key, storage_value=base64.b64decode(result.value)
+316 ),
+317 await self.http_client().eth.query_entities(query),
+318 )
+319 )
+320
+321 async def create_entities(
+322 self,
+323 creates: Sequence[GolemBaseCreate],
+324 ) -> Sequence[CreateEntityReturnType]:
+325 """
+326 Create entities in Golem Base
+327 """
+328 return (await self.send_transaction(creates=creates)).creates
+329
+330 async def update_entities(
+331 self,
+332 updates: Sequence[GolemBaseUpdate],
+333 ) -> Sequence[UpdateEntityReturnType]:
+334 """
+335 Update entities in Golem Base
+336 """
+337 return (await self.send_transaction(updates=updates)).updates
+338
+339 async def delete_entities(
+340 self,
+341 deletes: Sequence[GolemBaseDelete],
+342 ) -> Sequence[EntityKey]:
+343 """
+344 Delete entities from Golem Base
+345 """
+346 return (await self.send_transaction(deletes=deletes)).deletes
+347
+348 async def extend_entities(
+349 self,
+350 extensions: Sequence[GolemBaseExtend],
+351 ) -> Sequence[ExtendEntityReturnType]:
+352 """
+353 Extend the BTL of entities in Golem Base
+354 """
+355 return (await self.send_transaction(extensions=extensions)).extensions
+356
+357 async def send_transaction(
+358 self,
+359 creates: Optional[Sequence[GolemBaseCreate]] = None,
+360 updates: Optional[Sequence[GolemBaseUpdate]] = None,
+361 deletes: Optional[Sequence[GolemBaseDelete]] = None,
+362 extensions: Optional[Sequence[GolemBaseExtend]] = None,
+363 ) -> GolemBaseTransactionReceipt:
+364 """
+365 Send a generic transaction to Golem Base.
+366 This transaction can contain multiple create, update, delete and
+367 extend operations
+368 """
+369 tx = GolemBaseTransaction(
+370 creates,
+371 updates,
+372 deletes,
+373 extensions,
+374 )
+375 return await self._send_gb_transaction(tx)
+376
+377 async def _process_golem_base_log_receipt(
+378 self,
+379 log_receipt: LogReceipt,
+380 ) -> GolemBaseTransactionReceipt:
+381 # Read the first entry of the topics array,
+382 # which is the hash of the event signature, identifying the event
+383 topic = AsyncWeb3.to_hex(log_receipt["topics"][0])
+384 # Look up the corresponding event
+385 # If there is no such event in the ABI, it probably needs to be added
+386 event = self.golem_base_contract.get_event_by_topic(topic)
+387 # Use the event to process the whole log
+388 event_data = event.process_log(log_receipt)
+389
+390 creates: List[CreateEntityReturnType] = []
+391 updates: List[UpdateEntityReturnType] = []
+392 deletes: List[EntityKey] = []
+393 extensions: List[ExtendEntityReturnType] = []
+394
+395 match event_data["event"]:
+396 case "GolemBaseStorageEntityCreated":
+397 creates.append(
+398 CreateEntityReturnType(
+399 expiration_block=event_data["args"]["expirationBlock"],
+400 entity_key=EntityKey(
+401 GenericBytes(
+402 event_data["args"]["entityKey"].to_bytes(32, "big")
+403 )
+404 ),
+405 )
+406 )
+407 case "GolemBaseStorageEntityUpdated":
+408 updates.append(
+409 UpdateEntityReturnType(
+410 expiration_block=event_data["args"]["expirationBlock"],
+411 entity_key=EntityKey(
+412 GenericBytes(
+413 event_data["args"]["entityKey"].to_bytes(32, "big")
+414 )
+415 ),
+416 )
+417 )
+418 case "GolemBaseStorageEntityDeleted":
+419 deletes.append(
+420 EntityKey(
+421 GenericBytes(
+422 event_data["args"]["entityKey"].to_bytes(32, "big")
+423 ),
+424 )
+425 )
+426 case "GolemBaseStorageEntityBTLExtended":
+427 extensions.append(
+428 ExtendEntityReturnType(
+429 old_expiration_block=event_data["args"]["oldExpirationBlock"],
+430 new_expiration_block=event_data["args"]["newExpirationBlock"],
+431 entity_key=EntityKey(
+432 GenericBytes(
+433 event_data["args"]["entityKey"].to_bytes(32, "big")
+434 )
+435 ),
+436 )
+437 )
+438 # This is only here for backwards compatibility and can be removed
+439 # once we undeploy kaolin.
+440 case (
+441 "GolemBaseStorageEntityBTLExptended"
+442 | "GolemBaseStorageEntityTTLExptended"
+443 ):
+444 extensions.append(parse_legacy_btl_extended_log(log_receipt))
+445 case other:
+446 raise ValueError(f"Unknown event type: {other}")
+447
+448 return GolemBaseTransactionReceipt(
+449 creates=creates,
+450 updates=updates,
+451 deletes=deletes,
+452 extensions=extensions,
+453 )
+454
+455 async def _process_golem_base_receipt(
+456 self, receipt: TxReceipt
+457 ) -> GolemBaseTransactionReceipt:
+458 # There doesn't seem to be a method for this in the web3 lib.
+459 # The only option in the lib is to iterate over the events in the ABI
+460 # and call process_receipt on each of them to try and decode the logs.
+461 # This is inefficient though compared to reading the actual topic signature
+462 # and immediately selecting the right event from the ABI, which is what
+463 # we do here.
+464 async def process_receipt(
+465 receipt: TxReceipt,
+466 ) -> AsyncGenerator[GolemBaseTransactionReceipt, None]:
+467 for log in receipt["logs"]:
+468 yield await self._process_golem_base_log_receipt(log)
+469
+470 creates: List[CreateEntityReturnType] = []
+471 updates: List[UpdateEntityReturnType] = []
+472 deletes: List[EntityKey] = []
+473 extensions: List[ExtendEntityReturnType] = []
+474
+475 async for res in process_receipt(receipt):
+476 creates.extend(res.creates)
+477 updates.extend(res.updates)
+478 deletes.extend(res.deletes)
+479 extensions.extend(res.extensions)
+480
+481 return GolemBaseTransactionReceipt(
+482 creates=creates,
+483 updates=updates,
+484 deletes=deletes,
+485 extensions=extensions,
+486 )
+487
+488 async def _send_gb_transaction(
+489 self, tx: GolemBaseTransaction
+490 ) -> GolemBaseTransactionReceipt:
+491 txhash = await self.http_client().eth.send_transaction(
+492 {
+493 # https://github.com/pylint-dev/pylint/issues/3162
+494 # pylint: disable=no-member
+495 "to": STORAGE_ADDRESS.as_address(),
+496 "value": AsyncWeb3.to_wei(0, "ether"),
+497 "data": rlp_encode_transaction(tx),
+498 }
+499 )
+500 receipt = await self.http_client().eth.wait_for_transaction_receipt(txhash)
+501 return await self._process_golem_base_receipt(receipt)
+502
+503 async def watch_logs(
+504 self,
+505 create_callback: Callable[[CreateEntityReturnType], None],
+506 update_callback: Callable[[UpdateEntityReturnType], None],
+507 delete_callback: Callable[[EntityKey], None],
+508 extend_callback: Callable[[ExtendEntityReturnType], None],
+509 ) -> None:
+510 """
+511 Subscribe to events on Golem Base.
+512 You can pass in four different callbacks, and the right one will
+513 be invoked for every create, update, delete, and extend operation.
+514 """
+515
+516 async def log_handler(
+517 handler_context: LogsSubscriptionContext,
+518 ) -> None:
+519 # We only use this handler for log receipts
+520 # TypeDicts cannot be checked at runtime
+521 log_receipt = typing.cast(LogReceipt, handler_context.result)
+522 logger.debug("New log: %s", log_receipt)
+523 res = await self._process_golem_base_log_receipt(log_receipt)
+524
+525 for create in res.creates:
+526 create_callback(create)
+527 for update in res.updates:
+528 update_callback(update)
+529 for key in res.deletes:
+530 delete_callback(key)
+531 for extension in res.extensions:
+532 extend_callback(extension)
+533
+534 def create_subscription(topic: HexStr) -> LogsSubscription:
+535 return LogsSubscription(
+536 label=f"Golem Base subscription to topic {topic}",
+537 address=self.golem_base_contract.address,
+538 topics=[topic],
+539 handler=log_handler,
+540 # optional `handler_context` args to help parse a response
+541 handler_context={},
+542 )
+543
+544 async def handle_subscriptions() -> None:
+545 await self._ws_client.subscription_manager.subscribe(
+546 list(
+547 map(
+548 lambda event: create_subscription(event.topic),
+549 self.golem_base_contract.all_events(),
+550 )
+551 ),
+552 )
+553 # handle subscriptions via configured handlers:
+554 await self.ws_client().subscription_manager.handle_subscriptions()
+555
+556 # Create a long running task to handle subscriptions that we can run on
+557 # the asyncio event loop
+558 task = asyncio.create_task(handle_subscriptions())
+559 self._background_tasks.add(task)
+560
+561 def task_done(task: asyncio.Task) -> None:
+562 logger.info("Subscription background task done, removing...")
+563 self._background_tasks.discard(task)
+564
+565 task.add_done_callback(task_done)
@@ -709,509 +706,509 @@
67class GolemBaseClient: - 68 """ - 69 The Golem Base client used to interact with Golem Base. - 70 Many useful methods are implemented directly on this type, while more - 71 generic ethereum methods can be accessed through the underlying - 72 web3 client that you can access with the - 73 `GolemBaseClient.http_client()` - 74 method. - 75 """ - 76 - 77 _http_client: AsyncWeb3 - 78 _ws_client: AsyncWeb3 - 79 _golem_base_contract: AsyncContract - 80 _background_tasks: Set[asyncio.Task] - 81 - 82 @staticmethod - 83 async def create( - 84 rpc_url: str, ws_url: str, private_key: Sequence[bytes] - 85 ) -> "GolemBaseClient": - 86 """ - 87 Static method to create a `GolemBaseClient` instance, - 88 this is the preferred method to create an instance. - 89 """ - 90 ws_client = await AsyncWeb3(WebSocketProvider(ws_url)) - 91 return GolemBaseClient(rpc_url, ws_client, private_key) - 92 - 93 def __init__( - 94 self, rpc_url: str, ws_client: AsyncWeb3, private_key: Sequence[bytes] - 95 ) -> None: - 96 self._http_client = GolemBaseClient._create_client(rpc_url) - 97 self._ws_client = ws_client - 98 - 99 # Keep references to async tasks we created -100 self._background_tasks = set() -101 -102 def is_connected(client) -> Callable[[bool], Awaitable[bool]]: -103 async def inner(show_traceback: bool) -> bool: -104 try: -105 logger.debug("Calling eth_blockNumber to test connectivity...") -106 await client.eth.get_block_number() -107 return True -108 except (OSError, ProviderConnectionError) as e: -109 logger.debug( -110 "Problem connecting to provider", exc_info=show_traceback -111 ) -112 if show_traceback: -113 raise ProviderConnectionError( -114 "Problem connecting to provider" -115 ) from e -116 return False -117 -118 return inner -119 -120 # The default is_connected method calls web3_clientVersion, but the web3 -121 # API is not enabled on all our nodes, so let's monkey patch this to call -122 # eth_getBlockNumber instead. -123 # The method on the provider is usually not called directly, instead you -124 # can call the eponymous method on the client, which will delegate to the -125 # provider. -126 setattr( -127 self.http_client().provider, -128 "is_connected", -129 is_connected(self.http_client()), -130 ) -131 -132 # Allow caching of certain methods to improve performance -133 self.http_client().provider.cache_allowed_requests = True -134 -135 # Set up the ethereum account -136 self.account = self.http_client().eth.account.from_key(private_key) -137 # Inject a middleware that will sign transactions with the account that we created -138 self.http_client().middleware_onion.inject( -139 # pylint doesn't detect nested @curry annotations properly... -140 # pylint: disable=no-value-for-parameter -141 SignAndSendRawMiddlewareBuilder.build(self.account), -142 layer=0, -143 ) -144 # Set the account as the default, so we don't need to specify the from field -145 # every time -146 self.http_client().eth.default_account = self.account.address -147 logger.debug("Using account: %s", self.account.address) -148 -149 # https://github.com/pylint-dev/pylint/issues/3162 -150 # pylint: disable=no-member -151 self.golem_base_contract = self.http_client().eth.contract( -152 address=STORAGE_ADDRESS.as_address(), -153 abi=GOLEM_BASE_ABI, -154 ) -155 for event in self.golem_base_contract.all_events(): -156 logger.debug( -157 "Registered event %s with hash %s", event.signature, event.topic -158 ) -159 -160 @staticmethod -161 def _create_client(rpc_url: str) -> AsyncWeb3: -162 client = AsyncWeb3( -163 AsyncWeb3.AsyncHTTPProvider(rpc_url, request_kwargs={"timeout": 60}), -164 ) -165 client.eth.attach_methods( -166 { -167 "get_storage_value": Method( -168 json_rpc_method=RPCEndpoint("golembase_getStorageValue"), -169 mungers=[default_root_munger], -170 ), -171 "get_entity_metadata": Method( -172 json_rpc_method=RPCEndpoint("golembase_getEntityMetaData"), -173 mungers=[default_root_munger], -174 ), -175 "get_entities_to_expire_at_block": Method( -176 json_rpc_method=RPCEndpoint("golembase_getEntitiesToExpireAtBlock"), -177 mungers=[default_root_munger], -178 ), -179 "get_entity_count": Method( -180 json_rpc_method=RPCEndpoint("golembase_getEntityCount"), -181 mungers=[default_root_munger], -182 ), -183 "get_all_entity_keys": Method( -184 json_rpc_method=RPCEndpoint("golembase_getAllEntityKeys"), -185 mungers=[default_root_munger], -186 ), -187 "get_entities_of_owner": Method( -188 json_rpc_method=RPCEndpoint("golembase_getEntitiesOfOwner"), -189 mungers=[default_root_munger], -190 ), -191 "query_entities": Method( -192 json_rpc_method=RPCEndpoint("golembase_queryEntities"), -193 mungers=[default_root_munger], -194 ), -195 } -196 ) -197 return client -198 -199 def http_client(self): -200 """ -201 Get the underlying web3 http client -202 """ -203 return self._http_client -204 -205 def ws_client(self) -> AsyncWeb3: -206 """ -207 Get the underlying web3 websocket client -208 """ -209 return self._ws_client -210 -211 async def is_connected(self) -> bool: -212 """ -213 Check whether the client's underlying http client is connected -214 """ -215 return await self.http_client().is_connected() -216 -217 async def disconnect(self) -> None: -218 """ -219 Disconnect both the underlying http and ws clients and -220 unsubscribe from all subscriptions -221 """ -222 await self.http_client().provider.disconnect() -223 await self.ws_client().subscription_manager.unsubscribe_all() -224 await self.ws_client().provider.disconnect() -225 -226 def get_account_address(self) -> ChecksumAddress: -227 """ -228 Get the address associated with the private key that this client -229 was created with -230 """ -231 return self.account.address -232 -233 async def get_storage_value(self, entity_key: EntityKey) -> bytes: -234 """ -235 Get the storage value stored in the given entity -236 """ -237 return base64.b64decode( -238 await self.http_client().eth.get_storage_value(entity_key.as_hex_string()) -239 ) -240 -241 async def get_entity_metadata(self, entity_key: EntityKey) -> EntityMetadata: -242 """ -243 Get the metadata of the given entity -244 """ -245 metadata = await self.http_client().eth.get_entity_metadata( -246 entity_key.as_hex_string() -247 ) -248 -249 return EntityMetadata( -250 entity_key=entity_key, -251 owner=Address(GenericBytes.from_hex_string(metadata.owner)), -252 expires_at_block=metadata.expiresAtBlock, -253 string_annotations=list( -254 map( -255 lambda ann: Annotation(key=ann["key"], value=ann["value"]), -256 metadata.stringAnnotations, -257 ) -258 ), -259 numeric_annotations=list( -260 map( -261 lambda ann: Annotation(key=ann["key"], value=ann["value"]), -262 metadata.numericAnnotations, -263 ) -264 ), -265 ) -266 -267 async def get_entities_to_expire_at_block( -268 self, block_number: int -269 ) -> Iterable[EntityKey]: -270 """ -271 Get all entities that will expire at the given block -272 """ -273 return list( -274 map( -275 lambda e: EntityKey(GenericBytes.from_hex_string(e)), -276 await self.http_client().eth.get_entities_to_expire_at_block( -277 block_number -278 ), -279 ) -280 ) -281 -282 async def get_entity_count(self) -> int: -283 """ -284 Get the total entity count in Golem Base -285 """ -286 return await self.http_client().eth.get_entity_count() -287 -288 async def get_all_entity_keys(self) -> Sequence[EntityKey]: -289 """ -290 Get all entity keys in Golem Base -291 """ -292 return list( -293 map( -294 lambda e: EntityKey(GenericBytes.from_hex_string(e)), -295 await self.http_client().eth.get_all_entity_keys(), -296 ) -297 ) -298 -299 async def get_entities_of_owner(self, owner: Address) -> Sequence[EntityKey]: -300 """ -301 Get all the entities owned by the given address -302 """ -303 return list( -304 map( -305 lambda e: EntityKey(GenericBytes.from_hex_string(e)), -306 # https://github.com/pylint-dev/pylint/issues/3162 -307 # pylint: disable=no-member -308 await self.http_client().eth.get_entities_of_owner(owner), -309 ) -310 ) -311 -312 async def query_entities(self, query: str) -> Sequence[QueryEntitiesResult]: -313 """ -314 Get all entities that satisfy the given Golem Base query -315 """ -316 return list( -317 map( -318 lambda result: QueryEntitiesResult( -319 entity_key=result.key, storage_value=base64.b64decode(result.value) -320 ), -321 await self.http_client().eth.query_entities(query), -322 ) -323 ) -324 -325 async def create_entities( -326 self, -327 creates: Sequence[GolemBaseCreate], -328 ) -> Iterable[CreateEntityReturnType]: -329 """ -330 Create entities in Golem Base -331 """ -332 return (await self.send_transaction(creates=creates)).creates -333 -334 async def update_entities( -335 self, -336 updates: Sequence[GolemBaseUpdate], -337 ) -> Iterable[UpdateEntityReturnType]: -338 """ -339 Update entities in Golem Base -340 """ -341 return (await self.send_transaction(updates=updates)).updates -342 -343 async def delete_entities( -344 self, -345 deletes: Sequence[GolemBaseDelete], -346 ) -> Iterable[EntityKey]: -347 """ -348 Delete entities from Golem Base -349 """ -350 return (await self.send_transaction(deletes=deletes)).deletes -351 -352 async def extend_entities( -353 self, -354 extensions: Sequence[GolemBaseExtend], -355 ) -> Iterable[ExtendEntityReturnType]: -356 """ -357 Extend the BTL of entities in Golem Base -358 """ -359 return (await self.send_transaction(extensions=extensions)).extensions -360 -361 async def send_transaction( -362 self, -363 creates: Optional[Sequence[GolemBaseCreate]] = None, -364 updates: Optional[Sequence[GolemBaseUpdate]] = None, -365 deletes: Optional[Sequence[GolemBaseDelete]] = None, -366 extensions: Optional[Sequence[GolemBaseExtend]] = None, -367 ) -> GolemBaseTransactionReceipt: -368 """ -369 Send a generic transaction to Golem Base. -370 This transaction can contain multiple create, update, delete and -371 extend operations -372 """ -373 tx = GolemBaseTransaction( -374 creates, -375 updates, -376 deletes, -377 extensions, -378 ) -379 return await self._send_gb_transaction(tx) -380 -381 async def _process_golem_base_log_receipt( -382 self, -383 log_receipt: LogReceipt, -384 ) -> GolemBaseTransactionReceipt: -385 # Read the first entry of the topics array, -386 # which is the hash of the event signature, identifying the event -387 topic = AsyncWeb3.to_hex(log_receipt["topics"][0]) -388 # Look up the corresponding event -389 # If there is no such event in the ABI, it probably needs to be added -390 event = self.golem_base_contract.get_event_by_topic(topic) -391 # Use the event to process the whole log -392 event_data = event.process_log(log_receipt) -393 -394 creates: List[CreateEntityReturnType] = [] -395 updates: List[UpdateEntityReturnType] = [] -396 deletes: List[EntityKey] = [] -397 extensions: List[ExtendEntityReturnType] = [] -398 -399 match event_data["event"]: -400 case "GolemBaseStorageEntityCreated": -401 creates.append( -402 CreateEntityReturnType( -403 expiration_block=event_data["args"]["expirationBlock"], -404 entity_key=EntityKey( -405 GenericBytes( -406 event_data["args"]["entityKey"].to_bytes(32, "big") -407 ) -408 ), -409 ) -410 ) -411 case "GolemBaseStorageEntityUpdated": -412 updates.append( -413 UpdateEntityReturnType( -414 expiration_block=event_data["args"]["expirationBlock"], -415 entity_key=EntityKey( -416 GenericBytes( -417 event_data["args"]["entityKey"].to_bytes(32, "big") -418 ) -419 ), -420 ) -421 ) -422 case "GolemBaseStorageEntityDeleted": -423 deletes.append( -424 EntityKey( -425 GenericBytes( -426 event_data["args"]["entityKey"].to_bytes(32, "big") -427 ), -428 ) -429 ) -430 case "GolemBaseStorageEntityBTLExtended": -431 extensions.append( -432 ExtendEntityReturnType( -433 old_expiration_block=event_data["args"]["old_expirationBlock"], -434 new_expiration_block=event_data["args"]["new_expirationBlock"], -435 entity_key=EntityKey( -436 GenericBytes( -437 event_data["args"]["entityKey"].to_bytes(32, "big") -438 ) -439 ), -440 ) -441 ) -442 # This is only here for backwards compatibility and can be removed -443 # once we undeploy kaolin. -444 case ( -445 "GolemBaseStorageEntityBTLExptended" -446 | "GolemBaseStorageEntityTTLExptended" -447 ): -448 extensions.append(parse_legacy_btl_extended_log(log_receipt)) -449 case other: -450 raise ValueError(f"Unknown event type: {other}") -451 -452 return GolemBaseTransactionReceipt( -453 creates=creates, -454 updates=updates, -455 deletes=deletes, -456 extensions=extensions, -457 ) -458 -459 async def _process_golem_base_receipt( -460 self, receipt: TxReceipt -461 ) -> GolemBaseTransactionReceipt: -462 # There doesn't seem to be a method for this in the web3 lib. -463 # The only option in the lib is to iterate over the events in the ABI -464 # and call process_receipt on each of them to try and decode the logs. -465 # This is inefficient though compared to reading the actual topic signature -466 # and immediately selecting the right event from the ABI, which is what -467 # we do here. -468 async def process_receipt( -469 receipt: TxReceipt, -470 ) -> AsyncGenerator[GolemBaseTransactionReceipt, None]: -471 for log in receipt["logs"]: -472 yield await self._process_golem_base_log_receipt(log) -473 -474 creates: List[CreateEntityReturnType] = [] -475 updates: List[UpdateEntityReturnType] = [] -476 deletes: List[EntityKey] = [] -477 extensions: List[ExtendEntityReturnType] = [] -478 -479 async for res in process_receipt(receipt): -480 creates.extend(res.creates) -481 updates.extend(res.updates) -482 deletes.extend(res.deletes) -483 extensions.extend(res.extensions) -484 -485 return GolemBaseTransactionReceipt( -486 creates=creates, -487 updates=updates, -488 deletes=deletes, -489 extensions=extensions, -490 ) -491 -492 async def _send_gb_transaction( -493 self, tx: GolemBaseTransaction -494 ) -> GolemBaseTransactionReceipt: -495 txhash = await self.http_client().eth.send_transaction( -496 { -497 # https://github.com/pylint-dev/pylint/issues/3162 -498 # pylint: disable=no-member -499 "to": STORAGE_ADDRESS.as_address(), -500 "value": AsyncWeb3.to_wei(0, "ether"), -501 "data": rlp_encode_transaction(tx), -502 } -503 ) -504 receipt = await self.http_client().eth.wait_for_transaction_receipt(txhash) -505 return await self._process_golem_base_receipt(receipt) -506 -507 async def watch_logs( -508 self, -509 create_callback: Callable[[CreateEntityReturnType], None], -510 update_callback: Callable[[UpdateEntityReturnType], None], -511 delete_callback: Callable[[EntityKey], None], -512 extend_callback: Callable[[ExtendEntityReturnType], None], -513 ) -> None: -514 """ -515 Subscribe to events on Golem Base. -516 You can pass in four different callbacks, and the right one will -517 be invoked for every create, update, delete, and extend operation. -518 """ -519 -520 async def log_handler( -521 handler_context: LogsSubscriptionContext, -522 ) -> None: -523 # We only use this handler for log receipts -524 # TypeDicts cannot be checked at runtime -525 log_receipt = typing.cast(LogReceipt, handler_context.result) -526 logger.debug("New log: %s", log_receipt) -527 res = await self._process_golem_base_log_receipt(log_receipt) -528 -529 for create in res.creates: -530 create_callback(create) -531 for update in res.updates: -532 update_callback(update) -533 for key in res.deletes: -534 delete_callback(key) -535 for extension in res.extensions: -536 extend_callback(extension) -537 -538 def create_subscription(topic: HexStr) -> LogsSubscription: -539 return LogsSubscription( -540 label=f"Golem Base subscription to topic {topic}", -541 address=self.golem_base_contract.address, -542 topics=[topic], -543 handler=log_handler, -544 # optional `handler_context` args to help parse a response -545 handler_context={}, -546 ) -547 -548 async def handle_subscriptions() -> None: -549 await self._ws_client.subscription_manager.subscribe( -550 list( -551 map( -552 lambda event: create_subscription(event.topic), -553 self.golem_base_contract.all_events(), -554 ) -555 ), -556 ) -557 # handle subscriptions via configured handlers: -558 await self.ws_client().subscription_manager.handle_subscriptions() -559 -560 # Create a long running task to handle subscriptions that we can run on -561 # the asyncio event loop -562 task = asyncio.create_task(handle_subscriptions()) -563 self._background_tasks.add(task) -564 -565 def task_done(task: asyncio.Task) -> None: -566 logger.info("Subscription background task done, removing...") -567 self._background_tasks.discard(task) -568 -569 task.add_done_callback(task_done) +@@ -1228,78 +1225,76 @@64class GolemBaseClient: + 65 """ + 66 The Golem Base client used to interact with Golem Base. + 67 Many useful methods are implemented directly on this type, while more + 68 generic ethereum methods can be accessed through the underlying + 69 web3 client that you can access with the + 70 `GolemBaseClient.http_client()` + 71 method. + 72 """ + 73 + 74 _http_client: AsyncWeb3 + 75 _ws_client: AsyncWeb3 + 76 _golem_base_contract: AsyncContract + 77 _background_tasks: Set[asyncio.Task] + 78 + 79 @staticmethod + 80 async def create( + 81 rpc_url: str, ws_url: str, private_key: bytes + 82 ) -> "GolemBaseClient": + 83 """ + 84 Static method to create a `GolemBaseClient` instance, + 85 this is the preferred method to create an instance. + 86 """ + 87 ws_client = await AsyncWeb3(WebSocketProvider(ws_url)) + 88 return GolemBaseClient(rpc_url, ws_client, private_key) + 89 + 90 def __init__(self, rpc_url: str, ws_client: AsyncWeb3, private_key: bytes) -> None: + 91 self._http_client = GolemBaseClient._create_client(rpc_url) + 92 self._ws_client = ws_client + 93 + 94 # Keep references to async tasks we created + 95 self._background_tasks = set() + 96 + 97 def is_connected(client) -> Callable[[bool], Awaitable[bool]]: + 98 async def inner(show_traceback: bool) -> bool: + 99 try: +100 logger.debug("Calling eth_blockNumber to test connectivity...") +101 await client.eth.get_block_number() +102 return True +103 except (OSError, ProviderConnectionError) as e: +104 logger.debug( +105 "Problem connecting to provider", exc_info=show_traceback +106 ) +107 if show_traceback: +108 raise ProviderConnectionError( +109 "Problem connecting to provider" +110 ) from e +111 return False +112 +113 return inner +114 +115 # The default is_connected method calls web3_clientVersion, but the web3 +116 # API is not enabled on all our nodes, so let's monkey patch this to call +117 # eth_getBlockNumber instead. +118 # The method on the provider is usually not called directly, instead you +119 # can call the eponymous method on the client, which will delegate to the +120 # provider. +121 setattr( +122 self.http_client().provider, +123 "is_connected", +124 is_connected(self.http_client()), +125 ) +126 +127 # Allow caching of certain methods to improve performance +128 self.http_client().provider.cache_allowed_requests = True +129 +130 # Set up the ethereum account +131 self.account = self.http_client().eth.account.from_key(private_key) +132 # Inject a middleware that will sign transactions with the account that we created +133 self.http_client().middleware_onion.inject( +134 # pylint doesn't detect nested @curry annotations properly... +135 # pylint: disable=no-value-for-parameter +136 SignAndSendRawMiddlewareBuilder.build(self.account), +137 layer=0, +138 ) +139 # Set the account as the default, so we don't need to specify the from field +140 # every time +141 self.http_client().eth.default_account = self.account.address +142 logger.debug("Using account: %s", self.account.address) +143 +144 # https://github.com/pylint-dev/pylint/issues/3162 +145 # pylint: disable=no-member +146 self.golem_base_contract = self.http_client().eth.contract( +147 address=STORAGE_ADDRESS.as_address(), +148 abi=GOLEM_BASE_ABI, +149 ) +150 for event in self.golem_base_contract.all_events(): +151 logger.debug( +152 "Registered event %s with hash %s", event.signature, event.topic +153 ) +154 +155 @staticmethod +156 def _create_client(rpc_url: str) -> AsyncWeb3: +157 client = AsyncWeb3( +158 AsyncWeb3.AsyncHTTPProvider(rpc_url, request_kwargs={"timeout": 60}), +159 ) +160 client.eth.attach_methods( +161 { +162 "get_storage_value": Method( +163 json_rpc_method=RPCEndpoint("golembase_getStorageValue"), +164 mungers=[default_root_munger], +165 ), +166 "get_entity_metadata": Method( +167 json_rpc_method=RPCEndpoint("golembase_getEntityMetaData"), +168 mungers=[default_root_munger], +169 ), +170 "get_entities_to_expire_at_block": Method( +171 json_rpc_method=RPCEndpoint("golembase_getEntitiesToExpireAtBlock"), +172 mungers=[default_root_munger], +173 ), +174 "get_entity_count": Method( +175 json_rpc_method=RPCEndpoint("golembase_getEntityCount"), +176 mungers=[default_root_munger], +177 ), +178 "get_all_entity_keys": Method( +179 json_rpc_method=RPCEndpoint("golembase_getAllEntityKeys"), +180 mungers=[default_root_munger], +181 ), +182 "get_entities_of_owner": Method( +183 json_rpc_method=RPCEndpoint("golembase_getEntitiesOfOwner"), +184 mungers=[default_root_munger], +185 ), +186 "query_entities": Method( +187 json_rpc_method=RPCEndpoint("golembase_queryEntities"), +188 mungers=[default_root_munger], +189 ), +190 } +191 ) +192 return client +193 +194 def http_client(self): +195 """ +196 Get the underlying web3 http client +197 """ +198 return self._http_client +199 +200 def ws_client(self) -> AsyncWeb3: +201 """ +202 Get the underlying web3 websocket client +203 """ +204 return self._ws_client +205 +206 async def is_connected(self) -> bool: +207 """ +208 Check whether the client's underlying http client is connected +209 """ +210 return await self.http_client().is_connected() +211 +212 async def disconnect(self) -> None: +213 """ +214 Disconnect both the underlying http and ws clients and +215 unsubscribe from all subscriptions +216 """ +217 await self.http_client().provider.disconnect() +218 await self.ws_client().subscription_manager.unsubscribe_all() +219 await self.ws_client().provider.disconnect() +220 +221 def get_account_address(self) -> ChecksumAddress: +222 """ +223 Get the address associated with the private key that this client +224 was created with +225 """ +226 return self.account.address +227 +228 async def get_storage_value(self, entity_key: EntityKey) -> bytes: +229 """ +230 Get the storage value stored in the given entity +231 """ +232 return base64.b64decode( +233 await self.http_client().eth.get_storage_value(entity_key.as_hex_string()) +234 ) +235 +236 async def get_entity_metadata(self, entity_key: EntityKey) -> EntityMetadata: +237 """ +238 Get the metadata of the given entity +239 """ +240 metadata = await self.http_client().eth.get_entity_metadata( +241 entity_key.as_hex_string() +242 ) +243 +244 return EntityMetadata( +245 entity_key=entity_key, +246 owner=Address(GenericBytes.from_hex_string(metadata.owner)), +247 expires_at_block=metadata.expiresAtBlock, +248 string_annotations=list( +249 map( +250 lambda ann: Annotation(key=ann["key"], value=ann["value"]), +251 metadata.stringAnnotations, +252 ) +253 ), +254 numeric_annotations=list( +255 map( +256 lambda ann: Annotation(key=ann["key"], value=ann["value"]), +257 metadata.numericAnnotations, +258 ) +259 ), +260 ) +261 +262 async def get_entities_to_expire_at_block( +263 self, block_number: int +264 ) -> Sequence[EntityKey]: +265 """ +266 Get all entities that will expire at the given block +267 """ +268 return list( +269 map( +270 lambda e: EntityKey(GenericBytes.from_hex_string(e)), +271 await self.http_client().eth.get_entities_to_expire_at_block( +272 block_number +273 ), +274 ) +275 ) +276 +277 async def get_entity_count(self) -> int: +278 """ +279 Get the total entity count in Golem Base +280 """ +281 return await self.http_client().eth.get_entity_count() +282 +283 async def get_all_entity_keys(self) -> Sequence[EntityKey]: +284 """ +285 Get all entity keys in Golem Base +286 """ +287 return list( +288 map( +289 lambda e: EntityKey(GenericBytes.from_hex_string(e)), +290 await self.http_client().eth.get_all_entity_keys(), +291 ) +292 ) +293 +294 async def get_entities_of_owner( +295 self, owner: ChecksumAddress +296 ) -> Sequence[EntityKey]: +297 """ +298 Get all the entities owned by the given address +299 """ +300 return list( +301 map( +302 lambda e: EntityKey(GenericBytes.from_hex_string(e)), +303 # https://github.com/pylint-dev/pylint/issues/3162 +304 # pylint: disable=no-member +305 await self.http_client().eth.get_entities_of_owner(owner), +306 ) +307 ) +308 +309 async def query_entities(self, query: str) -> Sequence[QueryEntitiesResult]: +310 """ +311 Get all entities that satisfy the given Golem Base query +312 """ +313 return list( +314 map( +315 lambda result: QueryEntitiesResult( +316 entity_key=result.key, storage_value=base64.b64decode(result.value) +317 ), +318 await self.http_client().eth.query_entities(query), +319 ) +320 ) +321 +322 async def create_entities( +323 self, +324 creates: Sequence[GolemBaseCreate], +325 ) -> Sequence[CreateEntityReturnType]: +326 """ +327 Create entities in Golem Base +328 """ +329 return (await self.send_transaction(creates=creates)).creates +330 +331 async def update_entities( +332 self, +333 updates: Sequence[GolemBaseUpdate], +334 ) -> Sequence[UpdateEntityReturnType]: +335 """ +336 Update entities in Golem Base +337 """ +338 return (await self.send_transaction(updates=updates)).updates +339 +340 async def delete_entities( +341 self, +342 deletes: Sequence[GolemBaseDelete], +343 ) -> Sequence[EntityKey]: +344 """ +345 Delete entities from Golem Base +346 """ +347 return (await self.send_transaction(deletes=deletes)).deletes +348 +349 async def extend_entities( +350 self, +351 extensions: Sequence[GolemBaseExtend], +352 ) -> Sequence[ExtendEntityReturnType]: +353 """ +354 Extend the BTL of entities in Golem Base +355 """ +356 return (await self.send_transaction(extensions=extensions)).extensions +357 +358 async def send_transaction( +359 self, +360 creates: Optional[Sequence[GolemBaseCreate]] = None, +361 updates: Optional[Sequence[GolemBaseUpdate]] = None, +362 deletes: Optional[Sequence[GolemBaseDelete]] = None, +363 extensions: Optional[Sequence[GolemBaseExtend]] = None, +364 ) -> GolemBaseTransactionReceipt: +365 """ +366 Send a generic transaction to Golem Base. +367 This transaction can contain multiple create, update, delete and +368 extend operations +369 """ +370 tx = GolemBaseTransaction( +371 creates, +372 updates, +373 deletes, +374 extensions, +375 ) +376 return await self._send_gb_transaction(tx) +377 +378 async def _process_golem_base_log_receipt( +379 self, +380 log_receipt: LogReceipt, +381 ) -> GolemBaseTransactionReceipt: +382 # Read the first entry of the topics array, +383 # which is the hash of the event signature, identifying the event +384 topic = AsyncWeb3.to_hex(log_receipt["topics"][0]) +385 # Look up the corresponding event +386 # If there is no such event in the ABI, it probably needs to be added +387 event = self.golem_base_contract.get_event_by_topic(topic) +388 # Use the event to process the whole log +389 event_data = event.process_log(log_receipt) +390 +391 creates: List[CreateEntityReturnType] = [] +392 updates: List[UpdateEntityReturnType] = [] +393 deletes: List[EntityKey] = [] +394 extensions: List[ExtendEntityReturnType] = [] +395 +396 match event_data["event"]: +397 case "GolemBaseStorageEntityCreated": +398 creates.append( +399 CreateEntityReturnType( +400 expiration_block=event_data["args"]["expirationBlock"], +401 entity_key=EntityKey( +402 GenericBytes( +403 event_data["args"]["entityKey"].to_bytes(32, "big") +404 ) +405 ), +406 ) +407 ) +408 case "GolemBaseStorageEntityUpdated": +409 updates.append( +410 UpdateEntityReturnType( +411 expiration_block=event_data["args"]["expirationBlock"], +412 entity_key=EntityKey( +413 GenericBytes( +414 event_data["args"]["entityKey"].to_bytes(32, "big") +415 ) +416 ), +417 ) +418 ) +419 case "GolemBaseStorageEntityDeleted": +420 deletes.append( +421 EntityKey( +422 GenericBytes( +423 event_data["args"]["entityKey"].to_bytes(32, "big") +424 ), +425 ) +426 ) +427 case "GolemBaseStorageEntityBTLExtended": +428 extensions.append( +429 ExtendEntityReturnType( +430 old_expiration_block=event_data["args"]["oldExpirationBlock"], +431 new_expiration_block=event_data["args"]["newExpirationBlock"], +432 entity_key=EntityKey( +433 GenericBytes( +434 event_data["args"]["entityKey"].to_bytes(32, "big") +435 ) +436 ), +437 ) +438 ) +439 # This is only here for backwards compatibility and can be removed +440 # once we undeploy kaolin. +441 case ( +442 "GolemBaseStorageEntityBTLExptended" +443 | "GolemBaseStorageEntityTTLExptended" +444 ): +445 extensions.append(parse_legacy_btl_extended_log(log_receipt)) +446 case other: +447 raise ValueError(f"Unknown event type: {other}") +448 +449 return GolemBaseTransactionReceipt( +450 creates=creates, +451 updates=updates, +452 deletes=deletes, +453 extensions=extensions, +454 ) +455 +456 async def _process_golem_base_receipt( +457 self, receipt: TxReceipt +458 ) -> GolemBaseTransactionReceipt: +459 # There doesn't seem to be a method for this in the web3 lib. +460 # The only option in the lib is to iterate over the events in the ABI +461 # and call process_receipt on each of them to try and decode the logs. +462 # This is inefficient though compared to reading the actual topic signature +463 # and immediately selecting the right event from the ABI, which is what +464 # we do here. +465 async def process_receipt( +466 receipt: TxReceipt, +467 ) -> AsyncGenerator[GolemBaseTransactionReceipt, None]: +468 for log in receipt["logs"]: +469 yield await self._process_golem_base_log_receipt(log) +470 +471 creates: List[CreateEntityReturnType] = [] +472 updates: List[UpdateEntityReturnType] = [] +473 deletes: List[EntityKey] = [] +474 extensions: List[ExtendEntityReturnType] = [] +475 +476 async for res in process_receipt(receipt): +477 creates.extend(res.creates) +478 updates.extend(res.updates) +479 deletes.extend(res.deletes) +480 extensions.extend(res.extensions) +481 +482 return GolemBaseTransactionReceipt( +483 creates=creates, +484 updates=updates, +485 deletes=deletes, +486 extensions=extensions, +487 ) +488 +489 async def _send_gb_transaction( +490 self, tx: GolemBaseTransaction +491 ) -> GolemBaseTransactionReceipt: +492 txhash = await self.http_client().eth.send_transaction( +493 { +494 # https://github.com/pylint-dev/pylint/issues/3162 +495 # pylint: disable=no-member +496 "to": STORAGE_ADDRESS.as_address(), +497 "value": AsyncWeb3.to_wei(0, "ether"), +498 "data": rlp_encode_transaction(tx), +499 } +500 ) +501 receipt = await self.http_client().eth.wait_for_transaction_receipt(txhash) +502 return await self._process_golem_base_receipt(receipt) +503 +504 async def watch_logs( +505 self, +506 create_callback: Callable[[CreateEntityReturnType], None], +507 update_callback: Callable[[UpdateEntityReturnType], None], +508 delete_callback: Callable[[EntityKey], None], +509 extend_callback: Callable[[ExtendEntityReturnType], None], +510 ) -> None: +511 """ +512 Subscribe to events on Golem Base. +513 You can pass in four different callbacks, and the right one will +514 be invoked for every create, update, delete, and extend operation. +515 """ +516 +517 async def log_handler( +518 handler_context: LogsSubscriptionContext, +519 ) -> None: +520 # We only use this handler for log receipts +521 # TypeDicts cannot be checked at runtime +522 log_receipt = typing.cast(LogReceipt, handler_context.result) +523 logger.debug("New log: %s", log_receipt) +524 res = await self._process_golem_base_log_receipt(log_receipt) +525 +526 for create in res.creates: +527 create_callback(create) +528 for update in res.updates: +529 update_callback(update) +530 for key in res.deletes: +531 delete_callback(key) +532 for extension in res.extensions: +533 extend_callback(extension) +534 +535 def create_subscription(topic: HexStr) -> LogsSubscription: +536 return LogsSubscription( +537 label=f"Golem Base subscription to topic {topic}", +538 address=self.golem_base_contract.address, +539 topics=[topic], +540 handler=log_handler, +541 # optional `handler_context` args to help parse a response +542 handler_context={}, +543 ) +544 +545 async def handle_subscriptions() -> None: +546 await self._ws_client.subscription_manager.subscribe( +547 list( +548 map( +549 lambda event: create_subscription(event.topic), +550 self.golem_base_contract.all_events(), +551 ) +552 ), +553 ) +554 # handle subscriptions via configured handlers: +555 await self.ws_client().subscription_manager.handle_subscriptions() +556 +557 # Create a long running task to handle subscriptions that we can run on +558 # the asyncio event loop +559 task = asyncio.create_task(handle_subscriptions()) +560 self._background_tasks.add(task) +561 +562 def task_done(task: asyncio.Task) -> None: +563 logger.info("Subscription background task done, removing...") +564 self._background_tasks.discard(task) +565 +566 task.add_done_callback(task_done)
- GolemBaseClient( rpc_url: str, ws_client: web3.main.AsyncWeb3, private_key: Sequence[bytes]) + GolemBaseClient(rpc_url: str, ws_client: web3.main.AsyncWeb3, private_key: bytes)--93 def __init__( - 94 self, rpc_url: str, ws_client: AsyncWeb3, private_key: Sequence[bytes] - 95 ) -> None: - 96 self._http_client = GolemBaseClient._create_client(rpc_url) - 97 self._ws_client = ws_client - 98 - 99 # Keep references to async tasks we created -100 self._background_tasks = set() -101 -102 def is_connected(client) -> Callable[[bool], Awaitable[bool]]: -103 async def inner(show_traceback: bool) -> bool: -104 try: -105 logger.debug("Calling eth_blockNumber to test connectivity...") -106 await client.eth.get_block_number() -107 return True -108 except (OSError, ProviderConnectionError) as e: -109 logger.debug( -110 "Problem connecting to provider", exc_info=show_traceback -111 ) -112 if show_traceback: -113 raise ProviderConnectionError( -114 "Problem connecting to provider" -115 ) from e -116 return False -117 -118 return inner -119 -120 # The default is_connected method calls web3_clientVersion, but the web3 -121 # API is not enabled on all our nodes, so let's monkey patch this to call -122 # eth_getBlockNumber instead. -123 # The method on the provider is usually not called directly, instead you -124 # can call the eponymous method on the client, which will delegate to the -125 # provider. -126 setattr( -127 self.http_client().provider, -128 "is_connected", -129 is_connected(self.http_client()), -130 ) -131 -132 # Allow caching of certain methods to improve performance -133 self.http_client().provider.cache_allowed_requests = True -134 -135 # Set up the ethereum account -136 self.account = self.http_client().eth.account.from_key(private_key) -137 # Inject a middleware that will sign transactions with the account that we created -138 self.http_client().middleware_onion.inject( -139 # pylint doesn't detect nested @curry annotations properly... -140 # pylint: disable=no-value-for-parameter -141 SignAndSendRawMiddlewareBuilder.build(self.account), -142 layer=0, -143 ) -144 # Set the account as the default, so we don't need to specify the from field -145 # every time -146 self.http_client().eth.default_account = self.account.address -147 logger.debug("Using account: %s", self.account.address) -148 -149 # https://github.com/pylint-dev/pylint/issues/3162 -150 # pylint: disable=no-member -151 self.golem_base_contract = self.http_client().eth.contract( -152 address=STORAGE_ADDRESS.as_address(), -153 abi=GOLEM_BASE_ABI, -154 ) -155 for event in self.golem_base_contract.all_events(): -156 logger.debug( -157 "Registered event %s with hash %s", event.signature, event.topic -158 ) +@@ -1312,22 +1307,22 @@90 def __init__(self, rpc_url: str, ws_client: AsyncWeb3, private_key: bytes) -> None: + 91 self._http_client = GolemBaseClient._create_client(rpc_url) + 92 self._ws_client = ws_client + 93 + 94 # Keep references to async tasks we created + 95 self._background_tasks = set() + 96 + 97 def is_connected(client) -> Callable[[bool], Awaitable[bool]]: + 98 async def inner(show_traceback: bool) -> bool: + 99 try: +100 logger.debug("Calling eth_blockNumber to test connectivity...") +101 await client.eth.get_block_number() +102 return True +103 except (OSError, ProviderConnectionError) as e: +104 logger.debug( +105 "Problem connecting to provider", exc_info=show_traceback +106 ) +107 if show_traceback: +108 raise ProviderConnectionError( +109 "Problem connecting to provider" +110 ) from e +111 return False +112 +113 return inner +114 +115 # The default is_connected method calls web3_clientVersion, but the web3 +116 # API is not enabled on all our nodes, so let's monkey patch this to call +117 # eth_getBlockNumber instead. +118 # The method on the provider is usually not called directly, instead you +119 # can call the eponymous method on the client, which will delegate to the +120 # provider. +121 setattr( +122 self.http_client().provider, +123 "is_connected", +124 is_connected(self.http_client()), +125 ) +126 +127 # Allow caching of certain methods to improve performance +128 self.http_client().provider.cache_allowed_requests = True +129 +130 # Set up the ethereum account +131 self.account = self.http_client().eth.account.from_key(private_key) +132 # Inject a middleware that will sign transactions with the account that we created +133 self.http_client().middleware_onion.inject( +134 # pylint doesn't detect nested @curry annotations properly... +135 # pylint: disable=no-value-for-parameter +136 SignAndSendRawMiddlewareBuilder.build(self.account), +137 layer=0, +138 ) +139 # Set the account as the default, so we don't need to specify the from field +140 # every time +141 self.http_client().eth.default_account = self.account.address +142 logger.debug("Using account: %s", self.account.address) +143 +144 # https://github.com/pylint-dev/pylint/issues/3162 +145 # pylint: disable=no-member +146 self.golem_base_contract = self.http_client().eth.contract( +147 address=STORAGE_ADDRESS.as_address(), +148 abi=GOLEM_BASE_ABI, +149 ) +150 for event in self.golem_base_contract.all_events(): +151 logger.debug( +152 "Registered event %s with hash %s", event.signature, event.topic +153 )
@staticmethodasync def - create( rpc_url: str, ws_url: str, private_key: Sequence[bytes]) -> GolemBaseClient: + create( rpc_url: str, ws_url: str, private_key: bytes) -> GolemBaseClient:-82 @staticmethod -83 async def create( -84 rpc_url: str, ws_url: str, private_key: Sequence[bytes] -85 ) -> "GolemBaseClient": -86 """ -87 Static method to create a `GolemBaseClient` instance, -88 this is the preferred method to create an instance. -89 """ -90 ws_client = await AsyncWeb3(WebSocketProvider(ws_url)) -91 return GolemBaseClient(rpc_url, ws_client, private_key) +@@ -1370,11 +1365,11 @@79 @staticmethod +80 async def create( +81 rpc_url: str, ws_url: str, private_key: bytes +82 ) -> "GolemBaseClient": +83 """ +84 Static method to create a `GolemBaseClient` instance, +85 this is the preferred method to create an instance. +86 """ +87 ws_client = await AsyncWeb3(WebSocketProvider(ws_url)) +88 return GolemBaseClient(rpc_url, ws_client, private_key)
-199 def http_client(self): -200 """ -201 Get the underlying web3 http client -202 """ -203 return self._http_client +@@ -1394,11 +1389,11 @@194 def http_client(self): +195 """ +196 Get the underlying web3 http client +197 """ +198 return self._http_client
-205 def ws_client(self) -> AsyncWeb3: -206 """ -207 Get the underlying web3 websocket client -208 """ -209 return self._ws_client +@@ -1418,11 +1413,11 @@200 def ws_client(self) -> AsyncWeb3: +201 """ +202 Get the underlying web3 websocket client +203 """ +204 return self._ws_client
-211 async def is_connected(self) -> bool: -212 """ -213 Check whether the client's underlying http client is connected -214 """ -215 return await self.http_client().is_connected() +@@ -1442,14 +1437,14 @@206 async def is_connected(self) -> bool: +207 """ +208 Check whether the client's underlying http client is connected +209 """ +210 return await self.http_client().is_connected()
-217 async def disconnect(self) -> None: -218 """ -219 Disconnect both the underlying http and ws clients and -220 unsubscribe from all subscriptions -221 """ -222 await self.http_client().provider.disconnect() -223 await self.ws_client().subscription_manager.unsubscribe_all() -224 await self.ws_client().provider.disconnect() +@@ -1470,12 +1465,12 @@212 async def disconnect(self) -> None: +213 """ +214 Disconnect both the underlying http and ws clients and +215 unsubscribe from all subscriptions +216 """ +217 await self.http_client().provider.disconnect() +218 await self.ws_client().subscription_manager.unsubscribe_all() +219 await self.ws_client().provider.disconnect()
-226 def get_account_address(self) -> ChecksumAddress: -227 """ -228 Get the address associated with the private key that this client -229 was created with -230 """ -231 return self.account.address +@@ -1496,13 +1491,13 @@221 def get_account_address(self) -> ChecksumAddress: +222 """ +223 Get the address associated with the private key that this client +224 was created with +225 """ +226 return self.account.address
-233 async def get_storage_value(self, entity_key: EntityKey) -> bytes: -234 """ -235 Get the storage value stored in the given entity -236 """ -237 return base64.b64decode( -238 await self.http_client().eth.get_storage_value(entity_key.as_hex_string()) -239 ) +@@ -1522,31 +1517,31 @@228 async def get_storage_value(self, entity_key: EntityKey) -> bytes: +229 """ +230 Get the storage value stored in the given entity +231 """ +232 return base64.b64decode( +233 await self.http_client().eth.get_storage_value(entity_key.as_hex_string()) +234 )
241 async def get_entity_metadata(self, entity_key: EntityKey) -> EntityMetadata: -242 """ -243 Get the metadata of the given entity -244 """ -245 metadata = await self.http_client().eth.get_entity_metadata( -246 entity_key.as_hex_string() -247 ) -248 -249 return EntityMetadata( -250 entity_key=entity_key, -251 owner=Address(GenericBytes.from_hex_string(metadata.owner)), -252 expires_at_block=metadata.expiresAtBlock, -253 string_annotations=list( -254 map( -255 lambda ann: Annotation(key=ann["key"], value=ann["value"]), -256 metadata.stringAnnotations, -257 ) -258 ), -259 numeric_annotations=list( -260 map( -261 lambda ann: Annotation(key=ann["key"], value=ann["value"]), -262 metadata.numericAnnotations, -263 ) -264 ), -265 ) +@@ -1560,26 +1555,26 @@236 async def get_entity_metadata(self, entity_key: EntityKey) -> EntityMetadata: +237 """ +238 Get the metadata of the given entity +239 """ +240 metadata = await self.http_client().eth.get_entity_metadata( +241 entity_key.as_hex_string() +242 ) +243 +244 return EntityMetadata( +245 entity_key=entity_key, +246 owner=Address(GenericBytes.from_hex_string(metadata.owner)), +247 expires_at_block=metadata.expiresAtBlock, +248 string_annotations=list( +249 map( +250 lambda ann: Annotation(key=ann["key"], value=ann["value"]), +251 metadata.stringAnnotations, +252 ) +253 ), +254 numeric_annotations=list( +255 map( +256 lambda ann: Annotation(key=ann["key"], value=ann["value"]), +257 metadata.numericAnnotations, +258 ) +259 ), +260 )
async def - get_entities_to_expire_at_block(self, block_number: int) -> Iterable[golem_base_sdk.types.EntityKey]: + get_entities_to_expire_at_block(self, block_number: int) -> Sequence[golem_base_sdk.types.EntityKey]:--267 async def get_entities_to_expire_at_block( -268 self, block_number: int -269 ) -> Iterable[EntityKey]: -270 """ -271 Get all entities that will expire at the given block -272 """ -273 return list( -274 map( -275 lambda e: EntityKey(GenericBytes.from_hex_string(e)), -276 await self.http_client().eth.get_entities_to_expire_at_block( -277 block_number -278 ), -279 ) -280 ) +@@ -1599,11 +1594,11 @@262 async def get_entities_to_expire_at_block( +263 self, block_number: int +264 ) -> Sequence[EntityKey]: +265 """ +266 Get all entities that will expire at the given block +267 """ +268 return list( +269 map( +270 lambda e: EntityKey(GenericBytes.from_hex_string(e)), +271 await self.http_client().eth.get_entities_to_expire_at_block( +272 block_number +273 ), +274 ) +275 )
-282 async def get_entity_count(self) -> int: -283 """ -284 Get the total entity count in Golem Base -285 """ -286 return await self.http_client().eth.get_entity_count() +@@ -1623,16 +1618,16 @@277 async def get_entity_count(self) -> int: +278 """ +279 Get the total entity count in Golem Base +280 """ +281 return await self.http_client().eth.get_entity_count()
288 async def get_all_entity_keys(self) -> Sequence[EntityKey]: -289 """ -290 Get all entity keys in Golem Base -291 """ -292 return list( -293 map( -294 lambda e: EntityKey(GenericBytes.from_hex_string(e)), -295 await self.http_client().eth.get_all_entity_keys(), -296 ) -297 ) +@@ -1646,24 +1641,26 @@283 async def get_all_entity_keys(self) -> Sequence[EntityKey]: +284 """ +285 Get all entity keys in Golem Base +286 """ +287 return list( +288 map( +289 lambda e: EntityKey(GenericBytes.from_hex_string(e)), +290 await self.http_client().eth.get_all_entity_keys(), +291 ) +292 )
async def - get_entities_of_owner( self, owner: golem_base_sdk.types.Address) -> Sequence[golem_base_sdk.types.EntityKey]: + get_entities_of_owner( self, owner: eth_typing.evm.ChecksumAddress) -> Sequence[golem_base_sdk.types.EntityKey]:--299 async def get_entities_of_owner(self, owner: Address) -> Sequence[EntityKey]: -300 """ -301 Get all the entities owned by the given address -302 """ -303 return list( -304 map( -305 lambda e: EntityKey(GenericBytes.from_hex_string(e)), -306 # https://github.com/pylint-dev/pylint/issues/3162 -307 # pylint: disable=no-member -308 await self.http_client().eth.get_entities_of_owner(owner), -309 ) -310 ) +@@ -1683,18 +1680,18 @@294 async def get_entities_of_owner( +295 self, owner: ChecksumAddress +296 ) -> Sequence[EntityKey]: +297 """ +298 Get all the entities owned by the given address +299 """ +300 return list( +301 map( +302 lambda e: EntityKey(GenericBytes.from_hex_string(e)), +303 # https://github.com/pylint-dev/pylint/issues/3162 +304 # pylint: disable=no-member +305 await self.http_client().eth.get_entities_of_owner(owner), +306 ) +307 )
312 async def query_entities(self, query: str) -> Sequence[QueryEntitiesResult]: -313 """ -314 Get all entities that satisfy the given Golem Base query -315 """ -316 return list( -317 map( -318 lambda result: QueryEntitiesResult( -319 entity_key=result.key, storage_value=base64.b64decode(result.value) -320 ), -321 await self.http_client().eth.query_entities(query), -322 ) -323 ) +@@ -1708,20 +1705,20 @@309 async def query_entities(self, query: str) -> Sequence[QueryEntitiesResult]: +310 """ +311 Get all entities that satisfy the given Golem Base query +312 """ +313 return list( +314 map( +315 lambda result: QueryEntitiesResult( +316 entity_key=result.key, storage_value=base64.b64decode(result.value) +317 ), +318 await self.http_client().eth.query_entities(query), +319 ) +320 )
async def - create_entities( self, creates: Sequence[golem_base_sdk.types.GolemBaseCreate]) -> Iterable[golem_base_sdk.types.CreateEntityReturnType]: + create_entities( self, creates: Sequence[golem_base_sdk.types.GolemBaseCreate]) -> Sequence[golem_base_sdk.types.CreateEntityReturnType]:-325 async def create_entities( -326 self, -327 creates: Sequence[GolemBaseCreate], -328 ) -> Iterable[CreateEntityReturnType]: -329 """ -330 Create entities in Golem Base -331 """ -332 return (await self.send_transaction(creates=creates)).creates +@@ -1735,20 +1732,20 @@322 async def create_entities( +323 self, +324 creates: Sequence[GolemBaseCreate], +325 ) -> Sequence[CreateEntityReturnType]: +326 """ +327 Create entities in Golem Base +328 """ +329 return (await self.send_transaction(creates=creates)).creates
async def - update_entities( self, updates: Sequence[golem_base_sdk.types.GolemBaseUpdate]) -> Iterable[golem_base_sdk.types.UpdateEntityReturnType]: + update_entities( self, updates: Sequence[golem_base_sdk.types.GolemBaseUpdate]) -> Sequence[golem_base_sdk.types.UpdateEntityReturnType]:-334 async def update_entities( -335 self, -336 updates: Sequence[GolemBaseUpdate], -337 ) -> Iterable[UpdateEntityReturnType]: -338 """ -339 Update entities in Golem Base -340 """ -341 return (await self.send_transaction(updates=updates)).updates +@@ -1762,20 +1759,20 @@331 async def update_entities( +332 self, +333 updates: Sequence[GolemBaseUpdate], +334 ) -> Sequence[UpdateEntityReturnType]: +335 """ +336 Update entities in Golem Base +337 """ +338 return (await self.send_transaction(updates=updates)).updates
async def - delete_entities( self, deletes: Sequence[golem_base_sdk.types.GolemBaseDelete]) -> Iterable[golem_base_sdk.types.EntityKey]: + delete_entities( self, deletes: Sequence[golem_base_sdk.types.GolemBaseDelete]) -> Sequence[golem_base_sdk.types.EntityKey]:--343 async def delete_entities( -344 self, -345 deletes: Sequence[GolemBaseDelete], -346 ) -> Iterable[EntityKey]: -347 """ -348 Delete entities from Golem Base -349 """ -350 return (await self.send_transaction(deletes=deletes)).deletes +@@ -1789,20 +1786,20 @@340 async def delete_entities( +341 self, +342 deletes: Sequence[GolemBaseDelete], +343 ) -> Sequence[EntityKey]: +344 """ +345 Delete entities from Golem Base +346 """ +347 return (await self.send_transaction(deletes=deletes)).deletes
async def - extend_entities( self, extensions: Sequence[golem_base_sdk.types.GolemBaseExtend]) -> Iterable[golem_base_sdk.types.ExtendEntityReturnType]: + extend_entities( self, extensions: Sequence[golem_base_sdk.types.GolemBaseExtend]) -> Sequence[golem_base_sdk.types.ExtendEntityReturnType]:--352 async def extend_entities( -353 self, -354 extensions: Sequence[GolemBaseExtend], -355 ) -> Iterable[ExtendEntityReturnType]: -356 """ -357 Extend the BTL of entities in Golem Base -358 """ -359 return (await self.send_transaction(extensions=extensions)).extensions +@@ -1822,25 +1819,25 @@349 async def extend_entities( +350 self, +351 extensions: Sequence[GolemBaseExtend], +352 ) -> Sequence[ExtendEntityReturnType]: +353 """ +354 Extend the BTL of entities in Golem Base +355 """ +356 return (await self.send_transaction(extensions=extensions)).extensions
-361 async def send_transaction( -362 self, -363 creates: Optional[Sequence[GolemBaseCreate]] = None, -364 updates: Optional[Sequence[GolemBaseUpdate]] = None, -365 deletes: Optional[Sequence[GolemBaseDelete]] = None, -366 extensions: Optional[Sequence[GolemBaseExtend]] = None, -367 ) -> GolemBaseTransactionReceipt: -368 """ -369 Send a generic transaction to Golem Base. -370 This transaction can contain multiple create, update, delete and -371 extend operations -372 """ -373 tx = GolemBaseTransaction( -374 creates, -375 updates, -376 deletes, -377 extensions, -378 ) -379 return await self._send_gb_transaction(tx) +@@ -1862,69 +1859,69 @@358 async def send_transaction( +359 self, +360 creates: Optional[Sequence[GolemBaseCreate]] = None, +361 updates: Optional[Sequence[GolemBaseUpdate]] = None, +362 deletes: Optional[Sequence[GolemBaseDelete]] = None, +363 extensions: Optional[Sequence[GolemBaseExtend]] = None, +364 ) -> GolemBaseTransactionReceipt: +365 """ +366 Send a generic transaction to Golem Base. +367 This transaction can contain multiple create, update, delete and +368 extend operations +369 """ +370 tx = GolemBaseTransaction( +371 creates, +372 updates, +373 deletes, +374 extensions, +375 ) +376 return await self._send_gb_transaction(tx)
507 async def watch_logs( -508 self, -509 create_callback: Callable[[CreateEntityReturnType], None], -510 update_callback: Callable[[UpdateEntityReturnType], None], -511 delete_callback: Callable[[EntityKey], None], -512 extend_callback: Callable[[ExtendEntityReturnType], None], -513 ) -> None: -514 """ -515 Subscribe to events on Golem Base. -516 You can pass in four different callbacks, and the right one will -517 be invoked for every create, update, delete, and extend operation. -518 """ -519 -520 async def log_handler( -521 handler_context: LogsSubscriptionContext, -522 ) -> None: -523 # We only use this handler for log receipts -524 # TypeDicts cannot be checked at runtime -525 log_receipt = typing.cast(LogReceipt, handler_context.result) -526 logger.debug("New log: %s", log_receipt) -527 res = await self._process_golem_base_log_receipt(log_receipt) -528 -529 for create in res.creates: -530 create_callback(create) -531 for update in res.updates: -532 update_callback(update) -533 for key in res.deletes: -534 delete_callback(key) -535 for extension in res.extensions: -536 extend_callback(extension) -537 -538 def create_subscription(topic: HexStr) -> LogsSubscription: -539 return LogsSubscription( -540 label=f"Golem Base subscription to topic {topic}", -541 address=self.golem_base_contract.address, -542 topics=[topic], -543 handler=log_handler, -544 # optional `handler_context` args to help parse a response -545 handler_context={}, -546 ) -547 -548 async def handle_subscriptions() -> None: -549 await self._ws_client.subscription_manager.subscribe( -550 list( -551 map( -552 lambda event: create_subscription(event.topic), -553 self.golem_base_contract.all_events(), -554 ) -555 ), -556 ) -557 # handle subscriptions via configured handlers: -558 await self.ws_client().subscription_manager.handle_subscriptions() -559 -560 # Create a long running task to handle subscriptions that we can run on -561 # the asyncio event loop -562 task = asyncio.create_task(handle_subscriptions()) -563 self._background_tasks.add(task) -564 -565 def task_done(task: asyncio.Task) -> None: -566 logger.info("Subscription background task done, removing...") -567 self._background_tasks.discard(task) -568 -569 task.add_done_callback(task_done) +diff --git a/docs/golem_base_sdk/constants.html b/docs/golem_base_sdk/constants.html index f163f0a..106e031 100644 --- a/docs/golem_base_sdk/constants.html +++ b/docs/golem_base_sdk/constants.html @@ -63,79 +63,81 @@504 async def watch_logs( +505 self, +506 create_callback: Callable[[CreateEntityReturnType], None], +507 update_callback: Callable[[UpdateEntityReturnType], None], +508 delete_callback: Callable[[EntityKey], None], +509 extend_callback: Callable[[ExtendEntityReturnType], None], +510 ) -> None: +511 """ +512 Subscribe to events on Golem Base. +513 You can pass in four different callbacks, and the right one will +514 be invoked for every create, update, delete, and extend operation. +515 """ +516 +517 async def log_handler( +518 handler_context: LogsSubscriptionContext, +519 ) -> None: +520 # We only use this handler for log receipts +521 # TypeDicts cannot be checked at runtime +522 log_receipt = typing.cast(LogReceipt, handler_context.result) +523 logger.debug("New log: %s", log_receipt) +524 res = await self._process_golem_base_log_receipt(log_receipt) +525 +526 for create in res.creates: +527 create_callback(create) +528 for update in res.updates: +529 update_callback(update) +530 for key in res.deletes: +531 delete_callback(key) +532 for extension in res.extensions: +533 extend_callback(extension) +534 +535 def create_subscription(topic: HexStr) -> LogsSubscription: +536 return LogsSubscription( +537 label=f"Golem Base subscription to topic {topic}", +538 address=self.golem_base_contract.address, +539 topics=[topic], +540 handler=log_handler, +541 # optional `handler_context` args to help parse a response +542 handler_context={}, +543 ) +544 +545 async def handle_subscriptions() -> None: +546 await self._ws_client.subscription_manager.subscribe( +547 list( +548 map( +549 lambda event: create_subscription(event.topic), +550 self.golem_base_contract.all_events(), +551 ) +552 ), +553 ) +554 # handle subscriptions via configured handlers: +555 await self.ws_client().subscription_manager.handle_subscriptions() +556 +557 # Create a long running task to handle subscriptions that we can run on +558 # the asyncio event loop +559 task = asyncio.create_task(handle_subscriptions()) +560 self._background_tasks.add(task) +561 +562 def task_done(task: asyncio.Task) -> None: +563 logger.info("Subscription background task done, removing...") +564 self._background_tasks.discard(task) +565 +566 task.add_done_callback(task_done)2Constants used in the Golem Base SDK 3""" 4 - 5from .types import ( - 6 Address, - 7 GenericBytes, - 8) - 9 -10STORAGE_ADDRESS: Address = Address( -11 GenericBytes.from_hex_string("0x0000000000000000000000000000000060138453") -12) -13 -14GOLEM_BASE_ABI = [ -15 { -16 "anonymous": False, -17 "inputs": [ -18 {"indexed": True, "name": "entityKey", "type": "uint256"}, -19 {"indexed": False, "name": "expirationBlock", "type": "uint256"}, -20 ], -21 "name": "GolemBaseStorageEntityCreated", -22 "type": "event", -23 }, -24 { -25 "anonymous": False, -26 "inputs": [ -27 {"indexed": True, "name": "entityKey", "type": "uint256"}, -28 {"indexed": False, "name": "expirationBlock", "type": "uint256"}, -29 ], -30 "name": "GolemBaseStorageEntityUpdated", -31 "type": "event", -32 }, -33 { -34 "anonymous": False, -35 "inputs": [{"indexed": True, "name": "entityKey", "type": "uint256"}], -36 "name": "GolemBaseStorageEntityDeleted", -37 "type": "event", -38 }, -39 { -40 "anonymous": False, -41 "inputs": [ -42 {"indexed": True, "name": "entityKey", "type": "uint256"}, -43 {"indexed": False, "name": "oldExpirationBlock", "type": "uint256"}, -44 {"indexed": False, "name": "newExpirationBlock", "type": "uint256"}, -45 ], -46 "name": "GolemBaseStorageEntityBTLExtended", -47 "type": "event", -48 }, -49 # Old ABI event that has a typo in the name and a missing non-indexed argument. -50 # This can be removed once we retire the kaolin network (the only one using this event hash). -51 { -52 "anonymous": False, -53 "inputs": [ -54 {"indexed": True, "name": "entityKey", "type": "uint256"}, -55 {"indexed": False, "name": "expirationBlock", "type": "uint256"}, -56 ], -57 "name": "GolemBaseStorageEntityBTLExptended", -58 "type": "event", -59 }, -60 # Old ABI before rename of TTL -> BTL -61 { -62 "anonymous": False, -63 "inputs": [ -64 {"indexed": True, "name": "entityKey", "type": "uint256"}, -65 {"indexed": False, "name": "expirationBlock", "type": "uint256"}, -66 ], -67 "name": "GolemBaseStorageEntityTTLExptended", -68 "type": "event", -69 }, -70] + 5from typing import Any, Final, Sequence + 6 + 7from .types import ( + 8 Address, + 9 GenericBytes, +10) +11 +12STORAGE_ADDRESS: Final[Address] = Address( +13 GenericBytes.from_hex_string("0x0000000000000000000000000000000060138453") +14) +15 +16GOLEM_BASE_ABI: Final[Sequence[dict[str, Any]]] = [ +17 { +18 "anonymous": False, +19 "inputs": [ +20 {"indexed": True, "name": "entityKey", "type": "uint256"}, +21 {"indexed": False, "name": "expirationBlock", "type": "uint256"}, +22 ], +23 "name": "GolemBaseStorageEntityCreated", +24 "type": "event", +25 }, +26 { +27 "anonymous": False, +28 "inputs": [ +29 {"indexed": True, "name": "entityKey", "type": "uint256"}, +30 {"indexed": False, "name": "expirationBlock", "type": "uint256"}, +31 ], +32 "name": "GolemBaseStorageEntityUpdated", +33 "type": "event", +34 }, +35 { +36 "anonymous": False, +37 "inputs": [{"indexed": True, "name": "entityKey", "type": "uint256"}], +38 "name": "GolemBaseStorageEntityDeleted", +39 "type": "event", +40 }, +41 { +42 "anonymous": False, +43 "inputs": [ +44 {"indexed": True, "name": "entityKey", "type": "uint256"}, +45 {"indexed": False, "name": "oldExpirationBlock", "type": "uint256"}, +46 {"indexed": False, "name": "newExpirationBlock", "type": "uint256"}, +47 ], +48 "name": "GolemBaseStorageEntityBTLExtended", +49 "type": "event", +50 }, +51 # Old ABI event that has a typo in the name and a missing non-indexed argument. +52 # This can be removed once we retire the kaolin network (the only one using this event hash). +53 { +54 "anonymous": False, +55 "inputs": [ +56 {"indexed": True, "name": "entityKey", "type": "uint256"}, +57 {"indexed": False, "name": "expirationBlock", "type": "uint256"}, +58 ], +59 "name": "GolemBaseStorageEntityBTLExptended", +60 "type": "event", +61 }, +62 # Old ABI before rename of TTL -> BTL +63 { +64 "anonymous": False, +65 "inputs": [ +66 {"indexed": True, "name": "entityKey", "type": "uint256"}, +67 {"indexed": False, "name": "expirationBlock", "type": "uint256"}, +68 ], +69 "name": "GolemBaseStorageEntityTTLExptended", +70 "type": "event", +71 }, +72]
- STORAGE_ADDRESS: golem_base_sdk.types.Address = + STORAGE_ADDRESS: Final[golem_base_sdk.types.Address] = GenericBytes(0x0000000000000000000000000000000060138453) @@ -147,7 +149,7 @@@@ -265,33 +261,33 @@
- GOLEM_BASE_ABI = + GOLEM_BASE_ABI: Final[Sequence[dict[str, Any]]] = [{'anonymous': False, 'inputs': [{'indexed': True, 'name': 'entityKey', 'type': 'uint256'}, {'indexed': False, 'name': 'expirationBlock', 'type': 'uint256'}], 'name': 'GolemBaseStorageEntityCreated', 'type': 'event'}, {'anonymous': False, 'inputs': [{'indexed': True, 'name': 'entityKey', 'type': 'uint256'}, {'indexed': False, 'name': 'expirationBlock', 'type': 'uint256'}], 'name': 'GolemBaseStorageEntityUpdated', 'type': 'event'}, {'anonymous': False, 'inputs': [{'indexed': True, 'name': 'entityKey', 'type': 'uint256'}], 'name': 'GolemBaseStorageEntityDeleted', 'type': 'event'}, {'anonymous': False, 'inputs': [{'indexed': True, 'name': 'entityKey', 'type': 'uint256'}, {'indexed': False, 'name': 'oldExpirationBlock', 'type': 'uint256'}, {'indexed': False, 'name': 'newExpirationBlock', 'type': 'uint256'}], 'name': 'GolemBaseStorageEntityBTLExtended', 'type': 'event'}, {'anonymous': False, 'inputs': [{'indexed': True, 'name': 'entityKey', 'type': 'uint256'}, {'indexed': False, 'name': 'expirationBlock', 'type': 'uint256'}], 'name': 'GolemBaseStorageEntityBTLExptended', 'type': 'event'}, {'anonymous': False, 'inputs': [{'indexed': True, 'name': 'entityKey', 'type': 'uint256'}, {'indexed': False, 'name': 'expirationBlock', 'type': 'uint256'}], 'name': 'GolemBaseStorageEntityTTLExptended', 'type': 'event'}] diff --git a/docs/golem_base_sdk/utils.html b/docs/golem_base_sdk/utils.html index b7a50f7..63c0443 100644 --- a/docs/golem_base_sdk/utils.html +++ b/docs/golem_base_sdk/utils.html @@ -121,56 +121,54 @@@@ -225,27 +223,25 @@60 # Delete 61 list( 62 map( - 63 lambda el: [ - 64 el.entity_key.generic_bytes, - 65 ], - 66 tx.deletes, - 67 ) - 68 ), - 69 # Extend - 70 list( - 71 map( - 72 lambda el: [ - 73 el.entity_key.generic_bytes, - 74 el.number_of_blocks, - 75 ], - 76 tx.extensions, - 77 ) - 78 ), - 79 ] - 80 logger.debug("Payload before RLP encoding: %s", payload) - 81 encoded = rlp.encode(payload) - 82 logger.debug(encoded) - 83 return encoded - 84 - 85 - 86def parse_legacy_btl_extended_log(log_receipt: LogReceipt) -> ExtendEntityReturnType: - 87 """ - 88 For legacy extend ABI types, the type signature in the ABI does - 89 not correspond to the actual data returned, so we need - 90 to parse the data ourselves. - 91 """ - 92 # pylint: disable=line-too-long - 93 # Take the first 64 bytes by masking the rest - 94 # (shift 1 to the left 256 positions, then negate the number) - 95 # Example: - 96 # 0x 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 012f - 97 # 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0143 - 98 # mask this with: - 99 # 0x 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 -100 # 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 -101 # to obtain 0x143 -102 # and then shift the original number to the right -103 # by 256 to obtain 0x12f -104 data_parsed = int.from_bytes(log_receipt["data"], byteorder="big", signed=False) -105 new_expiration_block = data_parsed & ((1 << 256) - 1) -106 old_expiration_block = data_parsed >> 256 -107 -108 return ExtendEntityReturnType( -109 old_expiration_block=old_expiration_block, -110 new_expiration_block=new_expiration_block, -111 entity_key=EntityKey(GenericBytes(log_receipt["topics"][1])), -112 ) + 63 lambda el: el.entity_key.generic_bytes, + 64 tx.deletes, + 65 ) + 66 ), + 67 # Extend + 68 list( + 69 map( + 70 lambda el: [ + 71 el.entity_key.generic_bytes, + 72 el.number_of_blocks, + 73 ], + 74 tx.extensions, + 75 ) + 76 ), + 77 ] + 78 logger.debug("Payload before RLP encoding: %s", payload) + 79 encoded = rlp.encode(payload) + 80 logger.debug("Encoded payload: %s", encoded) + 81 return encoded + 82 + 83 + 84def parse_legacy_btl_extended_log(log_receipt: LogReceipt) -> ExtendEntityReturnType: + 85 """ + 86 For legacy extend ABI types, the type signature in the ABI does + 87 not correspond to the actual data returned, so we need + 88 to parse the data ourselves. + 89 """ + 90 # pylint: disable=line-too-long + 91 # Take the first 64 bytes by masking the rest + 92 # (shift 1 to the left 256 positions, then negate the number) + 93 # Example: + 94 # 0x 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 012f + 95 # 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0143 + 96 # mask this with: + 97 # 0x 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 + 98 # 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 + 99 # to obtain 0x143 +100 # and then shift the original number to the right +101 # by 256 to obtain 0x12f +102 data_parsed = int.from_bytes(log_receipt["data"], byteorder="big", signed=False) +103 new_expiration_block = data_parsed & ((1 << 256) - 1) +104 old_expiration_block = data_parsed >> 256 +105 +106 return ExtendEntityReturnType( +107 old_expiration_block=old_expiration_block, +108 new_expiration_block=new_expiration_block, +109 entity_key=EntityKey(GenericBytes(log_receipt["topics"][1])), +110 )
61 # Delete 62 list( 63 map( -64 lambda el: [ -65 el.entity_key.generic_bytes, -66 ], -67 tx.deletes, -68 ) -69 ), -70 # Extend -71 list( -72 map( -73 lambda el: [ -74 el.entity_key.generic_bytes, -75 el.number_of_blocks, -76 ], -77 tx.extensions, -78 ) -79 ), -80 ] -81 logger.debug("Payload before RLP encoding: %s", payload) -82 encoded = rlp.encode(payload) -83 logger.debug(encoded) -84 return encoded +64 lambda el: el.entity_key.generic_bytes, +65 tx.deletes, +66 ) +67 ), +68 # Extend +69 list( +70 map( +71 lambda el: [ +72 el.entity_key.generic_bytes, +73 el.number_of_blocks, +74 ], +75 tx.extensions, +76 ) +77 ), +78 ] +79 logger.debug("Payload before RLP encoding: %s", payload) +80 encoded = rlp.encode(payload) +81 logger.debug("Encoded payload: %s", encoded) +82 return encoded
87def parse_legacy_btl_extended_log(log_receipt: LogReceipt) -> ExtendEntityReturnType: - 88 """ - 89 For legacy extend ABI types, the type signature in the ABI does - 90 not correspond to the actual data returned, so we need - 91 to parse the data ourselves. - 92 """ - 93 # pylint: disable=line-too-long - 94 # Take the first 64 bytes by masking the rest - 95 # (shift 1 to the left 256 positions, then negate the number) - 96 # Example: - 97 # 0x 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 012f - 98 # 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0143 - 99 # mask this with: -100 # 0x 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 -101 # 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 -102 # to obtain 0x143 -103 # and then shift the original number to the right -104 # by 256 to obtain 0x12f -105 data_parsed = int.from_bytes(log_receipt["data"], byteorder="big", signed=False) -106 new_expiration_block = data_parsed & ((1 << 256) - 1) -107 old_expiration_block = data_parsed >> 256 -108 -109 return ExtendEntityReturnType( -110 old_expiration_block=old_expiration_block, -111 new_expiration_block=new_expiration_block, -112 entity_key=EntityKey(GenericBytes(log_receipt["topics"][1])), -113 ) +diff --git a/docs/search.js b/docs/search.js index a2c4cce..11413af 100644 --- a/docs/search.js +++ b/docs/search.js @@ -1,6 +1,6 @@ window.pdocSearch = (function(){ /** elasticlunr - http://weixsong.github.io * Copyright (C) 2017 Oliver Nightingale * Copyright (C) 2017 Wei Song * MIT Licensed */!function(){function e(e){if(null===e||"object"!=typeof e)return e;var t=e.constructor();for(var n in e)e.hasOwnProperty(n)&&(t[n]=e[n]);return t}var t=function(e){var n=new t.Index;return n.pipeline.add(t.trimmer,t.stopWordFilter,t.stemmer),e&&e.call(n,n),n};t.version="0.9.5",lunr=t,t.utils={},t.utils.warn=function(e){return function(t){e.console&&console.warn&&console.warn(t)}}(this),t.utils.toString=function(e){return void 0===e||null===e?"":e.toString()},t.EventEmitter=function(){this.events={}},t.EventEmitter.prototype.addListener=function(){var e=Array.prototype.slice.call(arguments),t=e.pop(),n=e;if("function"!=typeof t)throw new TypeError("last argument must be a function");n.forEach(function(e){this.hasHandler(e)||(this.events[e]=[]),this.events[e].push(t)},this)},t.EventEmitter.prototype.removeListener=function(e,t){if(this.hasHandler(e)){var n=this.events[e].indexOf(t);-1!==n&&(this.events[e].splice(n,1),0==this.events[e].length&&delete this.events[e])}},t.EventEmitter.prototype.emit=function(e){if(this.hasHandler(e)){var t=Array.prototype.slice.call(arguments,1);this.events[e].forEach(function(e){e.apply(void 0,t)},this)}},t.EventEmitter.prototype.hasHandler=function(e){return e in this.events},t.tokenizer=function(e){if(!arguments.length||null===e||void 0===e)return[];if(Array.isArray(e)){var n=e.filter(function(e){return null===e||void 0===e?!1:!0});n=n.map(function(e){return t.utils.toString(e).toLowerCase()});var i=[];return n.forEach(function(e){var n=e.split(t.tokenizer.seperator);i=i.concat(n)},this),i}return e.toString().trim().toLowerCase().split(t.tokenizer.seperator)},t.tokenizer.defaultSeperator=/[\s\-]+/,t.tokenizer.seperator=t.tokenizer.defaultSeperator,t.tokenizer.setSeperator=function(e){null!==e&&void 0!==e&&"object"==typeof e&&(t.tokenizer.seperator=e)},t.tokenizer.resetSeperator=function(){t.tokenizer.seperator=t.tokenizer.defaultSeperator},t.tokenizer.getSeperator=function(){return t.tokenizer.seperator},t.Pipeline=function(){this._queue=[]},t.Pipeline.registeredFunctions={},t.Pipeline.registerFunction=function(e,n){n in t.Pipeline.registeredFunctions&&t.utils.warn("Overwriting existing registered function: "+n),e.label=n,t.Pipeline.registeredFunctions[n]=e},t.Pipeline.getRegisteredFunction=function(e){return e in t.Pipeline.registeredFunctions!=!0?null:t.Pipeline.registeredFunctions[e]},t.Pipeline.warnIfFunctionNotRegistered=function(e){var n=e.label&&e.label in this.registeredFunctions;n||t.utils.warn("Function is not registered with pipeline. This may cause problems when serialising the index.\n",e)},t.Pipeline.load=function(e){var n=new t.Pipeline;return e.forEach(function(e){var i=t.Pipeline.getRegisteredFunction(e);if(!i)throw new Error("Cannot load un-registered function: "+e);n.add(i)}),n},t.Pipeline.prototype.add=function(){var e=Array.prototype.slice.call(arguments);e.forEach(function(e){t.Pipeline.warnIfFunctionNotRegistered(e),this._queue.push(e)},this)},t.Pipeline.prototype.after=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var i=this._queue.indexOf(e);if(-1===i)throw new Error("Cannot find existingFn");this._queue.splice(i+1,0,n)},t.Pipeline.prototype.before=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var i=this._queue.indexOf(e);if(-1===i)throw new Error("Cannot find existingFn");this._queue.splice(i,0,n)},t.Pipeline.prototype.remove=function(e){var t=this._queue.indexOf(e);-1!==t&&this._queue.splice(t,1)},t.Pipeline.prototype.run=function(e){for(var t=[],n=e.length,i=this._queue.length,o=0;n>o;o++){for(var r=e[o],s=0;i>s&&(r=this._queue[s](r,o,e),void 0!==r&&null!==r);s++);void 0!==r&&null!==r&&t.push(r)}return t},t.Pipeline.prototype.reset=function(){this._queue=[]},t.Pipeline.prototype.get=function(){return this._queue},t.Pipeline.prototype.toJSON=function(){return this._queue.map(function(e){return t.Pipeline.warnIfFunctionNotRegistered(e),e.label})},t.Index=function(){this._fields=[],this._ref="id",this.pipeline=new t.Pipeline,this.documentStore=new t.DocumentStore,this.index={},this.eventEmitter=new t.EventEmitter,this._idfCache={},this.on("add","remove","update",function(){this._idfCache={}}.bind(this))},t.Index.prototype.on=function(){var e=Array.prototype.slice.call(arguments);return this.eventEmitter.addListener.apply(this.eventEmitter,e)},t.Index.prototype.off=function(e,t){return this.eventEmitter.removeListener(e,t)},t.Index.load=function(e){e.version!==t.version&&t.utils.warn("version mismatch: current "+t.version+" importing "+e.version);var n=new this;n._fields=e.fields,n._ref=e.ref,n.documentStore=t.DocumentStore.load(e.documentStore),n.pipeline=t.Pipeline.load(e.pipeline),n.index={};for(var i in e.index)n.index[i]=t.InvertedIndex.load(e.index[i]);return n},t.Index.prototype.addField=function(e){return this._fields.push(e),this.index[e]=new t.InvertedIndex,this},t.Index.prototype.setRef=function(e){return this._ref=e,this},t.Index.prototype.saveDocument=function(e){return this.documentStore=new t.DocumentStore(e),this},t.Index.prototype.addDoc=function(e,n){if(e){var n=void 0===n?!0:n,i=e[this._ref];this.documentStore.addDoc(i,e),this._fields.forEach(function(n){var o=this.pipeline.run(t.tokenizer(e[n]));this.documentStore.addFieldLength(i,n,o.length);var r={};o.forEach(function(e){e in r?r[e]+=1:r[e]=1},this);for(var s in r){var u=r[s];u=Math.sqrt(u),this.index[n].addToken(s,{ref:i,tf:u})}},this),n&&this.eventEmitter.emit("add",e,this)}},t.Index.prototype.removeDocByRef=function(e){if(e&&this.documentStore.isDocStored()!==!1&&this.documentStore.hasDoc(e)){var t=this.documentStore.getDoc(e);this.removeDoc(t,!1)}},t.Index.prototype.removeDoc=function(e,n){if(e){var n=void 0===n?!0:n,i=e[this._ref];this.documentStore.hasDoc(i)&&(this.documentStore.removeDoc(i),this._fields.forEach(function(n){var o=this.pipeline.run(t.tokenizer(e[n]));o.forEach(function(e){this.index[n].removeToken(e,i)},this)},this),n&&this.eventEmitter.emit("remove",e,this))}},t.Index.prototype.updateDoc=function(e,t){var t=void 0===t?!0:t;this.removeDocByRef(e[this._ref],!1),this.addDoc(e,!1),t&&this.eventEmitter.emit("update",e,this)},t.Index.prototype.idf=function(e,t){var n="@"+t+"/"+e;if(Object.prototype.hasOwnProperty.call(this._idfCache,n))return this._idfCache[n];var i=this.index[t].getDocFreq(e),o=1+Math.log(this.documentStore.length/(i+1));return this._idfCache[n]=o,o},t.Index.prototype.getFields=function(){return this._fields.slice()},t.Index.prototype.search=function(e,n){if(!e)return[];e="string"==typeof e?{any:e}:JSON.parse(JSON.stringify(e));var i=null;null!=n&&(i=JSON.stringify(n));for(var o=new t.Configuration(i,this.getFields()).get(),r={},s=Object.keys(e),u=0;u85def parse_legacy_btl_extended_log(log_receipt: LogReceipt) -> ExtendEntityReturnType: + 86 """ + 87 For legacy extend ABI types, the type signature in the ABI does + 88 not correspond to the actual data returned, so we need + 89 to parse the data ourselves. + 90 """ + 91 # pylint: disable=line-too-long + 92 # Take the first 64 bytes by masking the rest + 93 # (shift 1 to the left 256 positions, then negate the number) + 94 # Example: + 95 # 0x 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 012f + 96 # 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0143 + 97 # mask this with: + 98 # 0x 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 + 99 # 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 +100 # to obtain 0x143 +101 # and then shift the original number to the right +102 # by 256 to obtain 0x12f +103 data_parsed = int.from_bytes(log_receipt["data"], byteorder="big", signed=False) +104 new_expiration_block = data_parsed & ((1 << 256) - 1) +105 old_expiration_block = data_parsed >> 256 +106 +107 return ExtendEntityReturnType( +108 old_expiration_block=old_expiration_block, +109 new_expiration_block=new_expiration_block, +110 entity_key=EntityKey(GenericBytes(log_receipt["topics"][1])), +111 )0&&t.push(e);for(var i in n)"docs"!==i&&"df"!==i&&this.expandToken(e+i,t,n[i]);return t},t.InvertedIndex.prototype.toJSON=function(){return{root:this.root}},t.Configuration=function(e,n){var e=e||"";if(void 0==n||null==n)throw new Error("fields should not be null");this.config={};var i;try{i=JSON.parse(e),this.buildUserConfig(i,n)}catch(o){t.utils.warn("user configuration parse failed, will use default configuration"),this.buildDefaultConfig(n)}},t.Configuration.prototype.buildDefaultConfig=function(e){this.reset(),e.forEach(function(e){this.config[e]={boost:1,bool:"OR",expand:!1}},this)},t.Configuration.prototype.buildUserConfig=function(e,n){var i="OR",o=!1;if(this.reset(),"bool"in e&&(i=e.bool||i),"expand"in e&&(o=e.expand||o),"fields"in e)for(var r in e.fields)if(n.indexOf(r)>-1){var s=e.fields[r],u=o;void 0!=s.expand&&(u=s.expand),this.config[r]={boost:s.boost||0===s.boost?s.boost:1,bool:s.bool||i,expand:u}}else t.utils.warn("field name in user configuration not found in index instance fields");else this.addAllFields2UserConfig(i,o,n)},t.Configuration.prototype.addAllFields2UserConfig=function(e,t,n){n.forEach(function(n){this.config[n]={boost:1,bool:e,expand:t}},this)},t.Configuration.prototype.get=function(){return this.config},t.Configuration.prototype.reset=function(){this.config={}},lunr.SortedSet=function(){this.length=0,this.elements=[]},lunr.SortedSet.load=function(e){var t=new this;return t.elements=e,t.length=e.length,t},lunr.SortedSet.prototype.add=function(){var e,t;for(e=0;e 1;){if(r===e)return o;e>r&&(t=o),r>e&&(n=o),i=n-t,o=t+Math.floor(i/2),r=this.elements[o]}return r===e?o:-1},lunr.SortedSet.prototype.locationFor=function(e){for(var t=0,n=this.elements.length,i=n-t,o=t+Math.floor(i/2),r=this.elements[o];i>1;)e>r&&(t=o),r>e&&(n=o),i=n-t,o=t+Math.floor(i/2),r=this.elements[o];return r>e?o:e>r?o+1:void 0},lunr.SortedSet.prototype.intersect=function(e){for(var t=new lunr.SortedSet,n=0,i=0,o=this.length,r=e.length,s=this.elements,u=e.elements;;){if(n>o-1||i>r-1)break;s[n]!==u[i]?s[n]u[i]&&i++:(t.add(s[n]),n++,i++)}return t},lunr.SortedSet.prototype.clone=function(){var e=new lunr.SortedSet;return e.elements=this.toArray(),e.length=e.elements.length,e},lunr.SortedSet.prototype.union=function(e){var t,n,i;this.length>=e.length?(t=this,n=e):(t=e,n=this),i=t.clone();for(var o=0,r=n.toArray();o GolemBase Python SDK\n"}, {"fullname": "golem_base_sdk.GolemBaseClient", "modulename": "golem_base_sdk", "qualname": "GolemBaseClient", "kind": "class", "doc": " The Golem Base client used to interact with Golem Base.\nMany useful methods are implemented directly on this type, while more\ngeneric ethereum methods can be accessed through the underlying\nweb3 client that you can access with the\n
\n"}, {"fullname": "golem_base_sdk.GolemBaseClient.__init__", "modulename": "golem_base_sdk", "qualname": "GolemBaseClient.__init__", "kind": "function", "doc": "\n", "signature": "(\trpc_url: str,\tws_client: web3.main.AsyncWeb3,\tprivate_key: Sequence[bytes])"}, {"fullname": "golem_base_sdk.GolemBaseClient.create", "modulename": "golem_base_sdk", "qualname": "GolemBaseClient.create", "kind": "function", "doc": "GolemBaseClient.http_client()\nmethod.Static method to create a
\n", "signature": "(\trpc_url: str,\tws_url: str,\tprivate_key: Sequence[bytes]) -> golem_base_sdk.GolemBaseClient:", "funcdef": "async def"}, {"fullname": "golem_base_sdk.GolemBaseClient.account", "modulename": "golem_base_sdk", "qualname": "GolemBaseClient.account", "kind": "variable", "doc": "\n"}, {"fullname": "golem_base_sdk.GolemBaseClient.golem_base_contract", "modulename": "golem_base_sdk", "qualname": "GolemBaseClient.golem_base_contract", "kind": "variable", "doc": "\n"}, {"fullname": "golem_base_sdk.GolemBaseClient.http_client", "modulename": "golem_base_sdk", "qualname": "GolemBaseClient.http_client", "kind": "function", "doc": "GolemBaseClientinstance,\nthis is the preferred method to create an instance.Get the underlying web3 http client
\n", "signature": "(self):", "funcdef": "def"}, {"fullname": "golem_base_sdk.GolemBaseClient.ws_client", "modulename": "golem_base_sdk", "qualname": "GolemBaseClient.ws_client", "kind": "function", "doc": "Get the underlying web3 websocket client
\n", "signature": "(self) -> web3.main.AsyncWeb3:", "funcdef": "def"}, {"fullname": "golem_base_sdk.GolemBaseClient.is_connected", "modulename": "golem_base_sdk", "qualname": "GolemBaseClient.is_connected", "kind": "function", "doc": "Check whether the client's underlying http client is connected
\n", "signature": "(self) -> bool:", "funcdef": "async def"}, {"fullname": "golem_base_sdk.GolemBaseClient.disconnect", "modulename": "golem_base_sdk", "qualname": "GolemBaseClient.disconnect", "kind": "function", "doc": "Disconnect both the underlying http and ws clients and\nunsubscribe from all subscriptions
\n", "signature": "(self) -> None:", "funcdef": "async def"}, {"fullname": "golem_base_sdk.GolemBaseClient.get_account_address", "modulename": "golem_base_sdk", "qualname": "GolemBaseClient.get_account_address", "kind": "function", "doc": "Get the address associated with the private key that this client\nwas created with
\n", "signature": "(self) -> eth_typing.evm.ChecksumAddress:", "funcdef": "def"}, {"fullname": "golem_base_sdk.GolemBaseClient.get_storage_value", "modulename": "golem_base_sdk", "qualname": "GolemBaseClient.get_storage_value", "kind": "function", "doc": "Get the storage value stored in the given entity
\n", "signature": "(self, entity_key: golem_base_sdk.types.EntityKey) -> bytes:", "funcdef": "async def"}, {"fullname": "golem_base_sdk.GolemBaseClient.get_entity_metadata", "modulename": "golem_base_sdk", "qualname": "GolemBaseClient.get_entity_metadata", "kind": "function", "doc": "Get the metadata of the given entity
\n", "signature": "(\tself,\tentity_key: golem_base_sdk.types.EntityKey) -> golem_base_sdk.types.EntityMetadata:", "funcdef": "async def"}, {"fullname": "golem_base_sdk.GolemBaseClient.get_entities_to_expire_at_block", "modulename": "golem_base_sdk", "qualname": "GolemBaseClient.get_entities_to_expire_at_block", "kind": "function", "doc": "Get all entities that will expire at the given block
\n", "signature": "(self, block_number: int) -> Iterable[golem_base_sdk.types.EntityKey]:", "funcdef": "async def"}, {"fullname": "golem_base_sdk.GolemBaseClient.get_entity_count", "modulename": "golem_base_sdk", "qualname": "GolemBaseClient.get_entity_count", "kind": "function", "doc": "Get the total entity count in Golem Base
\n", "signature": "(self) -> int:", "funcdef": "async def"}, {"fullname": "golem_base_sdk.GolemBaseClient.get_all_entity_keys", "modulename": "golem_base_sdk", "qualname": "GolemBaseClient.get_all_entity_keys", "kind": "function", "doc": "Get all entity keys in Golem Base
\n", "signature": "(self) -> Sequence[golem_base_sdk.types.EntityKey]:", "funcdef": "async def"}, {"fullname": "golem_base_sdk.GolemBaseClient.get_entities_of_owner", "modulename": "golem_base_sdk", "qualname": "GolemBaseClient.get_entities_of_owner", "kind": "function", "doc": "Get all the entities owned by the given address
\n", "signature": "(\tself,\towner: golem_base_sdk.types.Address) -> Sequence[golem_base_sdk.types.EntityKey]:", "funcdef": "async def"}, {"fullname": "golem_base_sdk.GolemBaseClient.query_entities", "modulename": "golem_base_sdk", "qualname": "GolemBaseClient.query_entities", "kind": "function", "doc": "Get all entities that satisfy the given Golem Base query
\n", "signature": "(self, query: str) -> Sequence[golem_base_sdk.types.QueryEntitiesResult]:", "funcdef": "async def"}, {"fullname": "golem_base_sdk.GolemBaseClient.create_entities", "modulename": "golem_base_sdk", "qualname": "GolemBaseClient.create_entities", "kind": "function", "doc": "Create entities in Golem Base
\n", "signature": "(\tself,\tcreates: Sequence[golem_base_sdk.types.GolemBaseCreate]) -> Iterable[golem_base_sdk.types.CreateEntityReturnType]:", "funcdef": "async def"}, {"fullname": "golem_base_sdk.GolemBaseClient.update_entities", "modulename": "golem_base_sdk", "qualname": "GolemBaseClient.update_entities", "kind": "function", "doc": "Update entities in Golem Base
\n", "signature": "(\tself,\tupdates: Sequence[golem_base_sdk.types.GolemBaseUpdate]) -> Iterable[golem_base_sdk.types.UpdateEntityReturnType]:", "funcdef": "async def"}, {"fullname": "golem_base_sdk.GolemBaseClient.delete_entities", "modulename": "golem_base_sdk", "qualname": "GolemBaseClient.delete_entities", "kind": "function", "doc": "Delete entities from Golem Base
\n", "signature": "(\tself,\tdeletes: Sequence[golem_base_sdk.types.GolemBaseDelete]) -> Iterable[golem_base_sdk.types.EntityKey]:", "funcdef": "async def"}, {"fullname": "golem_base_sdk.GolemBaseClient.extend_entities", "modulename": "golem_base_sdk", "qualname": "GolemBaseClient.extend_entities", "kind": "function", "doc": "Extend the BTL of entities in Golem Base
\n", "signature": "(\tself,\textensions: Sequence[golem_base_sdk.types.GolemBaseExtend]) -> Iterable[golem_base_sdk.types.ExtendEntityReturnType]:", "funcdef": "async def"}, {"fullname": "golem_base_sdk.GolemBaseClient.send_transaction", "modulename": "golem_base_sdk", "qualname": "GolemBaseClient.send_transaction", "kind": "function", "doc": "Send a generic transaction to Golem Base.\nThis transaction can contain multiple create, update, delete and\nextend operations
\n", "signature": "(\tself,\tcreates: Optional[Sequence[golem_base_sdk.types.GolemBaseCreate]] = None,\tupdates: Optional[Sequence[golem_base_sdk.types.GolemBaseUpdate]] = None,\tdeletes: Optional[Sequence[golem_base_sdk.types.GolemBaseDelete]] = None,\textensions: Optional[Sequence[golem_base_sdk.types.GolemBaseExtend]] = None) -> golem_base_sdk.types.GolemBaseTransactionReceipt:", "funcdef": "async def"}, {"fullname": "golem_base_sdk.GolemBaseClient.watch_logs", "modulename": "golem_base_sdk", "qualname": "GolemBaseClient.watch_logs", "kind": "function", "doc": "Subscribe to events on Golem Base.\nYou can pass in four different callbacks, and the right one will\nbe invoked for every create, update, delete, and extend operation.
\n", "signature": "(\tself,\tcreate_callback: Callable[[golem_base_sdk.types.CreateEntityReturnType], NoneType],\tupdate_callback: Callable[[golem_base_sdk.types.UpdateEntityReturnType], NoneType],\tdelete_callback: Callable[[golem_base_sdk.types.EntityKey], NoneType],\textend_callback: Callable[[golem_base_sdk.types.ExtendEntityReturnType], NoneType]) -> None:", "funcdef": "async def"}, {"fullname": "golem_base_sdk.constants", "modulename": "golem_base_sdk.constants", "kind": "module", "doc": "Constants used in the Golem Base SDK
\n"}, {"fullname": "golem_base_sdk.constants.STORAGE_ADDRESS", "modulename": "golem_base_sdk.constants", "qualname": "STORAGE_ADDRESS", "kind": "variable", "doc": "\n", "annotation": ": golem_base_sdk.types.Address", "default_value": "GenericBytes(0x0000000000000000000000000000000060138453)"}, {"fullname": "golem_base_sdk.constants.GOLEM_BASE_ABI", "modulename": "golem_base_sdk.constants", "qualname": "GOLEM_BASE_ABI", "kind": "variable", "doc": "\n", "default_value": "[{'anonymous': False, 'inputs': [{'indexed': True, 'name': 'entityKey', 'type': 'uint256'}, {'indexed': False, 'name': 'expirationBlock', 'type': 'uint256'}], 'name': 'GolemBaseStorageEntityCreated', 'type': 'event'}, {'anonymous': False, 'inputs': [{'indexed': True, 'name': 'entityKey', 'type': 'uint256'}, {'indexed': False, 'name': 'expirationBlock', 'type': 'uint256'}], 'name': 'GolemBaseStorageEntityUpdated', 'type': 'event'}, {'anonymous': False, 'inputs': [{'indexed': True, 'name': 'entityKey', 'type': 'uint256'}], 'name': 'GolemBaseStorageEntityDeleted', 'type': 'event'}, {'anonymous': False, 'inputs': [{'indexed': True, 'name': 'entityKey', 'type': 'uint256'}, {'indexed': False, 'name': 'oldExpirationBlock', 'type': 'uint256'}, {'indexed': False, 'name': 'newExpirationBlock', 'type': 'uint256'}], 'name': 'GolemBaseStorageEntityBTLExtended', 'type': 'event'}, {'anonymous': False, 'inputs': [{'indexed': True, 'name': 'entityKey', 'type': 'uint256'}, {'indexed': False, 'name': 'expirationBlock', 'type': 'uint256'}], 'name': 'GolemBaseStorageEntityBTLExptended', 'type': 'event'}, {'anonymous': False, 'inputs': [{'indexed': True, 'name': 'entityKey', 'type': 'uint256'}, {'indexed': False, 'name': 'expirationBlock', 'type': 'uint256'}], 'name': 'GolemBaseStorageEntityTTLExptended', 'type': 'event'}]"}, {"fullname": "golem_base_sdk.types", "modulename": "golem_base_sdk.types", "kind": "module", "doc": "Golem Base SDK Types
\n"}, {"fullname": "golem_base_sdk.types.GenericBytes", "modulename": "golem_base_sdk.types", "qualname": "GenericBytes", "kind": "class", "doc": "Class to represent bytes that can be converted to more meaningful types
\n"}, {"fullname": "golem_base_sdk.types.GenericBytes.__init__", "modulename": "golem_base_sdk.types", "qualname": "GenericBytes.__init__", "kind": "function", "doc": "\n", "signature": "(generic_bytes: bytes)"}, {"fullname": "golem_base_sdk.types.GenericBytes.generic_bytes", "modulename": "golem_base_sdk.types", "qualname": "GenericBytes.generic_bytes", "kind": "variable", "doc": "\n", "annotation": ": bytes"}, {"fullname": "golem_base_sdk.types.GenericBytes.as_hex_string", "modulename": "golem_base_sdk.types", "qualname": "GenericBytes.as_hex_string", "kind": "function", "doc": "Convert this instance to a hexadecimal string
\n", "signature": "(self) -> eth_typing.encoding.HexStr:", "funcdef": "def"}, {"fullname": "golem_base_sdk.types.GenericBytes.as_address", "modulename": "golem_base_sdk.types", "qualname": "GenericBytes.as_address", "kind": "function", "doc": "Convert this instance to a
\n", "signature": "(self) -> eth_typing.evm.ChecksumAddress:", "funcdef": "def"}, {"fullname": "golem_base_sdk.types.GenericBytes.from_hex_string", "modulename": "golem_base_sdk.types", "qualname": "GenericBytes.from_hex_string", "kind": "function", "doc": "eth_typing.ChecksumAddressCreate a
\n", "signature": "(hexstr: str) -> golem_base_sdk.types.GenericBytes:", "funcdef": "def"}, {"fullname": "golem_base_sdk.types.EntityKey", "modulename": "golem_base_sdk.types", "qualname": "EntityKey", "kind": "variable", "doc": "\n", "default_value": "golem_base_sdk.types.EntityKey"}, {"fullname": "golem_base_sdk.types.Address", "modulename": "golem_base_sdk.types", "qualname": "Address", "kind": "variable", "doc": "\n", "default_value": "golem_base_sdk.types.Address"}, {"fullname": "golem_base_sdk.types.Annotation", "modulename": "golem_base_sdk.types", "qualname": "Annotation", "kind": "class", "doc": "GenericBytesinstance from a hexadecimal stringClass to represent generic annotations
\n", "bases": "typing.Generic[V]"}, {"fullname": "golem_base_sdk.types.Annotation.__init__", "modulename": "golem_base_sdk.types", "qualname": "Annotation.__init__", "kind": "function", "doc": "\n", "signature": "(key: str, value: V)"}, {"fullname": "golem_base_sdk.types.Annotation.key", "modulename": "golem_base_sdk.types", "qualname": "Annotation.key", "kind": "variable", "doc": "\n", "annotation": ": str"}, {"fullname": "golem_base_sdk.types.Annotation.value", "modulename": "golem_base_sdk.types", "qualname": "Annotation.value", "kind": "variable", "doc": "\n", "annotation": ": V"}, {"fullname": "golem_base_sdk.types.GolemBaseCreate", "modulename": "golem_base_sdk.types", "qualname": "GolemBaseCreate", "kind": "class", "doc": "Class to represent a create operation in Golem Base
\n"}, {"fullname": "golem_base_sdk.types.GolemBaseCreate.__init__", "modulename": "golem_base_sdk.types", "qualname": "GolemBaseCreate.__init__", "kind": "function", "doc": "\n", "signature": "(\tdata: bytes,\tttl: int,\tstring_annotations: Sequence[golem_base_sdk.types.Annotation[str]],\tnumeric_annotations: Sequence[golem_base_sdk.types.Annotation[int]])"}, {"fullname": "golem_base_sdk.types.GolemBaseCreate.data", "modulename": "golem_base_sdk.types", "qualname": "GolemBaseCreate.data", "kind": "variable", "doc": "\n", "annotation": ": bytes"}, {"fullname": "golem_base_sdk.types.GolemBaseCreate.ttl", "modulename": "golem_base_sdk.types", "qualname": "GolemBaseCreate.ttl", "kind": "variable", "doc": "\n", "annotation": ": int"}, {"fullname": "golem_base_sdk.types.GolemBaseCreate.string_annotations", "modulename": "golem_base_sdk.types", "qualname": "GolemBaseCreate.string_annotations", "kind": "variable", "doc": "\n", "annotation": ": Sequence[golem_base_sdk.types.Annotation[str]]"}, {"fullname": "golem_base_sdk.types.GolemBaseCreate.numeric_annotations", "modulename": "golem_base_sdk.types", "qualname": "GolemBaseCreate.numeric_annotations", "kind": "variable", "doc": "\n", "annotation": ": Sequence[golem_base_sdk.types.Annotation[int]]"}, {"fullname": "golem_base_sdk.types.GolemBaseUpdate", "modulename": "golem_base_sdk.types", "qualname": "GolemBaseUpdate", "kind": "class", "doc": "Class to represent an update operation in Golem Base
\n"}, {"fullname": "golem_base_sdk.types.GolemBaseUpdate.__init__", "modulename": "golem_base_sdk.types", "qualname": "GolemBaseUpdate.__init__", "kind": "function", "doc": "\n", "signature": "(\tentity_key: golem_base_sdk.types.EntityKey,\tdata: bytes,\tttl: int,\tstring_annotations: Sequence[golem_base_sdk.types.Annotation[str]],\tnumeric_annotations: Sequence[golem_base_sdk.types.Annotation[int]])"}, {"fullname": "golem_base_sdk.types.GolemBaseUpdate.entity_key", "modulename": "golem_base_sdk.types", "qualname": "GolemBaseUpdate.entity_key", "kind": "variable", "doc": "\n", "annotation": ": golem_base_sdk.types.EntityKey"}, {"fullname": "golem_base_sdk.types.GolemBaseUpdate.data", "modulename": "golem_base_sdk.types", "qualname": "GolemBaseUpdate.data", "kind": "variable", "doc": "\n", "annotation": ": bytes"}, {"fullname": "golem_base_sdk.types.GolemBaseUpdate.ttl", "modulename": "golem_base_sdk.types", "qualname": "GolemBaseUpdate.ttl", "kind": "variable", "doc": "\n", "annotation": ": int"}, {"fullname": "golem_base_sdk.types.GolemBaseUpdate.string_annotations", "modulename": "golem_base_sdk.types", "qualname": "GolemBaseUpdate.string_annotations", "kind": "variable", "doc": "\n", "annotation": ": Sequence[golem_base_sdk.types.Annotation[str]]"}, {"fullname": "golem_base_sdk.types.GolemBaseUpdate.numeric_annotations", "modulename": "golem_base_sdk.types", "qualname": "GolemBaseUpdate.numeric_annotations", "kind": "variable", "doc": "\n", "annotation": ": Sequence[golem_base_sdk.types.Annotation[int]]"}, {"fullname": "golem_base_sdk.types.GolemBaseDelete", "modulename": "golem_base_sdk.types", "qualname": "GolemBaseDelete", "kind": "class", "doc": "Class to represent a delete operation in Golem Base
\n"}, {"fullname": "golem_base_sdk.types.GolemBaseDelete.__init__", "modulename": "golem_base_sdk.types", "qualname": "GolemBaseDelete.__init__", "kind": "function", "doc": "\n", "signature": "(entity_key: golem_base_sdk.types.EntityKey)"}, {"fullname": "golem_base_sdk.types.GolemBaseDelete.entity_key", "modulename": "golem_base_sdk.types", "qualname": "GolemBaseDelete.entity_key", "kind": "variable", "doc": "\n", "annotation": ": golem_base_sdk.types.EntityKey"}, {"fullname": "golem_base_sdk.types.GolemBaseExtend", "modulename": "golem_base_sdk.types", "qualname": "GolemBaseExtend", "kind": "class", "doc": "Class to represent a BTL extend operation in Golem Base
\n"}, {"fullname": "golem_base_sdk.types.GolemBaseExtend.__init__", "modulename": "golem_base_sdk.types", "qualname": "GolemBaseExtend.__init__", "kind": "function", "doc": "\n", "signature": "(entity_key: golem_base_sdk.types.EntityKey, number_of_blocks: int)"}, {"fullname": "golem_base_sdk.types.GolemBaseExtend.entity_key", "modulename": "golem_base_sdk.types", "qualname": "GolemBaseExtend.entity_key", "kind": "variable", "doc": "\n", "annotation": ": golem_base_sdk.types.EntityKey"}, {"fullname": "golem_base_sdk.types.GolemBaseExtend.number_of_blocks", "modulename": "golem_base_sdk.types", "qualname": "GolemBaseExtend.number_of_blocks", "kind": "variable", "doc": "\n", "annotation": ": int"}, {"fullname": "golem_base_sdk.types.GolemBaseTransaction", "modulename": "golem_base_sdk.types", "qualname": "GolemBaseTransaction", "kind": "class", "doc": "Class to represent a transaction in Golem Base.\nA transaction consist of one or more\n
\n"}, {"fullname": "golem_base_sdk.types.GolemBaseTransaction.__init__", "modulename": "golem_base_sdk.types", "qualname": "GolemBaseTransaction.__init__", "kind": "function", "doc": "\n", "signature": "(\tcreates: Optional[Sequence[golem_base_sdk.types.GolemBaseCreate]] = None,\tupdates: Optional[Sequence[golem_base_sdk.types.GolemBaseUpdate]] = None,\tdeletes: Optional[Sequence[golem_base_sdk.types.GolemBaseDelete]] = None,\textensions: Optional[Sequence[golem_base_sdk.types.GolemBaseExtend]] = None)"}, {"fullname": "golem_base_sdk.types.GolemBaseTransaction.creates", "modulename": "golem_base_sdk.types", "qualname": "GolemBaseTransaction.creates", "kind": "variable", "doc": "\n", "annotation": ": Sequence[golem_base_sdk.types.GolemBaseCreate]"}, {"fullname": "golem_base_sdk.types.GolemBaseTransaction.updates", "modulename": "golem_base_sdk.types", "qualname": "GolemBaseTransaction.updates", "kind": "variable", "doc": "\n", "annotation": ": Sequence[golem_base_sdk.types.GolemBaseUpdate]"}, {"fullname": "golem_base_sdk.types.GolemBaseTransaction.deletes", "modulename": "golem_base_sdk.types", "qualname": "GolemBaseTransaction.deletes", "kind": "variable", "doc": "\n", "annotation": ": Sequence[golem_base_sdk.types.GolemBaseDelete]"}, {"fullname": "golem_base_sdk.types.GolemBaseTransaction.extensions", "modulename": "golem_base_sdk.types", "qualname": "GolemBaseTransaction.extensions", "kind": "variable", "doc": "\n", "annotation": ": Sequence[golem_base_sdk.types.GolemBaseExtend]"}, {"fullname": "golem_base_sdk.types.CreateEntityReturnType", "modulename": "golem_base_sdk.types", "qualname": "CreateEntityReturnType", "kind": "class", "doc": "GolemBaseCreate,\nGolemBaseUpdate,\nGolemBaseDeleteand\nGolemBaseExtend\noperations.The return type of a Golem Base create operation
\n"}, {"fullname": "golem_base_sdk.types.CreateEntityReturnType.__init__", "modulename": "golem_base_sdk.types", "qualname": "CreateEntityReturnType.__init__", "kind": "function", "doc": "\n", "signature": "(expiration_block: int, entity_key: golem_base_sdk.types.EntityKey)"}, {"fullname": "golem_base_sdk.types.CreateEntityReturnType.expiration_block", "modulename": "golem_base_sdk.types", "qualname": "CreateEntityReturnType.expiration_block", "kind": "variable", "doc": "\n", "annotation": ": int"}, {"fullname": "golem_base_sdk.types.CreateEntityReturnType.entity_key", "modulename": "golem_base_sdk.types", "qualname": "CreateEntityReturnType.entity_key", "kind": "variable", "doc": "\n", "annotation": ": golem_base_sdk.types.EntityKey"}, {"fullname": "golem_base_sdk.types.UpdateEntityReturnType", "modulename": "golem_base_sdk.types", "qualname": "UpdateEntityReturnType", "kind": "class", "doc": "The return type of a Golem Base update operation
\n"}, {"fullname": "golem_base_sdk.types.UpdateEntityReturnType.__init__", "modulename": "golem_base_sdk.types", "qualname": "UpdateEntityReturnType.__init__", "kind": "function", "doc": "\n", "signature": "(expiration_block: int, entity_key: golem_base_sdk.types.EntityKey)"}, {"fullname": "golem_base_sdk.types.UpdateEntityReturnType.expiration_block", "modulename": "golem_base_sdk.types", "qualname": "UpdateEntityReturnType.expiration_block", "kind": "variable", "doc": "\n", "annotation": ": int"}, {"fullname": "golem_base_sdk.types.UpdateEntityReturnType.entity_key", "modulename": "golem_base_sdk.types", "qualname": "UpdateEntityReturnType.entity_key", "kind": "variable", "doc": "\n", "annotation": ": golem_base_sdk.types.EntityKey"}, {"fullname": "golem_base_sdk.types.ExtendEntityReturnType", "modulename": "golem_base_sdk.types", "qualname": "ExtendEntityReturnType", "kind": "class", "doc": "The return type of a Golem Base extend operation
\n"}, {"fullname": "golem_base_sdk.types.ExtendEntityReturnType.__init__", "modulename": "golem_base_sdk.types", "qualname": "ExtendEntityReturnType.__init__", "kind": "function", "doc": "\n", "signature": "(\told_expiration_block: int,\tnew_expiration_block: int,\tentity_key: golem_base_sdk.types.EntityKey)"}, {"fullname": "golem_base_sdk.types.ExtendEntityReturnType.old_expiration_block", "modulename": "golem_base_sdk.types", "qualname": "ExtendEntityReturnType.old_expiration_block", "kind": "variable", "doc": "\n", "annotation": ": int"}, {"fullname": "golem_base_sdk.types.ExtendEntityReturnType.new_expiration_block", "modulename": "golem_base_sdk.types", "qualname": "ExtendEntityReturnType.new_expiration_block", "kind": "variable", "doc": "\n", "annotation": ": int"}, {"fullname": "golem_base_sdk.types.ExtendEntityReturnType.entity_key", "modulename": "golem_base_sdk.types", "qualname": "ExtendEntityReturnType.entity_key", "kind": "variable", "doc": "\n", "annotation": ": golem_base_sdk.types.EntityKey"}, {"fullname": "golem_base_sdk.types.GolemBaseTransactionReceipt", "modulename": "golem_base_sdk.types", "qualname": "GolemBaseTransactionReceipt", "kind": "class", "doc": "The return type of a Golem Base transaction
\n"}, {"fullname": "golem_base_sdk.types.GolemBaseTransactionReceipt.__init__", "modulename": "golem_base_sdk.types", "qualname": "GolemBaseTransactionReceipt.__init__", "kind": "function", "doc": "\n", "signature": "(\tcreates: Sequence[golem_base_sdk.types.CreateEntityReturnType],\tupdates: Sequence[golem_base_sdk.types.UpdateEntityReturnType],\textensions: Sequence[golem_base_sdk.types.ExtendEntityReturnType],\tdeletes: Sequence[golem_base_sdk.types.EntityKey])"}, {"fullname": "golem_base_sdk.types.GolemBaseTransactionReceipt.creates", "modulename": "golem_base_sdk.types", "qualname": "GolemBaseTransactionReceipt.creates", "kind": "variable", "doc": "\n", "annotation": ": Sequence[golem_base_sdk.types.CreateEntityReturnType]"}, {"fullname": "golem_base_sdk.types.GolemBaseTransactionReceipt.updates", "modulename": "golem_base_sdk.types", "qualname": "GolemBaseTransactionReceipt.updates", "kind": "variable", "doc": "\n", "annotation": ": Sequence[golem_base_sdk.types.UpdateEntityReturnType]"}, {"fullname": "golem_base_sdk.types.GolemBaseTransactionReceipt.extensions", "modulename": "golem_base_sdk.types", "qualname": "GolemBaseTransactionReceipt.extensions", "kind": "variable", "doc": "\n", "annotation": ": Sequence[golem_base_sdk.types.ExtendEntityReturnType]"}, {"fullname": "golem_base_sdk.types.GolemBaseTransactionReceipt.deletes", "modulename": "golem_base_sdk.types", "qualname": "GolemBaseTransactionReceipt.deletes", "kind": "variable", "doc": "\n", "annotation": ": Sequence[golem_base_sdk.types.EntityKey]"}, {"fullname": "golem_base_sdk.types.EntityMetadata", "modulename": "golem_base_sdk.types", "qualname": "EntityMetadata", "kind": "class", "doc": "A class representing entity metadata
\n"}, {"fullname": "golem_base_sdk.types.EntityMetadata.__init__", "modulename": "golem_base_sdk.types", "qualname": "EntityMetadata.__init__", "kind": "function", "doc": "\n", "signature": "(\tentity_key: golem_base_sdk.types.EntityKey,\towner: golem_base_sdk.types.Address,\texpires_at_block: int,\tstring_annotations: Sequence[golem_base_sdk.types.Annotation[str]],\tnumeric_annotations: Sequence[golem_base_sdk.types.Annotation[int]])"}, {"fullname": "golem_base_sdk.types.EntityMetadata.entity_key", "modulename": "golem_base_sdk.types", "qualname": "EntityMetadata.entity_key", "kind": "variable", "doc": "\n", "annotation": ": golem_base_sdk.types.EntityKey"}, {"fullname": "golem_base_sdk.types.EntityMetadata.owner", "modulename": "golem_base_sdk.types", "qualname": "EntityMetadata.owner", "kind": "variable", "doc": "\n", "annotation": ": golem_base_sdk.types.Address"}, {"fullname": "golem_base_sdk.types.EntityMetadata.expires_at_block", "modulename": "golem_base_sdk.types", "qualname": "EntityMetadata.expires_at_block", "kind": "variable", "doc": "\n", "annotation": ": int"}, {"fullname": "golem_base_sdk.types.EntityMetadata.string_annotations", "modulename": "golem_base_sdk.types", "qualname": "EntityMetadata.string_annotations", "kind": "variable", "doc": "\n", "annotation": ": Sequence[golem_base_sdk.types.Annotation[str]]"}, {"fullname": "golem_base_sdk.types.EntityMetadata.numeric_annotations", "modulename": "golem_base_sdk.types", "qualname": "EntityMetadata.numeric_annotations", "kind": "variable", "doc": "\n", "annotation": ": Sequence[golem_base_sdk.types.Annotation[int]]"}, {"fullname": "golem_base_sdk.types.QueryEntitiesResult", "modulename": "golem_base_sdk.types", "qualname": "QueryEntitiesResult", "kind": "class", "doc": "A class representing the return value of a Golem Base query
\n"}, {"fullname": "golem_base_sdk.types.QueryEntitiesResult.__init__", "modulename": "golem_base_sdk.types", "qualname": "QueryEntitiesResult.__init__", "kind": "function", "doc": "\n", "signature": "(entity_key: golem_base_sdk.types.EntityKey, storage_value: bytes)"}, {"fullname": "golem_base_sdk.types.QueryEntitiesResult.entity_key", "modulename": "golem_base_sdk.types", "qualname": "QueryEntitiesResult.entity_key", "kind": "variable", "doc": "\n", "annotation": ": golem_base_sdk.types.EntityKey"}, {"fullname": "golem_base_sdk.types.QueryEntitiesResult.storage_value", "modulename": "golem_base_sdk.types", "qualname": "QueryEntitiesResult.storage_value", "kind": "variable", "doc": "\n", "annotation": ": bytes"}, {"fullname": "golem_base_sdk.utils", "modulename": "golem_base_sdk.utils", "kind": "module", "doc": "Utility methods
\n"}, {"fullname": "golem_base_sdk.utils.rlp_encode_transaction", "modulename": "golem_base_sdk.utils", "qualname": "rlp_encode_transaction", "kind": "function", "doc": "Encode a Golem Base transaction in RLP
\n", "signature": "(tx: golem_base_sdk.types.GolemBaseTransaction) -> bytes:", "funcdef": "def"}, {"fullname": "golem_base_sdk.utils.parse_legacy_btl_extended_log", "modulename": "golem_base_sdk.utils", "qualname": "parse_legacy_btl_extended_log", "kind": "function", "doc": "For legacy extend ABI types, the type signature in the ABI does\nnot correspond to the actual data returned, so we need\nto parse the data ourselves.
\n", "signature": "(\tlog_receipt: web3.types.LogReceipt) -> golem_base_sdk.types.ExtendEntityReturnType:", "funcdef": "def"}]; + /** pdoc search index */const docs = [{"fullname": "golem_base_sdk", "modulename": "golem_base_sdk", "kind": "module", "doc": "GolemBase Python SDK
\n"}, {"fullname": "golem_base_sdk.GolemBaseClient", "modulename": "golem_base_sdk", "qualname": "GolemBaseClient", "kind": "class", "doc": "The Golem Base client used to interact with Golem Base.\nMany useful methods are implemented directly on this type, while more\ngeneric ethereum methods can be accessed through the underlying\nweb3 client that you can access with the\n
\n"}, {"fullname": "golem_base_sdk.GolemBaseClient.__init__", "modulename": "golem_base_sdk", "qualname": "GolemBaseClient.__init__", "kind": "function", "doc": "\n", "signature": "(rpc_url: str, ws_client: web3.main.AsyncWeb3, private_key: bytes)"}, {"fullname": "golem_base_sdk.GolemBaseClient.create", "modulename": "golem_base_sdk", "qualname": "GolemBaseClient.create", "kind": "function", "doc": "GolemBaseClient.http_client()\nmethod.Static method to create a
\n", "signature": "(\trpc_url: str,\tws_url: str,\tprivate_key: bytes) -> golem_base_sdk.GolemBaseClient:", "funcdef": "async def"}, {"fullname": "golem_base_sdk.GolemBaseClient.account", "modulename": "golem_base_sdk", "qualname": "GolemBaseClient.account", "kind": "variable", "doc": "\n"}, {"fullname": "golem_base_sdk.GolemBaseClient.golem_base_contract", "modulename": "golem_base_sdk", "qualname": "GolemBaseClient.golem_base_contract", "kind": "variable", "doc": "\n"}, {"fullname": "golem_base_sdk.GolemBaseClient.http_client", "modulename": "golem_base_sdk", "qualname": "GolemBaseClient.http_client", "kind": "function", "doc": "GolemBaseClientinstance,\nthis is the preferred method to create an instance.Get the underlying web3 http client
\n", "signature": "(self):", "funcdef": "def"}, {"fullname": "golem_base_sdk.GolemBaseClient.ws_client", "modulename": "golem_base_sdk", "qualname": "GolemBaseClient.ws_client", "kind": "function", "doc": "Get the underlying web3 websocket client
\n", "signature": "(self) -> web3.main.AsyncWeb3:", "funcdef": "def"}, {"fullname": "golem_base_sdk.GolemBaseClient.is_connected", "modulename": "golem_base_sdk", "qualname": "GolemBaseClient.is_connected", "kind": "function", "doc": "Check whether the client's underlying http client is connected
\n", "signature": "(self) -> bool:", "funcdef": "async def"}, {"fullname": "golem_base_sdk.GolemBaseClient.disconnect", "modulename": "golem_base_sdk", "qualname": "GolemBaseClient.disconnect", "kind": "function", "doc": "Disconnect both the underlying http and ws clients and\nunsubscribe from all subscriptions
\n", "signature": "(self) -> None:", "funcdef": "async def"}, {"fullname": "golem_base_sdk.GolemBaseClient.get_account_address", "modulename": "golem_base_sdk", "qualname": "GolemBaseClient.get_account_address", "kind": "function", "doc": "Get the address associated with the private key that this client\nwas created with
\n", "signature": "(self) -> eth_typing.evm.ChecksumAddress:", "funcdef": "def"}, {"fullname": "golem_base_sdk.GolemBaseClient.get_storage_value", "modulename": "golem_base_sdk", "qualname": "GolemBaseClient.get_storage_value", "kind": "function", "doc": "Get the storage value stored in the given entity
\n", "signature": "(self, entity_key: golem_base_sdk.types.EntityKey) -> bytes:", "funcdef": "async def"}, {"fullname": "golem_base_sdk.GolemBaseClient.get_entity_metadata", "modulename": "golem_base_sdk", "qualname": "GolemBaseClient.get_entity_metadata", "kind": "function", "doc": "Get the metadata of the given entity
\n", "signature": "(\tself,\tentity_key: golem_base_sdk.types.EntityKey) -> golem_base_sdk.types.EntityMetadata:", "funcdef": "async def"}, {"fullname": "golem_base_sdk.GolemBaseClient.get_entities_to_expire_at_block", "modulename": "golem_base_sdk", "qualname": "GolemBaseClient.get_entities_to_expire_at_block", "kind": "function", "doc": "Get all entities that will expire at the given block
\n", "signature": "(self, block_number: int) -> Sequence[golem_base_sdk.types.EntityKey]:", "funcdef": "async def"}, {"fullname": "golem_base_sdk.GolemBaseClient.get_entity_count", "modulename": "golem_base_sdk", "qualname": "GolemBaseClient.get_entity_count", "kind": "function", "doc": "Get the total entity count in Golem Base
\n", "signature": "(self) -> int:", "funcdef": "async def"}, {"fullname": "golem_base_sdk.GolemBaseClient.get_all_entity_keys", "modulename": "golem_base_sdk", "qualname": "GolemBaseClient.get_all_entity_keys", "kind": "function", "doc": "Get all entity keys in Golem Base
\n", "signature": "(self) -> Sequence[golem_base_sdk.types.EntityKey]:", "funcdef": "async def"}, {"fullname": "golem_base_sdk.GolemBaseClient.get_entities_of_owner", "modulename": "golem_base_sdk", "qualname": "GolemBaseClient.get_entities_of_owner", "kind": "function", "doc": "Get all the entities owned by the given address
\n", "signature": "(\tself,\towner: eth_typing.evm.ChecksumAddress) -> Sequence[golem_base_sdk.types.EntityKey]:", "funcdef": "async def"}, {"fullname": "golem_base_sdk.GolemBaseClient.query_entities", "modulename": "golem_base_sdk", "qualname": "GolemBaseClient.query_entities", "kind": "function", "doc": "Get all entities that satisfy the given Golem Base query
\n", "signature": "(self, query: str) -> Sequence[golem_base_sdk.types.QueryEntitiesResult]:", "funcdef": "async def"}, {"fullname": "golem_base_sdk.GolemBaseClient.create_entities", "modulename": "golem_base_sdk", "qualname": "GolemBaseClient.create_entities", "kind": "function", "doc": "Create entities in Golem Base
\n", "signature": "(\tself,\tcreates: Sequence[golem_base_sdk.types.GolemBaseCreate]) -> Sequence[golem_base_sdk.types.CreateEntityReturnType]:", "funcdef": "async def"}, {"fullname": "golem_base_sdk.GolemBaseClient.update_entities", "modulename": "golem_base_sdk", "qualname": "GolemBaseClient.update_entities", "kind": "function", "doc": "Update entities in Golem Base
\n", "signature": "(\tself,\tupdates: Sequence[golem_base_sdk.types.GolemBaseUpdate]) -> Sequence[golem_base_sdk.types.UpdateEntityReturnType]:", "funcdef": "async def"}, {"fullname": "golem_base_sdk.GolemBaseClient.delete_entities", "modulename": "golem_base_sdk", "qualname": "GolemBaseClient.delete_entities", "kind": "function", "doc": "Delete entities from Golem Base
\n", "signature": "(\tself,\tdeletes: Sequence[golem_base_sdk.types.GolemBaseDelete]) -> Sequence[golem_base_sdk.types.EntityKey]:", "funcdef": "async def"}, {"fullname": "golem_base_sdk.GolemBaseClient.extend_entities", "modulename": "golem_base_sdk", "qualname": "GolemBaseClient.extend_entities", "kind": "function", "doc": "Extend the BTL of entities in Golem Base
\n", "signature": "(\tself,\textensions: Sequence[golem_base_sdk.types.GolemBaseExtend]) -> Sequence[golem_base_sdk.types.ExtendEntityReturnType]:", "funcdef": "async def"}, {"fullname": "golem_base_sdk.GolemBaseClient.send_transaction", "modulename": "golem_base_sdk", "qualname": "GolemBaseClient.send_transaction", "kind": "function", "doc": "Send a generic transaction to Golem Base.\nThis transaction can contain multiple create, update, delete and\nextend operations
\n", "signature": "(\tself,\tcreates: Optional[Sequence[golem_base_sdk.types.GolemBaseCreate]] = None,\tupdates: Optional[Sequence[golem_base_sdk.types.GolemBaseUpdate]] = None,\tdeletes: Optional[Sequence[golem_base_sdk.types.GolemBaseDelete]] = None,\textensions: Optional[Sequence[golem_base_sdk.types.GolemBaseExtend]] = None) -> golem_base_sdk.types.GolemBaseTransactionReceipt:", "funcdef": "async def"}, {"fullname": "golem_base_sdk.GolemBaseClient.watch_logs", "modulename": "golem_base_sdk", "qualname": "GolemBaseClient.watch_logs", "kind": "function", "doc": "Subscribe to events on Golem Base.\nYou can pass in four different callbacks, and the right one will\nbe invoked for every create, update, delete, and extend operation.
\n", "signature": "(\tself,\tcreate_callback: Callable[[golem_base_sdk.types.CreateEntityReturnType], NoneType],\tupdate_callback: Callable[[golem_base_sdk.types.UpdateEntityReturnType], NoneType],\tdelete_callback: Callable[[golem_base_sdk.types.EntityKey], NoneType],\textend_callback: Callable[[golem_base_sdk.types.ExtendEntityReturnType], NoneType]) -> None:", "funcdef": "async def"}, {"fullname": "golem_base_sdk.constants", "modulename": "golem_base_sdk.constants", "kind": "module", "doc": "Constants used in the Golem Base SDK
\n"}, {"fullname": "golem_base_sdk.constants.STORAGE_ADDRESS", "modulename": "golem_base_sdk.constants", "qualname": "STORAGE_ADDRESS", "kind": "variable", "doc": "\n", "annotation": ": Final[golem_base_sdk.types.Address]", "default_value": "GenericBytes(0x0000000000000000000000000000000060138453)"}, {"fullname": "golem_base_sdk.constants.GOLEM_BASE_ABI", "modulename": "golem_base_sdk.constants", "qualname": "GOLEM_BASE_ABI", "kind": "variable", "doc": "\n", "annotation": ": Final[Sequence[dict[str, Any]]]", "default_value": "[{'anonymous': False, 'inputs': [{'indexed': True, 'name': 'entityKey', 'type': 'uint256'}, {'indexed': False, 'name': 'expirationBlock', 'type': 'uint256'}], 'name': 'GolemBaseStorageEntityCreated', 'type': 'event'}, {'anonymous': False, 'inputs': [{'indexed': True, 'name': 'entityKey', 'type': 'uint256'}, {'indexed': False, 'name': 'expirationBlock', 'type': 'uint256'}], 'name': 'GolemBaseStorageEntityUpdated', 'type': 'event'}, {'anonymous': False, 'inputs': [{'indexed': True, 'name': 'entityKey', 'type': 'uint256'}], 'name': 'GolemBaseStorageEntityDeleted', 'type': 'event'}, {'anonymous': False, 'inputs': [{'indexed': True, 'name': 'entityKey', 'type': 'uint256'}, {'indexed': False, 'name': 'oldExpirationBlock', 'type': 'uint256'}, {'indexed': False, 'name': 'newExpirationBlock', 'type': 'uint256'}], 'name': 'GolemBaseStorageEntityBTLExtended', 'type': 'event'}, {'anonymous': False, 'inputs': [{'indexed': True, 'name': 'entityKey', 'type': 'uint256'}, {'indexed': False, 'name': 'expirationBlock', 'type': 'uint256'}], 'name': 'GolemBaseStorageEntityBTLExptended', 'type': 'event'}, {'anonymous': False, 'inputs': [{'indexed': True, 'name': 'entityKey', 'type': 'uint256'}, {'indexed': False, 'name': 'expirationBlock', 'type': 'uint256'}], 'name': 'GolemBaseStorageEntityTTLExptended', 'type': 'event'}]"}, {"fullname": "golem_base_sdk.types", "modulename": "golem_base_sdk.types", "kind": "module", "doc": "Golem Base SDK Types
\n"}, {"fullname": "golem_base_sdk.types.GenericBytes", "modulename": "golem_base_sdk.types", "qualname": "GenericBytes", "kind": "class", "doc": "Class to represent bytes that can be converted to more meaningful types
\n"}, {"fullname": "golem_base_sdk.types.GenericBytes.__init__", "modulename": "golem_base_sdk.types", "qualname": "GenericBytes.__init__", "kind": "function", "doc": "\n", "signature": "(generic_bytes: bytes)"}, {"fullname": "golem_base_sdk.types.GenericBytes.generic_bytes", "modulename": "golem_base_sdk.types", "qualname": "GenericBytes.generic_bytes", "kind": "variable", "doc": "\n", "annotation": ": bytes"}, {"fullname": "golem_base_sdk.types.GenericBytes.as_hex_string", "modulename": "golem_base_sdk.types", "qualname": "GenericBytes.as_hex_string", "kind": "function", "doc": "Convert this instance to a hexadecimal string
\n", "signature": "(self) -> eth_typing.encoding.HexStr:", "funcdef": "def"}, {"fullname": "golem_base_sdk.types.GenericBytes.as_address", "modulename": "golem_base_sdk.types", "qualname": "GenericBytes.as_address", "kind": "function", "doc": "Convert this instance to a
\n", "signature": "(self) -> eth_typing.evm.ChecksumAddress:", "funcdef": "def"}, {"fullname": "golem_base_sdk.types.GenericBytes.from_hex_string", "modulename": "golem_base_sdk.types", "qualname": "GenericBytes.from_hex_string", "kind": "function", "doc": "eth_typing.ChecksumAddressCreate a
\n", "signature": "(hexstr: str) -> golem_base_sdk.types.GenericBytes:", "funcdef": "def"}, {"fullname": "golem_base_sdk.types.EntityKey", "modulename": "golem_base_sdk.types", "qualname": "EntityKey", "kind": "variable", "doc": "\n", "default_value": "golem_base_sdk.types.EntityKey"}, {"fullname": "golem_base_sdk.types.Address", "modulename": "golem_base_sdk.types", "qualname": "Address", "kind": "variable", "doc": "\n", "default_value": "golem_base_sdk.types.Address"}, {"fullname": "golem_base_sdk.types.Annotation", "modulename": "golem_base_sdk.types", "qualname": "Annotation", "kind": "class", "doc": "GenericBytesinstance from a hexadecimal stringClass to represent generic annotations
\n", "bases": "typing.Generic[V]"}, {"fullname": "golem_base_sdk.types.Annotation.__init__", "modulename": "golem_base_sdk.types", "qualname": "Annotation.__init__", "kind": "function", "doc": "\n", "signature": "(key: str, value: V)"}, {"fullname": "golem_base_sdk.types.Annotation.key", "modulename": "golem_base_sdk.types", "qualname": "Annotation.key", "kind": "variable", "doc": "\n", "annotation": ": str"}, {"fullname": "golem_base_sdk.types.Annotation.value", "modulename": "golem_base_sdk.types", "qualname": "Annotation.value", "kind": "variable", "doc": "\n", "annotation": ": V"}, {"fullname": "golem_base_sdk.types.GolemBaseCreate", "modulename": "golem_base_sdk.types", "qualname": "GolemBaseCreate", "kind": "class", "doc": "Class to represent a create operation in Golem Base
\n"}, {"fullname": "golem_base_sdk.types.GolemBaseCreate.__init__", "modulename": "golem_base_sdk.types", "qualname": "GolemBaseCreate.__init__", "kind": "function", "doc": "\n", "signature": "(\tdata: bytes,\tttl: int,\tstring_annotations: Sequence[golem_base_sdk.types.Annotation[str]],\tnumeric_annotations: Sequence[golem_base_sdk.types.Annotation[int]])"}, {"fullname": "golem_base_sdk.types.GolemBaseCreate.data", "modulename": "golem_base_sdk.types", "qualname": "GolemBaseCreate.data", "kind": "variable", "doc": "\n", "annotation": ": bytes"}, {"fullname": "golem_base_sdk.types.GolemBaseCreate.ttl", "modulename": "golem_base_sdk.types", "qualname": "GolemBaseCreate.ttl", "kind": "variable", "doc": "\n", "annotation": ": int"}, {"fullname": "golem_base_sdk.types.GolemBaseCreate.string_annotations", "modulename": "golem_base_sdk.types", "qualname": "GolemBaseCreate.string_annotations", "kind": "variable", "doc": "\n", "annotation": ": Sequence[golem_base_sdk.types.Annotation[str]]"}, {"fullname": "golem_base_sdk.types.GolemBaseCreate.numeric_annotations", "modulename": "golem_base_sdk.types", "qualname": "GolemBaseCreate.numeric_annotations", "kind": "variable", "doc": "\n", "annotation": ": Sequence[golem_base_sdk.types.Annotation[int]]"}, {"fullname": "golem_base_sdk.types.GolemBaseUpdate", "modulename": "golem_base_sdk.types", "qualname": "GolemBaseUpdate", "kind": "class", "doc": "Class to represent an update operation in Golem Base
\n"}, {"fullname": "golem_base_sdk.types.GolemBaseUpdate.__init__", "modulename": "golem_base_sdk.types", "qualname": "GolemBaseUpdate.__init__", "kind": "function", "doc": "\n", "signature": "(\tentity_key: golem_base_sdk.types.EntityKey,\tdata: bytes,\tttl: int,\tstring_annotations: Sequence[golem_base_sdk.types.Annotation[str]],\tnumeric_annotations: Sequence[golem_base_sdk.types.Annotation[int]])"}, {"fullname": "golem_base_sdk.types.GolemBaseUpdate.entity_key", "modulename": "golem_base_sdk.types", "qualname": "GolemBaseUpdate.entity_key", "kind": "variable", "doc": "\n", "annotation": ": golem_base_sdk.types.EntityKey"}, {"fullname": "golem_base_sdk.types.GolemBaseUpdate.data", "modulename": "golem_base_sdk.types", "qualname": "GolemBaseUpdate.data", "kind": "variable", "doc": "\n", "annotation": ": bytes"}, {"fullname": "golem_base_sdk.types.GolemBaseUpdate.ttl", "modulename": "golem_base_sdk.types", "qualname": "GolemBaseUpdate.ttl", "kind": "variable", "doc": "\n", "annotation": ": int"}, {"fullname": "golem_base_sdk.types.GolemBaseUpdate.string_annotations", "modulename": "golem_base_sdk.types", "qualname": "GolemBaseUpdate.string_annotations", "kind": "variable", "doc": "\n", "annotation": ": Sequence[golem_base_sdk.types.Annotation[str]]"}, {"fullname": "golem_base_sdk.types.GolemBaseUpdate.numeric_annotations", "modulename": "golem_base_sdk.types", "qualname": "GolemBaseUpdate.numeric_annotations", "kind": "variable", "doc": "\n", "annotation": ": Sequence[golem_base_sdk.types.Annotation[int]]"}, {"fullname": "golem_base_sdk.types.GolemBaseDelete", "modulename": "golem_base_sdk.types", "qualname": "GolemBaseDelete", "kind": "class", "doc": "Class to represent a delete operation in Golem Base
\n"}, {"fullname": "golem_base_sdk.types.GolemBaseDelete.__init__", "modulename": "golem_base_sdk.types", "qualname": "GolemBaseDelete.__init__", "kind": "function", "doc": "\n", "signature": "(entity_key: golem_base_sdk.types.EntityKey)"}, {"fullname": "golem_base_sdk.types.GolemBaseDelete.entity_key", "modulename": "golem_base_sdk.types", "qualname": "GolemBaseDelete.entity_key", "kind": "variable", "doc": "\n", "annotation": ": golem_base_sdk.types.EntityKey"}, {"fullname": "golem_base_sdk.types.GolemBaseExtend", "modulename": "golem_base_sdk.types", "qualname": "GolemBaseExtend", "kind": "class", "doc": "Class to represent a BTL extend operation in Golem Base
\n"}, {"fullname": "golem_base_sdk.types.GolemBaseExtend.__init__", "modulename": "golem_base_sdk.types", "qualname": "GolemBaseExtend.__init__", "kind": "function", "doc": "\n", "signature": "(entity_key: golem_base_sdk.types.EntityKey, number_of_blocks: int)"}, {"fullname": "golem_base_sdk.types.GolemBaseExtend.entity_key", "modulename": "golem_base_sdk.types", "qualname": "GolemBaseExtend.entity_key", "kind": "variable", "doc": "\n", "annotation": ": golem_base_sdk.types.EntityKey"}, {"fullname": "golem_base_sdk.types.GolemBaseExtend.number_of_blocks", "modulename": "golem_base_sdk.types", "qualname": "GolemBaseExtend.number_of_blocks", "kind": "variable", "doc": "\n", "annotation": ": int"}, {"fullname": "golem_base_sdk.types.GolemBaseTransaction", "modulename": "golem_base_sdk.types", "qualname": "GolemBaseTransaction", "kind": "class", "doc": "Class to represent a transaction in Golem Base.\nA transaction consist of one or more\n
\n"}, {"fullname": "golem_base_sdk.types.GolemBaseTransaction.__init__", "modulename": "golem_base_sdk.types", "qualname": "GolemBaseTransaction.__init__", "kind": "function", "doc": "\n", "signature": "(\tcreates: Optional[Sequence[golem_base_sdk.types.GolemBaseCreate]] = None,\tupdates: Optional[Sequence[golem_base_sdk.types.GolemBaseUpdate]] = None,\tdeletes: Optional[Sequence[golem_base_sdk.types.GolemBaseDelete]] = None,\textensions: Optional[Sequence[golem_base_sdk.types.GolemBaseExtend]] = None)"}, {"fullname": "golem_base_sdk.types.GolemBaseTransaction.creates", "modulename": "golem_base_sdk.types", "qualname": "GolemBaseTransaction.creates", "kind": "variable", "doc": "\n", "annotation": ": Sequence[golem_base_sdk.types.GolemBaseCreate]"}, {"fullname": "golem_base_sdk.types.GolemBaseTransaction.updates", "modulename": "golem_base_sdk.types", "qualname": "GolemBaseTransaction.updates", "kind": "variable", "doc": "\n", "annotation": ": Sequence[golem_base_sdk.types.GolemBaseUpdate]"}, {"fullname": "golem_base_sdk.types.GolemBaseTransaction.deletes", "modulename": "golem_base_sdk.types", "qualname": "GolemBaseTransaction.deletes", "kind": "variable", "doc": "\n", "annotation": ": Sequence[golem_base_sdk.types.GolemBaseDelete]"}, {"fullname": "golem_base_sdk.types.GolemBaseTransaction.extensions", "modulename": "golem_base_sdk.types", "qualname": "GolemBaseTransaction.extensions", "kind": "variable", "doc": "\n", "annotation": ": Sequence[golem_base_sdk.types.GolemBaseExtend]"}, {"fullname": "golem_base_sdk.types.CreateEntityReturnType", "modulename": "golem_base_sdk.types", "qualname": "CreateEntityReturnType", "kind": "class", "doc": "GolemBaseCreate,\nGolemBaseUpdate,\nGolemBaseDeleteand\nGolemBaseExtend\noperations.The return type of a Golem Base create operation
\n"}, {"fullname": "golem_base_sdk.types.CreateEntityReturnType.__init__", "modulename": "golem_base_sdk.types", "qualname": "CreateEntityReturnType.__init__", "kind": "function", "doc": "\n", "signature": "(expiration_block: int, entity_key: golem_base_sdk.types.EntityKey)"}, {"fullname": "golem_base_sdk.types.CreateEntityReturnType.expiration_block", "modulename": "golem_base_sdk.types", "qualname": "CreateEntityReturnType.expiration_block", "kind": "variable", "doc": "\n", "annotation": ": int"}, {"fullname": "golem_base_sdk.types.CreateEntityReturnType.entity_key", "modulename": "golem_base_sdk.types", "qualname": "CreateEntityReturnType.entity_key", "kind": "variable", "doc": "\n", "annotation": ": golem_base_sdk.types.EntityKey"}, {"fullname": "golem_base_sdk.types.UpdateEntityReturnType", "modulename": "golem_base_sdk.types", "qualname": "UpdateEntityReturnType", "kind": "class", "doc": "The return type of a Golem Base update operation
\n"}, {"fullname": "golem_base_sdk.types.UpdateEntityReturnType.__init__", "modulename": "golem_base_sdk.types", "qualname": "UpdateEntityReturnType.__init__", "kind": "function", "doc": "\n", "signature": "(expiration_block: int, entity_key: golem_base_sdk.types.EntityKey)"}, {"fullname": "golem_base_sdk.types.UpdateEntityReturnType.expiration_block", "modulename": "golem_base_sdk.types", "qualname": "UpdateEntityReturnType.expiration_block", "kind": "variable", "doc": "\n", "annotation": ": int"}, {"fullname": "golem_base_sdk.types.UpdateEntityReturnType.entity_key", "modulename": "golem_base_sdk.types", "qualname": "UpdateEntityReturnType.entity_key", "kind": "variable", "doc": "\n", "annotation": ": golem_base_sdk.types.EntityKey"}, {"fullname": "golem_base_sdk.types.ExtendEntityReturnType", "modulename": "golem_base_sdk.types", "qualname": "ExtendEntityReturnType", "kind": "class", "doc": "The return type of a Golem Base extend operation
\n"}, {"fullname": "golem_base_sdk.types.ExtendEntityReturnType.__init__", "modulename": "golem_base_sdk.types", "qualname": "ExtendEntityReturnType.__init__", "kind": "function", "doc": "\n", "signature": "(\told_expiration_block: int,\tnew_expiration_block: int,\tentity_key: golem_base_sdk.types.EntityKey)"}, {"fullname": "golem_base_sdk.types.ExtendEntityReturnType.old_expiration_block", "modulename": "golem_base_sdk.types", "qualname": "ExtendEntityReturnType.old_expiration_block", "kind": "variable", "doc": "\n", "annotation": ": int"}, {"fullname": "golem_base_sdk.types.ExtendEntityReturnType.new_expiration_block", "modulename": "golem_base_sdk.types", "qualname": "ExtendEntityReturnType.new_expiration_block", "kind": "variable", "doc": "\n", "annotation": ": int"}, {"fullname": "golem_base_sdk.types.ExtendEntityReturnType.entity_key", "modulename": "golem_base_sdk.types", "qualname": "ExtendEntityReturnType.entity_key", "kind": "variable", "doc": "\n", "annotation": ": golem_base_sdk.types.EntityKey"}, {"fullname": "golem_base_sdk.types.GolemBaseTransactionReceipt", "modulename": "golem_base_sdk.types", "qualname": "GolemBaseTransactionReceipt", "kind": "class", "doc": "The return type of a Golem Base transaction
\n"}, {"fullname": "golem_base_sdk.types.GolemBaseTransactionReceipt.__init__", "modulename": "golem_base_sdk.types", "qualname": "GolemBaseTransactionReceipt.__init__", "kind": "function", "doc": "\n", "signature": "(\tcreates: Sequence[golem_base_sdk.types.CreateEntityReturnType],\tupdates: Sequence[golem_base_sdk.types.UpdateEntityReturnType],\textensions: Sequence[golem_base_sdk.types.ExtendEntityReturnType],\tdeletes: Sequence[golem_base_sdk.types.EntityKey])"}, {"fullname": "golem_base_sdk.types.GolemBaseTransactionReceipt.creates", "modulename": "golem_base_sdk.types", "qualname": "GolemBaseTransactionReceipt.creates", "kind": "variable", "doc": "\n", "annotation": ": Sequence[golem_base_sdk.types.CreateEntityReturnType]"}, {"fullname": "golem_base_sdk.types.GolemBaseTransactionReceipt.updates", "modulename": "golem_base_sdk.types", "qualname": "GolemBaseTransactionReceipt.updates", "kind": "variable", "doc": "\n", "annotation": ": Sequence[golem_base_sdk.types.UpdateEntityReturnType]"}, {"fullname": "golem_base_sdk.types.GolemBaseTransactionReceipt.extensions", "modulename": "golem_base_sdk.types", "qualname": "GolemBaseTransactionReceipt.extensions", "kind": "variable", "doc": "\n", "annotation": ": Sequence[golem_base_sdk.types.ExtendEntityReturnType]"}, {"fullname": "golem_base_sdk.types.GolemBaseTransactionReceipt.deletes", "modulename": "golem_base_sdk.types", "qualname": "GolemBaseTransactionReceipt.deletes", "kind": "variable", "doc": "\n", "annotation": ": Sequence[golem_base_sdk.types.EntityKey]"}, {"fullname": "golem_base_sdk.types.EntityMetadata", "modulename": "golem_base_sdk.types", "qualname": "EntityMetadata", "kind": "class", "doc": "A class representing entity metadata
\n"}, {"fullname": "golem_base_sdk.types.EntityMetadata.__init__", "modulename": "golem_base_sdk.types", "qualname": "EntityMetadata.__init__", "kind": "function", "doc": "\n", "signature": "(\tentity_key: golem_base_sdk.types.EntityKey,\towner: golem_base_sdk.types.Address,\texpires_at_block: int,\tstring_annotations: Sequence[golem_base_sdk.types.Annotation[str]],\tnumeric_annotations: Sequence[golem_base_sdk.types.Annotation[int]])"}, {"fullname": "golem_base_sdk.types.EntityMetadata.entity_key", "modulename": "golem_base_sdk.types", "qualname": "EntityMetadata.entity_key", "kind": "variable", "doc": "\n", "annotation": ": golem_base_sdk.types.EntityKey"}, {"fullname": "golem_base_sdk.types.EntityMetadata.owner", "modulename": "golem_base_sdk.types", "qualname": "EntityMetadata.owner", "kind": "variable", "doc": "\n", "annotation": ": golem_base_sdk.types.Address"}, {"fullname": "golem_base_sdk.types.EntityMetadata.expires_at_block", "modulename": "golem_base_sdk.types", "qualname": "EntityMetadata.expires_at_block", "kind": "variable", "doc": "\n", "annotation": ": int"}, {"fullname": "golem_base_sdk.types.EntityMetadata.string_annotations", "modulename": "golem_base_sdk.types", "qualname": "EntityMetadata.string_annotations", "kind": "variable", "doc": "\n", "annotation": ": Sequence[golem_base_sdk.types.Annotation[str]]"}, {"fullname": "golem_base_sdk.types.EntityMetadata.numeric_annotations", "modulename": "golem_base_sdk.types", "qualname": "EntityMetadata.numeric_annotations", "kind": "variable", "doc": "\n", "annotation": ": Sequence[golem_base_sdk.types.Annotation[int]]"}, {"fullname": "golem_base_sdk.types.QueryEntitiesResult", "modulename": "golem_base_sdk.types", "qualname": "QueryEntitiesResult", "kind": "class", "doc": "A class representing the return value of a Golem Base query
\n"}, {"fullname": "golem_base_sdk.types.QueryEntitiesResult.__init__", "modulename": "golem_base_sdk.types", "qualname": "QueryEntitiesResult.__init__", "kind": "function", "doc": "\n", "signature": "(entity_key: golem_base_sdk.types.EntityKey, storage_value: bytes)"}, {"fullname": "golem_base_sdk.types.QueryEntitiesResult.entity_key", "modulename": "golem_base_sdk.types", "qualname": "QueryEntitiesResult.entity_key", "kind": "variable", "doc": "\n", "annotation": ": golem_base_sdk.types.EntityKey"}, {"fullname": "golem_base_sdk.types.QueryEntitiesResult.storage_value", "modulename": "golem_base_sdk.types", "qualname": "QueryEntitiesResult.storage_value", "kind": "variable", "doc": "\n", "annotation": ": bytes"}, {"fullname": "golem_base_sdk.utils", "modulename": "golem_base_sdk.utils", "kind": "module", "doc": "Utility methods
\n"}, {"fullname": "golem_base_sdk.utils.rlp_encode_transaction", "modulename": "golem_base_sdk.utils", "qualname": "rlp_encode_transaction", "kind": "function", "doc": "Encode a Golem Base transaction in RLP
\n", "signature": "(tx: golem_base_sdk.types.GolemBaseTransaction) -> bytes:", "funcdef": "def"}, {"fullname": "golem_base_sdk.utils.parse_legacy_btl_extended_log", "modulename": "golem_base_sdk.utils", "qualname": "parse_legacy_btl_extended_log", "kind": "function", "doc": "For legacy extend ABI types, the type signature in the ABI does\nnot correspond to the actual data returned, so we need\nto parse the data ourselves.
\n", "signature": "(\tlog_receipt: web3.types.LogReceipt) -> golem_base_sdk.types.ExtendEntityReturnType:", "funcdef": "def"}]; // mirrored in build-search-index.js (part 1) // Also split on html tags. this is a cheap heuristic, but good enough.