Full Code of kennethreitz/coinbin.org for AI

master bc3232fe5157 cached
15 files
44.5 KB
16.3k tokens
31 symbols
1 requests
Download .txt
Repository: kennethreitz/coinbin.org
Branch: master
Commit: bc3232fe5157
Files: 15
Total size: 44.5 KB

Directory structure:
gitextract_12qrf40r/

├── .gitignore
├── Pipfile
├── Procfile
├── README.md
├── app.json
├── graph.py
├── predictions.py
├── scraper.py
├── server.py
├── static/
│   ├── LICENSE
│   ├── README.md
│   ├── latex.css
│   └── tufte.css
├── templates/
│   └── index.html
└── wallets.py

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================

/.envrc


================================================
FILE: Pipfile
================================================
[[source]]

url = "https://pypi.python.org/simple"
verify_ssl = true


[packages]

flask = "*"
records = "*"
"psycopg2" = "*"
maya = "*"
flask-sslify = "*"
pyquery = "*"
pandas = "*"
"html5lib" = "*"
"bs4" = "*"
requests = "*"
simplejson = "*"
flask-cache = "*"
flask-common = "*"
aiohttp = "<2.0.0"
crayons = "*"
scikit-learn = "*"
scipy = "*"
pandas-datareader = "*"
numpy = "*"
tablib = "==0.12.0"
fbprophet = "*"
cython = "*"
flask-graphql = "*"
graphene = "*"
"mpld3" = "*"
raven = {extras = ["flask"]}
"ruamel.ordereddict" = {version="*",  markers="python_version < '3.0.0'"}


[requires]

python_version = "3.6"


================================================
FILE: Procfile
================================================
web: gunicorn server:app -k gaiohttp

================================================
FILE: README.md
================================================
# ₿ Coinbin.org

### The Human–Friendly API Service for Crypto Currency Information.

This free web service exists to provide information on "coins". Supports all crypto–currencies.

### Example API Endpoints

`$ curl https://coinbin.org/lbc`

```json
{
  "coin": {
    "name": "LBRY Credits", 
    "rank": "100", 
    "ticker": "lbc", 
    "value": 0.429737, 
    "value.currency": "USD"
  }
}
```
      

`$ curl https://coinbin.org/lbc/42.01`

```json
{
  "coin": {
    "exchange_rate": 0.429737, 
    "value": 18.053251369999998, 
    "value.currency": "USD"
  }
}
```
      

`$ curl https://coinbin.org/lbc/to/sc`

```
{
  "coin": {
    "exchange_rate": 61.98696034733942
  }
}
```
      

`$ curl https://coinbin.org/lbc/42.01/to/sc`

```json
{
  "coin": {
    "exchange_rate": 61.98696034733942, 
    "value": 2604.072204191729, 
    "value.coin": "sc"
  }
}
```

`$ curl https://coinbin.org/lbc/history`

```json
{
  "history": [
    {
      "timestamp": "2017-08-24T04:00:55.932092Z",
      "value": 0.3404,
      "value.currency": "USD",
      "when": "today"
    }, ...

... {
      "timestamp": "2016-07-12T04:01:09.167162Z",
      "value": 0.239634,
      "value.currency": "USD",
      "when": "Jul 12 2016"
    }
  ]
}
```

## More Resources

