Example #1
0
    def fee(self, value=None, unit='satoshi'):
        """
        Set the miner fee, if unit is not set, assumes value is satoshi.
        If using 'optimal', make sure you have already added all outputs.
        """
        convert = None
        if not value:
            # no fee was specified, use $0.02 as default.
            convert = get_current_price(self.crypto, "usd")
            self.fee_satoshi = int(0.02 / convert * 1e8)
            verbose = "Using default fee of:"

        elif value == 'optimal':
            self.fee_satoshi = get_optimal_fee(self.crypto,
                                               self.estimate_size(),
                                               verbose=self.verbose)
            verbose = "Using optimal fee of:"
        else:
            self.fee_satoshi = self.from_unit_to_satoshi(value, unit)
            verbose = "Using manually set fee of:"

        if self.verbose:
            if not convert:
                convert = get_current_price(self.crypto, "usd")
            fee_dollar = convert * self.fee_satoshi / 1e8
            print(verbose + " %s satoshis ($%.2f)" %
                  (self.fee_satoshi, fee_dollar))
Example #2
0
 def calculate_exchange_rate(self):
     deposit_price = get_current_price(crypto=self.deposit_currency.code,
                                       fiat='usd')
     withdraw_price = get_current_price(crypto=self.withdraw_currency.code,
                                        fiat='usd')
     raw_rate = deposit_price / withdraw_price
     rate_with_fee = raw_rate * (1 +
                                 (settings.EXCHANGE_FEE_PERCENTAGE / 100.0))
     return rate_with_fee
Example #3
0
 def calculate_exchange_rate(self):
     deposit_price = get_current_price(
         crypto=self.deposit_currency.code, fiat='usd')
     withdraw_price = get_current_price(
         crypto=self.withdraw_currency.code, fiat='usd')
     raw_rate = deposit_price / withdraw_price
     rate_with_fee = raw_rate * \
         (1 + (settings.EXCHANGE_FEE_PERCENTAGE / 100.0))
     return rate_with_fee
Example #4
0
 def get_current_price(cls, crypto, fiat, verbose=False):
     price = cls.get_non_stale_price(crypto, fiat)
     if price:
         return price
     sources, price = get_current_price(crypto, fiat, report_services=True, verbose=verbose)
     tick = cls.record_price(price, crypto, fiat, sources[0].name)
     return tick
Example #5
0
 def get_current_price(cls, crypto, fiat, verbose=False):
     price = cls.get_non_stale_price(crypto, fiat)
     if price:
         return price
     sources, price = get_current_price(crypto,
                                        fiat,
                                        report_services=True,
                                        verbose=verbose)
     tick = cls.record_price(price, crypto, fiat, sources[0].name)
     return tick
Example #6
0
    def from_unit_to_satoshi(self, value, unit='satoshi'):
        """
        Convert a value to satoshis. units can be any fiat currency.
        By default the unit is satoshi.
        """
        if not unit or unit == 'satoshi':
            return value
        if unit == 'bitcoin' or unit == 'btc':
            return int(value * 1e8)

        # assume fiat currency that we can convert
        convert = get_current_price(self.crypto, unit)
        return int(value / convert * 1e8)
Example #7
0
    def from_unit_to_satoshi(self, value, unit='satoshi'):
        """
        Convert a value to satoshis. units can be any fiat currency.
        By default the unit is satoshi.
        """
        logging.info("from_unit_to_satoshi : Value: {}, unit: {}".format(
            value, unit))
        if not unit or unit == 'satoshi':
            return value
        if unit == 'bitcoin' or unit == 'btc':
            return value * 1e8

        # assume fiat currency that we can convert
        convert = get_current_price(self.crypto, unit)
        if isinstance(convert, tuple):
            convert = convert[0]
        logging.info("from_unit_to_satoshi : Convert: {}".format(convert))

        return int(value / convert * 1e8)
Example #8
0
    def get_tipped_value(self):
        """
        Check the blokchain to see how many tips have been collected.
        """
        if not self.address:
            return 0

        cache = caches['default']
        price = cache.get('btc-price')
        if not price:
            price, source = get_current_price('btc', 'usd')
            cache.set('btc-price', price)

        status_balance = cache.get(self.address)
        if not status_balance:
            balance = get_address_balance('btc', self.address)
            cache.set(self.address, ['OK', balance])
        else:
            status, balance = status_balance

        return balance * price
