protected function generateComposedTransactionModel($request_id, PaymentAddress $payment_address, $destination, $float_quantity, $asset, $float_fee, $float_btc_dust_size, $is_sweep) { // check to see if this signed transaction already exists in the database $composed_transaction_model = $this->composed_transaction_repository->getComposedTransactionByRequestID($request_id); if ($composed_transaction_model === null) { // build the signed transactions $change_address_collection = null; $built_transaction_to_send = $this->buildSignedTransactionToSend($payment_address, $destination, $float_quantity, $asset, $change_address_collection, $float_fee, $float_btc_dust_size, $is_sweep); // get the utxo identifiers $utxo_identifiers = $this->buildUTXOIdentifiersFromUTXOs($built_transaction_to_send->getInputUtxos()); // store the signed transactions to the database cache $signed_transaction_hex = $built_transaction_to_send->getTransactionHex(); $txid = $built_transaction_to_send->getTxId(); $composed_transaction_model = $this->composed_transaction_repository->storeOrFetchComposedTransaction($request_id, $txid, $signed_transaction_hex, $utxo_identifiers); // mark each UTXO as spent $this->txo_repository->updateByTXOIdentifiers($utxo_identifiers, ['spent' => 1]); // create the new UTXOs that belong to any of our addresses $account = AccountHandler::getAccount($payment_address); $this->clearPaymentAddressInfoCache(); foreach ($built_transaction_to_send->getOutputUtxos() as $output_utxo) { if ($output_utxo['amount'] <= 0) { // don't store OP_RETURN UTXOs with no value continue; } // create new UTXO $utxo_destination_address = AddressFactory::fromOutputScript(ScriptFactory::fromHex($output_utxo['script']))->getAddress(); list($found_payment_address, $found_account) = $this->loadPaymentAddressInfo($utxo_destination_address); if ($found_payment_address) { $this->txo_repository->create($found_payment_address, $found_account, ['txid' => $output_utxo['txid'], 'n' => $output_utxo['n'], 'amount' => $output_utxo['amount'], 'script' => $output_utxo['script'], 'type' => TXO::UNCONFIRMED, 'spent' => 0, 'green' => 1]); } } } return $composed_transaction_model; }
public function testComposeP2SHSourceCounterpartyTransaction() { list($sender_address_1, $wif_key_1, $private_key_1) = $this->newAddressAndKey(); list($sender_address_2, $wif_key_2, $private_key_2) = $this->newAddressAndKey(); list($sender_address_3, $wif_key_3, $private_key_3) = $this->newAddressAndKey(); // build a multisig address (2 of 3) $public_keys = [$private_key_1->getPublicKey(), $private_key_2->getPublicKey(), $private_key_3->getPublicKey()]; $p2sh_script = ScriptFactory::p2sh()->multisig(2, $public_keys); $sender_address = $p2sh_script->getAddress()->getAddress(); // variables $utxos = $this->fakeUTXOs($sender_address); $asset = 'SOUP'; $quantity = 45; $destination = '1AAAA1111xxxxxxxxxxxxxxxxxxy43CZ9j'; $fee = 0.0001; $btc_dust = 5.432E-5; // compose the send $composer = new Composer(); $composed_unsigned_send = $composer->composeSend($asset, CryptoQuantity::fromFloat($quantity), $destination, null, $utxos, $sender_address, $fee, $btc_dust); list($txid, $unsigned_hex, $new_utxos) = $this->decomposeComposedTransaction($composed_unsigned_send); // parse the signed hex $transaction = TransactionFactory::fromHex($unsigned_hex); // check output 1 $tx_output_0 = $transaction->getOutput(0); PHPUnit::assertEquals(intval(round($btc_dust * self::SATOSHI)), $tx_output_0->getValue()); PHPUnit::assertEquals($destination, AddressFactory::fromOutputScript($tx_output_0->getScript())->getAddress()); // check output 2 $tx_output_1 = $transaction->getOutput(1); $op_return = $tx_output_1->getScript()->getScriptParser()->decode()[1]->getData()->getHex(); $txid = $transaction->getInput(0)->getOutPoint()->getTxId()->getHex(); $hex = $this->arc4decrypt($txid, $op_return); $expected_hex = '434e54525052545900000000000000000004fadf000000010c388d00'; PHPUnit::assertEquals($expected_hex, $hex); // check output 3 $tx_output_2 = $transaction->getOutput(2); PHPUnit::assertEquals(intval(round((0.123 + 0.0005 - $fee - $btc_dust) * self::SATOSHI)), $tx_output_2->getValue()); PHPUnit::assertEquals($sender_address, AddressFactory::fromOutputScript($tx_output_2->getScript())->getAddress()); // check $new_utxos PHPUnit::assertNotEmpty($new_utxos); PHPUnit::assertEquals(5432, $new_utxos[0]['amount']); }