Compare commits

...
29 Commits
Author SHA1 Message Date
Victor Grau Serrat 4c84ea8efc DOC: release notes 0.5.8 2018-03-29 10:23:38 -06:00
Victor Grau Serrat c85e698ee2 BLD: [mktplace] switch to mainnet 2018-03-29 10:00:35 -06:00
Victor Grau Serrat 423e30da1e Merge branch 'develop' 2018-03-29 08:28:05 -06:00
Victor Grau Serrat c29b1ef3c1 BLD: deployment of marketplace on mainnet 2018-03-29 08:26:09 -06:00
Victor Grau Serrat 17f9906df4 DOC: updated release notes for 0.5.7 2018-03-29 08:01:58 -06:00
Avishai WeingartenandGitHub 41b5135ed4 Merge pull request #220 from westurner/feature/fix-docker-tags
BLD: Dockerfile[-dev]: s/quantopian/enigmampc/g
2018-03-29 08:49:52 +03:00
Victor Grau Serrat af85ee31c9 BUG: [mktplace] progress counters start at 1, not 0 2018-03-27 18:12:08 -06:00
Victor Grau Serrat 132dffd239 BLD: [mktplace] progress indicator for publishing data 2018-03-27 13:22:30 -06:00
VictorandGitHub 887a7cc825 BUG: [mktplace] removing whitespace from datasets to register 2018-03-26 17:22:53 -06:00
AvishaiW 22249506e6 BUG: #214 #287 added arguments to the _reduce_ function in tha Asset class 2018-03-25 22:53:01 +03:00
Victor Grau Serrat b979ffd123 BLD: [mktplace] json handling improvement 2018-03-23 12:38:37 -06:00
Victor Grau Serrat 0db9950347 DOC: link to forum from install doc 2018-03-22 15:24:50 -06:00
Victor 7c4467d800 DOC: added forum button in README 2018-03-22 15:21:17 -06:00
Victor 30dbeaa5fb DOC: Updated README with link to the forum. 2018-03-22 15:21:13 -06:00
VictorandGitHub 4d6837b5d6 DOC: Updated README with link to the forum. 2018-03-22 15:18:55 -06:00
VictorandGitHub 098a4c4fc6 DOC: added forum button in README 2018-03-22 15:15:31 -06:00
Victor Grau Serrat f5cb6e38d6 DOC: fixed formatting of release notes 2018-03-22 12:13:55 -06:00
Victor Grau Serrat 1bd65397b6 Merge branch 'develop' 2018-03-22 12:02:15 -06:00
Victor Grau Serrat c768b207bc MAINT: [marketplace] output formatting address list 2018-03-22 12:01:21 -06:00
VictorandGitHub e18686d5c5 Merge pull request #278 from izokay/develop
BUG: Error when ingesting marketcap on windows
2018-03-22 12:23:29 -05:00
VictorandGitHub b7779cf363 MAINT: general bug fix for existing path across OS 2018-03-22 11:23:06 -06:00
Victor Grau Serrat 28819b8a32 DOC: updated release notes for 0.5.6 2018-03-21 22:29:21 -06:00
Victor Grau Serrat a56d7f34c7 BLD: [mktplace] support for most wallets, switch to mycrypto 2018-03-21 20:35:18 -05:00
AvishaiW 9f0b3303f1 BUG: #285 #271 changed benchmark to be constant, so it wouldn't ingest data at all, for now 2018-03-21 21:19:40 +02:00
EmbarAlmog 9d7a35658b ENH: when ingesting data of non-existing pair it is now throwing log warning. 2018-03-20 16:12:13 +02:00
Victor Grau Serrat c58cebd1eb ENH: progress on marketplace bundle ingestion 2018-03-19 11:50:39 -06:00
izokayandGitHub 9eb649371b BUG: Error when ingesting on windows
Error message: Cannot create a file when that file already exists: '.catalyst\\data\\marketplace\\temp_bundles\\marketcap-hourly-2018' -> '.catalyst\\data\\marketplace\\marketcap'
2018-03-16 16:50:31 -04:00
izokayandGitHub 7f2ded65bc Merge pull request #2 from enigmampc/develop
Develop
2018-03-16 16:45:03 -04:00
westurner 2d5d2b21ee BLD: Dockerfile[-dev]: s/quantopian/enigmampc/g 2018-02-09 01:40:43 -05:00
16 changed files with 248 additions and 109 deletions
+2 -2
View File
@@ -1,11 +1,11 @@
#
# Dockerfile for an image with the currently checked out version of catalyst installed. To build:
#
# docker build -t quantopian/catalyst .
# docker build -t enigmampc/catalyst .
#
# To run the container:
#
# docker run -v /path/to/your/notebooks:/projects -v ~/.catalyst:/root/.catalyst -p 8888:8888/tcp --name catalyst -it quantopian/catalyst
# docker run -v /path/to/your/notebooks:/projects -v ~/.catalyst:/root/.catalyst -p 8888:8888/tcp --name catalyst -it enigmampc/catalyst
#
# To access Jupyter when running docker locally (you may need to add NAT rules):
#
+5 -5
View File
@@ -1,15 +1,15 @@
#
# Dockerfile for an image with the currently checked out version of catalyst installed. To build:
#
# docker build -t quantopian/catalystdev -f Dockerfile-dev .
# docker build -t enigmampc/catalystdev -f Dockerfile-dev .
#
# Note: the dev build requires a quantopian/catalyst image, which you can build as follows:
# Note: the dev build requires a enigmampc/catalyst image, which you can build as follows:
#
# docker build -t quantopian/catalyst -f Dockerfile .
# docker build -t enigmampc/catalyst -f Dockerfile .
#
# To run the container:
#
# docker run -v /path/to/your/notebooks:/projects -v ~/.catalyst:/root/.catalyst -p 8888:8888/tcp --name catalystdev -it quantopian/catalystdev
# docker run -v /path/to/your/notebooks:/projects -v ~/.catalyst:/root/.catalyst -p 8888:8888/tcp --name catalystdev -it enigmampc/catalystdev
#
# To access Jupyter when running docker locally (you may need to add NAT rules):
#
@@ -25,7 +25,7 @@
#
# docker exec -it catalystdev catalyst run -f /projects/my_algo.py --start 2015-1-1 --end 2016-1-1 /projects/result.pickle
#
FROM quantopian/catalyst
FROM enigmampc/catalyst
WORKDIR /catalyst
+9 -3
View File
@@ -5,6 +5,7 @@
|version tag|
|version status|
|forum|
|discord|
|twitter|
@@ -22,9 +23,11 @@ visit `enigma.co <https://www.enigma.co>`_ to learn more about Catalyst.
Catalyst builds on top of the well-established
`Zipline <https://github.com/quantopian/zipline>`_ project. We did our best to
minimize structural changes to the general API to maximize compatibility with
existing trading algorithms, developer knowledge, and tutorials. Join us on
`Discord <https://discord.gg/SJK32GY>`_ where we have a *#catalyst_dev* channel
for questions around Catalyst, algorithmic trading and technical support.
existing trading algorithms, developer knowledge, and tutorials. Join us on the
`Catalyst Forum <https://catalyst.enigma.co/>`_ for questions around Catalyst,
algorithmic trading and technical support. We also have a
`Discord <https://discord.gg/SJK32GY>`_ group with the *#catalyst_dev* and
*#catalyst_setup* dedicated channels.
Overview
========
@@ -60,6 +63,9 @@ Go to our `Documentation Website <https://enigmampc.github.io/catalyst/>`_.
.. |version status| image:: https://img.shields.io/pypi/pyversions/enigma-catalyst.svg
:target: https://pypi.python.org/pypi/enigma-catalyst
.. |forum| image:: https://img.shields.io/badge/forum-join-green.svg
:target: https://catalyst.enigma.co/
.. |discord| image:: https://img.shields.io/badge/discord-join%20chat-green.svg
:target: https://discordapp.com/invite/SJK32GY
+1 -1
View File
@@ -580,7 +580,7 @@ def ingest_exchange(ctx, exchange_name, data_frequency, start, end,
exchange_bundle = ExchangeBundle(exchange_name)
click.echo('Ingesting exchange bundle {}...'.format(exchange_name),
click.echo('Trying to ingest exchange bundle {}...'.format(exchange_name),
sys.stdout)
exchange_bundle.ingest(
data_frequency=data_frequency,
+8 -3
View File
@@ -630,23 +630,28 @@ cdef class TradingPair(Asset):
and whose second element is a tuple of all the attributes that should
be serialized/deserialized during pickling.
"""
#TODO: make sure that all fields set there
# added arguments for catalyst
return (self.__class__, (self.symbol,
self.exchange,
self.start_date,
self.asset_name,
self.sid,
self.leverage,
self.end_daily,
self.end_minute,
self.end_date,
self.exchange_symbol,
self.first_traded,
self.auto_close_date,
self.exchange_full,
self.min_trade_size,
self.max_trade_size,
self.maker,
self.taker,
self.lot,
self.decimals,
self.taker,
self.maker))
self.trading_state,
self.data_source))
def make_asset_array(int size, Asset asset):
cdef np.ndarray out = np.empty([size], dtype=object)
+4 -3
View File
@@ -24,8 +24,7 @@ AUTO_INGEST = False
AUTH_SERVER = 'https://data.enigma.co'
# TODO: switch to mainnet
ETH_REMOTE_NODE = 'https://rinkeby.infura.io/'
ETH_REMOTE_NODE = 'https://mainnet.infura.io'
MARKETPLACE_CONTRACT = 'https://raw.githubusercontent.com/enigmampc/' \
'catalyst/master/catalyst/marketplace/' \
@@ -35,7 +34,6 @@ MARKETPLACE_CONTRACT_ABI = 'https://raw.githubusercontent.com/enigmampc/' \
'catalyst/master/catalyst/marketplace/' \
'contract_marketplace_abi.json'
# TODO: switch to mainnet
ENIGMA_CONTRACT = 'https://raw.githubusercontent.com/enigmampc/' \
'catalyst/master/catalyst/marketplace/' \
'contract_enigma_address.txt'
@@ -43,3 +41,6 @@ ENIGMA_CONTRACT = 'https://raw.githubusercontent.com/enigmampc/' \
ENIGMA_CONTRACT_ABI = 'https://raw.githubusercontent.com/enigmampc/' \
'catalyst/master/catalyst/marketplace/' \
'contract_enigma_abi.json'
SUPPORTED_WALLETS = ['metamask', 'ledger', 'trezor', 'bitbox', 'keystore',
'key']
+2 -6
View File
@@ -199,12 +199,8 @@ class Exchange:
)
assets.append(asset)
except SymbolNotFoundOnExchange:
log.debug(
'skipping non-existent market {} {}'.format(
self.name, symbol
)
)
except SymbolNotFoundOnExchange as e:
log.warn(e)
return assets
def get_asset(self, symbol, data_frequency=None, is_exchange_symbol=False,
+45 -44
View File
@@ -22,7 +22,7 @@ from catalyst.exchange.exchange_errors import EmptyValuesInBundleError, \
PricingDataNotLoadedError, DataCorruptionError, PricingDataValueError
from catalyst.exchange.utils.bundle_utils import range_in_bundle, \
get_bcolz_chunk, get_df_from_arrays, get_assets
from catalyst.exchange.utils.datetime_utils import get_delta, get_start_dt, \
from catalyst.exchange.utils.datetime_utils import get_start_dt, \
get_period_label, get_month_start_end, get_year_start_end
from catalyst.exchange.utils.exchange_utils import get_exchange_folder, \
save_exchange_symbols, mixin_market_params, get_catalyst_symbol
@@ -232,12 +232,12 @@ class ExchangeBundle:
problem = '{name} ({start_dt} to {end_dt}) has empty ' \
'periods: {dates}'.format(
name=asset.symbol,
start_dt=asset.start_date.strftime(
DATE_TIME_FORMAT),
end_dt=end_dt.strftime(DATE_TIME_FORMAT),
dates=[date.strftime(
DATE_TIME_FORMAT) for date in dates])
name=asset.symbol,
start_dt=asset.start_date.strftime(
DATE_TIME_FORMAT),
end_dt=end_dt.strftime(DATE_TIME_FORMAT),
dates=[date.strftime(
DATE_TIME_FORMAT) for date in dates])
if empty_rows_behavior == 'warn':
log.warn(problem)
@@ -286,12 +286,12 @@ class ExchangeBundle:
problem = '{name} ({start_dt} to {end_dt}) has {threshold} ' \
'identical close values on: {dates}'.format(
name=asset.symbol,
start_dt=asset.start_date.strftime(DATE_TIME_FORMAT),
end_dt=end_dt.strftime(DATE_TIME_FORMAT),
threshold=threshold,
dates=[pd.to_datetime(date).strftime(DATE_TIME_FORMAT)
for date in dates])
name=asset.symbol,
start_dt=asset.start_date.strftime(DATE_TIME_FORMAT),
end_dt=end_dt.strftime(DATE_TIME_FORMAT),
threshold=threshold,
dates=[pd.to_datetime(date).strftime(DATE_TIME_FORMAT)
for date in dates])
problems.append(problem)
@@ -458,7 +458,7 @@ class ExchangeBundle:
last_entry = None
if start is None or \
(earliest_trade is not None and earliest_trade > start):
(earliest_trade is not None and earliest_trade > start):
start = earliest_trade
if last_entry is not None and (end is None or end > last_entry):
@@ -598,16 +598,41 @@ class ExchangeBundle:
# we want to give an end_date far in time
writer = self.get_writer(start_dt, end_dt, data_frequency)
if show_breakdown:
for asset in chunks:
if chunks:
for asset in chunks:
with maybe_show_progress(
chunks[asset],
show_progress,
label='Ingesting {frequency} price data for '
'{symbol} on {exchange}'.format(
exchange=self.exchange_name,
frequency=data_frequency,
symbol=asset.symbol
)) as it:
for chunk in it:
problems += self.ingest_ctable(
asset=chunk['asset'],
data_frequency=data_frequency,
period=chunk['period'],
writer=writer,
empty_rows_behavior='strip',
cleanup=True
)
else:
all_chunks = list(chain.from_iterable(itervalues(chunks)))
# We sort the chunks by end date to ingest most recent data first
if all_chunks:
all_chunks.sort(
key=lambda chunk: pd.to_datetime(chunk['period'])
)
with maybe_show_progress(
chunks[asset],
all_chunks,
show_progress,
label='Ingesting {frequency} price data for '
'{symbol} on {exchange}'.format(
label='Ingesting {frequency} price data on '
'{exchange}'.format(
exchange=self.exchange_name,
frequency=data_frequency,
symbol=asset.symbol
)) as it:
)) as it:
for chunk in it:
problems += self.ingest_ctable(
asset=chunk['asset'],
@@ -617,30 +642,6 @@ class ExchangeBundle:
empty_rows_behavior='strip',
cleanup=True
)
else:
all_chunks = list(chain.from_iterable(itervalues(chunks)))
# We sort the chunks by end date to ingest most recent data first
all_chunks.sort(
key=lambda chunk: pd.to_datetime(chunk['period'])
)
with maybe_show_progress(
all_chunks,
show_progress,
label='Ingesting {frequency} price data on '
'{exchange}'.format(
exchange=self.exchange_name,
frequency=data_frequency,
)) as it:
for chunk in it:
problems += self.ingest_ctable(
asset=chunk['asset'],
data_frequency=data_frequency,
period=chunk['period'],
writer=writer,
empty_rows_behavior='strip',
cleanup=True
)
if show_report and len(problems) > 0:
log.info('problems during ingestion:{}\n'.format(
+18 -5
View File
@@ -95,11 +95,24 @@ class TradingEnvironment(object):
if not trading_calendar:
trading_calendar = get_calendar("NYSE")
self.benchmark_returns, self.treasury_curves = load(
trading_calendar.day,
trading_calendar.schedule.index,
self.bm_symbol,
)
# todo: uncomment and add a well defined benchmark
# self.benchmark_returns, self.treasury_curves = load(
# trading_calendar.day,
# trading_calendar.schedule.index,
# self.bm_symbol,
# exchange=exchange,
# )
start_data = get_calendar('OPEN').first_trading_session
end_data = pd.Timestamp.utcnow()
treasure_cols = ['1month', '3month', '6month', '1year', '2year',
'3year', '5year', '7year', '10year', '20year', '30year']
self.benchmark_returns = pd.DataFrame(data=0.001,
index=pd.date_range(start_data, end_data),
columns=['close'])
self.treasury_curves = pd.DataFrame(data=0.001,
index=pd.date_range(start_data, end_data),
columns=treasure_cols)
self.exchange_tz = exchange_tz
@@ -1 +1 @@
0x39a54f480d922a58c963de8091a6c9afc69db2cf
0xf0ee6b27b759c9893ce4f094b49ad28fd15a23e4
@@ -1 +1 @@
0xa2b37c6cd52f60fd4eb46ca59fafcf22d081aebc
0xa64927358a82254be92eb1f1cb01de68d1787004
+46 -24
View File
@@ -69,7 +69,10 @@ class Marketplace:
contract_url.info().get_content_charset()).strip())
abi_url = urllib.urlopen(MARKETPLACE_CONTRACT_ABI)
abi = json.load(abi_url)
abi_url = abi_url.read().decode(
abi_url.info().get_content_charset())
abi = json.loads(abi_url)
self.mkt_contract = self.web3.eth.contract(
self.mkt_contract_address,
@@ -83,7 +86,10 @@ class Marketplace:
contract_url.info().get_content_charset()).strip())
abi_url = urllib.urlopen(ENIGMA_CONTRACT_ABI)
abi = json.load(abi_url)
abi_url = abi_url.read().decode(
abi_url.info().get_content_charset())
abi = json.loads(abi_url)
self.eng_contract = self.web3.eth.contract(
self.eng_contract_address,
@@ -126,9 +132,10 @@ class Marketplace:
else:
while True:
for i in range(0, len(self.addresses)):
print('{}\t{}\t{}'.format(
print('{}\t{}\t{}\t{}'.format(
i,
self.addresses[i]['pubAddr'],
self.addresses[i]['wallet'].ljust(10),
self.addresses[i]['desc'])
)
address_i = int(input('Choose your address associated with '
@@ -145,7 +152,7 @@ class Marketplace:
def sign_transaction(self, tx):
url = 'https://www.myetherwallet.com/#offline-transaction'
url = 'https://www.mycrypto.com/#offline-transaction'
print('\nVisit {url} and enter the following parameters:\n\n'
'From Address:\t\t{_from}\n'
'\n\tClick the "Generate Information" button\n\n'
@@ -430,10 +437,9 @@ class Marketplace:
merge_bundles(zsource, ztarget)
else:
shutil.rmtree(bundle_folder, ignore_errors=True)
os.rename(tmp_bundle, bundle_folder)
pass
def ingest(self, ds_name=None, start=None, end=None, force_download=False):
if ds_name is None:
@@ -498,20 +504,29 @@ class Marketplace:
key = self.addresses[address_i]['key']
secret = self.addresses[address_i]['secret']
else:
key, secret = get_key_secret(address)
key, secret = get_key_secret(address,
self.addresses[address_i]['wallet'])
headers = get_signed_headers(ds_name, key, secret)
log.debug('Starting download of dataset for ingestion...')
log.info('Starting download of dataset for ingestion...')
r = requests.post(
'{}/marketplace/ingest'.format(AUTH_SERVER),
headers=headers,
stream=True,
)
if r.status_code == 200:
log.info('Dataset downloaded successfully. Processing dataset...')
target_path = get_temp_bundles_folder()
try:
decoder = MultipartDecoder.from_response(r)
# with maybe_show_progress(
# iter(decoder.parts),
# True,
# label='Processing files') as part:
counter = 1
for part in decoder.parts:
log.info("Processing file {} of {}".format(
counter, len(decoder.parts)))
h = part.headers[b'Content-Disposition'].decode('utf-8')
# Extracting the filename from the header
name = re.search(r'filename="(.*)"', h).group(1)
@@ -525,6 +540,7 @@ class Marketplace:
f.write(part.content)
self.process_temp_bundle(ds_name, filename)
counter += 1
except NonMultipartContentTypeException:
response = r.json()
@@ -592,7 +608,6 @@ class Marketplace:
folder = get_bundle_folder(ds_name, data_frequency)
shutil.rmtree(folder)
pass
def create_metadata(self, key, secret, ds_name, data_frequency, desc,
has_history=True, has_live=True):
@@ -628,7 +643,7 @@ class Marketplace:
def register(self):
while True:
desc = input('Enter the name of the dataset to register: ')
dataset = desc.lower()
dataset = desc.lower().strip()
provider_info = self.mkt_contract.functions.getDataProviderInfo(
Web3.toHex(dataset)
).call()
@@ -684,7 +699,8 @@ class Marketplace:
key = self.addresses[address_i]['key']
secret = self.addresses[address_i]['secret']
else:
key, secret = get_key_secret(address)
key, secret = get_key_secret(address,
self.addresses[address_i]['wallet'])
grains = to_grains(price)
@@ -765,28 +781,34 @@ class Marketplace:
key = match['key']
secret = match['secret']
else:
key, secret = get_key_secret(provider_info[0])
key, secret = get_key_secret(provider_info[0], match['wallet'])
headers = get_signed_headers(dataset, key, secret)
filenames = glob.glob(os.path.join(datadir, '*.csv'))
if not filenames:
raise MarketplaceNoCSVFiles(datadir=datadir)
files = []
for file in filenames:
for idx, file in enumerate(filenames):
log.info('Uploading file {} of {}: {}'.format(
idx+1, len(filenames), file))
files = []
files.append(('file', open(file, 'rb')))
r = requests.post('{}/marketplace/publish'.format(AUTH_SERVER),
files=files,
headers=headers)
headers = get_signed_headers(dataset, key, secret)
r = requests.post('{}/marketplace/publish'.format(AUTH_SERVER),
files=files,
headers=headers)
if r.status_code != 200:
raise MarketplaceHTTPRequest(request='upload file',
error=r.status_code)
if r.status_code != 200:
raise MarketplaceHTTPRequest(request='upload file',
error=r.status_code)
if 'error' in r.json():
raise MarketplaceHTTPRequest(request='upload file',
error=r.json()['error'])
if 'error' in r.json():
raise MarketplaceHTTPRequest(request='upload file',
error=r.json()['error'])
print('Dataset {} uploaded successfully.'.format(dataset))
log.info('File processed successfully.')
print('\nDataset {} uploaded and processed successfully.'.format(
dataset))
+11 -9
View File
@@ -10,10 +10,10 @@ from catalyst.marketplace.marketplace_errors import (
MarketplaceEmptySignature)
from catalyst.marketplace.utils.path_utils import (
get_user_pubaddr, save_user_pubaddr)
from catalyst.constants import AUTH_SERVER
from catalyst.constants import AUTH_SERVER, SUPPORTED_WALLETS
def get_key_secret(pubAddr, wallet='mew'):
def get_key_secret(pubAddr, wallet):
"""
Obtain a new key/secret pair from authentication server
@@ -43,21 +43,22 @@ def get_key_secret(pubAddr, wallet='mew'):
auth_type, auth_info = header.split(None, 1)
d = requests.utils.parse_dict_header(auth_info)
nonce = '0x{}'.format(d['nonce'])
nonce = 'Catalyst nonce: 0x{}'.format(d['nonce'])
if wallet == 'mew':
url = 'https://www.myetherwallet.com/signmsg.html'
if wallet in SUPPORTED_WALLETS:
url = 'https://www.mycrypto.com/signmsg.html'
print('\nObtaining a key/secret pair to streamline all future '
'requests with the authentication server.\n'
'Visit {url} and sign the '
'following message:\n{nonce}'.format(
'following message (copy the entire line, without the '
'line break at the end):\n\n{nonce}'.format(
url=url,
nonce=nonce))
webbrowser.open_new(url)
signature = input('Copy and Paste the "sig" field from '
signature = input('\nCopy and Paste the "sig" field from '
'the signature here (without the double quotes, '
'only the HEX value):\n')
else:
@@ -91,7 +92,8 @@ def get_key_secret(pubAddr, wallet='mew'):
addresses = get_user_pubaddr()
match = next((l for l in addresses if
l['pubAddr'] == pubAddr), None)
l['pubAddr'].lower() == pubAddr.lower()), None)
match['key'] = response.json()['key']
match['secret'] = response.json()['secret']
@@ -121,7 +123,7 @@ def get_signed_headers(ds_name, key, secret):
-------
"""
nonce = str(int(time.time()))
nonce = str(int(time.time() * 1000))
signature = hmac.new(
secret.encode('utf-8'),
+49 -2
View File
@@ -2,6 +2,7 @@ import os
import json
import tarfile
from catalyst.constants import SUPPORTED_WALLETS
from catalyst.utils.deprecate import deprecated
from catalyst.utils.paths import data_root, ensure_directory
from catalyst.marketplace.marketplace_errors import MarketplaceJSONError
@@ -131,17 +132,63 @@ def get_user_pubaddr(environ=None):
try:
d = data[0]['pubAddr']
except Exception as e:
return [data, ]
data = [data, ]
changed = False
for idx, d in enumerate(data):
try:
if d['wallet'] not in SUPPORTED_WALLETS:
data[idx]['wallet'] = _choose_wallet(
d['pubAddr'], False)
changed = True
except KeyError:
data[idx]['wallet'] = _choose_wallet(
d['pubAddr'], True)
changed = True
if changed:
save_user_pubaddr(data)
return data
else:
data = []
data.append(dict(pubAddr='', desc=''))
data.append(dict(pubAddr='', desc='', wallet=''))
with open(filename, 'w') as f:
json.dump(data, f, sort_keys=False, indent=2,
separators=(',', ':'))
return data
def _choose_wallet(pubAddr, missing):
while True:
if missing:
print('\nYou need to specify a wallet for address '
'{}.'.format(pubAddr))
else:
print('\nThe wallet specified for address {} is not '
'supported.'.format(pubAddr))
print('Please choose among the following options:')
for idx, wallet in enumerate(SUPPORTED_WALLETS):
print('{}\t{}'.format(idx, wallet))
lw = len(SUPPORTED_WALLETS)-1
w = input('Choose a number between 0 and {}: '.format(
lw))
try:
w = int(w)
except ValueError:
print('Enter a number between 0 and {}'.format(lw))
else:
if w not in range(0, lw+1):
print('Enter a number between 0 and '
'{}'.format(lw))
else:
return SUPPORTED_WALLETS[w]
def save_user_pubaddr(data, environ=None):
"""
Saves the user's public addresses and their related metadata in
+4
View File
@@ -562,6 +562,10 @@ If after following the instructions above, and going through the
*Troubleshooting* sections, you still experience problems installing Catalyst,
you can seek additional help through the following channels:
- Join our `Catalyst Forum <https://catalyst.enigma.co/>`_, and browse a variety
of topics and conversations around common issues that others face when using
Catalyst, and how to resolve them. And join the conversation!
- Join our `Discord community <https://discord.gg/SJK32GY>`_, and head over
the #catalyst_dev channel where many other users (as well as the project
developers) hang out, and can assist you with your particular issue. The
+42
View File
@@ -2,6 +2,48 @@
Release Notes
=============
Version 0.5.8
^^^^^^^^^^^^^
**Release Date**: 2018-03-29
Bug Fixes
~~~~~~~~~
- Fix proper release of Data Marketplace on mainnet.
Version 0.5.7
^^^^^^^^^^^^^
**Release Date**: 2018-03-29
Build
~~~~~
- Data Marketplace deployed on mainnet.
- Added progress indicators for publishing data, and made the data publishing
synchronous to provide feedback to the publisher.
Bug Fixes
~~~~~~~~~
- Added arguments to the ``reduce`` function in tha Asset class :issue:`214`,
:issue:`287`
Version 0.5.6
^^^^^^^^^^^^^
**Release Date**: 2018-03-22
Build
~~~~~
- Data Marketplace: ensures compatibility across wallets, now fully supporting
``ledger``, ``trezor``, ``keystore``, ``private key``. Partial support for
``metamask`` (includes sign_msg, but not sign_tx). Current support for
``Digital Bitbox`` is unknown, but believed to be supported.
- Data Marketplace: Switched online provider from MyEtherWallet to MyCrypto.
- Data Marketplace: Added progress indicator for data ingestion.
Bug Fixes
~~~~~~~~~
- Changed benchmark to be constant, so it doesn't ingest data at all. Temporary
fix for :issue:`271`, :issue:`285`
Version 0.5.5
^^^^^^^^^^^^^
**Release Date**: 2018-03-19