Example #9
0
    def get_tipped_value(self):
        """
        Check the blokchain to see how many tips have been collected.
        """
        if not self.address:
            return 0

        cache = caches['default']
        price = cache.get('btc-price')
        if not price:
            price, source = get_current_price('btc', 'usd')
            cache.set('btc-price', price)

        status_balance = cache.get(self.address)
        if not status_balance:
            balance = get_address_balance('btc', self.address)
            cache.set(self.address, ['OK', balance])
        else:
            status, balance = status_balance

        return balance * price
Example #10
0
def fetch_wallet_balances(wallets, fiat, **modes):
    """
    Wallets must be list of two item lists. First item is crypto, second item
    is the address. example:

    [
        ['btc', '1PZ3Ps9RvCmUW1s1rHE25FeR8vtKUrhEai'],
        ['ltc', 'Lb78JDGxMcih1gs3AirMeRW6jaG5V9hwFZ']
    ]
    """
    price_fetch = set([x[0] for x in wallets])
    balances = {}
    prices = {}

    fetch_length = len(wallets) + len(price_fetch)

    helpers = {fiat.lower(): {}}
    if not modes.get('async', False):
        # synchronous fetching
        for crypto in price_fetch:
            try:
                p = get_current_price(
                    crypto, fiat, helper_prices=helpers, report_services=True, **modes
                )
                prices[crypto] = {'price': p}
                if crypto in ['btc', 'ltc', 'doge', 'uno']:
                    helpers[fiat.lower()][crypto] = p
            except NoService as exc:
                prices[crypto] = {'error': str(exc)}

        for crypto, address in wallets:
            if address.replace('.', '').isdigit():
                balances[address] = {'balance': float(address)}
                continue

            try:
                balances[address] = {'balance': get_address_balance(crypto, address.strip(), **modes)}
            except NoService as exc:
                balances[address] = {'error': str(exc)}

    else:
        # asynchronous fetching
        if modes.get('verbose', False):
            print("Need to make", fetch_length, "external calls")

        with futures.ThreadPoolExecutor(max_workers=int(fetch_length / 2)) as executor:
            future_to_key = dict(
                (executor.submit(
                    get_current_price, crypto, fiat, report_services=True, **modes
                ), crypto) for crypto in price_fetch
            )

            future_to_key.update(dict(
                (executor.submit(
                    get_address_balance, crypto, address.strip(), **modes
                ), address) for crypto, address in wallets
            ))

            done, not_done = futures.wait(future_to_key, return_when=futures.ALL_COMPLETED)
            if len(not_done) > 0:
                print (not_done)
                import debug
                raise Exception("Broke") #not_done.pop().exception()

            for future in done:
                key = future_to_key[future]
                if len(key) > 5: # this will break if a crypto symbol is longer than 5 chars.
                    which = balances
                else:
                    which = prices

                res = future.result()
                which[key] = res

    ret = []

    for crypto, address in wallets:
        error = None
        if 'balance' in balances[address]:
            crypto_value = balances[address]['balance']
        else:
            crypto_value = 0
            error = balances[address]['error']

        if 'price' in prices[crypto]:
            sources, fiat_price = prices[crypto]['price']
        else:
            sources, fiat_price = [], 0
            error = prices[crypto]['error']

        ret.append({
            'crypto': crypto,
            'address': address,
            'crypto_value': crypto_value,
            'fiat_value': (crypto_value or 0) * (fiat_price or 0),
            'conversion_price': fiat_price,
            'price_source': sources[0].name if sources else "None",
            'error': error
        })

    return ret
