Пример #1
0
        //scan derived addresses for any balance
        public static long GetExtendedBalance(string extPubKey, uint start, uint cnt, uint stopAfter, bool testnet)
        {
            CheckNullOrEmpty(new object[] { extPubKey }, new string[] { "extPubKey" });

            List <Tuple <string, string> > recAddrList = GetDerivedKeys(extPubKey, start, cnt, false, testnet); //receive addresses
            List <Tuple <string, string> > chgAddrList = GetDerivedKeys(extPubKey, start, cnt, true, testnet);  //change addresses

            string[] recAddrListAddr = new string[recAddrList.Count];                                           //short address - myB9vrgbz4THVf....
            string[] recAddrListExt  = new string[recAddrList.Count];                                           //extended address - tpubD6NzVbkrYh.....

            int ctr = 0;

            foreach (var t in recAddrList)
            {
                recAddrListAddr[ctr++] = t.Item1;                 //short - address
            }
            ctr = 0;
            foreach (var t in recAddrList)
            {
                recAddrListExt[ctr++] = t.Item2;                 //long - public key
            }
            string[] chgAddrListAddr = new string[recAddrList.Count];
            string[] chgAddrListExt  = new string[recAddrList.Count];

            ctr = 0;
            foreach (var t in chgAddrList)
            {
                chgAddrListAddr[ctr++] = t.Item1;
            }
            ctr = 0;
            foreach (var t in chgAddrList)
            {
                chgAddrListExt[ctr++] = t.Item2;
            }

            long bal = 0;

            //add up all UTXOs (unspent inputs) in address list
            MainWindow.MainWin.UpdateStatus(">>>> Receive Addresses");
            bal += ElectrumX.GetBalance(recAddrListAddr, stopAfter, ElectrumXhost, ElectrumXport);
            MainWindow.MainWin.UpdateStatus(">>>> Change Addresses");
            bal += ElectrumX.GetBalance(chgAddrListAddr, stopAfter, ElectrumXhost, ElectrumXport);
            return(bal);
        }
Пример #2
0
        //get all unspent inputs for extended public key
        public static UTXO[] GetExtendedUTXOs(string extPublicKey, uint start, uint maxcnt, bool testnet)
        {
            CheckNullOrEmpty(new object[] { extPublicKey }, new string[] { "extPublicKey" });

            //get child keys for extended public key
            List <Tuple <string, string> > keysRec = GetDerivedKeys(extPublicKey, start, maxcnt, false, testnet);         //receive addresses
            List <Tuple <string, string> > keysChg = GetDerivedKeys(extPublicKey, start, maxcnt, true, testnet);          //change addresses
            List <UTXO> lst = new List <UTXO>();

            //use ElectrumX server to get all unspent inputs
            lst.AddRange(ElectrumX.GetUTXOs(keysRec, ElectrumXhost, ElectrumXport));
            lst.AddRange(ElectrumX.GetUTXOs(keysChg, ElectrumXhost, ElectrumXport));
            //we actually used maxcnt twice (for receiving addresses and change addresses), so may need to truncate
            if (lst.Count > maxcnt)
            {
                lst.Resize((int)maxcnt);
            }
            return(lst.ToArray());
        }
Пример #3
0
 public static long EstimateFee()
 {
     return(ElectrumX.EstimateFee(20, ElectrumXhost, ElectrumXport));
 }
