Skip to content

Commit

Permalink
feat(py-sdk): factory (#111)
Browse files Browse the repository at this point in the history
* refactor(contract): deployment tracking in ape-config.yaml

* feat(py-sdk): add support for release detection and deployments

* refactor(example): made exmaple bot more multi-process friendly
  • Loading branch information
fubuloubu authored Sep 24, 2024
1 parent 0e09989 commit 7be36a3
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 9 deletions.
14 changes: 9 additions & 5 deletions ape-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,17 @@ ethereum:

deployments:
ethereum:
sepolia: &chaosnet
# NOTE: Deployed with salt=`ApePay v0.1`
sepolia: &releases
- contract_type: StreamFactory
address: 0x92823EB2DB42b8df354EDB5A1FB3668057e2935D
salt: "ApePay v0.3"

- contract_type: StreamManager
address: 0x3543faeeddb7babcbbb216b3627f9c5e0c39ce41
address: 0x6A1aa538ebB85Fd98655eCEe5EaB7D9cb3cbCD2B
salt: "ApePay v0.3"
blueprint: true

arbitrum:
mainnet: *chaosnet
mainnet: *releases
optimism:
mainnet: *chaosnet
mainnet: *releases
6 changes: 2 additions & 4 deletions bots/example.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,12 @@ async def grant_product(stream):
async def update_product_funding(stream):
# NOTE: properties of stream have changed, you may not need to handle this, but typically you
# would want to update `stream.time_left` in db for use in user Stream life notifications
db[stream.creator].pop(stream.stream_id)
db[stream.creator].insert(stream.stream_id, stream)
db[stream.creator][stream.stream_id] = stream
return stream.time_left


@sm.on_stream_cancelled(app)
async def revoke_product(stream):
print(f"unprovisioning product for {stream.creator}")
db[stream.creator].pop(stream.stream_id)
db[stream.creator].insert(stream.stream_id, None)
db[stream.creator][stream.stream_id] = None
return stream.time_left
3 changes: 3 additions & 0 deletions sdk/py/apepay/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from .factory import StreamFactory, releases
from .manager import StreamManager
from .streams import Stream
from .validators import Validator
Expand All @@ -8,6 +9,8 @@

__all__ = [
Stream.__name__,
StreamFactory.__name__,
StreamManager.__name__,
Validator.__name__,
"releases",
]
7 changes: 7 additions & 0 deletions sdk/py/apepay/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@ class ApePayException(Exception):
pass


class NoFactoryAvailable(ApePayException, RuntimeError):
def __init__(self):
super().__init__(
"No deployment of 'StreamFactory' on this chain, please use an explicit address."
)


class MissingCreationReceipt(ApePayException, NotImplementedError):
def __init__(self):
super().__init__("Missing creation transaction for stream. Functionality unavailabie.")
Expand Down
58 changes: 58 additions & 0 deletions sdk/py/apepay/factory.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
from typing import Any

from ape.contracts import ContractInstance
from ape.types import AddressType, BaseInterfaceModel
from pydantic import field_validator

from .exceptions import NoFactoryAvailable
from .manager import StreamManager
from .package import MANIFEST


class StreamFactory(BaseInterfaceModel):
address: AddressType

def __init__(self, address=None, /, *args, **kwargs):
if address is not None:
kwargs["address"] = address

elif len(MANIFEST.StreamFactory.deployments) == 0:
raise NoFactoryAvailable()

else:
kwargs["address"] = MANIFEST.StreamFactory.deployments[-1]

super().__init__(*args, **kwargs)

def __hash__(self) -> int:
return self.address.__hash__()

@field_validator("address", mode="before")
def normalize_address(cls, value: Any) -> AddressType:
return cls.conversion_manager.convert(value, AddressType)

@property
def contract(self) -> ContractInstance:
return MANIFEST.StreamFactory.at(self.address)

def get_deployment(self, deployer: Any) -> StreamManager:
# TODO: Add product selection to the factory using `product=` kwarg (defaults to empty)
return StreamManager(self.contract.deployments(deployer))


class Releases:
def __getitem__(self, release: int) -> StreamFactory:
if (
len(MANIFEST.StreamFactory.deployments) < release
or len(MANIFEST.StreamFactory.deployments) == 0
):
raise IndexError("release index out of range") from NoFactoryAvailable()

return StreamFactory(MANIFEST.StreamFactory.deployments[release])

@property
def latest(self) -> StreamFactory:
return StreamFactory()


releases = Releases()

0 comments on commit 7be36a3

Please sign in to comment.