Example #11
0
def perform_giveaway(dry_run=True, giveaway_private_key=None):
    giveaway_address = '1K65TijR56S4CcwjXBnecYEKmTNrMag5uq'
    #giveaway_address = '1BUxsE6s6Kkpwn4ZQiYuu3zVAtVffJEyDP' # for testing

    tx = Transaction('btc')
    tx.add_input(giveaway_address, giveaway_private_key)
    giveaway_balance = tx.total_input_satoshis() / 1e8

    to_be_given_away = giveaway_balance * 0.02
    dollars_per_btc, source = get_current_price('btc', 'usd')

    print "%.8f BTC (%.2f USD) in donate address %.8f BTC (%.2f USD) will be given away" % (
        giveaway_balance, giveaway_balance * dollars_per_btc, to_be_given_away,
        to_be_given_away * dollars_per_btc)

    drawing_date = datetime.datetime.now()
    week_ago = drawing_date - datetime.timedelta(days=7)

    raw_submissions = list(
        GiveawaySubmission.objects.filter(date_created__gt=week_ago,
                                          date_created__lt=drawing_date,
                                          winner=False))

    # for now, try to send to unique addresses instead of multiple entries to
    # the same address. This code should be removed when there are more unique
    # entries per drawing.
    all_submissions = []
    for sub in raw_submissions:
        if sub.address not in [x.address for x in all_submissions]:
            all_submissions.append(sub)

    submission_count = len(all_submissions)  #.count()
    print submission_count, "submissions received"
    if submission_count == 0:
        return

    target_count = int(submission_count / 1.0)
    reward_amount = to_be_given_away / target_count

    print "%d submissions (half of all submissions) will be each awarded %.8f BTC (%.2f USD)" % (
        target_count, reward_amount, reward_amount * dollars_per_btc)

    payout_amount_satoshi = int(reward_amount * 1e8)

    # replace the last 3 digits in the amount with "887" so the extenstion
    # can know it has been awarded.
    payout_amount_satoshi_encoded = int("%s887" %
                                        str(payout_amount_satoshi)[:-3])

    print "satoshi award:", payout_amount_satoshi
    print "encoded reward:", payout_amount_satoshi_encoded

    # this is theamount each potential winner needs to have to hae tipped to be
    # eligible for a payout.
    min_tip_amount = 0.04 / dollars_per_btc

    total_awarded_satoshi = 0
    while len(tx.outs) < target_count:
        candidate = random.choice(all_submissions)
        if candidate.is_eligible(min_tip_amount):
            print "** Winner!", candidate
            tx.add_output(address=candidate.address,
                          value=payout_amount_satoshi_encoded)
            candidate.winner = True
            candidate.save()
            total_awarded_satoshi += payout_amount_satoshi_encoded
        else:
            print "Rejected, Not eligible", candidate

    print "Total satoshis added to giveaway TX:", total_awarded_satoshi

    if not dry_run:
        print tx.get_hex()
        raw_input("Press enter to push TX, ctrl-c to cancel")
        print tx.push()
    else:
        GiveawaySubmission.objects.all().update(winner=False)
        print tx.get_hex()
Example #12
0
def get_price(cc, c):
    get_price.result = get_current_price(cc, c)
Example #13
0
def get_exchange_rate(request):
    crypto = request.GET['crypto']
    fiat = request.GET['fiat']
    return HttpResponse(get_current_price(crypto, fiat),
                        content_type="application/json")
def fetch_wallet_balances(wallets, fiat, **modes):
    """
    Wallets must be list of two item lists. First item is crypto, second item
    is the address. example:

    [
        ['btc', '1PZ3Ps9RvCmUW1s1rHE25FeR8vtKUrhEai'],
        ['ltc', 'Lb78JDGxMcih1gs3AirMeRW6jaG5V9hwFZ']
    ]
    """
    price_fetch = set([x[0] for x in wallets])
    balances = {}
    prices = {}

    fetch_length = len(wallets) + len(price_fetch)

    if not modes.get('async', False):
        # synchronous fetching
        for crypto in price_fetch:
            prices[crypto] = get_current_price(crypto,
                                               fiat,
                                               report_services=True,
                                               **modes)

        for crypto, address in wallets:
            balances[address] = get_address_balance(crypto, address.strip(),
                                                    **modes)

    else:
        # asynchronous fetching
        if modes.get('verbose', False):
            print("Need to make", fetch_length, "external calls")

        with futures.ThreadPoolExecutor(max_workers=int(fetch_length /
                                                        2)) as executor:
            future_to_key = dict((executor.submit(
                get_current_price, crypto, fiat, report_services=True, **
                modes), crypto) for crypto in price_fetch)

            future_to_key.update(
                dict((executor.submit(get_address_balance, crypto,
                                      address.strip(), **modes), address)
                     for crypto, address in wallets))

            done, not_done = futures.wait(future_to_key,
                                          return_when=futures.FIRST_EXCEPTION)
            if len(not_done) > 0:
                raise not_done.pop().exception()

            for future in done:
                key = future_to_key[future]
                if len(
                        key
                ) > 5:  # this will break if a crypto symbol is longer than 5 chars.
                    which = balances
                else:
                    which = prices

                res = future.result()
                which[key] = res

    ret = []

    for crypto, address in wallets:
        crypto_value = balances[address]
        sources, fiat_price = prices[crypto]
        ret.append({
            'crypto': crypto,
            'address': address,
            'crypto_value': crypto_value,
            'fiat_value': crypto_value * fiat_price,
            'conversion_price': fiat_price,
            'price_source': sources[0].name
        })

    return ret