Пример #4
0
        //take in tx parameters, return tx object
        public static TxSerial CreateTx(string extPubKey, string pubToAddr, string chgAddr, int walletId, long satToSend, long fee, bool testnet)
        {
            CheckNullOrEmpty(new object[] { extPubKey, pubToAddr, ElectrumXhost },
                             new string[] { "extPubKey", "pubToAddr", "ElectrumXhost" });

            string err = "";

            if (satToSend == 0)
            {
                err += "satoshiToSend = 0, ";
            }
            if (fee == 0)
            {
                err += "satoshiFee = 0, ";
            }
            if (err != "")
            {
                throw new Exception("[CreateTx] " + err);
            }

            //get first 100+100 child address from ext pub key
            List <Tuple <string, string> > recAddrList = GetDerivedKeys(extPubKey, 0, 20, false, testnet);         //receive addresses
            List <Tuple <string, string> > chgAddrList = GetDerivedKeys(extPubKey, 0, 20, true, testnet);          //change addresses

            //TODO - create process for getting next change address, so address never used twice
            if (chgAddr == null || chgAddr == "")             //get first chg addr for extPubKey
            {
                chgAddr = chgAddrList.First().Item1;
            }

            //server status check
            string info = ElectrumX.GetServerInfo(ElectrumXhost, ElectrumXport);

            if (info == null)
            {
                throw new Exception("[CreateTx] ElectrumX Server Check Failed");
            }

            string[] recAddrListAddr = new string[recAddrList.Count];            //short address
            string[] recAddrListExt  = new string[recAddrList.Count];            //long address
            int      ctr             = 0;

            foreach (var t in recAddrList)
            {
                recAddrListAddr[ctr++] = t.Item1;                 //short
            }
            ctr = 0;
            foreach (var t in recAddrList)
            {
                recAddrListExt[ctr++] = t.Item2;                 //long - hash
            }
            string[] chgAddrListAddr = new string[recAddrList.Count];
            string[] chgAddrListExt  = new string[recAddrList.Count];
            ctr = 0;
            foreach (var t in chgAddrList)
            {
                chgAddrListAddr[ctr++] = t.Item1;
            }
            ctr = 0;
            foreach (var t in chgAddrList)
            {
                chgAddrListExt[ctr++] = t.Item2;
            }

            //get all UTXOs (unspent inputs) from receive addresses
            UTXO[] recUTXOs = ElectrumX.GetUTXOs(recAddrList, ElectrumXhost, ElectrumXport);
            UTXO.SetAddressType(recUTXOs, 0);             //receiver
            //get all UTXOs (unspent inputs) from change addresses
            UTXO[] chgUTXOs = ElectrumX.GetUTXOs(chgAddrList, ElectrumXhost, ElectrumXport);
            UTXO.SetAddressType(chgUTXOs, 1);             //change

            //start new tx
            TransactionBuilder bldr = new TransactionBuilder();

            bldr.Send(new BitcoinPubKeyAddress(pubToAddr), Money.Satoshis(satToSend)); //amount to send to recipient
            bldr.SetChange(new BitcoinPubKeyAddress(chgAddr));                         //send change to this address
            bldr.SendFees(Money.Satoshis(fee));                                        //miner (tx) fee

            //collect all UTXOs
            List <UTXO> allUTXOs = new List <UTXO>();

            allUTXOs.AddRange(recUTXOs);
            allUTXOs.AddRange(chgUTXOs);

            List <ICoin> lstTxCoins = new List <ICoin>();           //Coin is a UTXO

            //add new coin for each UTXO
            foreach (UTXO x in allUTXOs)             //tx builder will select coins from this list
            {
                BitcoinPubKeyAddress fromAddr = new BitcoinPubKeyAddress(x.Address);
                NBitcoin.Coin        cn       = null;
                //create new coin from UTXO
                bldr.AddCoins(cn = new NBitcoin.Coin(
                                  new OutPoint(new uint256(x.Tx_hash), x.Tx_pos),              //tx that funded wallet, spend this coin
                                  new TxOut(Money.Satoshis(x.Value), fromAddr.ScriptPubKey))); //specify full coin amount, else SetChange ignored
                lstTxCoins.Add(cn);                                                            //add coin to transaction, may not be used
                x.tmp = cn;                                                                    //link UTXO with coin
            }

            List <UTXO> usedUTXOs = new List <UTXO>();              //coins actually used in tx

            NBitcoin.Transaction tx = bldr.BuildTransaction(false); //sort\filter coins, some coins will not be needed\used
            //coin objects not stored in tx, so we need to determine which coins were used
            //scan tx inputs for matching coins, ignore other coins
            foreach (UTXO u in allUTXOs)
            {
                foreach (TxIn i in tx.Inputs)
                {
                    if (i.PrevOut == ((NBitcoin.Coin)u.tmp).Outpoint) //this coin in tx
                    {
                        usedUTXOs.Add(u);                             //this UTXO will be used\spent in tx
                    }
                }
            }
            //populate return object
            TxSerial txs = new TxSerial()
            {
                SendAmt      = satToSend,
                Fee          = fee,
                ExtPublicKey = extPubKey,
                ToAddress    = pubToAddr,
                ChgAddress   = chgAddr,
                WalletId     = walletId
            };
            txs.ExtPublicKey = extPubKey;

            foreach (UTXO u in usedUTXOs)
            {
                u.tmp = null;                 //don't serialize coin object, will rebuild coins in signing process
            }
            txs.InputUTXOs = new List <UTXO>();
            txs.InputUTXOs.AddRange(usedUTXOs);
            //string jsn = Newtonsoft.Json.JsonConvert.SerializeObject(txs, Newtonsoft.Json.Formatting.Indented);
            return(txs);
        }