Skip to content

Commit

Permalink
refactor(demo): create a local experiment, and a demo Silverback app
Browse files Browse the repository at this point in the history
  • Loading branch information
fubuloubu committed Sep 20, 2024
1 parent 325385c commit da5bbb3
Show file tree
Hide file tree
Showing 3 changed files with 145 additions and 55 deletions.
49 changes: 49 additions & 0 deletions bots/example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import os
from datetime import timedelta

from ape_ethereum import multicall
from silverback import SilverbackApp

from apepay import StreamManager

app = SilverbackApp()
# NOTE: You should use one bot per-supported network
# NOTE: This bot assumes you use a new bot per deployment
sm = StreamManager(os.environ["APEPAY_CONTRACT_ADDRESS"])

global db
# NOTE: You would probably want to index this by network and deployment,
# if you were operating on multiple networks or deployments
db = []
# TODO: Migrate to `app.state.db` when feature becomes available


@app.on_startup()
async def load_db(_):
global db

for stream in sm.active_streams():
db.append(stream)

db = sorted(db)


@sm.on_stream_created(app)
async def grant_product(stream):
db.append(stream)
print(f"provisioning product for {stream.creator}")
return stream.time_left


@sm.on_stream_funded(app)
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 record
db.append(stream)
return stream.time_left


@sm.on_stream_cancelled(app)
async def revoke_product(stream):
print(f"unprovisioning product for {stream.creator}")
db.remove(stream)
96 changes: 96 additions & 0 deletions scripts/demo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
"""
A demo showing some accounts randomly creating, modifying, and cancelling streams
"""

import random
from datetime import timedelta

import click
from ape.cli import ConnectedProviderCommand, ape_cli_context

from apepay import StreamManager


@click.command(cls=ConnectedProviderCommand)
@ape_cli_context()
@click.option("-l", "--min-stream-life", default=0)
@click.option("-n", "--num-accounts", default=10)
@click.option("-b", "--num-blocks", default=1000)
@click.option("-m", "--max-streams", default=10)
@click.option("-c", "--create-stream", type=float, default=0.1)
@click.option("-f", "--fund-stream", type=float, default=0.7)
@click.option("-k", "--cancel-stream", type=float, default=0.2)
def cli(
cli_ctx,
min_stream_life,
num_accounts,
num_blocks,
max_streams,
create_stream,
fund_stream,
cancel_stream,
):
# Initialize experiment
deployer = cli_ctx.account_manager.test_accounts[-1]
token = cli_ctx.local_project.TestToken.deploy(sender=deployer)
sm = StreamManager(
cli_ctx.local_project.StreamManager.deploy(
deployer, min_stream_life, [], [token], sender=deployer
)
)

# Wait for user to start the example SB app...
click.secho(
f"Please run `APEPAY_CONTRACT_ADDRESS={sm.address} silverback run bots.example:app`",
fg="bright_magenta",
)
if not click.confirm("Start experiment?"):
return

# Make sure all accounts have some tokens
accounts = cli_ctx.account_manager.test_accounts[:num_accounts]
decimals = token.decimals()
for account in accounts:
token.DEBUG_mint(account, 10_000 * 10**decimals, sender=account)

# 26 tokens per day
starting_life = timedelta(minutes=5).total_seconds()
starting_tokens = 26 * 10**decimals
funding_amount = 2 * 10**decimals
streams = {a.address: [] for a in accounts}

while cli_ctx.chain_manager.blocks.head.number < num_blocks:
payer = random.choice(accounts)

# Do a little garbage collection
for stream in streams[payer.address]:
click.echo(f"{payer}:{stream.stream_id} - {stream.time_left}")
if not stream.is_active:
click.echo(f"Stream '{payer}:{stream.stream_id}' is expired, removing...")
streams[payer.address].remove(stream)

if len(streams[payer.address]) > 0:
stream = random.choice(streams[payer.address])

if token.balanceOf(payer) >= 10 ** (decimals + 1) and random.random() < fund_stream:
click.echo(
f"Stream '{payer}:{stream.stream_id}' is being funded "
f"w/ {funding_amount / 10**decimals:.2f} tokens..."
)
token.approve(sm.address, funding_amount, sender=payer)
stream.add_funds(funding_amount, sender=payer)

elif random.random() < cancel_stream:
click.echo(f"Stream '{payer}:{stream.stream_id}' is being cancelled...")
stream.cancel(sender=payer)
streams[payer.address].remove(stream)

elif token.balanceOf(payer) < starting_tokens:
continue

elif len(streams[payer.address]) < max_streams and random.random() < create_stream:
click.echo(f"'{payer}' is creating a new stream...")
token.approve(sm.address, starting_tokens, sender=payer)
stream = sm.create(token, int(starting_tokens / starting_life), sender=payer)
streams[payer.address].append(stream)
click.echo(f"Stream '{payer}:{stream.stream_id}' was created successfully.")
55 changes: 0 additions & 55 deletions scripts/example.py

This file was deleted.

0 comments on commit da5bbb3

Please sign in to comment.