use of com.samourai.wallet.bip47.rpc.PaymentCode in project samourai-wallet-android by Samourai-Wallet.
the class JobRefreshService method onHandleWork.
@Override
protected void onHandleWork(@NonNull Intent intent) {
boolean dragged = intent.getBooleanExtra("dragged", false);
boolean launch = intent.getBooleanExtra("launch", false);
boolean notifTx = intent.getBooleanExtra("notifTx", false);
Log.d("JobRefreshService", "doInBackground()");
APIFactory.getInstance(this.getApplicationContext()).stayingAlive();
APIFactory.getInstance(this.getApplicationContext()).initWallet();
try {
int acc = 0;
if (AddressFactory.getInstance().getHighestTxReceiveIdx(acc) > HD_WalletFactory.getInstance(this.getApplicationContext()).get().getAccount(acc).getReceive().getAddrIdx()) {
HD_WalletFactory.getInstance(this.getApplicationContext()).get().getAccount(acc).getReceive().setAddrIdx(AddressFactory.getInstance().getHighestTxReceiveIdx(acc));
}
if (AddressFactory.getInstance().getHighestTxChangeIdx(acc) > HD_WalletFactory.getInstance(this.getApplicationContext()).get().getAccount(acc).getChange().getAddrIdx()) {
HD_WalletFactory.getInstance(this.getApplicationContext()).get().getAccount(acc).getChange().setAddrIdx(AddressFactory.getInstance().getHighestTxChangeIdx(acc));
}
if (AddressFactory.getInstance().getHighestBIP49ReceiveIdx() > BIP49Util.getInstance(this.getApplicationContext()).getWallet().getAccount(0).getReceive().getAddrIdx()) {
BIP49Util.getInstance(this.getApplicationContext()).getWallet().getAccount(0).getReceive().setAddrIdx(AddressFactory.getInstance().getHighestBIP49ReceiveIdx());
}
if (AddressFactory.getInstance().getHighestBIP49ChangeIdx() > BIP49Util.getInstance(this.getApplicationContext()).getWallet().getAccount(0).getChange().getAddrIdx()) {
BIP49Util.getInstance(this.getApplicationContext()).getWallet().getAccount(0).getChange().setAddrIdx(AddressFactory.getInstance().getHighestBIP49ChangeIdx());
}
if (AddressFactory.getInstance().getHighestBIP84ReceiveIdx() > BIP84Util.getInstance(this.getApplicationContext()).getWallet().getAccount(0).getReceive().getAddrIdx()) {
BIP84Util.getInstance(this.getApplicationContext()).getWallet().getAccount(0).getReceive().setAddrIdx(AddressFactory.getInstance().getHighestBIP84ReceiveIdx());
}
if (AddressFactory.getInstance().getHighestBIP84ChangeIdx() > BIP84Util.getInstance(this.getApplicationContext()).getWallet().getAccount(0).getChange().getAddrIdx()) {
BIP84Util.getInstance(this.getApplicationContext()).getWallet().getAccount(0).getChange().setAddrIdx(AddressFactory.getInstance().getHighestBIP84ChangeIdx());
}
} catch (IOException | MnemonicException.MnemonicLengthException | NullPointerException ioe) {
ioe.printStackTrace();
} finally {
Intent _intent = new Intent("com.samourai.wallet.BalanceFragment.DISPLAY");
LocalBroadcastManager.getInstance(this.getApplicationContext()).sendBroadcast(_intent);
}
PrefsUtil.getInstance(this.getApplicationContext()).setValue(PrefsUtil.FIRST_RUN, false);
if (notifTx && !AppUtil.getInstance(this.getApplicationContext()).isOfflineMode()) {
//
try {
PaymentCode pcode = BIP47Util.getInstance(this.getApplicationContext()).getPaymentCode();
// Log.i("BalanceFragment", "payment code:" + pcode.toString());
// Log.i("BalanceFragment", "notification address:" + pcode.notificationAddress().getAddressString());
APIFactory.getInstance(this.getApplicationContext()).getNotifAddress(pcode.notificationAddress(SamouraiWallet.getInstance().getCurrentNetworkParams()).getAddressString());
} catch (AddressFormatException afe) {
afe.printStackTrace();
Toast.makeText(this.getApplicationContext(), "HD wallet error", Toast.LENGTH_SHORT).show();
} catch (Exception ex) {
ex.printStackTrace();
}
//
// check on outgoing payment code notification tx
//
List<Pair<String, String>> outgoingUnconfirmed = BIP47Meta.getInstance().getOutgoingUnconfirmed();
// Log.i("BalanceFragment", "outgoingUnconfirmed:" + outgoingUnconfirmed.size());
for (Pair<String, String> pair : outgoingUnconfirmed) {
// Log.i("BalanceFragment", "outgoing payment code:" + pair.getLeft());
// Log.i("BalanceFragment", "outgoing payment code tx:" + pair.getRight());
int confirmations = APIFactory.getInstance(this.getApplicationContext()).getNotifTxConfirmations(pair.getRight());
if (confirmations > 0) {
BIP47Meta.getInstance().setOutgoingStatus(pair.getLeft(), BIP47Meta.STATUS_SENT_CFM);
}
if (confirmations == -1) {
BIP47Meta.getInstance().setOutgoingStatus(pair.getLeft(), BIP47Meta.STATUS_NOT_SENT);
}
}
Intent _intent = new Intent("com.samourai.wallet.MainActivity2.RESTART_SERVICE");
LocalBroadcastManager.getInstance(this.getApplicationContext()).sendBroadcast(_intent);
}
if (launch) {
if (PrefsUtil.getInstance(this.getApplicationContext()).getValue(PrefsUtil.GUID_V, 0) < 4) {
Log.i("JobIntentService", "guid_v < 4");
try {
String _guid = AccessFactory.getInstance(this.getApplicationContext()).createGUID();
String _hash = AccessFactory.getInstance(this.getApplicationContext()).getHash(_guid, new CharSequenceX(AccessFactory.getInstance(this.getApplicationContext()).getPIN()), AESUtil.DefaultPBKDF2Iterations);
PayloadUtil.getInstance(this.getApplicationContext()).saveWalletToJSON(new CharSequenceX(_guid + AccessFactory.getInstance().getPIN()));
PrefsUtil.getInstance(this.getApplicationContext()).setValue(PrefsUtil.ACCESS_HASH, _hash);
PrefsUtil.getInstance(this.getApplicationContext()).setValue(PrefsUtil.ACCESS_HASH2, _hash);
Log.i("JobIntentService", "guid_v == 4");
} catch (MnemonicException.MnemonicLengthException | IOException | JSONException | DecryptionException e) {
;
}
}
if (!PrefsUtil.getInstance(this.getApplicationContext().getApplicationContext()).getValue(PrefsUtil.XPUB44LOCK, false)) {
try {
String[] s = HD_WalletFactory.getInstance(this.getApplicationContext()).get().getXPUBs();
APIFactory.getInstance(this.getApplicationContext()).lockXPUB(s[0], 44, null);
} catch (IOException | MnemonicException.MnemonicLengthException e) {
;
}
}
if (!PrefsUtil.getInstance(this.getApplicationContext()).getValue(PrefsUtil.XPUB49LOCK, false)) {
String ypub = BIP49Util.getInstance(this.getApplicationContext()).getWallet().getAccount(0).ypubstr();
APIFactory.getInstance(this.getApplicationContext()).lockXPUB(ypub, 49, null);
}
if (!PrefsUtil.getInstance(this.getApplicationContext()).getValue(PrefsUtil.XPUB84LOCK, false)) {
String zpub = BIP84Util.getInstance(this.getApplicationContext()).getWallet().getAccount(0).zpubstr();
APIFactory.getInstance(this.getApplicationContext()).lockXPUB(zpub, 84, null);
}
if (!PrefsUtil.getInstance(this.getApplicationContext()).getValue(PrefsUtil.XPUBPRELOCK, false)) {
String zpub = BIP84Util.getInstance(this.getApplicationContext()).getWallet().getAccountAt(WhirlpoolMeta.getInstance(this.getApplicationContext()).getWhirlpoolPremixAccount()).zpubstr();
APIFactory.getInstance(this.getApplicationContext()).lockXPUB(zpub, 84, PrefsUtil.XPUBPRELOCK);
}
if (!PrefsUtil.getInstance(this.getApplicationContext()).getValue(PrefsUtil.XPUBPOSTLOCK, false)) {
String zpub = BIP84Util.getInstance(this.getApplicationContext()).getWallet().getAccountAt(WhirlpoolMeta.getInstance(this.getApplicationContext()).getWhirlpoolPostmix()).zpubstr();
APIFactory.getInstance(this.getApplicationContext()).lockXPUB(zpub, 84, PrefsUtil.XPUBPRELOCK);
}
if (!PrefsUtil.getInstance(this.getApplicationContext()).getValue(PrefsUtil.XPUBBADBANKLOCK, false)) {
String zpub = BIP84Util.getInstance(this.getApplicationContext()).getWallet().getAccountAt(WhirlpoolMeta.getInstance(this.getApplicationContext()).getWhirlpoolBadBank()).zpubstr();
APIFactory.getInstance(this.getApplicationContext()).lockXPUB(zpub, 84, PrefsUtil.XPUBBADBANKLOCK);
}
} else {
try {
PayloadUtil.getInstance(this.getApplicationContext()).saveWalletToJSON(new CharSequenceX(AccessFactory.getInstance(this.getApplicationContext()).getGUID() + AccessFactory.getInstance(this.getApplicationContext()).getPIN()));
} catch (Exception ignored) {
;
}
}
Intent _intent = new Intent("com.samourai.wallet.BalanceFragment.DISPLAY");
LocalBroadcastManager.getInstance(this.getApplicationContext()).sendBroadcast(_intent);
}
use of com.samourai.wallet.bip47.rpc.PaymentCode in project samourai-wallet-android by Samourai-Wallet.
the class RicochetMeta method script.
public JSONObject script(long spendAmount, long feePerKBAmount, String strDestination, int nbHops, String strPCode, boolean samouraiFeeViaBIP47, boolean useTimeLock) {
JSONObject jObj = new JSONObject();
try {
BigInteger biSpend = BigInteger.valueOf(spendAmount);
// default 4 hops min. for base fee, each additional hop 0.001
BigInteger biSamouraiFee = BigInteger.valueOf(samouraiFeeAmountV2.longValue() * ((nbHops - defaultNbHops) + 1));
BigInteger biFeePerKB = BigInteger.valueOf(feePerKBAmount);
long latestBlock = APIFactory.getInstance(context).getLatestBlockHeight();
long nTimeLock = 0L;
if (useTimeLock && latestBlock > 0L) {
nTimeLock = latestBlock;
}
jObj.put("ts", System.currentTimeMillis() / 1000L);
jObj.put("hops", nbHops);
jObj.put("spend_amount", biSpend.longValue());
jObj.put("samourai_fee", biSamouraiFee.longValue());
jObj.put("samourai_fee_via_bip47", samouraiFeeViaBIP47);
jObj.put("feeKB", biFeePerKB.longValue());
jObj.put("destination", strDestination);
if (strPCode != null) {
jObj.put("pcode", strPCode);
}
if (useTimeLock) {
jObj.put("nTimeLock", nTimeLock);
}
JSONObject jHop = new JSONObject();
JSONArray jHops = new JSONArray();
int hopSz = 0;
if (samouraiFeeViaBIP47) {
hopSz = FeeUtil.getInstance().estimatedSize(1, 2);
} else {
hopSz = FeeUtil.getInstance().estimatedSize(1, 1);
}
BigInteger biFeePerHop = FeeUtil.getInstance().calculateFee(hopSz, biFeePerKB);
Pair<List<UTXO>, BigInteger> pair = getHop0UTXO(spendAmount, nbHops, biFeePerHop.longValue(), samouraiFeeViaBIP47);
List<UTXO> utxos = pair.getLeft();
long totalValueSelected = 0L;
for (UTXO u : utxos) {
totalValueSelected += u.getValue();
}
// Log.d("RicochetMeta", "totalValueSelected (return):" + totalValueSelected);
// hop0 'leaves' wallet, change returned to wallet
BigInteger hop0 = biSpend.add(biSamouraiFee).add(biFeePerHop.multiply(BigInteger.valueOf((long) nbHops)));
// BigInteger hop0Fee = FeeUtil.getInstance().calculateFee(hop0sz, biFeePerKB);
BigInteger hop0Fee = pair.getRight();
// Log.d("RicochetMeta", "hop0Fee (return):" + hop0Fee.longValue());
Transaction txHop0 = getHop0Tx(utxos, hop0.longValue(), getDestinationAddress(index), hop0Fee.longValue(), samouraiFeeViaBIP47, nTimeLock);
if (txHop0 == null) {
return null;
}
// Log.d("RicochetMeta", "searching for:" + getDestinationAddress(index));
int prevTxN = 0;
for (int i = 0; i < txHop0.getOutputs().size(); i++) {
Script script = txHop0.getOutputs().get(i).getScriptPubKey();
// Log.d("RicochetMeta", "script:" + Hex.toHexString(script.getProgram()));
String address = null;
if (Hex.toHexString(script.getProgram()).startsWith("0014")) {
String hrp = null;
if (SamouraiWallet.getInstance().getCurrentNetworkParams() instanceof TestNet3Params) {
hrp = "tb";
} else {
hrp = "bc";
}
try {
String _script = Hex.toHexString(script.getProgram());
address = Bech32Segwit.encode(hrp, (byte) 0x00, Hex.decode(_script.substring(4).getBytes()));
} catch (Exception e) {
;
}
// Log.d("RicochetMeta", "bech32:" + address);
} else {
address = new Script(script.getProgram()).getToAddress(SamouraiWallet.getInstance().getCurrentNetworkParams()).toString();
// Log.d("RicochetMeta", "address from script:" + address);
}
if (address.equals(getDestinationAddress(index))) {
prevTxN = i;
// Log.d("RicochetMeta", "tx output n:" + prevTxN);
break;
}
}
jHop.put("seq", 0);
jHop.put("spend_amount", hop0.longValue());
jHop.put("fee", hop0Fee.longValue());
jHop.put("fee_per_hop", biFeePerHop.longValue());
jHop.put("index", index);
jHop.put("destination", getDestinationAddress(index));
// Log.d("RicochetMeta", "destination:" + getDestinationAddress(index));
int prevIndex = index;
index++;
jHop.put("tx", new String(Hex.encode(txHop0.bitcoinSerialize())));
jHop.put("hash", txHop0.getHash().toString());
if (useTimeLock) {
jHop.put("nTimeLock", nTimeLock);
}
jHops.put(jHop);
List<Pair<String, Long>> samouraiFees = new ArrayList<Pair<String, Long>>();
if (samouraiFeeViaBIP47) {
long baseVal = samouraiFeeAmountV2.longValue() / 4L;
long totalVal = 0L;
SecureRandom random = new SecureRandom();
int _outgoingIdx = BIP47Meta.getInstance().getOutgoingIdx(BIP47Meta.strSamouraiDonationPCode);
for (int i = 0; i < 4; i++) {
int val = random.nextInt(25000);
int sign = random.nextInt(1);
if (sign == 0) {
val *= -1L;
}
long feeVal = 0L;
if (i == 3) {
feeVal = samouraiFeeAmountV2.longValue() - totalVal;
} else {
feeVal = baseVal + val;
totalVal += feeVal;
}
//
try {
PaymentCode pcode = new PaymentCode(BIP47Meta.strSamouraiDonationPCode);
PaymentAddress paymentAddress = BIP47Util.getInstance(context).getSendAddress(pcode, _outgoingIdx + i);
// String strAddress = paymentAddress.getSendECKey().toAddress(SamouraiWallet.getInstance().getCurrentNetworkParams()).toString();
//
// derive as bech32
//
SegwitAddress segwitAddress = new SegwitAddress(paymentAddress.getSendECKey().getPubKey(), SamouraiWallet.getInstance().getCurrentNetworkParams());
String strAddress = segwitAddress.getBech32AsString();
samouraiFees.add(Pair.of(strAddress, feeVal));
// samouraiFees.add(Pair.of(strAddress, 200000L / 4L));
} catch (Exception e) {
samouraiFees.add(Pair.of(SendNotifTxFactory.SAMOURAI_NOTIF_TX_FEE_ADDRESS, feeVal));
}
}
}
Transaction txHop = null;
String prevTxHash = txHop0.getHash().toString();
String prevScriptPubKey = Hex.toHexString(txHop0.getOutput(prevTxN).getScriptPubKey().getProgram());
BigInteger remainingSamouraiFee = BigInteger.ZERO;
long prevSpendValue = hop0.longValue();
if (!samouraiFeeViaBIP47) {
prevSpendValue -= biSamouraiFee.longValue();
} else {
remainingSamouraiFee = samouraiFeeAmountV2;
}
int _hop = 0;
for (int i = (nbHops - 1); i >= 0; i--) {
_hop++;
BigInteger hopx = null;
if (samouraiFeeViaBIP47) {
remainingSamouraiFee = remainingSamouraiFee.subtract(BigInteger.valueOf(samouraiFees.get(_hop - 1).getRight()));
hopx = biSpend.add(biFeePerHop.multiply(BigInteger.valueOf((long) i))).add(remainingSamouraiFee);
} else {
hopx = biSpend.add(biFeePerHop.multiply(BigInteger.valueOf((long) i)));
}
if (useTimeLock && latestBlock > 0L) {
nTimeLock = latestBlock + _hop;
}
// Log.d("RicochetMeta", "doing hop:" + _hop);
if (samouraiFeeViaBIP47 && ((_hop - 1) < 4)) {
txHop = getHopTx(prevTxHash, prevTxN, prevIndex, prevSpendValue, hopx.longValue(), _hop < nbHops ? getDestinationAddress(index) : strDestination, samouraiFees.get(_hop - 1), nTimeLock);
} else {
txHop = getHopTx(prevTxHash, prevTxN, prevIndex, prevSpendValue, hopx.longValue(), _hop < nbHops ? getDestinationAddress(index) : strDestination, null, nTimeLock);
}
if (txHop == null) {
return null;
}
jHop = new JSONObject();
jHop.put("seq", (nbHops - i));
jHop.put("spend_amount", hopx.longValue());
jHop.put("fee", biFeePerHop.longValue());
jHop.put("prev_tx_hash", prevTxHash);
jHop.put("prev_tx_n", prevTxN);
jHop.put("prev_spend_value", prevSpendValue);
jHop.put("script", prevScriptPubKey);
jHop.put("tx", new String(Hex.encode(txHop.bitcoinSerialize())));
jHop.put("hash", txHop.getHash().toString());
if (useTimeLock) {
jHop.put("nTimeLock", nTimeLock);
}
if (_hop < nbHops) {
jHop.put("index", index);
jHop.put("destination", getDestinationAddress(index));
// Log.d("RicochetMeta", "destination:" + getDestinationAddress(index));
prevIndex = index;
index++;
} else {
jHop.put("destination", strDestination);
// Log.d("RicochetMeta", "destination:" + strDestination);
}
if (samouraiFeeViaBIP47) {
jObj.put("samourai_fee_address", samouraiFees.get(_hop - 1).getLeft());
jObj.put("samourai_fee_amount", samouraiFees.get(_hop - 1).getRight());
}
jHops.put(jHop);
prevTxHash = txHop.getHash().toString();
prevTxN = 0;
prevSpendValue = hopx.longValue();
prevScriptPubKey = Hex.toHexString(txHop.getOutputs().get(0).getScriptPubKey().getProgram());
}
jObj.put("hops", jHops);
BigInteger totalAmount = hop0.add(hop0Fee);
jObj.put("total_spend", totalAmount.longValue());
} catch (JSONException je) {
return null;
}
System.out.println("RicochetMeta:" + jObj.toString());
return jObj;
}
Aggregations