Example #15
0
def fetch_wallet_balances(wallets, fiat, **modes):
    """
    Wallets must be list of two item lists. First item is crypto, second item
    is the address. example:

    [
        ['btc', '1PZ3Ps9RvCmUW1s1rHE25FeR8vtKUrhEai'],
        ['ltc', 'Lb78JDGxMcih1gs3AirMeRW6jaG5V9hwFZ']
    ]
    """
    price_fetch = set([x[0] for x in wallets])
    balances = {}
    prices = {}

    fetch_length = len(wallets) + len(price_fetch)

    if not modes.get('async', False):
        # synchronous fetching
        for crypto in price_fetch:
            prices[crypto] = get_current_price(crypto, fiat, **modes)

        for crypto, address in wallets:
            balances[address] = get_address_balance(crypto, address.strip(), **modes)

    else:
        # asynchronous fetching
        if modes.get('verbose', False):
            print("Need to make", fetch_length, "external calls")

        with futures.ThreadPoolExecutor(max_workers=int(fetch_length / 2)) as executor:
            future_to_key = dict(
                (executor.submit(
                    get_current_price, crypto, fiat, **modes
                ), crypto) for crypto in price_fetch
            )

            future_to_key.update(dict(
                (executor.submit(
                    get_address_balance, crypto, address.strip(), **modes
                ), address) for crypto, address in wallets
            ))

            done, not_done = futures.wait(future_to_key, return_when=futures.FIRST_EXCEPTION)
            if len(done) > 0:
                raise not_done.pop().exception()

            for future in done:
                key = future_to_key[future]
                if len(key) > 5: # this will break if a crypto symbol is longer than 5 chars.
                    which = balances
                else:
                    which = prices

                res = future.result()
                which[key] = res

    ret = []
    for crypto, address in wallets:
        crypto_value = balances[address]
        fiat_price, source = prices[crypto]
        ret.append({
            'crypto': crypto,
            'address': address,
            'crypto_value': crypto_value,
            'fiat_value': crypto_value * fiat_price,
            'conversion_price': fiat_price,
            'price_source': source
        })

    return ret
Example #16
0
zec_low = 225   # Zcash
zec_high = 275


print("Monitoring stock market and cryptocurrency rates...")
while True:
    # Print actual timestamp
    print(datetime.now().strftime("%d/%m/%y %H:%M:%S"))

    # Get actual stock market prices
    TSLA = float(Stock('TSLA').get_latest_price()[0]["LastTradePriceOnly"])  # Tesla
    MSFT = float(Stock('MSFT').get_latest_price()[0]["LastTradePriceOnly"])  # Microsoft
    NVDA = float(Stock('NVDA').get_latest_price()[0]["LastTradePriceOnly"])  # NVIDIA
    WESAS = float(Stock('WES.AS').get_latest_price()[0]["LastTradePriceOnly"])  # WES.AS

    btc = get_current_price('btc', 'eur')  # Bitcoin
    eth = get_current_price('eth', 'eur')  # Ethereum
    etc = get_current_price('etc', 'eur')  # Ethereum Classic
    zec = get_current_price('zec', 'eur')  # Zcash


    # Trigger telegram's alert (if any)
    if TSLA < TSLA_low: telegram_alert("Tesla low price: " + str(TSLA))
    if TSLA > TSLA_high: telegram_alert("Tesla high price: " + str(TSLA))
    if MSFT < MSFT_low: telegram_alert("Microsoft low price: " + str(MSFT))
    if MSFT > MSFT_high: telegram_alert("Microsoft high price: " + str(MSFT))
    if NVDA < NVDA_low: telegram_alert("NVIDIA low price: " + str(NVDA))
    if NVDA > NVDA_high: telegram_alert("NVIDIA high price: " + str(NVDA))
    if WESAS < WESAS_low: telegram_alert("WES.AS low price: " + str(WESAS))
    if WESAS > WESAS_high: telegram_alert("WES.AS high price: " + str(WESAS))