- [Awesome Crypto Currency Tools & Algorithms (Guide)](https://github.com/kennethreitz/awesome-coins)


================================================
FILE: app.json
================================================
{
  "name": "coinbin.org",
  "scripts": {
  },
  "env": {
    "API_KEYS": {
      "required": true
    },
    "HEROKU_POSTGRESQL_AMBER_URL": {
      "required": true
    },
    "HEROKU_POSTGRESQL_TEAL_URL": {
      "required": true
    },
    "SENTRY_DSN": {
      "required": true
    },
    "WEB_CONCURRENCY": {
      "required": true
    }
  },
  "formation": {
  },
  "addons": [
    "heroku-postgresql",
    "heroku-postgresql",
    "sentry"
  ],
  "buildpacks": [
    {
      "url": "heroku/python"
    }
  ]
}


================================================
FILE: graph.py
================================================
import scraper

import graphene


def name_to_ticker(name):
    for coin in scraper.get_coins().values():
        if coin['name'].lower() == name.lower():
            return coin['ticker']



class Coin(graphene.ObjectType):
    ticker = graphene.String()
    name = graphene.String()
    rank = graphene.Int()
    usd = graphene.Float()

    @classmethod
    def from_coin(klass, c):

        klass.ticker = c.ticker
        klass.name = c.name
        klass.rank = c.rank
        klass.usd = c.usd

        return klass


class Query(graphene.ObjectType):
    coin = graphene.Field(Coin, name=graphene.String())
    recent_top_coins = graphene.List(Coin)

    @graphene.resolve_only_args
    def resolve_coin(self, name=None, ticker=None):
        if name and not ticker:
            ticker = name_to_ticker(name)

        c = Coin.from_coin(scraper.Coin(ticker))

        c.name = name
        return c

schema = graphene.Schema(query=Query)

================================================
FILE: predictions.py
================================================
import time
import uuid

import records
import os

import maya
import numpy as np
import pandas as pd

# Matplotlib hack.

import matplotlib
matplotlib.use('agg')

import mpld3
from fbprophet import Prophet

from scraper import Coin, MWT, convert_to_decimal


PERIODS = 30
GRAPH_PERIODS = 365



@MWT(timeout=300)
def get_predictions(coin, render=False):
    """Returns a list of predictions, unless render is True.
    Otherwise, returns the path of a rendered image.
    """

    c = Coin(coin)

    q = "SELECT date as ds, value as y from api_coin WHERE name=:coin"

    db = records.Database()
    rows = db.query(q, coin=c.name)

    df = rows.export('df')

    df['y_orig'] = df['y']  # to save a copy of the original data..you'll see why shortly. 

    # log-transform y
    df['y'] = np.log(df['y'])

    model = Prophet(weekly_seasonality=True, yearly_seasonality=True)
    model.fit(df)

    periods = PERIODS if not render else GRAPH_PERIODS

    future_data = model.make_future_dataframe(periods=periods, freq='d')
    forecast_data = model.predict(future_data)

    if render:
        matplotlib.pyplot.gcf()
        fig = model.plot(forecast_data, xlabel='Date', ylabel='log($)')
        return mpld3.fig_to_html(fig)

    forecast_data_orig = forecast_data  # make sure we save the original forecast data
    forecast_data_orig['yhat'] = np.exp(forecast_data_orig['yhat'])
    forecast_data_orig['yhat_lower'] = np.exp(forecast_data_orig['yhat_lower'])
    forecast_data_orig['yhat_upper'] = np.exp(forecast_data_orig['yhat_upper'])

    df['y_log'] = df['y']  #copy the log-transformed data to another column
    df['y'] = df['y_orig']  #copy the original data to 'y'

    # print(forecast_data_orig)
    d = forecast_data_orig['yhat'].to_dict()
    predictions = []

    for i, k in enumerate(list(d.keys())[-PERIODS:]):
        w = maya.when(f'{i+1} days from now')
        predictions.append({
            'when': w.slang_time(),
            'timestamp': w.iso8601(),
            'usd': convert_to_decimal(d[k]),
        })

    return predictions


if __name__ == '__main__':
    print(get_predictions('btc'))


================================================
FILE: scraper.py
================================================
import pandas
import requests

import crayons
from pyquery import PyQuery as pq

import time
from collections import OrderedDict
from decimal import Decimal

url = 'https://coinmarketcap.com/currencies/views/all/'
session = requests.Session()


class MWT(object):
    """Memoize With Timeout"""
    _caches = {}
    _timeouts = {}

    def __init__(self, timeout=2):
        self.timeout = timeout

    def collect(self):
        """Clear cache of results which have timed out"""
        for func in self._caches:
            cache = {}
            for key in self._caches[func]:
                if (time.time() - self._caches[func][key][1]) < self._timeouts[func]:
                    cache[key] = self._caches[func][key]
            self._caches[func] = cache

    def __call__(self, f):
        self.cache = self._caches[f] = {}
        self._timeouts[f] = self.timeout

        def func(*args, **kwargs):
            kw = sorted(kwargs.items())
            key = (args, tuple(kw))
            try:
                v = self.cache[key]
                if (time.time() - v[1]) > self.timeout:
                    raise KeyError
            except KeyError:
                v = self.cache[key] = f(*args, **kwargs), time.time()
            return v[0]
        func.func_name = f.__name__

        return func


def convert_to_decimal(f):
    return Decimal("{0:.8f}".format(f))


class Coin():
    """A Coin, unlike Mario's."""

    def __init__(self, ticker):
        self.ticker = ticker
        self.name = None
        self.rank = None
        self._value = None

        self.update()

    def update(self):
        coins = get_coins()
        print(f'Fetching data on {crayons.cyan(self.ticker)}...')

        self.name = coins[self.ticker]['name']
        self.rank = coins[self.ticker]['rank']
        self._usd = coins[self.ticker]['usd']

    @property
    def usd(self):
        return self._usd

    @property
    def btc(self):
        coins = get_coins()
        rate = coins['btc']['usd']
        return convert_to_decimal(self.usd / rate)

    def value(self, coin):
        """Example: BTC -> ETH"""
        return convert_to_decimal(self.btc / Coin(coin).btc)

    def __repr__(self):
        return f'<Coin ticker={self.ticker!r}>'


@MWT(timeout=300)
def get_coins():
    coins_db = OrderedDict()

    print(crayons.yellow('Scraping CoinMaketCap...'))

    r = session.get(url)
    html = pq(pq(r.content)('table')[0]).html()
    df = pandas.read_html("<table>{}</table>".format(html))
    df = pandas.concat(df)

    btc_value = float(df.to_dict()['Price'][0][1:].replace(',', ''))

    for row in df.itertuples():

        rank = int(row[1])
        name = ' '.join(row[2].split()[1:])
        ticker = row[3].lower()
        try:
            usd = float(row[5][1:].replace(',', ''))
        except ValueError:
            usd = 0
        finally:
            pass

        btc = convert_to_decimal(usd / btc_value)

        coins_db.update({ticker: {'rank': rank, 'name': name, 'ticker': ticker, 'usd': usd, 'btc': btc}})

    return coins_db


def get_coin(ticker):
    return Coin(ticker)
	
if __name__ == '__main__':
	print(get_coins())


================================================
FILE: server.py
================================================
import os

from scraper import get_coins, get_coin, Coin, convert_to_decimal
from predictions import get_predictions
from graph import schema

from flask import Flask, jsonify, render_template, request, send_file
from flask_graphql import GraphQLView
from flask_cache import Cache
from flask_common import Common
from flask_sslify import SSLify

import crayons
import maya
import requests
import records


API_KEYS = os.environ.get('API_KEYS', '').split(':')

db = records.Database()
pro_db = records.Database(os.environ['HEROKU_POSTGRESQL_TEAL_URL'])

app = Flask(__name__)
app.debug = 'DEBUG' in os.environ

common = Common(app)
sslify = SSLify(app)

@app.route('/')
@common.cache.cached(timeout=60)
def hello():

    lbc = get_coin('lbc')
    lbc_42 = get_value_int('lbc', 42.01)
    lbc_sc = get_exchange('lbc', 'sc')
    lbc_42_sc = get_exchange_value('lbc', 'sc', 42.01)
    lbc_forecast = get_forecast('lbc')

    return render_template('index.html', lbc=lbc, lbc_42=lbc_42, lbc_sc=lbc_sc, lbc_42_sc=lbc_42_sc, coins=get_coins().values(), lbc_forecast=lbc_forecast)

@app.route('/coins')
def all_coins():
    return jsonify(coins=get_coins())


@app.route('/<coin>')
def get_coin(coin):
    c = Coin(coin.lower())

    return jsonify(coin={
        'name': c.name,
        'ticker': c.ticker,
        'rank': c.rank,
        'usd': c.usd,
        'btc': c.btc
    })


@app.route('/<coin>/forecast')
def get_forecast(coin):
    return jsonify(forecast=get_predictions(coin.lower()))


@app.route('/<coin>/forecast/graph')
def get_forecast_graph(coin):
    return get_predictions(coin.lower(), render=True)
    # return send_file(f_name, mimetype='image/png')


@app.route('/<coin>/<float:n>')
def get_value(coin, n):
    c = Coin(coin.lower())
    return jsonify(coin={
        'usd': convert_to_decimal(c.usd * n),
        'exchange_rate': c.usd
    })


@app.route('/<coin>/<int:n>')
def get_value_int(coin, n):
    return get_value(coin, n)


@app.route('/<coin>/history')
def get_history(coin):
    c = Coin(coin.lower())

    q = "SELECT * from api_coin WHERE name=:coin ORDER BY date desc"

    if request.args.get('key') in API_KEYS:
        print(crayons.red('Pro request!'))
        rows = pro_db.query(q, coin=c.name)
    else:
        rows = db.query(q, coin=c.name)

    return jsonify(history=[
        {
            'value': r.value,
            'value.currency': 'USD',
            'timestamp': maya.MayaDT.from_datetime(r.date).subtract(hours=4).iso8601(),
            'when': maya.MayaDT.from_datetime(r.date).subtract(hours=4).slang_time()
        } for r in rows]
    )

@app.route('/<coin1>/to/<coin2>')
def get_exchange(coin1, coin2):
    c = Coin(coin1.lower())
    return jsonify(coin={
        # 'name': c.name,
        # 'ticker': c.ticker,
        'exchange_rate': c.value(coin2.lower()),
    })


@app.route('/<coin1>/<float:n>/to/<coin2>/')
def get_exchange_value(coin1, coin2, n):
    c = Coin(coin1.lower())
    v = c.value(coin2.lower())
    n = convert_to_decimal(n)

    return jsonify(coin={
        'value': convert_to_decimal(v * n),
        'value.coin': coin2,
        'exchange_rate': v
    })


@app.route('/<coin1>/<int:n>/to/<coin2>/')
def get_exchange_value_int(coin1, coin2, n):
    return get_exchange_value(coin1.lower(), coin2, n)


# GraphQL stuff.
app.add_url_rule('/graphql', view_func=GraphQLView.as_view('graphql', schema=schema, graphiql=True))
# app.add_url_rule('/graphql/batch', view_func=GraphQLView.as_view('graphql', schema=schema, batch=True))


if __name__ == '__main__':
    common.serve()


================================================
FILE: static/LICENSE
================================================
The MIT License (MIT)

Copyright (c) 2014 Dave Liepmann

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.



================================================
FILE: static/README.md
================================================
Tufte CSS
=========
Edward Tufte uses a distinctive style in his handouts: simple, with well-set
typography, extensive sidenotes, and tight integration of graphics and
charts. `tufte-css` brings that style to HTML documents.

This project is directly inspired by and
based on [Tufte-LaTeX](https://tufte-latex.github.io/tufte-latex/) and the
[R Markdown Tufte Handout](http://rmarkdown.rstudio.com/examples/tufte-handout.pdf).

Getting Started
-
The file *index.html* is a self-describing demonstration document that walks through
the features of Tufte CSS. The live version at
[https://edwardtufte.github.io/tufte-css/](https://edwardtufte.github.io/tufte-css/)
is the best overview of the project.

To use Tufte CSS, just copy `tufte.css` and the `et-book` font
directory to your project and add the following to your HTML doc's
head block:

```html
<link rel="stylesheet" href="tufte.css"/>
```

All other files in the repository can be ignored, as they are merely
used by the demonstration document.

Contributing
-
If you notice something wrong or broken, let us know by opening an
issue. **Pull requests are very welcome**.

For best results, keep pull requests to one change at a time, and
test your fix or new functionality against `index.html` on screens as
small as an iPhone 4 and as big as, well, as big as you use
normally. (If you don't have a mobile device handy, fake different
devices with your browser's developer tools.)  See the Issues page, especially
[Help Wanted](https://github.com/edwardtufte/tufte-css/labels/help%20wanted),
for opportunities to contribute. Keep our style guide in mind:

CSS Style Guide
-
>Every major open-source project has its own style guide: a set of
>conventions (sometimes arbitrary) about how to write code for that
>project. It is much easier to understand a large codebase when all the
>code in it is in a consistent style. <br/>
> -- [Google Style Guide](https://github.com/google/styleguide)

Tufte CSS aims for clarity, concision, and uniformity. Here's a basic
example of our CSS conventions:

```css
p { font-size: 1.4rem;
    line-height: 2rem;
    margin-top: 1.4rem;
    margin-bottom: 1.4rem;
    width: 55%;
    padding-right: 0;
    vertical-align: baseline; }
    
@media screen and (max-width: 600px) { p { width: 70%; }}
@media screen and (max-width: 400px) { p { width: 90%; }}
```

Notice the single spacing between most syntactic markers, the single
blank lines between unrelated blocks, and the absence of line breaks
after an open-paren and before end-parens. Notice also that these
rules change slightly for media queries.

Contributors
-
 - Dave Liepmann (creator, project maintainer, design)
 - Edward Tufte (editing, direction, design)
 - [Adam Schwartz](https://github.com/adamschwartz) (ET Book font, descender-clearing link underlines)
 - [Clay Harmon](https://github.com/edwardtufte/tufte-css/commits/master?author=clayh53) (media queries, rem units)
 - [Linjie Ding](https://github.com/edwardtufte/tufte-css/commits/master?author=pyrocat101) (italic typeface)
 - [Stephen A Thomas](https://github.com/edwardtufte/tufte-css/commits/master?author=sathomas) (automagically numbered sidenotes)
 - [Ben Newman](https://github.com/edwardtufte/tufte-css/pull/9) (sidenote numbering style)
 - [Kevin Godby](https://github.com/edwardtufte/tufte-css/commits/master?author=godbyk) (booktabs tables)
 - [James Kolce](https://github.com/edwardtufte/tufte-css/commits/master?author=jameskolce) (sidenote fixes)
 - [Chris MacKay](https://github.com/crmackay) (sidenote toggling on small screens)
 - [Paul Rodriguez](https://github.com/edwardtufte/tufte-css/commits/master?author=ruricolist)
   (sidenote style tweaks)
 - [Claudiu-Vlad Ursache](https://github.com/edwardtufte/tufte-css/commits/master?author=ursachec) (HTML5 conformity)

License
-
Released under the MIT license. See [LICENSE](https://github.com/edwardtufte/tufte-css/blob/gh-pages/LICENSE).


================================================
FILE: static/latex.css
================================================
.latex-sub, .latex-sup { text-transform: uppercase;
                         font-size: smaller;
                         position: relative; }

.latex-sub { top: 0.2rem;
             margin-left: -0.1667rem;
             margin-right: -0.125rem; }

.latex-sup { top: -0.2rem;
             margin-left: -0.36rem;
             margin-right: -0.15rem;
             text-shadow: none; }

.latex::selection, .latex span:not(.latex-sup)::selection { text-shadow: 0.03em 0 #b4d5fe, -0.03em 0 #b4d5fe, 0 0.03em #b4d5fe, 0 -0.03em #b4d5fe, 0.06em 0 #b4d5fe, -0.06em 0 #b4d5fe, 0.09em 0 #b4d5fe, -0.09em 0 #b4d5fe, 0.12em 0 #b4d5fe, -0.12em 0 #b4d5fe, 0.15em 0 #b4d5fe, -0.15em 0 #b4d5fe;
                    background: #b4d5fe; }

.latex::-moz-selection, .latex span:not(.latex-sup)::-moz-selection { text-shadow: 0.03em 0 #b4d5fe, -0.03em 0 #b4d5fe, 0 0.03em #b4d5fe, 0 -0.03em #b4d5fe, 0.06em 0 #b4d5fe, -0.06em 0 #b4d5fe, 0.09em 0 #b4d5fe, -0.09em 0 #b4d5fe, 0.12em 0 #b4d5fe, -0.12em 0 #b4d5fe, 0.15em 0 #b4d5fe, -0.15em 0 #b4d5fe;
                         background: #b4d5fe; }


================================================
FILE: static/tufte.css
================================================
@charset "UTF-8";

/* Import ET Book styles
   adapted from https://github.com/edwardtufte/et-book/blob/gh-pages/et-book.css */

@font-face { font-family: "et-book";
             src: url("et-book/et-book-roman-line-figures/et-book-roman-line-figures.eot");
             src: url("et-book/et-book-roman-line-figures/et-book-roman-line-figures.eot?#iefix") format("embedded-opentype"), url("et-book/et-book-roman-line-figures/et-book-roman-line-figures.woff") format("woff"), url("et-book/et-book-roman-line-figures/et-book-roman-line-figures.ttf") format("truetype"), url("et-book/et-book-roman-line-figures/et-book-roman-line-figures.svg#etbookromanosf") format("svg");
             font-weight: normal;
             font-style: normal; }

@font-face { font-family: "et-book";
             src: url("et-book/et-book-display-italic-old-style-figures/et-book-display-italic-old-style-figures.eot");
             src: url("et-book/et-book-display-italic-old-style-figures/et-book-display-italic-old-style-figures.eot?#iefix") format("embedded-opentype"), url("et-book/et-book-display-italic-old-style-figures/et-book-display-italic-old-style-figures.woff") format("woff"), url("et-book/et-book-display-italic-old-style-figures/et-book-display-italic-old-style-figures.ttf") format("truetype"), url("et-book/et-book-display-italic-old-style-figures/et-book-display-italic-old-style-figures.svg#etbookromanosf") format("svg");
             font-weight: normal;
             font-style: italic; }

@font-face { font-family: "et-book";
             src: url("et-book/et-book-bold-line-figures/et-book-bold-line-figures.eot");
             src: url("et-book/et-book-bold-line-figures/et-book-bold-line-figures.eot?#iefix") format("embedded-opentype"), url("et-book/et-book-bold-line-figures/et-book-bold-line-figures.woff") format("woff"), url("et-book/et-book-bold-line-figures/et-book-bold-line-figures.ttf") format("truetype"), url("et-book/et-book-bold-line-figures/et-book-bold-line-figures.svg#etbookromanosf") format("svg");
             font-weight: bold;
             font-style: normal; }

@font-face { font-family: "et-book-roman-old-style";
             src: url("et-book/et-book-roman-old-style-figures/et-book-roman-old-style-figures.eot");
             src: url("et-book/et-book-roman-old-style-figures/et-book-roman-old-style-figures.eot?#iefix") format("embedded-opentype"), url("et-book/et-book-roman-old-style-figures/et-book-roman-old-style-figures.woff") format("woff"), url("et-book/et-book-roman-old-style-figures/et-book-roman-old-style-figures.ttf") format("truetype"), url("et-book/et-book-roman-old-style-figures/et-book-roman-old-style-figures.svg#etbookromanosf") format("svg");
             font-weight: normal;
             font-style: normal; }

/* Tufte CSS styles */
html { font-size: 15px; }

body { width: 87.5%;
       margin-left: auto;
       margin-right: auto;
       padding-left: 12.5%;
       font-family: et-book, Palatino, "Palatino Linotype", "Palatino LT STD", "Book Antiqua", Georgia, serif;
       background-color: #fffff8;
       color: #111;
       max-width: 1400px;
       counter-reset: sidenote-counter; }

h1 { font-weight: 400;
     margin-top: 4rem;
     margin-bottom: 1.5rem;
     font-size: 3.2rem;
     line-height: 1; }

h2 { font-style: italic;
     font-weight: 400;
     margin-top: 2.1rem;
     margin-bottom: 0;
     font-size: 2.2rem;
     line-height: 1; }

h3 { font-style: italic;
     font-weight: 400;
     font-size: 1.7rem;
     margin-top: 2rem;
     margin-bottom: 0;
     line-height: 1; }

hr { display: block;
     height: 1px;
     width: 55%;
     border: 0;
     border-top: 1px solid #ccc;
     margin: 1em 0;
     padding: 0; }

p.subtitle { font-style: italic;
             margin-top: 1rem;
             margin-bottom: 1rem;
             font-size: 1.8rem;
             display: block;
             line-height: 1; }

.numeral { font-family: et-book-roman-old-style; }

.danger { color: red; }

article { position: relative;
          padding: 5rem 0rem; }

article pre { overflow: auto; }

section { padding-top: 1rem;
          padding-bottom: 1rem; }

p, ol, ul { font-size: 1.4rem; }

p { line-height: 2rem;
    margin-top: 1.4rem;
    margin-bottom: 1.4rem;
    padding-right: 0;
    vertical-align: baseline; }

/* Chapter Epigraphs */
div.epigraph { margin: 5em 0; }

div.epigraph > blockquote { margin-top: 3em;
                            margin-bottom: 3em; }

div.epigraph > blockquote, div.epigraph > blockquote > p { font-style: italic; }

div.epigraph > blockquote > footer { font-style: normal; }

div.epigraph > blockquote > footer > cite { font-style: italic; }
/* end chapter epigraphs styles */

blockquote { font-size: 1.4rem; }

blockquote p { width: 55%;
               margin-right: 40px; }

blockquote footer { width: 55%;
                    font-size: 1.1rem;
                    text-align: right; }

section>ol, section>ul { width: 45%;
                         -webkit-padding-start: 5%;
                         -webkit-padding-end: 5%; }

li { padding: 0.5rem 0; }

figure { padding: 0;
         border: 0;
         font-size: 100%;
         font: inherit;
         vertical-align: baseline;
         max-width: 55%;
         -webkit-margin-start: 0;
         -webkit-margin-end: 0;
         margin: 0 0 3em 0; }

figcaption { float: right;
             clear: right;
             margin-top: 0;
             margin-bottom: 0;
             font-size: 1.1rem;
             line-height: 1.6;
             vertical-align: baseline;
             position: relative;
             max-width: 40%; }

figure.fullwidth figcaption { margin-right: 24%; }

/* Links: replicate underline that clears descenders */
a:link, a:visited { color: inherit; }

a:link { text-decoration: none;
         background: -webkit-linear-gradient(#fffff8, #fffff8), -webkit-linear-gradient(#fffff8, #fffff8), -webkit-linear-gradient(#333, #333);
         background: linear-gradient(#fffff8, #fffff8), linear-gradient(#fffff8, #fffff8), linear-gradient(#333, #333);
         -webkit-background-size: 0.05em 1px, 0.05em 1px, 1px 1px;
         -moz-background-size: 0.05em 1px, 0.05em 1px, 1px 1px;
         background-size: 0.05em 1px, 0.05em 1px, 1px 1px;
         background-repeat: no-repeat, no-repeat, repeat-x;
         text-shadow: 0.03em 0 #fffff8, -0.03em 0 #fffff8, 0 0.03em #fffff8, 0 -0.03em #fffff8, 0.06em 0 #fffff8, -0.06em 0 #fffff8, 0.09em 0 #fffff8, -0.09em 0 #fffff8, 0.12em 0 #fffff8, -0.12em 0 #fffff8, 0.15em 0 #fffff8, -0.15em 0 #fffff8;
         background-position: 0% 93%, 100% 93%, 0% 93%; }

@media screen and (-webkit-min-device-pixel-ratio: 0) { a:link { background-position-y: 87%, 87%, 87%; } }

a:link::selection { text-shadow: 0.03em 0 #b4d5fe, -0.03em 0 #b4d5fe, 0 0.03em #b4d5fe, 0 -0.03em #b4d5fe, 0.06em 0 #b4d5fe, -0.06em 0 #b4d5fe, 0.09em 0 #b4d5fe, -0.09em 0 #b4d5fe, 0.12em 0 #b4d5fe, -0.12em 0 #b4d5fe, 0.15em 0 #b4d5fe, -0.15em 0 #b4d5fe;
                    background: #b4d5fe; }

a:link::-moz-selection { text-shadow: 0.03em 0 #b4d5fe, -0.03em 0 #b4d5fe, 0 0.03em #b4d5fe, 0 -0.03em #b4d5fe, 0.06em 0 #b4d5fe, -0.06em 0 #b4d5fe, 0.09em 0 #b4d5fe, -0.09em 0 #b4d5fe, 0.12em 0 #b4d5fe, -0.12em 0 #b4d5fe, 0.15em 0 #b4d5fe, -0.15em 0 #b4d5fe;
                         background: #b4d5fe; }

/* Sidenotes, margin notes, figures, captions */
img { max-width: 100%; }

.sidenote, .marginnote { float: right;
                         clear: right;
                         margin-right: -60%;
                         width: 50%;
                         margin-top: 0;
                         margin-bottom: 0;
                         font-size: 1.1rem;
                         line-height: 1.3;
                         vertical-align: baseline;
                         position: relative; }

.sidenote-number { counter-increment: sidenote-counter; }

.sidenote-number:after, .sidenote:before { content: counter(sidenote-counter) " ";
                                           font-family: et-book-roman-old-style;
                                           position: relative;
                                           vertical-align: baseline; }

.sidenote-number:after { content: counter(sidenote-counter);
                         font-size: 1rem;
                         top: -0.5rem;
                         left: 0.1rem; }

.sidenote:before { content: counter(sidenote-counter) " ";
                   top: -0.5rem; }

blockquote .sidenote, blockquote .marginnote { margin-right: -82%;
                                               min-width: 59%;
                                               text-align: left; }    

p, footer, table { width: 55%; }

div.fullwidth, table.fullwidth { width: 100%; }

div.table-wrapper { overflow-x: auto;
                    font-family: "Trebuchet MS", "Gill Sans", "Gill Sans MT", sans-serif; }

.sans { font-family: "Gill Sans", "Gill Sans MT", Calibri, sans-serif;
        letter-spacing: .03em; }

code { font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;
       font-size: 1.0rem;
       line-height: 1.42; }

.sans > code { font-size: 1.2rem; }

h1 > code, h2 > code, h3 > code { font-size: 0.80em; }

.marginnote > code, .sidenote > code { font-size: 1rem; }

pre.code { font-size: 0.9rem;
           width: 52.5%;
           margin-left: 2.5%;
           overflow-x: auto; }

pre.code.fullwidth { width: 90%; }

.fullwidth { max-width: 90%;
             clear:both; }

span.newthought { font-variant: small-caps;
                  font-size: 1.2em; }

input.margin-toggle { display: none; }

label.sidenote-number { display: inline; }

label.margin-toggle:not(.sidenote-number) { display: none; }

@media (max-width: 760px) { body { width: 84%;
                                   padding-left: 8%;
                                   padding-right: 8%; }
                            p, footer { width: 100%; }
                            pre.code { width: 97%; }
                            section > ol { width: 90%; }
                            section > ul { width: 90%; }
                            figure { max-width: 90%; }
                            figcaption, figure.fullwidth figcaption { margin-right: 0%;
                                                                      max-width: none; }
                            blockquote { margin-left: 1.5em;
                                         margin-right: 0em; }
                            blockquote p, blockquote footer { width: 100%; }
                            label.margin-toggle:not(.sidenote-number) { display: inline; }
                            .sidenote, .marginnote { display: none; }
                            .margin-toggle:checked + .sidenote,
                            .margin-toggle:checked + .marginnote { display: block;
                                                                   float: left;
                                                                   left: 1rem;
                                                                   clear: both;
                                                                   width: 95%;
                                                                   margin: 1rem 2.5%;
                                                                   vertical-align: baseline;
                                                                   position: relative; }
                            label { cursor: pointer; }
                            div.table-wrapper, table { width: 85%; }
                            img { width: 100%; } }

================================================
FILE: templates/index.html
================================================
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8"/>
    <title>Coinbin.org: A Human–Friendly API Service for Crypto Currency Information</title>
    <link rel="stylesheet" href="{{ url_for('static', filename='tufte.css') }}"/>
    <link rel="stylesheet" href="{{ url_for('static', filename='latex.css') }}"/>
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">

    <script>
      function resizeIframe(obj) {
        obj.style.height = obj.contentWindow.document.body.scrollHeight + 'px';
        obj.style.width = obj.contentWindow.document.body.scrollWidth + 'px';
      }
    </script>

  </head>

  <body>

    <article>
      <h1 id="tufte-css">₿ Coinbin.org</h1>

      <p class="subtitle">A Human–Friendly API Service for Crypto Currency Information.</p>

      <p>This service provides machine (and human) friendly JSON data for all known crypto–currencies. All {{ coins|length }} active &amp; known coins are supported.</p>

      <p>Historical data, exchange rates, conversion ratios, and value conversion endpoints are all available, free of charge. Data is refreshed every five minutes.</p>

      <p>There is no rate limit. There never will be.</p>


      <h2>Example API Endpoints</h2>
      <p></p>
      <code><strong>$ curl <a href="https://coinbin.org/lbc">https://coinbin.org/lbc</a></strong></code>
      <!-- <p><small>Returns current market data for any given coin.</small></p> -->
      <!-- <q>Returns current market data for any given coin.</q> -->
      <pre>
{{ lbc.data.decode('utf-8') }}
      </pre>
      <p></p>
<code><strong>$ curl <a href="https://coinbin.org/lbc/42.01">https://coinbin.org/lbc/42.01</a></strong></code>
      <pre>
{{ lbc_42.data.decode('utf-8') }}
      </pre>

      <p></p>
<code><strong>$ curl <a href="https://coinbin.org/lbc/to/sc">https://coinbin.org/lbc/to/sc</a></strong></code>
      <pre>
{{ lbc_sc.data.decode('utf-8') }}
      </pre>


      <p></p>
<code><strong>$ curl <a href="https://coinbin.org/lbc/42.01/to/sc">https://coinbin.org/lbc/42.01/to/sc</a></strong></code>
      <pre>
{{ lbc_42_sc.data.decode('utf-8') }} </pre>

      <p></p>
<code><strong>$ curl <a href="https://coinbin.org/lbc/history">https://coinbin.org/lbc/history</a></strong></code>
      <pre>
{
  "history": [
    {
      "timestamp": "2017-08-24T04:00:55.932092Z",
      "value": 0.3404,
      "value.currency": "USD",
      "when": "today"
    }, ...

... {
      "timestamp": "2016-07-12T04:01:09.167162Z",
      "value": 0.239634,
      "value.currency": "USD",
      "when": "Jul 12 2016"
    }
  ]
}</pre>
<p><small>This endpoint returns up to four years of daily USD data, on any given coin.</small></p>

<h2>Pro Version</h2>

<p>We're collecting historical data, moving forward<label for="sn-in-his-later-books" class="margin-toggle sidenote-number"></label></span><input type="checkbox" id="sn-in-his-later-books" class="margin-toggle"/><span class="sidenote"><em>We may backfill our historical data as well, if customers interest is high.</em></span>, every ten minutes (instead of daily). If you'd like access to this data, <a href="mailto:me@kennethreitz.org">send us an email</a>. We accept payment in coins.</p>

<h2>Experimental (e.g. <em>fun</em>) Endpoints</h2>

      <h3><a href="https://coinbin.org/btc/forecast/graph">Prediction of BTC Price</a> (using <em>machine learning</em>)</h3>
      <p>&nbsp;</p>
      <p><em><strong>Note — </strong>This information is presented for informational purposes
        only, and is not recommended for making actual trading decisions.</em></p>

      <pre><iframe src="/btc/forecast/graph" frameborder="0" scrolling="no" onload="resizeIframe(this)"></iframe></pre>

      <p></p>
<code><strong>$ curl <a href="https://coinbin.org/btc/forecast">https://coinbin.org/btc/forecast</a></strong></code>
      <pre>
{{ lbc_forecast.data.decode('utf-8') }} </pre>


<h2>Full List of Supported Coins (Ordered by Rank)</h2>

  <p></p>
<code><strong>$ curl <a href="https://coinbin.org/coins">https://coinbin.org/coins</a></strong></code>
      <pre>
{
  "coins": [{% for coin in coins %}
    "<strong><a href="/{{ coin['ticker'] }}">{{ coin['ticker'] }}</a></strong>":
      {{ coin|tojson }},{% endfor %}
  ]
}
      </pre>


<h2>More Resources</h2>
<ul>

  <li><a href="https://github.com/kennethreitz/awesome-coins">Awesome Crypto Currency Tools & Algorithms (Guide)</a></li>
  <li><a href="https://github.com/shrayasr/Coinbin.net">.NET Client for Coinbin.org</a></li>
</ul>


    </article>

  <script type="text/javascript">
  var _gauges = _gauges || [];
  (function() {
    var t   = document.createElement('script');
    t.type  = 'text/javascript';
    t.async = true;
    t.id    = 'gauges-tracker';
    t.setAttribute('data-site-id', '599e2dbcbad3a763b70d2f2f');
    t.setAttribute('data-track-path', 'https://track.gaug.es/track.gif');
    t.src = 'https://d36ee2fcip1434.cloudfront.net/track.js';
    var s = document.getElementsByTagName('script')[0];
    s.parentNode.insertBefore(t, s);
  })();
</script>

<a href="https://github.com/kennethreitz/coinbin.org" class="github-corner" aria-label="View source on Github">
  <svg width="80" height="80" viewBox="0 0 250 250" style="fill:#151513; color:#fff; position: absolute; top: 0; border: 0; right: 0;" aria-hidden="true">
    <path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path>
    <path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path>
    <path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path>
  </svg>
</a>
<style>.github-corner:hover .octo-arm{animation:octocat-wave 560ms ease-in-out}@keyframes octocat-wave{0%,100%{transform:rotate(0)}20%,60%{transform:rotate(-25deg)}40%,80%{transform:rotate(10deg)}}@media (max-width:500px){.github-corner:hover .octo-arm{animation:none}.github-corner .octo-arm{animation:octocat-wave 560ms ease-in-out}}</style>

  </body>
</html>



================================================
FILE: wallets.py
================================================
wallets = {
    'btc': '1PYZH8SCXQF7c2qgpsQ8kDgKixXeYvVsKv',
    'ltc': 'LXPtxt68njDdTBdu1ZvHUbARhHsPm9T3Zq',
    'doge': 'DRDjoTo3zg64QHpq3xgrVVJnerLAvVzMbc',
    'vtc': 'VvNd9XoYKavHagE6VkLNPeAazFmpgMZgQ5',
    'ppc': 'PMQWpq15QxT4dR6h6NrvrJMNtehcmRVxYW',
    'ftc': '6zDLXZmoNBdz87ZMvtK2JF7C3NRuKu2nVr',
    'rdd': 'RudBYrzAQeYmDXHhMXs7hPsYJc7n1C7Trt',
    'dash': 'XvtKBmKUhiEPQyEgNxvSRt9hyHBCN8Mia7',
    'pot': 'PTjS6cpqGoUUbEKyUWMqHk92ymvXMi84Ti',
    'blk': 'BKNihHBXHy24q7wWM6A45xnDWTvcKrcmXN',
    'emc2': 'EbMSP6TnLgfiJEnL1SUf4N8tjSHsY2L8zA',
    'xmy': 'MQPjf1pCpKQDVabTXe3do4JTQ9A81oJyHp',
    'aur': 'AVdVKHAvQij7QWmZ8p8P3qArK1eunrUukK',
    'gld': 'E6UVrbrd4VnvspMuDqDw7FfMhGAqj26dZE',
    'fair': 'fVkBYTPiQpcWCmFGSTtxhug2yW2nDZw6x7',
    'slr': '8WUGQdSjo6XikocLF54KfHfBJ2HQqwtE3t',
    'ptc': 'LJ7NefEUuJ9DC8qneEW2541p5iJzxNMqyQ',
    'grs': 'FZg2ceLVCRFaV48C1BViKd1ersC9pxcHeb',
    'nlg': 'GTEBkz4H73YJgTNhAVtwvwZwUgTsEezVjR',
    'xwc': 'WXiGQuL7YNhDj93GMdRWJK3gdPMJfQWB8e',
    'mona': 'MSE8zn8b7tdHnCL45em7nes5BtTQfPuSwc',
    'enrg': 'eBzzqNtRCsxYLDyKkBT4CSiu2c6hFK8N5X',
    'rby': 'RRcRzBTcz8HhfNncH9rbKM1hppwMB4EpPj',
    'thc': 'HMemWrgjEfmgutjkM7C2zMqgpj97SJtW7g',
    'erc': 'EWeL8eYZRJJZnMFrwMvhidxJsXDcfsELgL',
    'vrc': 'VUmKQQdfVdsNfSzGtWZddWnv1gD1VuYPSa',
    'cure': 'BE1rrjqnMPXnLbsTXdbhe13wuRRN1q5qTy',
    'cloak': 'BtMtdrXRWBw6YMfSsxtkBiRP1wYeFH2Xrk',
    'bsd': 'iPcwLWBxp2BYfDCyGYbvHbjRCzGL7rjE2U',
    'start': 'sdvC9GSopsBmJ8VtVmNxKf1xwcGtY9bzwz',
    'kore': 'K8iJwoL5ojPWw2kjhnWJrNwm1rsoWewErb',
    'trust': 'TUFooWK6jqDYHKUggZyREvPAeK6nhSYHAX',
    'nav': 'NUBRSjHJ8h52bqF2d2U4iXzEF3v6fgskw4',
    'xst': 'S6L8FQGNLhpGEhcZzt4YMYNHq1H98QKkmK',
    'btcd': 'RCJPmNM6BaNBTiomfJ83c2hEjMpnLjFghe',
    'via': 'Vcd9Be6s1NePuci1LvC16K21kBytYmRf1t',
    'uno': 'uZsGhq6VfNpYPUtNqg9fdushmsuc6B9GMA',
    'pink': '2EjF3ACSNJqudSKZaEeSHvkGqVFg4JtUSA',
    'ioc': 'iZmhHdNtPGfEVwswTkaLEDEuxrHQFDGD77',
    'cann': 'CemM7gxYYJK9weV6Ed8sw4B7fvPQgY8hfW',
    'sys': 'SUNH2SNQqaZvxqqPvuQcBVNdZshPRq2ZTv',
    'neos': 'NTM232LiTUz8tgXmAWg8TxbrKtcAkDW9Mr',
    'dgb': 'DA2eLVocFESdqVETtgVLP6k1m319o4g4Yq',
    'excl': 'EPdycUjUzcYvFFGvTPC8z9NriZ8EgxLL7P',
    'dope': 'D6NTRES89hzLNYx55AEuqWuAs8rUsR3sVc',
    'block': 'Ba3yDhGLkiqN28YXoMYgBPuSjKht4a2ZGK',
    'aby': 'AMbFZwYzjMJHtjJL3fHti2k2JtpfqrX7Ud',
    'byc': 'BGD2TfaNbN6wq6CZXHMG9fSEWdniVZhJzn',
    'blitz': 'oWZsQvU3T9FU25FdmRnAousz5CpzXjd6Eg',
    'bay': 'BFDi3ZSZorDPX17iYrmhRFRSQK5DniqG4v',
    'spr': 'SYeuSdejAg8jbhrC6pYmwMMPn99egVmyaP',
    'vtr': 'xr14J4LzdL4jYfRNpP5WdPjtq5dC2YNXiZA27ZayWqC87o4B4UwibZFWr6U5B3B3T7gdjfCqsN5c3btYhFSzBCf2fDL9Bvj1LAPqYQ',
    'game': 'GMn4k4jXVDjVbSMCWabNguczwADkQxnnRu',
    'nxs': '2RQbTTGVYJB1qkghsoZunueS71EPfc6KfCbhJqXveLJFCCK4U35',
    'bitb': '2UjoiH7RmYhvdzJRGXAt5SVeP1iw9MP3Ka',
    'xvg': 'DAtQMkVj14Vs4jUww8EcnurUGz1c92pBV9',
    'geo': 'GR7Zj1EsHWc7M3KU5BDhTCSx4y9QR9nEEo',
    'flo': 'FMSEzFyS9dWhb69ch72VF1ETePnXnb2qxY',
    'nbt': 'BBijzpMJo92pT4dp1NxwGXY1kBJGxz1QJr',
    'grc': 'S1t5Jr2WwxZSeSNn8p5RkAAycHa2ZraShi',
    'mue': '7bSsG2TBa4645qitQsfBPj9Gp7ZW8QTa87',
    'xvc': 'VpYaBkNXNCtYg3HTP7onhdvhTqtvGBwBCo',
    'clam': 'xVJ7ySQNPfN3XKmAykTYapuZzZun23xsr5',
    'dmd': 'dGRJXSHNiF9SoAatLeuoKYxmCbKJ8aXkga',
    'gam': 'GSqe2k3G2EQQy3QNPwGyyyW33m7eEr6Df6',
    'sphr': 'BPpGQCDR63NcN6Po9Lvo2D8nqQbhpiSHcE',
    'ok': 'PGuDs5iu3sEaeAr1kMnMSwNCwJW2xUMTwA',
    'snrg': 'SYkCDBer4Kap91ftY4cdDfrjnTh3nRvNqk',
    'pkb': 'PLvXxUE6NrJqvoP1imR8sS23hDCmXoWcxz',
    'cpc': 'CYWUbfBTAVW9H4zAPRe6yckWWBVRXaznT1',
    'eth': '0xcf4c939ccae5c0ecc8b63505cce1513e5ef0d567',
    'gcr': 'GRxryTQ43RET8xfzm38L42wYchim9H3cHf',
    'tx': 'TixtGQBFrzfFH5Z1ouKjM4UDGqkKXcyw8p',
    'exp': '0xbc4ee321e752cdd8ca54e4405de71c5f4f5b5f24',
    'infx': 'iBJzRkcQk6coYUE4UFFDzvfi8Y1URMzyyA',
    'omni': '15rebjRT6mESSbHU9yyLTh8oADdC4x4RWg',
    'usdt': '1Ne3DYc5tJSAjS3rwqDt3GSN1FYMrHLPWr',
    'amp': '13f3KoRoFD5iJw1zdQBw5Hum5EYRs9pB3x',
    'agrs': '16EPWtBErUnT6fEsKmJfB4gxnJx5qndMCJ',
    'bta': 'BJD3NHuuiibB85FrxYULSHTgJmye25PRKF',
    'club': 'Ce9MJXxjasVSbVPntihwote3SjMbfqnvDJ',
    'vox': 'VV5QjvbWFC9rvWtLyxMvsJDT1FFk9jgbWa',
    'emc': 'EgPN6YhGXqgTL7np3UtAM2UReMs7eWVD8K',
    'fct': 'FA3EuMt78kTLHdJsfS65r15xE4acVRtARBfUnKTqfMmGUyTzcNtP',
    'maid': '1gUbRQjyQX2uJkezY8WY7KSEGGEmD9Zme',
    'egc': 'EZYWa2KKhzUstJnTZG1SA8zp7stiyrt2Up',
    'sls': 'SZVpV5LtN9WXdafou3BoHsacDhMcmCjUzr',
    'rads': 'XcML29TJXQihsV5JmphEVbTPcS6xPkcZFj',
    'dcr': 'DsUcYM48ZravjWaLCoeAxYQvTcNigqYaQVf',
    'safex': '1jTMyxf2iP9NxNzMDAZVhQVQskj7zvDj9',
    'pivx': 'DU6uyNH7E5VPse3hh4RZr4A12VQtM2E3Ue',
    'meme': 'PCXXZ3NKQUMA26GsX5cjozE48yvM5uUnrR',
    '2give': 'GpG7ygLvdd3GKsbAUvPRZbMR8GtXa7JizS',
    'lsk': '3548326455915242856L',
    'pdc': '12ZeM7mrPnZBM5rZWXh9QpNbe6eSTykxCr',
    'dgd': '0x7e7cec0a54cbda02b44e6c24a298b2d89b8f3c31',
    'brk': 'brfTVJS9JGtNX8prmKQBaQtWbtj1b1WJB7X',
    'waves': '3P6H2V28Zzs9qX3U86Rs5hzTFkcCJrbDJEm',
    'lbc': 'bVQKmE9tkLHxkjnu97SSe8eQHT9q4c69Zb',
    'brx': 'bxVriVBdAZ1jXkKFvBAA3zQkS819kZFqWVd',
    'etc': '0xb52c0534da8d758943e8604916b6be70071bc6d3',
    'strat': 'Sf8iKKeaAFRX772JA5TWXDwZMJZkJNwmSZ',
    'unb': '13izqwELn1jTt1j7umfoJKUPRUBBPmwpHv',
    'ebst': 'e91xYCEFKh2J2VogvUraooeCFUUcCbrUnM',
    'vrm': 'VXYWrM5h6YE7pU1zPjFpXYcGVoYnLAETyK',
    'xaur': '0x1253295779080ec136551724a27143e4470073a2',
    'seq': 'Se8Eg7u1k6izqAW3nmKAwuBewiJu1G2fbD',
    'sngls': '0x6f4f433ff62347998785e4ed30f3048a2281fd98',
    'rep': '0x16169642de5a4c43a5f3bcbc5eea36ca767ecc4d',
    'shift': '3548326455915242856S',
    'xzc': 'a3vmJpgzqDu4Yg6FPt9uj27m3sBAbMwtRs',
    'neo': 'AG2dY41SYEMmZLLy5dS1gNwHkWEAshE3ft',
    'zec': 't1fnCgLKXy7Q1ovFD5obWcH1Vmpp6ivVhJu',
    'zcl': 't1bHV2hFD8mVoVH2S7KVSfAmdTX615xXGgy',
    'iop': 'pEP4niYzA8eiPUfCcy5pnPxoETu7zx6n4G',
    'ubq': '0x98b3ffb0a988308304b32077ba31e5b300be1567',
    'hkg': '0x1567685a30ee1d1ace1f1e6291b727b1e2ca5eea',
    'sib': 'Sicrwdsg9mVMCACVJJq23RfqSXiNfH7H2f',
    'ion': 'ia2ts12ZrprJ9GjsuJChY1HmzeFnwy6k5x',
    'lmc': 'LZFKYiQRjX3zLaBRMTzF6kaRReoAqsTGgX',
    'qwark': '0xe4f1f6665f68489f6ff512194553918df13a1ae6',
    'crw': '12rCC2LwBBuue46KELC9zE9H75Tq9ff492',
    'swt': '0xaef9799c36cc1459d7876b56383a4a2107bc4b66',
    'time': '0x1ddcfde92c5c82f5fc919b69478ce65db5446483',
    'mln': '0x8c1d250c58133ff94b224390c3137d8dc4bf02bc',
    'tks': '3PESLYrs1s5sNYGBHD8bZnqWvB3pW3BMcWd',
    'ark': 'AJrDLieoPW46gg3XRANt3J8emDFdQPDUmq',
    'music': '0x9248334cf30082b5e301bef6fa29642c3170e2e4',
    'incnt': '3PEuNUJZpE4mjqhHZDCmisGabd4g1qzAeve',
    'gbyte': 'RYLB7TCEBR4WK3ZEBMGOSLHOPU2COVMZ',
    'gnt': '0x7da2d058575c81a0b5658878a3b3efed0de142d4',
    'nxc': '0x06e1d5c1e7dded4b9e32f45845e1d352c0cf8bc5',
    'edg': '0xdc8e6d7de95fb75774f2b3be2d03efd29d9242e8',
    'lgd': '0xce7591232523f66b14189c4cec4679e3ab7b3d8e',
    'trst': '0xa60ff29d26d373a88afbe74f6dbcab3aeca677e6',
    'wings': '0xb4466e1575882d28388820a719516d1dff412961',
    'rlc': '0xab916ef71e19c56c98de93d0dba99469b1283db1',
    'bcc': '1LVojXegSH5EhrNQncWfxg7ErVh4N9HCAL',
    'qtum': '0x1646d7c096047756ab0b1cb636cf5dd5d36959d2',
    'part': 'Ph9oGH1vwtsFTHmAwYh3iS9J1vcVhoLXFk',
    'cvc': '0x584827cad4a2cb47582ebd5a5ee6e4fd5ea63255',
    'omg': '0xef24cccdad02b96e8bd3c68757c1aab5547ecda7',
    'adx': '0x36f8b284fa87405389e672d74898d0bf2930a5d9',
    'storj': '0x05feda4008e2d9253bc339332a29a5a862c8c5d2',
    'mtl': '0x7b610ddc59fd76c1e8a23ff69904e5d4898bbf78',
    'pay': '0x3a957df561559587b43eb77b4266c8f0063ec948',
    'fun': '0xd9a996f367802920aa7bb5bce48de183f45eeb54',
    'adt': '0x7853d58160a73d538e89278bb036d2b80e00c351',
    'mco': '0xf3959d90b9b880ee29e62f1210a37fe9b54ce0c1',
    'snt': '0x3f6526ddd2e452ca6f93033653f0f39ace19f71e',
    'nmr': '0xcb83ccdd55939de0653b455d7aebf21982357320',
    'bnt': '0x3363f5a728901533511427d27f3151fe9df152a0',
    'cfi': '0xa27c5edf5d5ca32a3f3926f7d46d4dcbea43241d',
    'myst': '0x9dfe066e10215254e7e62c86a30fd0aea1884be3',
    'ptoy': '0x5bc546675be2ea8b3a56eab0161e7f8c6615930a',
    'crb': '0x3e12bb90fffebdab71dffca9557a81587d32862f',
    'qrl': '0x7e4b07296fc5a54031ca133b98546d350c0cd293',
    '1st': '0x919865c75dd7949fb061e7a2102290b79e4d9150',
    'bat': '0x04db9cf3de9183f8e5d5b7609c5793e4448c9bf6',
    'sc': '6197b45062c2d75d8d94d7c7fe4a6530cc6fe6422e0edd9f285d237646b2392541c03005947d',
    'zen': 'znmGXVrq1UcF3r59C8V75t6zqFkmqMzC4YY',
    'ant': '0xd54c9c210d286e5bae0e5f59ca8817e9dc2378de',
    'hmq': '0x0c3a58dc40e933b2031d0cbfe08cf0738f55a17d',
    'tkn': '0x5a020b51b748b21274078e42b10a7eb3988e89e1',
    'apx': '0x2c4588d7d92700966fc6101af9b1af4181ab5358',
    'lun': '0x12c38554537d9677aef623cf7bd9b9460d51045b',
    'gup': '0xf4b6b5fce73e455e93f80190b7f7e5999864a3de',
    'gno': '0x8e2118d168713e639b624851958cc5fa46ebce2a',
    'rlc': '0xab916ef71e19c56c98de93d0dba99469b1283db1'
}
Download .txt
gitextract_12qrf40r/

├── .gitignore
├── Pipfile
├── Procfile
├── README.md
├── app.json
├── graph.py
├── predictions.py
├── scraper.py
├── server.py
├── static/
│   ├── LICENSE
│   ├── README.md
│   ├── latex.css
│   └── tufte.css
├── templates/
│   └── index.html
└── wallets.py
Download .txt
SYMBOL INDEX (31 symbols across 4 files)

FILE: graph.py
  function name_to_ticker (line 6) | def name_to_ticker(name):
  class Coin (line 13) | class Coin(graphene.ObjectType):
    method from_coin (line 20) | def from_coin(klass, c):
  class Query (line 30) | class Query(graphene.ObjectType):
    method resolve_coin (line 35) | def resolve_coin(self, name=None, ticker=None):

FILE: predictions.py
  function get_predictions (line 28) | def get_predictions(coin, render=False):

FILE: scraper.py
  class MWT (line 15) | class MWT(object):
    method __init__ (line 20) | def __init__(self, timeout=2):
    method collect (line 23) | def collect(self):
    method __call__ (line 32) | def __call__(self, f):
  function convert_to_decimal (line 51) | def convert_to_decimal(f):
  class Coin (line 55) | class Coin():
    method __init__ (line 58) | def __init__(self, ticker):
    method update (line 66) | def update(self):
    method usd (line 75) | def usd(self):
    method btc (line 79) | def btc(self):
    method value (line 84) | def value(self, coin):
    method __repr__ (line 88) | def __repr__(self):
  function get_coins (line 93) | def get_coins():
  function get_coin (line 124) | def get_coin(ticker):

FILE: server.py
  function hello (line 32) | def hello():
  function all_coins (line 43) | def all_coins():
  function get_coin (line 48) | def get_coin(coin):
  function get_forecast (line 61) | def get_forecast(coin):
  function get_forecast_graph (line 66) | def get_forecast_graph(coin):
  function get_value (line 72) | def get_value(coin, n):
  function get_value_int (line 81) | def get_value_int(coin, n):
  function get_history (line 86) | def get_history(coin):
  function get_exchange (line 107) | def get_exchange(coin1, coin2):
  function get_exchange_value (line 117) | def get_exchange_value(coin1, coin2, n):
  function get_exchange_value_int (line 130) | def get_exchange_value_int(coin1, coin2, n):
Condensed preview — 15 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (48K chars).
[
  {
    "path": ".gitignore",
    "chars": 9,
    "preview": "\n/.envrc\n"
  },
  {
    "path": "Pipfile",
    "chars": 619,
    "preview": "[[source]]\n\nurl = \"https://pypi.python.org/simple\"\nverify_ssl = true\n\n\n[packages]\n\nflask = \"*\"\nrecords = \"*\"\n\"psycopg2\" "
  },
  {
    "path": "Procfile",
    "chars": 36,
    "preview": "web: gunicorn server:app -k gaiohttp"
  },
  {
    "path": "README.md",
    "chars": 1361,
    "preview": "# ₿ Coinbin.org\n\n### The Human–Friendly API Service for Crypto Currency Information.\n\nThis free web service exists to pr"
  },
  {
    "path": "app.json",
    "chars": 517,
    "preview": "{\n  \"name\": \"coinbin.org\",\n  \"scripts\": {\n  },\n  \"env\": {\n    \"API_KEYS\": {\n      \"required\": true\n    },\n    \"HEROKU_PO"
  },
  {
    "path": "graph.py",
    "chars": 944,
    "preview": "import scraper\n\nimport graphene\n\n\ndef name_to_ticker(name):\n    for coin in scraper.get_coins().values():\n        if coi"
  },
  {
    "path": "predictions.py",
    "chars": 2130,
    "preview": "import time\nimport uuid\n\nimport records\nimport os\n\nimport maya\nimport numpy as np\nimport pandas as pd\n\n# Matplotlib hack"
  },
  {
    "path": "scraper.py",
    "chars": 3163,
    "preview": "import pandas\nimport requests\n\nimport crayons\nfrom pyquery import PyQuery as pq\n\nimport time\nfrom collections import Ord"
  },
  {
    "path": "server.py",
    "chars": 3559,
    "preview": "import os\n\nfrom scraper import get_coins, get_coin, Coin, convert_to_decimal\nfrom predictions import get_predictions\nfro"
  },
  {
    "path": "static/LICENSE",
    "chars": 1081,
    "preview": "The MIT License (MIT)\n\nCopyright (c) 2014 Dave Liepmann\n\nPermission is hereby granted, free of charge, to any person obt"
  },
  {
    "path": "static/README.md",
    "chars": 3925,
    "preview": "Tufte CSS\n=========\nEdward Tufte uses a distinctive style in his handouts: simple, with well-set\ntypography, extensive s"
  },
  {
    "path": "static/latex.css",
    "chars": 1077,
    "preview": ".latex-sub, .latex-sup { text-transform: uppercase;\n                         font-size: smaller;\n                       "
  },
  {
    "path": "static/tufte.css",
    "chars": 11582,
    "preview": "@charset \"UTF-8\";\n\n/* Import ET Book styles\n   adapted from https://github.com/edwardtufte/et-book/blob/gh-pages/et-book"
  },
  {
    "path": "templates/index.html",
    "chars": 6682,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\"/>\n    <title>Coinbin.org: A Human–Friendly API Servi"
  },
  {
    "path": "wallets.py",
    "chars": 8874,
    "preview": "wallets = {\n    'btc': '1PYZH8SCXQF7c2qgpsQ8kDgKixXeYvVsKv',\n    'ltc': 'LXPtxt68njDdTBdu1ZvHUbARhHsPm9T3Zq',\n    'doge'"
  }
]

About this extraction

This page contains the full source code of the kennethreitz/coinbin.org GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 15 files (44.5 KB), approximately 16.3k tokens, and a symbol index with 31 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!