From e0c8178932a17632ca8ef7fcf0363b7f9436341a Mon Sep 17 00:00:00 2001 From: Frederic Fortier Date: Tue, 9 Jan 2018 22:42:09 -0500 Subject: [PATCH] BLD: improved smart contract and catalyst commands --- catalyst/__main__.py | 4 +- catalyst/constants.py | 2 + catalyst/marketplace/marketplace.py | 95 +++++++++++++++++++++++---- marketplace/contracts/Marketplace.sol | 2 +- marketplace/test/TestMarketplace.sol | 8 +-- tests/marketplace/test_marketplace.py | 14 +++- 6 files changed, 102 insertions(+), 23 deletions(-) diff --git a/catalyst/__main__.py b/catalyst/__main__.py index d86276ba..5f70b985 100644 --- a/catalyst/__main__.py +++ b/catalyst/__main__.py @@ -5,7 +5,7 @@ from functools import wraps import click import logbook import pandas as pd -from catalyst.alt_data.marketplace import Marketplace +from catalyst.marketplace.marketplace import Marketplace from six import text_type from catalyst.data import bundles as bundles_module @@ -578,7 +578,7 @@ def ingest_exchange(ctx, exchange_name, data_frequency, start, end, @click.pass_context def ls_data(ctx): click.echo( - 'Listing available alternative data sources' + 'The alternative data sources:' ) marketplace = Marketplace() marketplace.list() diff --git a/catalyst/constants.py b/catalyst/constants.py index c4111fdd..6b3fc235 100644 --- a/catalyst/constants.py +++ b/catalyst/constants.py @@ -15,4 +15,6 @@ SYMBOLS_URL = 'https://s3.amazonaws.com/enigmaco/catalyst-exchanges/' \ DATE_TIME_FORMAT = '%Y-%m-%d %H:%M' DATE_FORMAT = '%Y-%m-%d' +ROOT_DIR = os.path.dirname(os.path.abspath(__file__)) + AUTO_INGEST = False diff --git a/catalyst/marketplace/marketplace.py b/catalyst/marketplace/marketplace.py index a6c0ff0b..9de33328 100644 --- a/catalyst/marketplace/marketplace.py +++ b/catalyst/marketplace/marketplace.py @@ -1,29 +1,26 @@ import json import os +import pandas as pd from web3 import Web3, HTTPProvider +from catalyst.exchange.utils.stats_utils import set_print_settings +from catalyst.constants import ROOT_DIR + +REMOTE_NODE = 'http://localhost:7545' CONTRACT_PATH = os.path.join( - '..', '..', 'marketplace', 'build', 'contracts', 'Marketplace.json' + ROOT_DIR, '..', 'marketplace', 'build', 'contracts', 'Marketplace.json' ) CONTRACT_ADDRESS = Web3.toChecksumAddress( - '0x345ca3e014aaf5dca488057592ee47305d9b3e10' + '0xd8672a4a1bf37d36bef74e36edb4f17845e76f4e' ) -# we'll use one of our default accounts to deploy from. every write to the chain requires a -# payment of ethereum called "gas". if we were running an actual test ethereum node locally, -# then we'd have to go on the test net and get some free ethereum to play with. that is beyond -# the scope of this tutorial so we're using a mini local node that has unlimited ethereum and -# the only chain we're using is our own local one - - class Marketplace: def __init__(self): with open(CONTRACT_PATH) as handle: json_interface = json.load(handle) - - w3 = Web3(HTTPProvider('http://localhost:7545')) + w3 = Web3(HTTPProvider(REMOTE_NODE)) self.contract = w3.eth.contract( CONTRACT_ADDRESS, @@ -33,16 +30,86 @@ class Marketplace: pass + def get_data_sources_map(self): + return [ + dict( + name='Marketcap', + desc='The marketcap value in USD.', + start_date=pd.to_datetime('2017-01-01'), + end_date=pd.to_datetime('2018-01-15'), + ), + dict( + name='GitHub', + desc='The rate of development activity on GitHub.', + start_date=pd.to_datetime('2017-01-01'), + end_date=pd.to_datetime('2018-01-15'), + ), + dict( + name='Influencers', + desc='Tweets and related sentiments by selected influencers.', + start_date=pd.to_datetime('2017-01-01'), + end_date=pd.to_datetime('2018-01-15'), + ), + ] + def list(self): subscribers = self.contract.call( {'from': self.default_account} ).getSubscribers() + + subscribed = [] + for index, address in enumerate(subscribers): + if address == self.default_account: + subscribed.append(index) + + data_sources = self.get_data_sources_map() + + data = [] + for index, data_source in enumerate(data_sources): + data.append( + dict( + id=index, + subscribed=index in subscribed, + **data_source, + ) + ) + + df = pd.DataFrame(data) + df.set_index(['id', 'name', 'desc'], drop=True, inplace=True) + set_print_settings() + + formatters = dict( + subscribed=lambda s: u'\u2713' if s else '', + ) + print(df.to_string(formatters=formatters)) + pass def register(self, data_source_name): - test = self.contract.transact( - {'from': self.default_account} - ).subscribe(0) + data_sources = self.get_data_sources_map() + index = next( + (index for (index, d) in enumerate(data_sources) if + d['name'].lower() == data_source_name.lower()), + None + ) + if index is None: + raise ValueError( + 'Data source not found.' + ) + + try: + self.contract.transact( + {'from': self.default_account} + ).subscribe(index) + print( + 'Subscribed to data source {} successfully'.format( + data_source_name + ) + ) + + except Exception as e: + print('Unable to subscribe to data source: {}'.format(e)) + pass def ingest(self, data_source_name, data_frequency, start, end): diff --git a/marketplace/contracts/Marketplace.sol b/marketplace/contracts/Marketplace.sol index 30401e5b..1cc1cf75 100644 --- a/marketplace/contracts/Marketplace.sol +++ b/marketplace/contracts/Marketplace.sol @@ -5,7 +5,7 @@ contract Marketplace { // Adopting a pet function subscribe(uint dataSourceId) public returns (uint) { - require(dataSourceId >= 0 && dataSourceId <= 5); + require(dataSourceId >= 0 && dataSourceId <= 15); subscribers[dataSourceId] = msg.sender; diff --git a/marketplace/test/TestMarketplace.sol b/marketplace/test/TestMarketplace.sol index ea1c7fb3..5c4f6411 100644 --- a/marketplace/test/TestMarketplace.sol +++ b/marketplace/test/TestMarketplace.sol @@ -9,9 +9,9 @@ contract TestMarketplace { // Testing the adopt() function function testUserCanSubscribe() public { - uint returnedId = marketplace.subscribe(0); + uint returnedId = marketplace.subscribe(2); - uint expected = 0; + uint expected = 2; Assert.equal(returnedId, expected, "Adoption of pet ID 8 should be recorded."); } @@ -21,7 +21,7 @@ contract TestMarketplace { // Expected owner is this contract address expected = this; - address adopter = marketplace.subscribers(0); + address adopter = marketplace.subscribers(2); Assert.equal(adopter, expected, "Owner of data source ID 0 should be recorded."); } @@ -34,6 +34,6 @@ contract TestMarketplace { // Store adopters in memory rather than contract's storage address[16] memory subscribers = marketplace.getSubscribers(); - Assert.equal(subscribers[0], expected, "Owner of pet ID 0 should be recorded."); + Assert.equal(subscribers[2], expected, "Owner of pet ID 2 should be recorded."); } } \ No newline at end of file diff --git a/tests/marketplace/test_marketplace.py b/tests/marketplace/test_marketplace.py index e03efc43..1faf0648 100644 --- a/tests/marketplace/test_marketplace.py +++ b/tests/marketplace/test_marketplace.py @@ -1,4 +1,14 @@ from catalyst.marketplace.marketplace import Marketplace +from catalyst.testing.fixtures import WithLogger, ZiplineTestCase -marketplace = Marketplace() -pass \ No newline at end of file + +class TestMarketplace(WithLogger, ZiplineTestCase): + def test_list(self): + marketplace = Marketplace() + marketplace.list() + pass + + def test_register(self): + marketplace = Marketplace() + marketplace.register('GitHub') + pass