Example #17
0
def fetch_wallet_balances(wallets, fiat, **modes):
    """
    Wallets must be list of two item lists. First item is crypto, second item
    is the address. example:

    [
        ['btc', '1ACMqsyyuoggTpiHqGePuFSVzk54wfZWDv'],
        ['ltc', 'Lb78JDGxMcih1gs3AirMeRW6jaG5V9hwFZ']
    ]
    """
    price_fetch = set([x[0] for x in wallets])
    balances = {}
    prices = {}

    fetch_length = len(wallets) + len(price_fetch)

    helpers = {fiat.lower(): {}}
    if not modes.get('async', False):
        # synchronous fetching
        for crypto in price_fetch:
            try:
                p = get_current_price(
                    crypto, fiat, helper_prices=helpers, report_services=True, **modes
                )
                prices[crypto] = {'price': p}
                if crypto in ['btc', 'ltc', 'doge', 'uno']:
                    helpers[fiat.lower()][crypto] = p
            except NoService as exc:
                prices[crypto] = {'error': str(exc)}

        for crypto, address in wallets:
            if address.replace('.', '').isdigit():
                balances[address] = {'balance': float(address)}
                continue

            try:
                balances[address] = {'balance': get_address_balance(crypto, address.strip(), **modes)}
            except NoService as exc:
                balances[address] = {'error': str(exc)}

    else:
        # asynchronous fetching
        if modes.get('verbose', False):
            print("Need to make", fetch_length, "external calls")

        with futures.ThreadPoolExecutor(max_workers=int(fetch_length / 2)) as executor:
            future_to_key = dict(
                (executor.submit(
                    get_current_price, crypto, fiat, report_services=True, **modes
                ), crypto) for crypto in price_fetch
            )

            future_to_key.update(dict(
                (executor.submit(
                    get_address_balance, crypto, address.strip(), **modes
                ), address) for crypto, address in wallets
            ))

            done, not_done = futures.wait(future_to_key, return_when=futures.ALL_COMPLETED)
            if len(not_done) > 0:
                print (not_done)
                import debug
                raise Exception("Broke") #not_done.pop().exception()

            for future in done:
                key = future_to_key[future]
                if len(key) > 5: # this will break if a crypto symbol is longer than 5 chars.
                    which = balances
                else:
                    which = prices

                res = future.result()
                which[key] = res

    ret = []

    for crypto, address in wallets:
        error = None
        if 'balance' in balances[address]:
            crypto_value = balances[address]['balance']
        else:
            crypto_value = 0
            error = balances[address]['error']

        if 'price' in prices[crypto]:
            sources, fiat_price = prices[crypto]['price']
        else:
            sources, fiat_price = [None], 0
            error = prices[crypto]['error']

        ret.append({
            'crypto': crypto,
            'address': address,
            'crypto_value': crypto_value,
            'fiat_value': (crypto_value or 0) * (fiat_price or 0),
            'conversion_price': fiat_price,
            'price_source': sources[0].name,
            'error': error
        })

    return ret
Example #18
0
def get_exchange_rate(request):
    crypto = request.GET['crypto']
    fiat = request.GET['fiat']
    return HttpResponse(get_current_price(crypto, fiat), content_type="application/json")
