public function testUtils()
 {
     // public key from WIF
     PHPUnit::assertEquals('03f05b88087b2392611d0eb388f11543b02b21d12c18aba21699e73e97a61fee15', BitcoinKeyUtils::publicKeyFromWIF('L2KB5RqtHwLKrNaVuxQCiNs549vbp4oy7FTF2zs2GChLXXnXyMee'));
     $caught_error = false;
     try {
         BitcoinKeyUtils::publicKeyFromWIF('BADWIF');
     } catch (Exception $e) {
         $caught_error = true;
     }
     PHPUnit::assertTrue($caught_error);
     // address from WIF
     PHPUnit::assertEquals('1NjZ3zsBySHtCWX3NtPFfmUXEwx7XeG82H', BitcoinKeyUtils::addressFromWIF('L2KB5RqtHwLKrNaVuxQCiNs549vbp4oy7FTF2zs2GChLXXnXyMee'));
     $caught_error = false;
     try {
         BitcoinKeyUtils::addressFromWIF('BADWIF');
     } catch (Exception $e) {
         $caught_error = true;
     }
     PHPUnit::assertTrue($caught_error);
     $generator = $this->getGenerator();
     $private_key = $generator->privateKey('mytoken1');
     PHPUnit::assertEquals('034fba8396613ae90defdc45e2e924a4bda2e1b94d653d4d28111523cc57ccb8d7', BitcoinKeyUtils::publicKeyFromPrivateKey($private_key)->getHex());
     PHPUnit::assertEquals('L4iQRBZz1XuqvE6qyfQZAn6AtiudyT9dnQTvnHU5n3TQ9G45sPJ3', BitcoinKeyUtils::WIFFromPrivateKey($private_key));
 }
 protected function buildSignedTransactionToSend(PaymentAddress $payment_address, $destination, $float_quantity, $asset, $change_address_collection = null, $float_fee = null, $float_btc_dust_size = null, $is_sweep = false)
 {
     $signed_transaction = null;
     if ($float_fee === null) {
         $float_fee = self::DEFAULT_FEE;
     }
     if ($float_btc_dust_size === null) {
         $float_btc_dust_size = self::DEFAULT_REGULAR_DUST_SIZE;
     }
     $private_key = $this->address_generator->privateKey($payment_address['private_key_token']);
     $wif_private_key = BitcoinKeyUtils::WIFFromPrivateKey($private_key);
     if ($is_sweep) {
         if (strtoupper($asset) != 'BTC') {
             throw new Exception("Sweep is only allowed for BTC.", 1);
         }
         // compose the BTC transaction
         $chosen_txos = $this->txo_repository->findByPaymentAddress($payment_address, [TXO::UNCONFIRMED, TXO::CONFIRMED], true);
         $float_quantity = CurrencyUtil::satoshisToValue($this->sumUTXOs($chosen_txos)) - $float_fee;
         $composed_transaction = $this->transaction_composer->composeSend('BTC', $float_quantity, $destination, $wif_private_key, $chosen_txos, null, $float_fee);
     } else {
         if (strtoupper($asset) == 'BTC') {
             // compose the BTC transaction
             if ($this->isPrimeSend($payment_address, $destination)) {
                 $float_prime_size = $this->getPrimeSendSize($destination, $float_quantity);
                 $chosen_txos = $this->txo_chooser->chooseUTXOsForPriming($payment_address, $float_quantity, $float_fee, null, $float_prime_size);
                 $debug_strategy_text = 'prime';
             } else {
                 $chosen_txos = $this->txo_chooser->chooseUTXOs($payment_address, $float_quantity, $float_fee, null, TXOChooser::STRATEGY_BALANCED);
                 $debug_strategy_text = 'balanced';
             }
             Log::debug("strategy={$debug_strategy_text} Chosen UTXOs: " . $this->debugDumpUTXOs($chosen_txos));
             if (!$chosen_txos) {
                 throw new Exception("Unable to select transaction outputs (UTXOs)", 1);
             }
             // $signed_transaction = $this->bitcoin_payer->buildSignedTransactionHexToSendBTC($payment_address['address'], $destination, $float_quantity, $wif_private_key, $float_fee);
             if ($change_address_collection === null) {
                 $change_address_collection = $payment_address['address'];
             }
             $composed_transaction = $this->transaction_composer->composeSend('BTC', $float_quantity, $destination, $wif_private_key, $chosen_txos, $change_address_collection, $float_fee);
         } else {
             // calculate the quantity
             $is_divisible = $this->asset_cache->isDivisible($asset);
             $quantity = new Quantity($float_quantity, $is_divisible);
             // compose the Counterpary and BTC transaction
             $chosen_txos = $this->txo_chooser->chooseUTXOs($payment_address, $float_btc_dust_size, $float_fee);
             Log::debug("Counterparty send Chosen UTXOs: " . $this->debugDumpUTXOs($chosen_txos));
             // build the change
             if ($change_address_collection === null) {
                 $change_address_collection = $payment_address['address'];
             }
             $composed_transaction = $this->transaction_composer->composeSend($asset, $quantity, $destination, $wif_private_key, $chosen_txos, $change_address_collection, $float_fee, $float_btc_dust_size);
             // debug
             try {
                 $_debug_parsed_tx = app('\\TransactionComposerHelper')->parseCounterpartyTransaction($composed_transaction->getTransactionHex());
                 Log::debug("Counterparty send: \$_debug_parsed_tx=" . json_encode($_debug_parsed_tx, 192));
             } catch (Exception $e) {
                 Log::debug("Error composing send: {$asset}, " . ($quantity instanceof Quantity ? $quantity->getRawValue() : $quantity) . ", {$destination}  " . $e->getMessage());
                 throw $e;
             }
         }
     }
     return $composed_transaction;
 }