def list_recent_btc_transactions(self):
        ''' Limits to 30, add pagination if you want more '''
        LIST_TX_URL = 'https://coinbase.com/api/v1/transactions'

        r = get_cb_request(
            url=LIST_TX_URL,
            api_key=self.api_key,
            api_secret=self.api_secret,
        )

        # Log the API call
        APICall.objects.create(api_name=APICall.COINBASE_LIST_BTC_TRANSACTIONS,
                               url_hit=LIST_TX_URL,
                               response_code=r.status_code,
                               post_params=None,
                               api_results=r.content,
                               merchant=self.merchant,
                               credential=self)

        self.handle_status_code(r.status_code)

        json_resp = json.loads(r.content)

        # Record the balance
        BaseBalance.objects.create(satoshis=btc_to_satoshis(
            json_resp['balance']['amount']),
                                   credential=self)

        # Return transactions
        return json_resp['transactions']
Beispiel #2
0
 def get_satoshis_from_fiat(self):
     merchant = self.merchant
     currency_code = self.currency_code_when_created
     fiat_btc = BTCTransaction.get_btc_market_price(currency_code)
     basis_points_markup = merchant.get_cashin_percent_markup() * 100.00
     markup_fee = fiat_btc * basis_points_markup / 10000.00
     fiat_btc = fiat_btc + markup_fee
     total_btc = self.fiat_amount / Decimal(fiat_btc)
     satoshis = btc_to_satoshis(total_btc)
     return satoshis
    def get_balance(self):
        """
        Return acount balance in satoshis
        """
        BALANCE_URL = 'https://www.bitstamp.net/api/balance/'
        trading_obj = self.get_trading_obj()

        try:
            balance_dict = trading_obj.account_balance()
            # Log the API call
            APICall.objects.create(
                api_name=APICall.BITSTAMP_BALANCE,
                url_hit=BALANCE_URL,
                response_code=200,
                post_params=None,  # not accurate
                api_results=balance_dict,
                merchant=self.merchant,
                credential=self)

            self.mark_success()

        except Exception as e:
            # Log the API call
            APICall.objects.create(
                api_name=APICall.BITSTAMP_BALANCE,
                url_hit=BALANCE_URL,
                response_code=0,  # this is not accurate
                post_params=None,  # not accurate
                api_results=str(e),
                merchant=self.merchant,
                credential=self)

            self.mark_failure()
            print 'Error was: %s' % e
            return False

        satoshis = btc_to_satoshis(balance_dict['btc_available'])

        # Record the balance results
        BaseBalance.objects.create(satoshis=satoshis, credential=self)

        return satoshis
    def get_balance(self):
        """
        Return acount balance in satoshis

        We return False when there's an API fail
        This prevents the front-end from breaking while still passing the neccessary info back

        """
        BALANCE_URL = 'https://coinbase.com/api/v1/account/balance'
        r = get_cb_request(url=BALANCE_URL,
                           api_key=self.api_key,
                           api_secret=self.api_secret)

        # Log the API call
        APICall.objects.create(api_name=APICall.COINBASE_BALANCE,
                               url_hit=BALANCE_URL,
                               response_code=r.status_code,
                               post_params=None,
                               api_results=r.content,
                               merchant=self.merchant,
                               credential=self)

        status_code_is_valid = self.handle_status_code(r.status_code)

        if not status_code_is_valid:
            return False

        resp_json = json.loads(r.content)

        if 'currency' not in resp_json and resp_json['currency'] != 'BTC':
            self.mark_failure()
            return False

        satoshis = btc_to_satoshis(resp_json['amount'])

        # Record the balance results
        BaseBalance.objects.create(satoshis=satoshis, credential=self)

        return satoshis
    def send_btc(self,
                 satoshis_to_send,
                 destination_btc_address,
                 destination_email_address=None,
                 notes=None):
        """
        Send satoshis to a destination address or email address.
        CB requires a fee for txns < .001 BTC, so this method will
        automatically include txn fees for those.

        Returns a tuple of the form (some or all may be none):
            btc_txn, sent_btc_obj, api_call, err_str
        """

        msg = "Can't have both a destination email and BTC address. %s | %s" % (
            destination_email_address, destination_btc_address)
        assert not (destination_email_address and destination_btc_address), msg

        msg = 'Must send to a destination email OR BTC address'
        assert destination_email_address or destination_btc_address, msg

        dest_addr_to_use = None

        if destination_btc_address:
            dest_addr_to_use = destination_btc_address
            send_btc_dict = {
                'destination_btc_address': destination_btc_address
            }

            msg = '%s is not a valid bitcoin address' % destination_btc_address
            assert is_valid_btc_address(destination_btc_address), msg

        if destination_email_address:
            dest_addr_to_use = destination_email_address
            send_btc_dict = {'destination_email': destination_email_address}

            msg = '%s is not a valid email address' % destination_email_address
            # FIXME: implement

        btc_to_send = satoshis_to_btc(satoshis_to_send)

        SEND_URL = 'https://coinbase.com/api/v1/transactions/send_money'

        body = 'transaction[to]=%s&transaction[amount]=%s' % (dest_addr_to_use,
                                                              btc_to_send)
        post_params = {'to': dest_addr_to_use, 'amount': btc_to_send}

        if satoshis_to_send <= btc_to_satoshis(
                .001) and not destination_email_address:
            # https://coinbase.com/api/doc/1.0/transactions/send_money.html
            # Coinbase pays transaction fees on payments greater than or equal to 0.001 BTC.
            # But for smaller amounts you have to add your own
            # For some reason, coinbase requires 2x fees of .2 mBTC vs (.1 mBTC)
            body += '&transaction[user_fee]=0.0002'
            post_params['user_fee'] = 0.0002

        if notes:
            # TODO: url encode this?
            body += '&transaction[notes]=' + notes
            post_params['notes'] = notes

        r = get_cb_request(url=SEND_URL,
                           api_key=self.api_key,
                           api_secret=self.api_secret,
                           body=body)

        # Log the API call
        api_call = APICall.objects.create(api_name=APICall.COINBASE_SEND_BTC,
                                          url_hit=SEND_URL,
                                          response_code=r.status_code,
                                          post_params=post_params,
                                          api_results=r.content,
                                          merchant=self.merchant,
                                          credential=self)

        self.handle_status_code(r.status_code)

        resp_json = json.loads(r.content)

        if resp_json.get('error') or resp_json.get('errors'):
            err_str = resp_json.get('error')
            # combine the two
            if resp_json.get('errors'):
                if err_str:
                    err_str += ' %s' % resp_json.get('errors')
                else:
                    err_str = resp_json.get('errors')

            # this assumes all error messages here are safe to display to the user
            return None, None, api_call, err_str

        transaction = resp_json['transaction']

        satoshis = -1 * btc_to_satoshis(transaction['amount']['amount'])

        txn_hash = transaction['hsh']

        # Record the Send
        send_btc_dict.update({
            'credential': self,
            'txn_hash': txn_hash,
            'satoshis': satoshis,
            'transaction_id': transaction['id'],
            'notes': notes,
        })
        sent_btc_obj = CBSSentBTC.objects.create(**send_btc_dict)

        if txn_hash:
            return BTCTransaction.objects.create(
                txn_hash=txn_hash, satoshis=satoshis,
                conf_num=0), sent_btc_obj, api_call, None
        else:
            # Coinbase seems finicky about transaction hashes
            return None, sent_btc_obj, api_call, None
    def request_cashout(self, satoshis_to_sell):
        SELL_URL = 'https://coinbase.com/api/v1/sells'

        btc_to_sell = satoshis_to_btc(satoshis_to_sell)
        body_to_use = 'qty=%s' % btc_to_sell

        r = get_cb_request(
            url=SELL_URL,
            api_key=self.api_key,
            api_secret=self.api_secret,
            body=body_to_use,
        )

        # Log the API call
        APICall.objects.create(api_name=APICall.COINBASE_CASHOUT_BTC,
                               url_hit=SELL_URL,
                               response_code=r.status_code,
                               api_results=r.content,
                               post_params={'qty': btc_to_sell},
                               merchant=self.merchant,
                               credential=self)

        self.handle_status_code(r.status_code)

        resp_json = json.loads(r.content)

        success = resp_json['success']
        assert success is True, '%s: %s' % (success, resp_json.get('errors'))

        transfer = resp_json['transfer']

        status = transfer['status']
        assert status.lower() in ('pending', 'created'), status

        btc_obj = transfer['btc']
        assert btc_obj['currency'] == 'BTC', btc_obj

        satoshis = btc_to_satoshis(btc_obj['amount'])
        assert satoshis == satoshis_to_sell, btc_obj['amount']

        currency_to_recieve = transfer['total']['currency']

        fiat_fees_in_cents = 0
        for fee_key in transfer['fees']:
            fee = transfer['fees'][fee_key]
            fiat_fees_in_cents += int(fee['cents'])
            msg = '%s != %s' % (fee['currency_iso'], currency_to_recieve)
            assert fee['currency_iso'] == currency_to_recieve, msg
        fiat_fees = fiat_fees_in_cents / 100.0

        cbs_sell_btc = CBSSellBTC.objects.create(
            coinbase_code=transfer['code'])

        return CBSSellBTC.objects.create(
            credential=self,
            cbs_sell_btc=cbs_sell_btc,
            satoshis=satoshis,
            currency_code=currency_to_recieve,
            fees_in_fiat=fiat_fees,
            to_receive_in_fiat=float(transfer['total']['amount']),
        )