Example #19
0
def _make_moneywagon_fetch(Service,
                           service_mode,
                           service_id,
                           address,
                           addresses,
                           xpub,
                           currency,
                           currency_name,
                           block_args,
                           fiat=None,
                           txid=None,
                           random_mode=False,
                           **k):

    if Service:
        if Service.supported_cryptos and currency not in Service.supported_cryptos:
            raise Exception("%s not supported for %s with %s" %
                            (currency_name, service_mode, Service.name))
        services = [Service]
    else:
        services = []  # fallback mode

    modes = dict(report_services=True,
                 services=services,
                 random=random_mode,
                 timeout=10.0,
                 verbose=settings.DEBUG)

    if service_id.startswith("paranoid"):
        modes['paranoid'] = int(service_id[8:])
    elif service_id.startswith("average"):
        modes['average'] = int(service_id[7:])
    elif service_id.startswith("private"):
        modes['private'] = int(service_id[7:])
        if modes['private'] > 30:
            raise Exception("Private mode maximum of 30")

    if address:
        modes['address'] = address
    elif addresses:
        modes['addresses'] = addresses.split(',')

    if service_mode == 'current_price':
        used_services, price = get_current_price(currency, fiat, **modes)
        PriceTick.record_price(price, currency, fiat, used_services[0].name)
        ret = {'current_price': price}
    elif service_mode == 'address_balance':
        used_services, balance = get_address_balance(currency, **modes)
        ret = {'balance': balance}
    elif service_mode == 'unspent_outputs':
        used_services, utxos = get_unspent_outputs(currency, **modes)
        ret = {'utxos': sorted(utxos, key=lambda x: x['output'])}
    elif service_mode == 'historical_transactions':
        used_services, txs = get_historical_transactions(currency, **modes)
        ret = {'transactions': sorted(txs, key=lambda x: x['txid'])}
    elif service_mode == 'single_transaction':
        used_services = None
        tx = CachedTransaction.fetch_full_tx(currency, txid=txid, fiat=fiat)
        ret = {'transaction': tx}
    elif service_mode == 'get_block':
        if block_args['block_number']:
            block_args['block_number'] = int(block_args['block_number'])
        modes.update(block_args)
        used_services, block_data = get_block(currency, **modes)
        ret = {'block': block_data}
    elif service_mode == 'optimal_fee':
        used_services, fee = get_optimal_fee(currency, 1024, **modes)
        ret = {'optimal_fee_per_KiB': fee}
    else:
        raise Exception("Unsupported Service mode")

    if not used_services:
        pass  # private mode does not return services
    elif len(used_services) == 1:
        s = used_services[0]
        if s:
            ret['url'] = s.last_url
            ret['raw_response'] = s.last_raw_response.json()
            ret['service_name'] = s.name
            ret['service_id'] = s.service_id
    else:
        ret['services'] = [{
            'name': s.name,
            'id': s.service_id,
            'raw_response': s.last_raw_response.json()
        } for s in used_services]

    return ret
Example #20
0
def _make_moneywagon_fetch(Service, service_mode, service_id, address, addresses,
    xpub, currency, currency_name, block_args, fiat=None, txid=None, random_mode=False, **k):

    if Service:
        if Service.supported_cryptos and currency not in Service.supported_cryptos:
            raise Exception("%s not supported for %s with %s" % (
                currency_name, service_mode, Service.name
            ))
        services = [Service]
    else:
        services = [] # fallback mode

    modes = dict(
        report_services=True,
        services=services,
        random=random_mode,
        timeout=10.0,
        verbose=settings.DEBUG
    )

    if service_id.startswith("paranoid"):
        modes['paranoid'] = int(service_id[8:])
    elif service_id.startswith("average"):
        modes['average'] = int(service_id[7:])
    elif service_id.startswith("private"):
        modes['private'] = int(service_id[7:])
        if modes['private'] > 30:
            raise Exception("Private mode maximum of 30")

    if address:
        modes['address'] = address
    elif addresses:
        modes['addresses'] = addresses.split(',')

    if service_mode == 'current_price':
        used_services, price = get_current_price(currency, fiat, **modes)
        PriceTick.record_price(price, currency, fiat, used_services[0].name)
        ret = {'current_price': price}
    elif service_mode == 'address_balance':
        used_services, balance = get_address_balance(currency, **modes)
        ret = {'balance': balance}
    elif service_mode == 'unspent_outputs':
        used_services, utxos = get_unspent_outputs(currency, **modes)
        ret = {'utxos': sorted(utxos, key=lambda x: x['output'])}
    elif service_mode == 'historical_transactions':
        used_services, txs = get_historical_transactions(currency, **modes)
        ret = {'transactions': sorted(txs, key=lambda x: x['txid'])}
    elif service_mode == 'single_transaction':
        used_services = None
        tx = CachedTransaction.fetch_full_tx(currency, txid=txid, fiat=fiat)
        ret = {'transaction': tx}
    elif service_mode == 'get_block':
        if block_args['block_number']:
            block_args['block_number'] = int(block_args['block_number'])
        modes.update(block_args)
        used_services, block_data = get_block(currency, **modes)
        ret = {'block': block_data}
    elif service_mode == 'optimal_fee':
        used_services, fee = get_optimal_fee(currency, 1024, **modes)
        ret = {'optimal_fee_per_KiB': fee}
    else:
        raise Exception("Unsupported Service mode")

    if not used_services:
        pass # private mode does not return services
    elif len(used_services) == 1:
        s = used_services[0]
        if s:
            ret['url'] = s.last_url
            ret['raw_response'] = s.last_raw_response.json()
            ret['service_name'] = s.name
            ret['service_id'] = s.service_id
    else:
        ret['services'] = [
            {'name': s.name, 'id': s.service_id, 'raw_response': s.last_raw_response.json()}
            for s in used_services
        ]

    return ret