def test_parsing_with_four_character_symbol(self): coin = Coin.create(name='foocoin', symbol='DASH') ping('DASH') dash = Coin.get(Coin.symbol == 'DASH') ticker = Ticker.get(Ticker.coin == dash) self.assertEqual(ticker.price, Decimal('56.12345678')) self.assertEqual(ticker.price_change_day_pct, Decimal('-1.23456789'))
def test_parsing_with_many_coins(self): ping('BTC', 'ETH') btc = Coin.get(Coin.symbol == 'BTC') eth = Coin.get(Coin.symbol == 'ETH') btc_ticker = Ticker.get(Ticker.coin == btc) eth_ticker = Ticker.get(Ticker.coin == eth) self.assertEqual(btc_ticker.price, Decimal('56.12345678')) self.assertEqual(btc_ticker.price_change_day_pct, Decimal('-1.23456789')) self.assertEqual(eth_ticker.price, Decimal('42.98765432')) self.assertEqual(eth_ticker.price_change_day_pct, Decimal('-8.98765432'))
def test_parsing_with_many_ping_calls(self): ping('BTC') btc = Coin.get(Coin.symbol == 'BTC') btc_ticker = Ticker.get(Ticker.coin == btc) self.assertEqual(btc_ticker.price, Decimal('56.12345678')) self.assertEqual(btc_ticker.price_change_day_pct, Decimal('-2.33334567')) Ticker.delete().execute() ping('BTC') btc = Coin.get(Coin.symbol == 'BTC') btc_ticker = Ticker.get(Ticker.coin == btc) self.assertEqual(btc_ticker.price, Decimal('56.12345678')) self.assertEqual(btc_ticker.price_change_day_pct, Decimal('-2.33334567'))
def test_parsing_with_one_coin(self): ping('BTC') btc = Coin.get(Coin.symbol == 'BTC') btc_ticker = Ticker.get(Ticker.coin == btc) self.assertEqual(btc_ticker.price, Decimal('56.12345678')) self.assertEqual(btc_ticker.price_change_day_pct, Decimal('-2.33334567'))
def get_coins_by_game_id(game_id): coins_query = Coin.select().join(GameCoin).where(GameCoin.game == game_id) if coins_query.count() == 0: raise BadRequest('Coins not found') coins = [] for coin in coins_query: coins.append(coin) return coins
def test_parsing_with_one_coin(self, check_global_timed_game, check_price_alerts_mock, mock_ticker, mock_coin): mock_coin.get.return_value = Coin(symbol='FOO', name='Foocoin') ping('FOO') mock_ticker.create.assert_called_with( coin=mock_coin.get.return_value, price=Decimal('56.12345678'), price_change_day_pct=Decimal('-1.23456789'), )
def create_gamecoins_for_game(game, active_coins): if len(active_coins) == 0: raise BadRequest('At least one coin must be allowed in a game') res = [] for coin in active_coins: coin = Coin.get_or_none(Coin.id == coin['id']) if coin is None: raise BadRequest('Invalid coin') res.append(GameCoin.create( game=game, coin=coin, )) return res
def test_parsing_with_many_coins(self, check_global_timed_game, check_price_alerts_mock, mock_ticker, mock_coin): side_effect = [ Coin(symbol='FOO', name='Foocoin'), Coin(symbol='BAR', name='Barcoin'), ] mock_coin.get.side_effect = side_effect ping('FOO', 'BAR') calls = [ call( coin=side_effect[0], price=Decimal('56.12345678'), price_change_day_pct=Decimal('-1.23456789'), ), call( coin=side_effect[1], price=Decimal('42.98765432'), price_change_day_pct=Decimal('-1.23456789'), ), ] mock_ticker.create.assert_has_calls(calls, any_order=False)
def ping(*coins): res = requests.get(get_api_url(*coins)) tickers = [] for coin_res in res.json(): symbol = coin_res['symbol'] coin = Coin.get(Coin.symbol == symbol) price = Decimal(coin_res['price']) price_change_day_pct = Decimal(coin_res['1d']['price_change_pct']) ticker = Ticker.create(coin=coin, price=price, price_change_day_pct=price_change_day_pct) tickers.append(ticker) check_price_alerts(ticker) check_global_timed_game() return tickers
def test_get_coins_success(self): profile = Profile.get_or_none(Profile.username == 'theusername') GameProfile.create(game=1, profile=profile, cash=10000) GameCoin.create( game=1, coin=1, ) for coin in Coin.select(): Ticker.create( coin=coin, price=30.0, captured_at=(datetime.utcnow()).isoformat(), price_change_day_pct=1.1, ) res = self.client.get( '/game/1/coins?timeSpan=1&sortBy=0&numPerPage=10&pageNum=1', headers={'Authorization': 'Bearer ' + self.token}) self.assertEqual(int(HTTPStatus.OK), res._status_code)
def begin(cb=None): env = os.environ['FLASK_ENV'] if env == 'testing': # TODO stubbed implementation return elif env == 'development': if os.environ.get('WERKZEUG_RUN_MAIN') != 'true': return while True: coins = Coin.select() tickers = list(stubbed(*coins)) if cb is not None: cb(tickers) time.sleep(WAIT) elif env == 'production': while True: tickers = list(ping('BTC', 'ETH', 'LTC')) if cb is not None: cb(tickers) time.sleep(WAIT)
def get_coins_by_game_id_and_sorting(game_id, sorting_int, page_num, num_per_page): coins_query = Coin.select().join(GameCoin).where(GameCoin.game == game_id) if coins_query.count() == 0: raise BadRequest('Incorrect Sorting') if sorting_int == 1: coins_query = coins_query.order_by(+Coin.name) if sorting_int == 2: coins_query = coins_query.order_by(-Coin.name) if sorting_int == 3: coins_query = coins_query.order_by( -Coin.price) # TODO: Double check if this should +/- if sorting_int == 4: coins_query = coins_query.order_by( +Coin.price) # TODO: Double check if this should +/- coins_query = coins_query.paginate(page_num, num_per_page) coins = [] for coin in coins_query: coins.append(coin) return coins
def test_price_alerts(self): os.environ['NOMICS_BASE_URL'] = 'foo' profile = Profile.create(username='******', hashed_password='******') coin = Coin.create(name='foocoin', symbol='FOO') alert = PriceAlert.create( profile=profile, above=True, coin=coin, strike_price=Decimal(0.1), ) alert = PriceAlert.create( profile=profile, above=False, coin=coin, strike_price=Decimal(0.1), ) ping('FOO') self.assertEqual(1, Notification.select().count()) # ok, the line below throws an exception which causes all other tests to fail # as tearDown is not called and because db is in inconsistent state notif = Notification.get(Notification.profile == profile)
def create_price_alert_route(profile): validated_data: dict = CreatePriceAlertRequestSerializer.deserialize( request.json) try: strike_price = Decimal(validated_data['strike_price']) if strike_price < 0: raise BadRequest('The strike price cannot be negative') except: raise BadRequest('Invalid decimal number for strike price') coin_id = validated_data['coin_id'] type = validated_data['type'] coin = Coin.get_or_none(Coin.id == coin_id) if coin is None: raise BadRequest('Invalid coin id') if type == 'above': alert = create_price_alert(profile, coin, strike_price, above=True) elif type == 'below': alert = create_price_alert(profile, coin, strike_price, above=False) else: raise BadRequest( 'The type of a price alert must be "above" or "below"') return jsonify(PriceAlertSerializer.serialize(alert))
def check_global_timed_game(): game = Game.get(Game.shareable_link == 'TIMED') if game.ends_at < datetime.utcnow(): # end global timed game, and start another profiles = [] for game_profile in GameProfile.select().where(GameProfile.game == game): profiles.append(game_profile.profile) send_notification(game_profile.profile, 'The global timed game has expired') game_profile.delete_instance(recursive=True) game.delete_instance(recursive=True) global_timed = Game.create(name='Global Timed', starting_cash=10000.00, shareable_link='TIMED', shareable_code='TIMED', ends_at=datetime.utcnow() + timedelta(minutes=1)) # CHANGEME for devel purposes, making it 1 min for now GameCoin.create(game=global_timed, coin=Coin.get()) for profile in profiles: GameProfile.create( game=global_timed, profile=profile, cash=global_timed.starting_cash )
def get_coins(): return jsonify(CoinsResponse.serialize(Coin.select(), many=True))
def up(db): with db.atomic(): migrator = PostgresqlMigrator(db) db.bind(MODELS, bind_refs=False, bind_backrefs=False) db.create_tables(MODELS) if Coin.get_or_none(Coin.id == 1) is None: Coin.create(name='Bitcoin', symbol='BTC') Coin.create(name='Ethereum', symbol='ETH') Coin.create(name='Litecoin', symbol='LTC') Coin.create(name='Coin 3', symbol='CO3') Coin.create(name='Coin 4', symbol='CO4') Coin.create(name='Coin 5', symbol='CO5') global_indef = Game.create(name='Global Indefinite', starting_cash=10000.00, shareable_link='INDEF', shareable_code='INDEF', ends_at=None) # insert achievements into database Achievement.create( name="Win", description="Finish in first place in a private game") Achievement.create( name="Double net worth", description="Achieved by doubling your net worth in a game") Achievement.create(name="Identity Crisis", description="Change your username") # insert goals into database Goal.create(name="Entrepreneur", description="Create a private game") all_coins = Coin.select() for coin in all_coins: GameCoin.create(game=global_indef, coin=coin) global_timed = Game.create(name='Global Timed', starting_cash=10000.00, shareable_link='TIMED', shareable_code='TIMED', ends_at=datetime.utcnow() + timedelta(minutes=1)) # CHANGEME for devel purposes, making it 1 min for now GameCoin.create(game=global_timed, coin=Coin.get()) # from auth.services import register hashed = bcrypt.hashpw("admin".encode(), bcrypt.gensalt()).decode() admin = Profile.create(username="******", hashed_password=hashed, is_admin=True) # Required so that admin can still view graphs in the landing page GameProfile.create(profile=admin, game=global_indef, cash=0.0)