示例#1
0
 def withdraw_proportion_all(cls, address, bitcoin_payments_proportions):
     """hash BitcoinPayment -> Proportion"""
     final_amount = Decimal("0.0")
     print bitcoin_payments_proportions
     for bp, proportion in bitcoin_payments_proportions.iteritems():
         am = bp.calculate_amount(proportion)
         final_amount += am
         bp.add_transaction(am, address)
     bitcoind.send(address, final_amount)
     return True
示例#2
0
 def withdraw_proportion_all(cls, address, bitcoin_payments_proportions):
     """hash BitcoinPayment -> Proportion"""
     final_amount=Decimal("0.0")
     print bitcoin_payments_proportions
     for bp, proportion in bitcoin_payments_proportions.iteritems():
         am=bp.calculate_amount(proportion)
         final_amount+=am
         bp.add_transaction(am, address)
     bitcoind.send(address, final_amount)
     return True
示例#3
0
    def withdraw_proportion(self, address, proportion):
        if proportion<=Decimal("0") or proportion>Decimal("100"):
            raise Exception("Illegal proportion.")

        amount = self.calculate_amount(proportion)

        if self.amount-self.withdrawn_total > amount:
            raise Exception("Trying to withdraw too much.")

        self.add_transaction(amount, address)
        bitcoind.send(address, amount)
示例#4
0
    def withdraw_proportion(self, address, proportion):
        if proportion <= Decimal("0") or proportion > Decimal("100"):
            raise Exception("Illegal proportion.")

        amount = self.calculate_amount(proportion)

        if self.amount - self.withdrawn_total > amount:
            raise Exception("Trying to withdraw too much.")

        self.add_transaction(amount, address)
        bitcoind.send(address, amount)
示例#5
0
 def withdraw_all(cls, bitcoinpayments, addresses_shares):
     # if len(bitcoinpayments)!=len(addresses_shares):
     #    raise Exception("")
     amounts_all = Payment.calculate_amounts(bitcoinpayments, addresses_shares)
     for bp in bitcoinpayments:
         am = bp.withdraw_amounts(addresses_shares)
         bp.withdraw_addresses = ",".join(addresses_shares.keys())
         bp.withdraw_proportions = ",".join([str(x) for x in addresses_shares.values()])
         bp.withdraw_amounts = ",".join([str(x) for x in am])
         bp.withdrawn_at = datetime.datetime.now()
         bp.withdrawn_total = sum(am)
         bp.save()
     for i, share in enumerate(addresses_shares.keys()):
         bitcoind.send(share, amounts_all[i])
     return True
示例#6
0
def process_outgoing_transactions():
    with CacheLock('process_outgoing_transactions'):
        update_wallets = []
        for ot in OutgoingTransaction.objects.filter(executed_at=None):
            result = None
            OutgoingTransaction.objects.filter(id=ot.id).update(executed_at=datetime.datetime.now(), txid=result)
            db_transaction.commit()
            try:
                result = bitcoind.send(ot.to_bitcoinaddress, ot.amount)
            except jsonrpc.JSONRPCException:
                raise
            OutgoingTransaction.objects.filter(id=ot.id).update(txid=result)
            transaction = bitcoind.gettransaction(result)
            if Decimal(transaction['fee']) < Decimal(0):
                wt = ot.wallettransaction_set.all()[0]
                fee_transaction = WalletTransaction.objects.create(
                    amount=Decimal(transaction['fee']) * Decimal(-1),
                    from_wallet_id=wt.from_wallet_id)
                update_wallets.append(wt.from_wallet_id)
        db_transaction.commit()

        for wid in update_wallets:
            if getattr(django_settings, "CELERY_ALWAYS_EAGER", False):
                # Do not do asyncrhonous transaction processing
                update_wallet_balance(wid)
                db_transaction.commit()
            else:
                update_wallet_balance.delay(wid)
