class HWBalance(Base): """A Hot Wallet Balance, for internal use only""" id = sa.Column(sa.Integer, sa.Sequence('hwbalance_id_seq'), primary_key=True) available = sa.Column(LedgerAmount, nullable=False) total = sa.Column(LedgerAmount, nullable=False) currency = sa.Column(sa.String(4), nullable=False) # i.e. BTC, DASH, USDT network = sa.Column(sa.String(64), nullable=False) # i.e. Bitcoin, Dash, Crypto Capital time = sa.Column(sa.DateTime(), default=datetime.datetime.utcnow) def __init__(self, available, total, currency, network): self.available = available self.total = total self.currency = currency self.network = network self.load_commodities() @orm.reconstructor def load_commodities(self): """ Load the commodities for Amounts in this object. """ if isinstance(self.available, Amount): self.available = Amount("{0:.8f} {1}".format(self.available.to_double(), self.currency)) else: self.available = Amount("{0:.8f} {1}".format(self.available, self.currency)) if isinstance(self.total, Amount): self.total = Amount("{0:.8f} {1}".format(self.total.to_double(), self.currency)) else: self.total = Amount("{0:.8f} {1}".format(self.total, self.currency))
class Credit(Base): """A Credit, which adds tokens to a User's Balance.""" id = sa.Column(sa.Integer, sa.Sequence('credit_id_seq'), primary_key=True) amount = sa.Column(LedgerAmount, nullable=False) address = sa.Column(sa.String(64), nullable=False) # i.e. 1PkzTWAyfR9yoFw2jptKQ3g6E5nKXPsy8r, XhwWxABXPVG5Z3ePyLVA3VixPRkARK6FKy currency = sa.Column(sa.String(4), nullable=False) # i.e. BTC, DASH, USD network = sa.Column(sa.String(64), nullable=False) # i.e. Bitcoin, Dash, Crypto Capital transaction_state = sa.Column(sa.Enum("unconfirmed", "complete", "error", "canceled", name='transaction_state'), nullable=False) reference = sa.Column(sa.String(256), nullable=True) # i.e. invoice#1 ref_id = sa.Column(sa.String(256), nullable=False, unique=True) # i.e. 4cef42f9ff334b9b11bffbd9da21da54176103d92c1c6e4442cbe28ca43540fd:0 time = sa.Column(sa.DateTime(), nullable=False) # foreign key reference to the owner of this user_id = sa.Column( sa.Integer, sa.ForeignKey('user.id'), nullable=False) user = orm.relationship("User", foreign_keys=[user_id]) def __init__(self, amount, address, currency, network, transaction_state, reference, ref_id, user_id, time): self.amount = amount self.address = address self.currency = currency self.network = network self.transaction_state = transaction_state self.reference = reference self.ref_id = ref_id self.user_id = user_id # self.time = pytz.utc.localize(time) self.time = time.replace(tzinfo=None) self.load_commodities() def __repr__(self): return "<Credit(amount=%s, address='%s', currency='%s', network='%s', transaction_state='%s', reference='%s', " \ "ref_id='%s', time=%s)>" % ( self.amount, self.address, self.currency, self.network, self.transaction_state, self.network, self.ref_id, datetime_rfc3339(self.time)) def get_ledger_entry(self): date = self.time.strftime('%Y/%m/%d %H:%M:%S') ledger = "%s %s %s %s\n" % (date, self.reference, 'credit', self.currency) ledger += " Assets:{0}:{1}:credit {2}\n".format(self.network, self.currency, self.amount) ledger += " Equity:Wallet:{0}:debit {1}\n".format(self.currency, -self.amount) ledger += "\n" return ledger @orm.reconstructor def load_commodities(self): """ Load the commodities for Amounts in this object. """ if isinstance(self.amount, Amount): self.amount = Amount("{0:.8f} {1}".format(self.amount.to_double(), self.currency)) else: self.amount = Amount("{0:.8f} {1}".format(self.amount, self.currency))
class Balance(Base): """A user's balance in a single currency. Only the latest record is valid.""" id = sa.Column(sa.Integer, sa.Sequence('balance_id_seq'), primary_key=True) total = sa.Column(LedgerAmount, nullable=False) available = sa.Column(LedgerAmount, nullable=False) currency = sa.Column(sa.String(4), nullable=False) # i.e. BTC, DASH, USD time = sa.Column(sa.DateTime(), default=datetime.datetime.utcnow) reference = sa.Column(sa.String(256), nullable=True) # foreign key reference to the owner of this user_id = sa.Column( sa.Integer, sa.ForeignKey('user.id'), nullable=False) user = orm.relationship("User", foreign_keys=[user_id]) def __init__(self, total, available, currency, reference, user_id, time=None): self.total = total self.available = available self.currency = currency self.reference = reference self.user_id = user_id self.time = time if time is not None else datetime.datetime.utcnow() self.load_commodities() def __repr__(self): return "<Balance(total=%s, available=%s, currency='%s', reference='%s', user_id=%s, time=%s)>" % ( self.total, self.available, self.currency, self.reference, self.user_id, datetime_rfc3339(self.time)) @orm.reconstructor def load_commodities(self): """ Load the commodities for Amounts in this object. """ if isinstance(self.available, Amount): self.available = Amount("{0:.8f} {1}".format(self.available.to_double(), self.currency)) else: self.available = Amount("{0:.8f} {1}".format(self.available, self.currency)) if isinstance(self.total, Amount): self.total = Amount("{0:.8f} {1}".format(self.total.to_double(), self.currency)) else: self.total = Amount("{0:.8f} {1}".format(self.total, self.currency))
def fib_fan(side, amount, ticker, session): def calc_price(sid, index, offset): if sid == 'ask': return index * (Amount("1 %s" % index.commodity) + Amount("%s %s" % (offset, index.commodity)) / 100) else: return index * (Amount("1 %s" % index.commodity) - Amount("%s %s" % (offset, index.commodity)) / 100) usdamount = get_usd_value(amount) if usdamount <= MINORDER: print "ignoring dusty order %s worth %s" % (usdamount, usdamount) return fibseq = [1, 2, 3, 5, 8, 13] index = ticker.calculate_index() base = ticker.market.split("_")[0] if usdamount / Amount("{0} USD".format(len(fibseq))) <= MINORDER: price = calc_price(side, index, fibseq[int(round(len(fibseq) / 2))]) if side == 'bid': amount = Amount("{0:.8f} {1}".format(amount.to_double(), base)) / \ Amount("{0:.8f} {1}".format(index.to_double(), base)) # usdval = get_usd_value(amount) # print "{0} {1} @ {2:0.6f} {3} worth ${4:0.2f})".format(side, amount, price.to_double(), ticker.market, # usdval.to_double()) create_order(ticker.exchange, price=price, amount=amount, market=ticker.market, side=side, session=session) else: if side == 'bid': amount = Amount("{0:.8f} {1}".format((amount / len(fibseq)).to_double(), base)) / \ Amount("{0:.8f} {1}".format(index.to_double(), base)) else: amount /= len(fibseq) for fib in fibseq: price = calc_price(side, index, fib) create_order(ticker.exchange, price=price, amount=amount, market=ticker.market, side=side, session=session) # usdval = get_usd_value(amount) * price / index # print "{0} {1} @ {2:0.6f} {3} worth ${4:0.2f})".format(side, amount, price.to_double(), # ticker.market, usdval.to_double()) sync_balances(ticker.exchange)
def test_money_cycle(): fee = Amount("%s BTC" % CFG.get('internal', 'FEE')) amount = Amount("%s BTC" % 0.01) # Receive Internal to user addy = client.get_model('Address')(currency='BTC', network='Internal') address = client.address.createAddress(address=addy).result() internal_credit(address.address, amount + fee, session=ses) for i in range(0, 60): c = ses.query(wm.Credit).filter(wm.Credit.address == address.address).first() if c is not None: break else: time.sleep(1) assert c is not None assert c.address == address.address assert c.amount == amount + fee assert c.currency == 'BTC' assert c.network == 'Internal' assert len(c.ref_id) > 0 # ses.close() bal = ses.query(wm.Balance).filter(wm.Balance.user_id == user.id).filter(wm.Balance.currency == 'BTC').first() assert bal.total > Amount("0 BTC") assert bal.available == Amount("0 BTC") bal.available = bal.available + c.amount ses.add(bal) try: ses.commit() except Exception as e: ses.rollback() print "skipping test" return ses.close() # send Internal internally to user 2 addy = client2.get_model('Address')(currency='BTC', network='Internal') address = client2.address.createAddress(address=addy).result() debit = client.debit.sendMoney(debit={'amount': 0.01, 'fee': fee.to_double(), 'address': address.address, 'currency': 'BTC', 'network': 'Internal', 'state': 'unconfirmed', 'reference': 'test send money internal internal', 'ref_id': ''}).result() assert debit.transaction_state == 'complete' assert debit.amount == 0.01 assert debit.reference == 'test send money internal internal' assert debit.network == 'internal' for i in range(0, 60): c = ses.query(wm.Credit).filter(wm.Credit.address == address.address).first() if c is not None: break else: time.sleep(1) assert c is not None assert c.transaction_state == 'complete' assert c.amount == Amount("0.01 BTC") assert c.reference == 'test send money internal internal' assert c.network == 'internal' assert int(debit.ref_id) == c.id assert int(c.ref_id) == debit.id bal = ses.query(wm.Balance).filter(wm.Balance.user_id == user.id).filter(wm.Balance.currency == 'BTC').first() assert bal.total == Amount("0 BTC") assert bal.available == Amount("0 BTC") bal = ses.query(wm.Balance).filter(wm.Balance.user_id == user2.id).filter(wm.Balance.currency == 'BTC').first() assert bal.total == Amount("0.01 BTC") assert bal.available == Amount("0.01 BTC") ses.close() # send BTC internally to user 2 addy = client2.get_model('Address')(currency='BTC', network='Internal') address = client2.address.createAddress(address=addy).result() debit = client2.debit.sendMoney(debit={'amount': 0.0099, 'fee': CFG.get('internal', 'FEE'), 'address': address.address, 'currency': 'BTC', 'network': 'Internal', 'state': 'unconfirmed', 'reference': 'test send money internal internal', 'ref_id': ''}).result() assert debit.transaction_state == 'complete' assert debit.amount == 0.0099 assert debit.reference == 'test send money internal internal' assert debit.network == 'internal' for i in range(0, 60): c = ses.query(wm.Credit).filter(wm.Credit.address == address.address).first() if c is not None: break else: time.sleep(1) assert c is not None assert c.transaction_state == 'complete' assert c.amount == Amount("0.0099 BTC") assert c.reference == 'test send money internal internal' assert c.network == 'internal' assert int(debit.ref_id) == c.id assert int(c.ref_id) == debit.id bal = ses.query(wm.Balance).filter(wm.Balance.user_id == user.id).filter(wm.Balance.currency == 'BTC').first() assert bal.total == Amount("0 BTC") assert bal.available == Amount("0 BTC") bal = ses.query(wm.Balance).filter(wm.Balance.user_id == user2.id).filter(wm.Balance.currency == 'BTC').first() assert bal.total == Amount("0.0099 BTC") assert bal.available == Amount("0.0099 BTC") ses.close() # Send Internal from user2 addy = internal_address() debit = client2.debit.sendMoney(debit={'amount': 0.0098, 'fee': CFG.get('internal', 'FEE'), 'address': addy, 'currency': 'BTC', 'network': 'Internal', 'state': 'unconfirmed', 'reference': 'test send money internal', 'ref_id': ''}).result() time.sleep(0.1) for i in range(0, 60): d = ses.query(wm.Debit).filter(wm.Debit.address == addy).first() if d is not None: break else: time.sleep(1) assert d is not None assert d.address == addy assert d.amount == Amount("0.0098 BTC") bal = ses.query(wm.Balance).filter(wm.Balance.user_id == user2.id).filter(wm.Balance.currency == 'BTC') assert bal.first().total == Amount("0 BTC") assert bal.first().available == Amount("0 BTC")