Android Open Source - My-Wallet-Android My Block Chain






From Project

Back to project page My-Wallet-Android.

License

The source code is released under:

GNU General Public License

If you think the Android project My-Wallet-Android listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*
 * Copyright 2011-2012 the original author or authors.
 *//w  ww . j  a va 2s. co m
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package piuk;

import java.math.BigInteger;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentSkipListSet;

import org.json.simple.JSONValue;

import piuk.blockchain.android.Constants;


import com.google.bitcoin.bouncycastle.util.encoders.Hex;
import com.google.bitcoin.core.AbstractWalletEventListener;
import com.google.bitcoin.core.Block;
import com.google.bitcoin.core.BlockChain;
import com.google.bitcoin.core.NetworkParameters;
import com.google.bitcoin.core.PeerEventListener;
import com.google.bitcoin.core.ProtocolException;
import com.google.bitcoin.core.Sha256Hash;
import com.google.bitcoin.core.StoredBlock;
import com.google.bitcoin.core.TransactionInput;
import com.google.bitcoin.core.TransactionOutput;
import com.google.bitcoin.core.Wallet;
import com.google.bitcoin.core.WalletEventListener;
import com.google.bitcoin.core.WalletTransaction;
import com.google.bitcoin.store.BlockStoreException;
import com.google.bitcoin.store.MemoryBlockStore;

import de.roderick.weberknecht.WebSocketConnection;
import de.roderick.weberknecht.WebSocketEventHandler;
import de.roderick.weberknecht.WebSocketException;
import de.roderick.weberknecht.WebSocketMessage;

public class MyBlockChain extends BlockChain implements WebSocketEventHandler {
  final String URL = "ws://api.blockchain.info:8335/inv";
  int nfailures = 0;
  WebSocketConnection _websocket;
  MyRemoteWallet remoteWallet;
  StoredBlock latestBlock;
  boolean isConnected = false;
  boolean isRunning = true;

  public MyRemoteWallet getRemoteWallet() {
    return remoteWallet;
  }

  public static class MyBlock extends Block {
    private static final long serialVersionUID = 1L;

    long time;
    Sha256Hash hash;
    int blockIndex;

    public MyBlock(NetworkParameters params) throws ProtocolException {
      super(params);
    }

    @Override
    public long getTimeSeconds() {
      return time;
    }

    @Override
    public Sha256Hash getHash() {
      return hash;
    }
  }

  public Set<PeerEventListener> listeners = new ConcurrentSkipListSet<PeerEventListener>();

  @Override
  public int getBestChainHeight() {
    return getChainHead().getHeight();
  }

  @Override
  public StoredBlock getChainHead() {
    if (latestBlock != null) {
      return latestBlock;
    } else {
      return remoteWallet._multiAddrBlock;
    }
  }