示例#7
0
    def send_to_address(self, address, amount, description=''):
        if settings.BITCOIN_DISABLE_OUTGOING:
            raise Exception("Outgoing transactions disabled! contact support.")
        address = address.strip()

        if type(amount) != Decimal:
            amount = Decimal(amount)
        amount = amount.quantize(Decimal('0.00000001'))

        if not is_valid_btc_address(str(address)):
            raise Exception(_("Not a valid bitcoin address") + ":" + address)
        if amount <= 0:
            raise Exception(_("Can't send zero or negative amounts"))
        # concurrency check
        with db_transaction.autocommit():
            db_transaction.enter_transaction_management()
            db_transaction.commit()
            avail = self.total_balance()
            updated = Wallet.objects.filter(Q(id=self.id)).update(last_balance=avail)
            if amount > avail:
                raise Exception(_("Trying to send too much"))
            new_balance = avail - amount
            updated = Wallet.objects.filter(Q(id=self.id) & Q(transaction_counter=self.transaction_counter) & 
                Q(last_balance=avail) )\
              .update(last_balance=new_balance, transaction_counter=self.transaction_counter+1)
            if not updated:
                print "address transaction concurrency:", new_balance, avail, self.transaction_counter, self.last_balance, self.total_balance()
                raise Exception(_("Concurrency error with transactions. Please try again."))
            # concurrency check end
            bwt = WalletTransaction.objects.create(
                amount=amount,
                from_wallet=self,
                to_bitcoinaddress=address,
                description=description)
            try:
                result = bitcoind.send(address, amount)
            except jsonrpc.JSONRPCException:
                bwt.delete()
                raise
            self.transaction_counter = self.transaction_counter+1
            self.last_balance = new_balance
        
            # check if a transaction fee exists, and deduct it from the wallet
            # TODO: because fee can't be known beforehand, can result in negative wallet balance.
            # currently isn't much of a issue, but might be in the future, depending of the application
            transaction = bitcoind.gettransaction(result)
            fee_transaction = None
            total_amount = amount
            if Decimal(transaction['fee']) < Decimal(0):
                fee_transaction = WalletTransaction.objects.create(
                    amount=Decimal(transaction['fee']) * Decimal(-1),
                    from_wallet=self)
                total_amount += fee_transaction.amount
            if settings.BITCOIN_TRANSACTION_SIGNALING:
                balance_changed.send(sender=self, 
                    changed=(Decimal(-1) * total_amount), transaction=bwt)
                balance_changed_confirmed.send(sender=self, 
                    changed=(Decimal(-1) * total_amount), transaction=bwt)
            return (bwt, fee_transaction)
示例#8
0
 def withdraw_all(cls, bitcoinpayments, addresses_shares):
     #if len(bitcoinpayments)!=len(addresses_shares):
     #    raise Exception("")
     amounts_all = Payment.calculate_amounts(bitcoinpayments,
                                             addresses_shares)
     for bp in bitcoinpayments:
         am = bp.withdraw_amounts(addresses_shares)
         bp.withdraw_addresses = ",".join(addresses_shares.keys())
         bp.withdraw_proportions = ",".join(
             [str(x) for x in addresses_shares.values()])
         bp.withdraw_amounts = ",".join([str(x) for x in am])
         bp.withdrawn_at = datetime.datetime.now()
         bp.withdrawn_total = sum(am)
         bp.save()
     for i, share in enumerate(addresses_shares.keys()):
         bitcoind.send(share, amounts_all[i])
     return True
