Skip to content

Commit

Permalink
A0-1766: Sketch out the pricing script (#852)
Browse files Browse the repository at this point in the history
* Sketch out the pricing script

* Format the pricing table prettier

* Improve cosmetics

* Improve cosmetics

Co-authored-by: Michal Handzlik <h4nsu@users.noreply.github.com>
  • Loading branch information
obrok and h4nsu committed Jan 13, 2023
1 parent 585a842 commit 901d3ec
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 0 deletions.
24 changes: 24 additions & 0 deletions scripts/pricing/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
Pricing script
==============

The `./run.py` script in this directory will deploy some contracts and print a summary of how much some basic operations
on them cost.

It requires `python3` and an Ink 4-compatible version of `cargo contract`, to install:

```bash
$ cargo install cargo-contract --version 2.0.0-beta.1
```

Afterwards, install the python deps and run the script:

```bash
$ pip install -r requirements.txt
$ ./run.py
```

For more info on options see:

```bash
$ ./run.py --help
```
1 change: 1 addition & 0 deletions scripts/pricing/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
tabulate==0.9.0
101 changes: 101 additions & 0 deletions scripts/pricing/run.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
#!/usr/bin/python3

import argparse
import random
import subprocess
import json
from tabulate import tabulate
import urllib.request

AZERO = 1_000_000_000_000


parser = argparse.ArgumentParser(
description='Check the prices of some common contract operations')
parser.add_argument('--url', type=str,
default='ws://localhost:9944', help='URL of the node to connect to')
parser.add_argument('--suri', type=str, default='//Alice',
help='Secret key URI to use for calls')
parser.add_argument('--adder-dir', type=str,
help='Directory of the adder contract', default='../../contracts/adder')

args = parser.parse_args()

COMMON_ARGS = ['--suri', args.suri, '--url',
args.url, '--skip-confirm', '--output-json']


def random_salt():
return ''.join(random.choice('0123456789abcdef') for _ in range(10))


def deploy(directory):
res = subprocess.check_output(['cargo', 'contract', 'instantiate', '--salt',
random_salt()] + COMMON_ARGS, cwd=directory)
return json.loads(res.decode('utf-8'))


def call(directory, contract, message, *args):
args = [x for a in args for x in ['--args', a]]
res = subprocess.check_output(['cargo', 'contract', 'call', '--contract', contract,
'--message', message] + args + COMMON_ARGS, cwd=directory)
return json.loads(res.decode('utf-8'))


def event_field(event, field):
for f in event['fields']:
if f['name'] == field:
return f['value']


def deployer_account_id(deploy_result):
setup_event = next(filter(
lambda e: e['name'] == 'Transfer' and account_id(event_field(e, 'to')) == adder_address, deploy_result['events']), None)

return account_id(event_field(setup_event, 'from'))


def account_id(value):
match value:
case {'Literal': account_id}: return account_id
case _: raise ValueError(f'Invalid account id: {value}')


def uint(value):
match value:
case {'UInt': value}: return value
case _: raise ValueError(f'Invalid uint: {value}')


def find_fee(events, by_whom):
fee_event = next(filter(lambda e: e['name'] == 'TransactionFeePaid' and account_id(
event_field(e, 'who')) == by_whom, events), None)
return uint(event_field(fee_event, 'actual_fee'))


with urllib.request.urlopen('https://api.coingecko.com/api/v3/simple/price?ids=aleph-zero&vs_currencies=usd') as response:
data = json.load(response)
aleph_usd = data['aleph-zero']['usd']


def format_fee(fee):
return "%f AZERO ($%f)" % (fee / AZERO, fee / AZERO * aleph_usd)


deploy_result = deploy(args.adder_dir)

adder_address = deploy_result['contract']
suri_address = deployer_account_id(deploy_result)
instantiate_fee = find_fee(deploy_result['events'], suri_address)

events = call(args.adder_dir, adder_address, 'add', '42')
add_fee = find_fee(events, suri_address)

headers = ['Operation', 'Fee']
prices = [
["Instantiate contract with single storage value",
format_fee(instantiate_fee)],
["Call contract with single storage update", format_fee(add_fee)]
]

print(tabulate(prices, headers=headers, tablefmt="github"))

0 comments on commit 901d3ec

Please sign in to comment.