public List<Balance> getBalances() { if (mHDWallet == null) return null; List<Balance> balances = new LinkedList<Balance>(); mHDWallet.getBalances(balances); return balances; }
public void rescanBlockchain(long rescanTime) { mLogger.info(String.format("RESCANNING from %d", rescanTime)); // Make sure we are in a good state for this. if (mState != State.READY) { mLogger.warn("can't rescan until the wallet is ready"); return; } switch (mSyncState) { case SYNCHRONIZED: mSyncState = SyncState.RESCAN; break; default: mSyncState = SyncState.RERESCAN; break; } // Remove our wallet event listener. mKit.wallet().removeEventListener(mWalletListener); // Persist and remove our HDWallet. // // NOTE - It's best not to clear the balances here. When the // transactions are filling in on the transactions screen it's // disturbing to see negative historical balances. They'll // get completely refigured when the sync is done anyway ... // mHDWallet.persist(mApp); mHDWallet = null; mLogger.info("resetting wallet state"); mKit.wallet().clearTransactions(0); mKit.wallet().setLastBlockSeenHeight(-1); // magic value mKit.wallet().setLastBlockSeenHash(null); mLogger.info("shutting kit down"); try { mKit.shutDown(); mKit = null; } catch (Exception ex) { mLogger.error("kit shutdown failed: " + ex.toString()); return; } File dir = mApp.getWalletDir(); String spvpath = mApp.getWalletPrefix() + ".spvchain"; mLogger.info("removing spvchain file " + dir + spvpath); File chainFile = new File(dir, spvpath); if (!chainFile.delete()) mLogger.error("delete of spvchain file failed"); mLogger.info("restarting wallet"); mKeyCrypter = mApp.mKeyCrypter; mAesKey = mApp.mAesKey; setState(State.SETUP); mTask = new SetupWalletTask(); mTask.execute(rescanTime); }
public long computeRecommendedFee(int acctnum, long amount, boolean spendUnconfirmed) throws IllegalArgumentException, InsufficientMoneyException { mLogger.info("computeRecommendedFee starting"); long fee = mHDWallet.computeRecommendedFee(mKit.wallet(), acctnum, amount, spendUnconfirmed); mLogger.info("computeRecommendedFee finished"); return fee; }
public void changePasscode(KeyParameter oldAesKey, KeyCrypter keyCrypter, KeyParameter aesKey) { mLogger.info("changePasscode starting"); // Change the parameters on our HDWallet. mHDWallet.setPersistCrypter(keyCrypter, aesKey); mHDWallet.persist(mApp); mLogger.info("persisted HD wallet"); // Decrypt the wallet with the old key. mKit.wallet().decrypt(oldAesKey); mLogger.info("decrypted base wallet"); // Encrypt the wallet using the new key. mKit.wallet().encrypt(keyCrypter, aesKey); mLogger.info("reencrypted base wallet"); }
@Override public void onWalletChanged(Wallet wallet) { // Compute balances and transaction counts. Iterable<WalletTransaction> iwt = mKit.wallet().getWalletTransactions(); mHDWallet.applyAllTransactions(iwt); // Check to make sure we have sufficient margins. int maxExtended = mHDWallet.ensureMargins(mKit.wallet()); // Persist the new state. mHDWallet.persist(mApp); Intent intent = new Intent("wallet-state-changed"); mLBM.sendBroadcast(intent); if (maxExtended > HDChain.maxSafeExtend()) { mLogger.info(String.format("%d addresses added, rescanning", maxExtended)); rescanBlockchain(HDAddress.EPOCH); } }
public void sweepKey(ECKey key, long fee, int accountId, JSONArray outputs) { mLogger.info("sweepKey starting"); mLogger.info("key addr " + key.toAddress(mParams).toString()); Transaction tx = new Transaction(mParams); long balance = 0; ArrayList<Script> scripts = new ArrayList<Script>(); try { for (int ii = 0; ii < outputs.length(); ++ii) { JSONObject output; output = outputs.getJSONObject(ii); String tx_hash = output.getString("tx_hash"); int tx_output_n = output.getInt("tx_output_n"); String script = output.getString("script"); // Reverse byte order, create hash. Sha256Hash hash = new Sha256Hash(WalletUtil.msgHexToBytes(tx_hash)); tx.addInput( new TransactionInput( mParams, tx, new byte[] {}, new TransactionOutPoint(mParams, tx_output_n, hash))); scripts.add(new Script(Hex.decode(script))); balance += output.getLong("value"); } } catch (JSONException e) { e.printStackTrace(); throw new RuntimeException("trouble parsing unspent outputs"); } // Compute balance - fee. long amount = balance - fee; mLogger.info(String.format("sweeping %d", amount)); // Figure out the destination address. Address to = mHDWallet.nextReceiveAddress(accountId); mLogger.info("sweeping to " + to.toString()); // Add output. tx.addOutput(BigInteger.valueOf(amount), to); WalletUtil.signTransactionInputs(tx, Transaction.SigHash.ALL, key, scripts); mLogger.info("tx bytes: " + new String(Hex.encode(tx.bitcoinSerialize()))); // mKit.peerGroup().broadcastTransaction(tx); broadcastTransaction(mKit.peerGroup(), tx); mLogger.info("sweepKey finished"); }
public void addAccount() { mLogger.info("add account"); // Make sure we are in a good state for this. if (mState != State.READY) { mLogger.warn("can't add an account until the wallet is ready"); return; } mHDWallet.addAccount(); mHDWallet.ensureMargins(mKit.wallet()); // Set the new keys creation time to now. long now = Utils.now().getTime() / 1000; // Adding all the keys is overkill, but it is simpler for now. ArrayList<ECKey> keys = new ArrayList<ECKey>(); mHDWallet.gatherAllKeys(now, keys); mLogger.info(String.format("adding %d keys", keys.size())); mKit.wallet().addKeys(keys); mHDWallet.persist(mApp); }
public void sendCoinsFromAccount( int acctnum, String address, long amount, long fee, boolean spendUnconfirmed) throws RuntimeException { if (mHDWallet == null) return; try { Address dest = new Address(mParams, address); mLogger.info( String.format( "send coins: acct=%d, dest=%s, val=%d, fee=%d", acctnum, address, amount, fee)); mHDWallet.sendAccountCoins(mKit.wallet(), acctnum, dest, amount, fee, spendUnconfirmed); } catch (WrongNetworkException ex) { String msg = "Address for wrong network: " + ex.getMessage(); throw new RuntimeException(msg); } catch (AddressFormatException ex) { String msg = "Malformed bitcoin address: " + ex.getMessage(); throw new RuntimeException(msg); } }
public long balanceForAccount(int acctnum) { return mHDWallet.balanceForAccount(acctnum); }
public HDAddressDescription findAddress(Address addr) { return mHDWallet.findAddress(addr); }
public byte[] getWalletSeed() { return mHDWallet == null ? null : mHDWallet.getWalletSeed(); }
public void persist() { mHDWallet.persist(mApp); }
@Override protected Integer doInBackground(Long... params) { // scanTime 0 : full rescan // scanTime t : scan from time t final Long scanTime = params[0]; setState(State.WALLET_SETUP); mLogger.info("setting up wallet, scanTime=" + scanTime.toString()); mLogger.info("getting network parameters"); mParams = Constants.getNetworkParameters(getApplicationContext()); // Try to restore existing wallet. mHDWallet = null; try { mHDWallet = HDWallet.restore(mApp, mParams, mKeyCrypter, mAesKey); } catch (InvalidCipherTextException ex) { mLogger.error("wallet restore failed: " + ex.toString()); } catch (IOException ex) { mLogger.error("wallet restore failed: " + ex.toString()); } catch (RuntimeException ex) { mLogger.error("wallet restore failed: " + ex.toString()); } if (mHDWallet == null) { mLogger.error("WalletService started with bad HDWallet"); System.exit(0); } mLogger.info("creating new wallet app kit"); // Checkpointing fails on full rescan because the earliest // create time is earlier than the genesis block time. // InputStream chkpntis = null; if (scanTime != 0) { try { chkpntis = getAssets().open(Constants.CHECKPOINTS_FILENAME); } catch (IOException e) { chkpntis = null; } } mKit = new MyWalletAppKit( mParams, mApp.getWalletDir(), mApp.getWalletPrefix(), mKeyCrypter, scanTime) { @Override protected void onSetupCompleted() { mLogger.info("adding keys"); setState(WalletService.State.KEYS_ADD); // Add all the existing keys, they'll be // ignored if they are already in the // WalletAppKit. // ArrayList<ECKey> keys = new ArrayList<ECKey>(); mHDWallet.gatherAllKeys(HDAddress.EPOCH, keys); mLogger.info(String.format("adding %d keys", keys.size())); wallet().addKeys(keys); // Do we have enough margin on all our chains? // Add keys to chains which don't have enough // unused addresses at the end. // mHDWallet.ensureMargins(wallet()); peerGroup() .setFastCatchupTimeSecs( (scanTime == 0 ? mParams.getGenesisBlock().getTimeSeconds() : scanTime)); if (mPrefs.getBoolean("pref_reduceBloomFalsePositives", false)) { mLogger.info("reducing bloom false positives"); peerGroup().setBloomFilterFalsePositiveRate(0.000001); } // We don't need to check for HDChain.maxSafeExtend() // here because we are about to scan anyway. // We'll check again after the scan ... // Now we're peering. setState(WalletService.State.PEERING); } }; mKit.setDownloadListener(mkDownloadListener()); if (chkpntis != null) mKit.setCheckpoints(chkpntis); setState(State.WALLET_SETUP); mLogger.info("waiting for blockchain setup"); // Download the block chain and wait until it's done. mKit.startAndWait(); mLogger.info("blockchain setup finished, state = " + getStateString()); // Bail if we're being shutdown ... if (mState == State.SHUTDOWN) { mHDWallet.persist(mApp); return null; } mBalanceAvailable = mKit.wallet().getBalance(BalanceType.AVAILABLE); mBalanceEstimated = mKit.wallet().getBalance(BalanceType.ESTIMATED); mLogger.info("avail balance = " + mBalanceAvailable.toString()); mLogger.info("estim balance = " + mBalanceEstimated.toString()); // Compute balances and transaction counts. Iterable<WalletTransaction> iwt = mKit.wallet().getWalletTransactions(); mHDWallet.applyAllTransactions(iwt); // Check the margins again, since transactions may have arrived. int maxExtended = mHDWallet.ensureMargins(mKit.wallet()); // Persist the new state. mHDWallet.persist(mApp); // Listen for future wallet changes. mKit.wallet().addEventListener(mWalletListener); setState(State.READY); // This may be temporary ... return maxExtended; }
public long availableForAccount(int acctnum) { return mHDWallet.availableForAccount(acctnum); }
public List<HDAccount> getAccounts() { if (mHDWallet == null) return null; return mHDWallet.getAccounts(); }
public HDAccount getAccount(int accountId) { if (mHDWallet == null) return null; return mHDWallet.getAccount(accountId); }
public String getPairingCode() { JSONObject obj = mHDWallet.dumps(true); return obj.toString(); }
public Address nextReceiveAddress(int acctnum) { return mHDWallet.nextReceiveAddress(acctnum); }
public String getFormatVersionString() { return mHDWallet.getFormatVersionString(); }
public AmountAndFee useAll(int acctnum, boolean spendUnconfirmed) throws InsufficientMoneyException { return mHDWallet.useAll(mKit.wallet(), acctnum, spendUnconfirmed); }
public HDWallet.HDStructVersion getHDStructVersion() { return mHDWallet.getHDStructVersion(); }
public MnemonicCodeX.Version getBIP39Version() { return mHDWallet.getBIP39Version(); }
public long amountForAccount(WalletTransaction wtx, int acctnum) { return mHDWallet.amountForAccount(wtx, acctnum); }