package com.msgilligan.bitcoinj.money;

import org.javamoney.moneta.ExchangeRateBuilder;
import org.javamoney.moneta.spi.DefaultNumberValue;
import org.javamoney.moneta.spi.LazyBoundCurrencyConversion;
import org.javamoney.moneta.spi.base.BaseExchangeRateProvider;
import org.knowm.xchange.Exchange;
import org.knowm.xchange.ExchangeFactory;
import org.knowm.xchange.currency.CurrencyPair;
import org.knowm.xchange.dto.marketdata.Ticker;
import org.knowm.xchange.service.polling.marketdata.PollingMarketDataService;

import javax.money.CurrencyQuery;
import javax.money.CurrencyQueryBuilder;
import javax.money.CurrencyUnit;
import javax.money.NumberValue;
import javax.money.convert.ConversionContext;
import javax.money.convert.ConversionQuery;
import javax.money.convert.CurrencyConversion;
import javax.money.convert.ExchangeRate;
import javax.money.convert.ProviderContext;
import javax.money.convert.RateType;
import javax.money.spi.CurrencyProviderSpi;
import java.io.IOException;
import java.util.Set;

/**
 *  Base ExchangeRateProvider using XChange library
 */
public abstract class BaseXChangeExchangeRateProvider extends BaseExchangeRateProvider {
    protected final ProviderContext providerContext;
    protected CurrencyProviderSpi bitcoinCurrencyProvider = new BitcoinCurrencyProvider();
    protected CurrencyUnit btc;
    protected String provider;
    protected Exchange exchange;
    protected PollingMarketDataService marketDataService;
    protected Ticker ticker;
    protected CurrencyPair btcusdPair;

    protected BaseXChangeExchangeRateProvider(Class<? extends Exchange> exchangeClass,
                                              CurrencyPair btcusdPair) {
        exchange = ExchangeFactory.INSTANCE.createExchange(exchangeClass.getName());
        this.btcusdPair = btcusdPair;
        provider = exchange.getExchangeSpecification().getExchangeName();
        providerContext = ProviderContext.of(provider, RateType.DEFERRED);
        marketDataService = exchange.getPollingMarketDataService();
        CurrencyQuery query = CurrencyQueryBuilder.of().setCurrencyCodes("BTC").build();
        Set<CurrencyUnit> currencies = bitcoinCurrencyProvider.getCurrencies(query);
        btc = (CurrencyUnit) currencies.toArray()[0];
        poll();
    }

    protected void poll() {
        try {
            ticker = marketDataService.getTicker(btcusdPair);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public ProviderContext getContext() {
        return providerContext;
    }

    @Override
    public boolean isAvailable(ConversionQuery conversionQuery) {
        return getExchangeRate(conversionQuery) != null;
    }

    @Override
    public ExchangeRate getExchangeRate(ConversionQuery conversionQuery) {
        if (!(  conversionQuery.getBaseCurrency().getCurrencyCode().equals("BTC") &&
                conversionQuery.getCurrency().getCurrencyCode().equals("USD"))) {
            return null;
        }
        final NumberValue factor = DefaultNumberValue.of(ticker.getLast());
        return new ExchangeRateBuilder(provider, RateType.DEFERRED)
                .setBase(conversionQuery.getBaseCurrency())
                .setTerm(conversionQuery.getCurrency())
                .setFactor(factor)
                .build();
    }

    @Override
    public CurrencyConversion getCurrencyConversion(ConversionQuery conversionQuery) {
        return new LazyBoundCurrencyConversion(conversionQuery, this, ConversionContext
                .of(getContext().getProviderName(), getContext().getRateTypes().iterator().next()));
    }

}

@@ -1002,16 +1002,192 @@
 til.Set;
+%0Aimport java.util.concurrent.Executors;%0Aimport java.util.concurrent.ScheduledExecutorService;%0Aimport java.util.concurrent.ScheduledFuture;%0Aimport java.util.concurrent.TimeUnit;
 %0A%0A/**%0A *
@@ -1694,16 +1694,187 @@
 usdPair;
+%0A    private ScheduledExecutorService stpe;%0A    private ScheduledFuture%3C?%3E future;%0A    private static final int initialDelay = 0;%0A    private static final int period = 60;
 %0A%0A    pr
@@ -2603,20 +2603,723 @@
         
-poll
+start();%0A    %7D%0A%0A    protected void start() %7B%0A        stpe = Executors.newScheduledThreadPool(2);%0A        final BaseXChangeExchangeRateProvider that = this;%0A        Runnable task = new Runnable() %7B%0A            @Override%0A            public void run() %7B%0A                that.poll();%0A            %7D%0A        %7D;%0A        future = stpe.scheduleWithFixedDelay(task, initialDelay, period, TimeUnit.SECONDS);%0A    %7D%0A%0A    public void stop() %7B%0A        final ScheduledFuture%3C?%3E handle = future;%0A        Runnable task = new Runnable() %7B%0A            @Override%0A            public void run() %7B%0A                handle.cancel(true);%0A            %7D%0A        %7D;%0A        stpe.schedule(task, 0, TimeUnit.SECONDS);%0A        stpe.shutdown
 ();%0A    
@@ -4000,24 +4000,24 @@
 (%22USD%22))) %7B%0A
-
             
@@ -4031,32 +4031,155 @@
 null;%0A        %7D%0A
+        if (ticker == null) %7B%0A            return null;    // ticker not loaded yet (is returning null ok, here?)%0A        %7D%0A
         final Nu

Use scheduled execution to update the rate