  final private WalletEventListener walletEventListener = new AbstractWalletEventListener()
  {
    @Override
    public void onChange(Wallet wallet)
    {
      try {
        if (remoteWallet._multiAddrBlock != null) {

          if (latestBlock == null || latestBlock.getHeight() < remoteWallet._multiAddrBlock.getHeight()) {
            latestBlock = remoteWallet._multiAddrBlock;

            for (PeerEventListener listener : listeners) {
              listener.onBlocksDownloaded(null, latestBlock.getHeader(), 0);
            }
          }
        }

        if (isRunning) {
          start();
        } else if (isConnected()){
          //Disconnect and reconnect
          //To resubscribe
          subscribe();
        }
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
  };


  public MyBlockChain(NetworkParameters params, MyRemoteWallet remoteWallet) throws BlockStoreException, WebSocketException, URISyntaxException {
    super(params, remoteWallet.getBitcoinJWallet(), new MemoryBlockStore(params));

    this._websocket = new WebSocketConnection(new URI(URL));

    this._websocket.setEventHandler(this);

    this.remoteWallet = remoteWallet;
  }

  public synchronized void subscribe() {
    try {
      String message = "{\"op\":\"blocks_sub\"}{\"op\":\"wallet_sub\",\"guid\":\""+remoteWallet.getGUID()+"\"}";

      for (Map<String, Object> key : this.remoteWallet.getKeysMap()) {        
        message += "{\"op\":\"addr_sub\", \"addr\":\""+key.get("addr")+"\"}";
      }

      _websocket.send(message);

    } catch (WebSocketException e) {
      e.printStackTrace();
    }
  }


  public void removePeerEventListener(PeerEventListener listener) {
    listeners.remove(listener);
  }

  public void addPeerEventListener(PeerEventListener listener) {
    listeners.add(listener);
  }

  public void onClose() {
    System.out.println("onClose()");

    this.isConnected = false;

    if (!isRunning)
      return;

    for (PeerEventListener listener : listeners) {
      listener.onPeerConnected(null, 0);
    }

    if (nfailures < 5) {
      try {
        ++nfailures;

        _websocket.connect();
      } catch (WebSocketException e) {
        e.printStackTrace();
      }
    }
  }

  public boolean isConnected() {
    return this.isConnected;
  }

  public void stop() {
    System.out.println("start()");

    try {
      this.isRunning = false;

      _websocket.close();
    } catch (WebSocketException e) {
      e.printStackTrace();
    }

    remoteWallet.getBitcoinJWallet().removeEventListener(walletEventListener);
  }

  public void start() {
    this.isRunning = true;

    System.out.println("start()");

    try {
      _websocket.connect();
    } catch (WebSocketException e) {
      e.printStackTrace();
    }

    remoteWallet.getBitcoinJWallet().addEventListener(walletEventListener);
  }

  @SuppressWarnings("unchecked")
  public void onMessage(WebSocketMessage wmessage) {

    System.out.println("OnMessage()");

    try {
      String message = wmessage.getText();

      System.out.println("Websocket() onMessage() " + message);

      Map<String, Object> top = (Map<String, Object>) JSONValue.parse(message);


      if (top == null)
        return;

      String op = (String) top.get("op");


      if (op.equals("block")) {
        Map<String, Object> x = (Map<String, Object>) top.get("x");

        Sha256Hash hash = new Sha256Hash(Hex.decode((String)x.get("hash")));
        int blockIndex = ((Number)x.get("blockIndex")).intValue();
        int blockHeight = ((Number)x.get("height")).intValue();
        long time = ((Number)x.get("time")).longValue();

        MyBlock block = new MyBlock(Constants.NETWORK_PARAMETERS);
        block.hash = hash;
        block.blockIndex = blockIndex;
        block.time = time;

        this.latestBlock = new StoredBlock(block, BigInteger.ZERO, blockHeight);

        List<MyTransaction> transactions = remoteWallet.getMyTransactions();
        List<Number> txIndexes = (List<Number>) x.get("txIndexes");
        for (Number txIndex : txIndexes) {
          for (MyTransaction tx : transactions) {

            MyTransactionConfidence confidence = (MyTransactionConfidence) tx.getConfidence();

            if (tx.txIndex == txIndex.intValue() && confidence.height != blockHeight) {
              confidence.height = blockHeight;
              confidence.runListeners(); 
            }
          }
        }

        for (PeerEventListener listener : listeners) {
          listener.onBlocksDownloaded(null, block, 0);
        }

      } else if (op.equals("utx")) {
        Map<String, Object> x = (Map<String, Object>) top.get("x");

        WalletTransaction tx = MyTransaction.fromJSONDict(x);

        BigInteger result = BigInteger.ZERO;

        BigInteger previousBalance = remoteWallet.getBitcoinJWallet().final_balance;

        for (TransactionInput input : tx.getTransaction().getInputs()) {
          //if the input is from me subtract the value
          MyTransactionInput myinput = (MyTransactionInput) input;

          if (remoteWallet.isAddressMine(input.getFromAddress().toString())) {
            result = result.subtract(myinput.value);

            remoteWallet.getBitcoinJWallet().final_balance = remoteWallet.getBitcoinJWallet().final_balance.subtract(myinput.value);
            remoteWallet.getBitcoinJWallet().total_sent = remoteWallet.getBitcoinJWallet().total_sent.add(myinput.value);
          }
        }

        for (TransactionOutput output : tx.getTransaction().getOutputs()) {
          //if the input is from me subtract the value
          MyTransactionOutput myoutput = (MyTransactionOutput) output;

          if (remoteWallet.isAddressMine(myoutput.getToAddress().toString())) {
            result = result.add(myoutput.getValue());

            remoteWallet.getBitcoinJWallet().final_balance = remoteWallet.getBitcoinJWallet().final_balance.add(myoutput.getValue());
            remoteWallet.getBitcoinJWallet().total_received = remoteWallet.getBitcoinJWallet().total_sent.add(myoutput.getValue());
          }
        }

        MyTransaction mytx = (MyTransaction) tx.getTransaction();

        mytx.result = result;

        remoteWallet.getBitcoinJWallet().addWalletTransaction(tx);

        if (result.compareTo(BigInteger.ZERO) >= 0) {
          System.out.println("On Received");

          remoteWallet.getBitcoinJWallet().invokeOnCoinsReceived(tx.getTransaction(), previousBalance, remoteWallet.getBitcoinJWallet().final_balance);
        } else {
          remoteWallet.getBitcoinJWallet().invokeOnCoinsSent(tx.getTransaction(), previousBalance, remoteWallet.getBitcoinJWallet().final_balance);
        }
      } else if (op.equals("on_change")) {
        String newChecksum = (String) top.get("checksum");
        String oldChecksum = remoteWallet.getChecksum();

        System.out.println("On change " + newChecksum + " " + oldChecksum);
        
        if (!newChecksum.equals(oldChecksum)) {
          try {
            String newPayload = MyRemoteWallet.getWalletPayload(remoteWallet.getGUID(), remoteWallet.getSharedKey(), oldChecksum);

            if (newPayload == null) 
              return;
            
            remoteWallet.setPayload(newPayload);
            
            remoteWallet.getBitcoinJWallet().invokeOnChange();
            
          } catch (Exception e) {
            e.printStackTrace();
          }

        }

      }

    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  public void onOpen() {
    System.out.println("onOpen()");

    this.isConnected = true;

    subscribe();

    for (PeerEventListener listener : listeners) {
      listener.onPeerConnected(null, 1);
    }

    nfailures = 0;
  }
}




Java Source Code List

piuk.BitcoinAddress.java
piuk.BitcoinScript.java
piuk.Hash.java
piuk.MyBlockChain.java
piuk.MyRemoteWallet.java
piuk.MyTransactionConfidence.java
piuk.MyTransactionInput.java
piuk.MyTransactionOutPoint.java
piuk.MyTransactionOutput.java
piuk.MyTransaction.java
piuk.MyWallet.java
piuk.blockchain.android.AddressBookProvider.java
piuk.blockchain.android.BlockchainService.java
piuk.blockchain.android.Constants.java
piuk.blockchain.android.DetermineFirstSeenThread.java
piuk.blockchain.android.ExchangeRatesProvider.java
piuk.blockchain.android.WalletApplication.java
piuk.blockchain.android.WalletBalanceWidgetProvider.java
piuk.blockchain.android.ui.AbstractWalletActivity.java
piuk.blockchain.android.ui.AmountCalculatorFragment.java
piuk.blockchain.android.ui.CurrencyAmountView.java
piuk.blockchain.android.ui.CurrencyCodeDrawable.java
piuk.blockchain.android.ui.EditAddressBookEntryFragment.java
piuk.blockchain.android.ui.ExchangeRatesFragment.java
piuk.blockchain.android.ui.NewAccountFragment.java
piuk.blockchain.android.ui.PairWalletActivity.java
piuk.blockchain.android.ui.PreferencesActivity.java
piuk.blockchain.android.ui.RequestCoinsActivity.java
piuk.blockchain.android.ui.RequestCoinsFragment.java
piuk.blockchain.android.ui.SecondPasswordFragment.java
piuk.blockchain.android.ui.SendCoinsActivity.java
piuk.blockchain.android.ui.SendCoinsFragment.java
piuk.blockchain.android.ui.SendingAddressesFragment.java
piuk.blockchain.android.ui.TransactionActivity.java
piuk.blockchain.android.ui.TransactionFragment.java
piuk.blockchain.android.ui.WalletActivity.java
piuk.blockchain.android.ui.WalletAddressesFragment.java
piuk.blockchain.android.ui.WalletBalanceFragment.java
piuk.blockchain.android.ui.WalletTransactionsFragment.java
piuk.blockchain.android.ui.WelcomeFragment.java
piuk.blockchain.android.util.ActionBarFragment.java
piuk.blockchain.android.util.Base43.java
piuk.blockchain.android.util.CircularProgressView.java
piuk.blockchain.android.util.ErrorReporter.java
piuk.blockchain.android.util.IOUtils.java
piuk.blockchain.android.util.Iso8601Format.java
piuk.blockchain.android.util.NfcTools.java
piuk.blockchain.android.util.QrDialog.java
piuk.blockchain.android.util.ViewPagerTabs.java
piuk.blockchain.android.util.WalletUtils.java