示例#9
0
    def send_to_address(self, address, amount, description=''):
        if settings.BITCOIN_DISABLE_OUTGOING:
            raise Exception("Outgoing transactions disabled! contact support.")
        address = address.strip()

        if type(amount) != Decimal:
            amount = Decimal(amount)
        amount = amount.quantize(Decimal('0.00000001'))

        if not is_valid_btc_address(str(address)):
            raise Exception(_("Not a valid bitcoin address") + ":" + address)
        if amount <= 0:
            raise Exception(_("Can't send zero or negative amounts"))
        # concurrency check
        with db_transaction.autocommit():
            avail = self.total_balance()
            updated = Wallet.objects.filter(Q(id=self.id)).update(last_balance=avail)
            if amount > avail:
                raise Exception(_("Trying to send too much"))
            new_balance = avail - amount
            updated = Wallet.objects.filter(Q(id=self.id) & Q(transaction_counter=self.transaction_counter) & 
                Q(last_balance=avail) )\
              .update(last_balance=new_balance, transaction_counter=self.transaction_counter+1)
            if not updated:
                print "address transaction concurrency:", new_balance, avail, self.transaction_counter, self.last_balance, self.total_balance()
                raise Exception(_("Concurrency error with transactions. Please try again."))
            # concurrency check end
            bwt = WalletTransaction.objects.create(
                amount=amount,
                from_wallet=self,
                to_bitcoinaddress=address,
                description=description)
            try:
                result = bitcoind.send(address, amount)
            except jsonrpc.JSONRPCException:
                bwt.delete()
                raise
            self.transaction_counter = self.transaction_counter+1
            self.last_balance = new_balance
        
            # check if a transaction fee exists, and deduct it from the wallet
            # TODO: because fee can't be known beforehand, can result in negative wallet balance.
            # currently isn't much of a issue, but might be in the future, depending of the application
            transaction = bitcoind.gettransaction(result)
            fee_transaction = None
            total_amount = amount
            if Decimal(transaction['fee']) < Decimal(0):
                fee_transaction = WalletTransaction.objects.create(
                    amount=Decimal(transaction['fee']) * Decimal(-1),
                    from_wallet=self)
                total_amount += fee_transaction.amount
            if settings.BITCOIN_TRANSACTION_SIGNALING:
                balance_changed.send(sender=self, 
                    changed=(Decimal(-1) * total_amount), transaction=bwt)
                balance_changed_confirmed.send(sender=self, 
                    changed=(Decimal(-1) * total_amount), transaction=bwt)
            return (bwt, fee_transaction)
示例#10
0
 def handle_noargs(self, **options):
     final_wallets = []
     process_num = random.randint(0, 1000)
     with warnings.catch_warnings():
         warnings.filterwarnings("ignore", category=RuntimeWarning)
         for i in range(0, 3):
             w = Wallet.objects.create()
             # print "starting w.id", w.id
             addr = w.receiving_address()
             # print "taddr", w.id, addr
             final_wallets.append(w)
     for w in final_wallets:
         if w.total_balance_sql() > 0:
             print str(process_num) + " error", w.id
             raise Exception("damn!")
         # print "final", w.id, w.static_receiving_address(), w.receiving_address()
     print str(
         process_num
     ) + " loading 0.001 to wallet #1", w1.static_receiving_address()
     w1 = final_wallets[0]
     w2 = final_wallets[1]
     w3 = final_wallets[2]
     bitcoind.send(w1.static_receiving_address(), Decimal("0.001"))
     while w1.total_balance_sql() <= 0:
         sleep(1)
         w1 = Wallet.objects.get(id=w1.id)
         # print w1.last_balance
     print str(process_num) + " w1.last_balance " + str(w1.last_balance)
     print str(process_num) + "loading"
     w1.send_to_wallet(w2, Decimal("0.0002"))
     w1.send_to_wallet(w3, Decimal("0.0005"))
     w3.send_to_address(w1, Decimal("0.0004"))
     print str(process_num) + " w1.last_balance " + str(w1.last_balance)
     print str(process_num) + " w2.last_balance " + str(w2.last_balance)
     print str(process_num) + " w3.last_balance " + str(w3.last_balance)
     while w1.total_balance_sql() <= 0:
         sleep(1)
         w1 = Wallet.objects.get(id=w1.id)
     print str(process_num) + "catching"
     print str(process_num) + " w1.last_balance " + str(w1.last_balance)
     print str(process_num) + " w2.last_balance " + str(w2.last_balance)
     print str(process_num) + " w3.last_balance " + str(w3.last_balance)
 def handle_noargs(self, **options):
     final_wallets = []
     process_num = random.randint(0, 1000)
     with warnings.catch_warnings():
         warnings.filterwarnings("ignore", category=RuntimeWarning)
         for i in range(0, 3):
             w = Wallet.objects.create()
             # print "starting w.id", w.id
             addr = w.receiving_address()
             # print "taddr", w.id, addr
             final_wallets.append(w)
     for w in final_wallets:
         if w.total_balance_sql() > 0:
             print str(process_num) + " error", w.id
             raise Exception("damn!")
         # print "final", w.id, w.static_receiving_address(), w.receiving_address()
     print str(process_num) + " loading 0.001 to wallet #1", w1.static_receiving_address()
     w1 = final_wallets[0]
     w2 = final_wallets[1]
     w3 = final_wallets[2]
     bitcoind.send(w1.static_receiving_address(), Decimal("0.001"))
     while w1.total_balance_sql() <= 0:
         sleep(1)
         w1 = Wallet.objects.get(id=w1.id)
         # print w1.last_balance
     print str(process_num) + " w1.last_balance " + str(w1.last_balance)
     print str(process_num) + "loading"
     w1.send_to_wallet(w2, Decimal("0.0002"))
     w1.send_to_wallet(w3, Decimal("0.0005"))
     w3.send_to_address(w1, Decimal("0.0004"))
     print str(process_num) + " w1.last_balance " + str(w1.last_balance)
     print str(process_num) + " w2.last_balance " + str(w2.last_balance)
     print str(process_num) + " w3.last_balance " + str(w3.last_balance)
     while w1.total_balance_sql() <= 0:
         sleep(1)
         w1 = Wallet.objects.get(id=w1.id)
     print str(process_num) + "catching"
     print str(process_num) + " w1.last_balance " + str(w1.last_balance)
     print str(process_num) + " w2.last_balance " + str(w2.last_balance)
     print str(process_num) + " w3.last_balance " + str(w3.last_balance)
示例#12
0
def process_outgoing_transactions():
    if cache.get("process_outgoing_transactions"):
        print "process ongoing, skipping..."
        db_transaction.rollback()
        return
    if cache.get("wallet_downtime_utc"):
        db_transaction.rollback()
        return
    # try out bitcoind connection
    print bitcoind.bitcoind_api.getinfo()
    with NonBlockingCacheLock('process_outgoing_transactions'):
        update_wallets = []
        for ot in OutgoingTransaction.objects.filter(executed_at=None)[:3]:
            result = None
            updated = OutgoingTransaction.objects.filter(id=ot.id,
                executed_at=None, txid=None, under_execution=False).select_for_update().update(executed_at=datetime.datetime.now(), txid=result)
            db_transaction.commit()
            if updated:
                try:
                    result = bitcoind.send(ot.to_bitcoinaddress, ot.amount)
                    updated2 = OutgoingTransaction.objects.filter(id=ot.id, txid=None).select_for_update().update(txid=result)
                    db_transaction.commit()
                    if updated2:
                        transaction = bitcoind.gettransaction(result)
                        if Decimal(transaction['fee']) < Decimal(0):
                            wt = ot.wallettransaction_set.all()[0]
                            fee_transaction = WalletTransaction.objects.create(
                                amount=Decimal(transaction['fee']) * Decimal(-1),
                                from_wallet_id=wt.from_wallet_id)
                            update_wallets.append(wt.from_wallet_id)
                except jsonrpc.JSONRPCException as e:
                    if e.error == u"{u'message': u'Insufficient funds', u'code': -4}":
                        OutgoingTransaction.objects.filter(id=ot.id, txid=None, 
                            under_execution=False).select_for_update().update(executed_at=None)
                        db_transaction.commit()
                        # sleep(10)
                        raise
                    else:
                        OutgoingTransaction.objects.filter(id=ot.id).select_for_update().update(under_execution=True)
                        db_transaction.commit()
                        raise
                
            else:
                raise Exception("Outgoingtransaction can't be updated!")
        db_transaction.commit()
        for wid in update_wallets:
            update_wallet_balance.delay(wid)