<commit_before><?php

namespace Blocktrail\SDK\Tests;

use Blocktrail\SDK\BlocktrailSDK;
use Blocktrail\SDK\BlocktrailSDKInterface;
use Blocktrail\SDK\Services\BlocktrailBitcoinService;
use Blocktrail\SDK\UnspentOutputFinder;

/**
 * Class WalletRecoveryTest
 *
 * ! IMPORTANT NODE !
 * throughout the test cases we use key_index=9999 to force an insecure development key on the API side
 *  this insecure key is used instead of the normal one so that we can reproduce the result on our staging environment
 *  without our private keys having to leaving our safe production environment
 *
 *
 * @package Blocktrail\SDK\Tests
 */
class WalletRecoveryTest extends \PHPUnit_Framework_TestCase {

    protected $wallets = [];

    /**
     * setup an instance of BlocktrailSDK
     *
     * @return BlocktrailSDKInterface
     */
    public function setupBlocktrailSDK() {
        $client = new BlocktrailSDK("MY_APIKEY", "MY_APISECRET", "BTC", true, 'v1');
        // $client->setCurlDebugging();
        return $client;
    }

    protected function tearDown() {
        $this->cleanUp();
    }

    protected function onNotSuccessfulTest(\Exception $e) {
        //called when a test fails
        $this->cleanUp();
        throw $e;
    }

    protected function cleanUp() {
        //...
    }

    public function testBlocktrailBicoinService() {
        //test the blocktrail bitcoin data service provider
        $blockchainDataService = new BlocktrailBitcoinService("MY_APIKEY", "MY_APISECRET", "BTC", true, 'v1');

        //get unspent outputs for a single address
        $address = '<KEY>';
        $result = $blockchainDataService->getUnspentOutputs($address);
    }

    public function testUnspentOutputFinder() {
        //some addresses with known unspent outputs, and some without any
        $addresses = array(
            '<KEY>',      //has 0.1 tbtc
            '2NA7zpiq5PcYUx6oraEwz8zPzn6HefSvdLA',      //has 0.1 tbtc
            '2Mu1xrQAEd8LsiRHNvgXDaU8kQU5WKqzCq7'       //has 0 tbtc
        );

        $blockchainDataService = new BlocktrailBitcoinService("MY_APIKEY", "MY_APISECRET", "BTC", true, 'v1');
        $unspenOutputFinder = new UnspentOutputFinder($blockchainDataService);

        //get unspent outputs for an array of addresses
        $result = $unspenOutputFinder->getUTXOs($addresses);

        $this->assertTrue(true);
    }

    public function testWalletSweep() {
        /*
         * We have set up a testnet wallet with known unspent outputs in certain addresses for this test
         */
        $walletIdentifier = "unittest-wallet-recovery";
        $walletPass = "password";
        $primaryMnemonic = "olive six drill desk jealous nice chronic draw reveal super already stick wear hurt aunt crazy step mechanic derive already kangaroo render tenant honey large cabin better guitar biology metal angry tide boat father slam title maple notice salmon shy mass shock dog cream twelve strong marble sudden";
        $backupMnemonic = "adapt finger below junk slam power opinion finish vapor measure code know stove mom confirm design chaos goat cradle mansion target fuel empty fox pill recycle brisk flush swap chimney dance mind brass moral stay shoulder slide shove march wise animal frame shed require alien moral onion auto";
        $blocktrailKeys = array(
            [
                'keyIndex'=> 0,
                'path' => "M/0'",
                'pubkey' => '<KEY>',
            ],
            [
                'keyIndex'=> 9999,
                'path' => "M/9999'",
                'pubkey' => '<KEY>',
            ]
        );

        $this->assertTrue(true);
    }
}<commit_msg>tests for wallet recovery and unspent output discovery<commit_after><?php

namespace Blocktrail\SDK\Tests;

use Blocktrail\SDK\BlocktrailSDK;
use Blocktrail\SDK\BlocktrailSDKInterface;
use Blocktrail\SDK\Services\BlocktrailBitcoinService;
use Blocktrail\SDK\UnspentOutputFinder;
use Blocktrail\SDK\WalletSweeper;

/**
 * Class WalletRecoveryTest
 * We have set up a testnet wallet with known unspent outputs in certain addresses for these test
 *
 *
 * @package Blocktrail\SDK\Tests
 */
class WalletRecoveryTest extends \PHPUnit_Framework_TestCase {

    protected $wallets = [];

    /**
     * setup an instance of BlocktrailSDK
     *
     * @return BlocktrailSDKInterface
     */
    public function setupBlocktrailSDK() {
        // $client->setCurlDebugging();
        $client = new BlocktrailSDK("MY_APIKEY", "MY_APISECRET", "BTC", true, 'v1');
        return $client;
    }

    protected function tearDown() {
        $this->cleanUp();
    }

    protected function onNotSuccessfulTest(\Exception $e) {
        //called when a test fails
        $this->cleanUp();
        throw $e;
    }

    protected function cleanUp() {
        //No cleanup to do
        //...
    }

    public function testBlocktrailBicoinService() {
        //test the blocktrail bitcoin data service provider
        $blockchainDataService = new BlocktrailBitcoinService("MY_APIKEY", "MY_APISECRET", "BTC", true, 'v1');

        //get unspent outputs for a single address
        $address = '2NA7zpiq5PcYUx6oraEwz8zPzn6HefSvdLA';   //has 0.2 tbtc in 2 utxos
        $result = $blockchainDataService->getUnspentOutputs($address);
        $this->assertEquals(2, count($result));
        $this->assertArrayHasKey('hash', $result[0]);
        $this->assertArrayHasKey('index', $result[0]);
        $this->assertArrayHasKey('value', $result[0]);
        $this->assertArrayHasKey('script_hex', $result[0]);
        $this->assertEquals(10000000, $result[0]['value']);
        $this->assertEquals(10000000, $result[1]['value']);


        $address = '2Mu1xrQAEd8LsiRHNvgXDaU8kQU5WKqzCq7';   //has 0 tbtc in 0 utxos
        $result = $blockchainDataService->getUnspentOutputs($address);
        $this->assertEquals(0, count($result));
    }

    public function testUnspentOutputFinder() {
        //some addresses with known unspent outputs, and some without any
        $addresses = array(
            '<KEY>',      //has 0.1 tbtc in 1 utxo
            '2NA7zpiq5PcYUx6oraEwz8zPzn6HefSvdLA',      //has 0.2 tbtc in 2 utxos
            '2Mu1xrQAEd8LsiRHNvgXDaU8kQU5WKqzCq7',      //has 0 tbtc
            '2N9ijhGSX3kGbe16RMCQ2hviH8RLAVdaqZg'       //has 0.1 tbtc in 1 utxo
        );

        $blockchainDataService = new BlocktrailBitcoinService("MY_APIKEY", "MY_APISECRET", "BTC", true, 'v1');
        $unspenOutputFinder = new UnspentOutputFinder($blockchainDataService);

        //get unspent outputs for an array of addresses
        $result = $unspenOutputFinder->getUTXOs($addresses);
        $this->assertEquals(3, count($result), "expected results for 3 of the 4 given addresses");
        $this->assertArrayHasKey('2NG3QEhJc1xzN5qxPdNAZfGaTdGAv3ixMbH', $result);
        $this->assertArrayHasKey('2NA7zpiq5PcYUx6oraEwz8zPzn6HefSvdLA', $result);
        $this->assertArrayHasKey('2N9ijhGSX3kGbe16RMCQ2hviH8RLAVdaqZg', $result);
        $this->assertEquals(2, count($result['2NA7zpiq5PcYUx6oraEwz8zPzn6HefSvdLA']), "expected address to have 2 unspent outputs");
        $this->assertArrayHasKey('hash', $result['2NA7zpiq5PcYUx6oraEwz8zPzn6HefSvdLA'][0]);
        $this->assertArrayHasKey('index', $result['2NA7zpiq5PcYUx6oraEwz8zPzn6HefSvdLA'][0]);
        $this->assertArrayHasKey('value', $result['2NA7zpiq5PcYUx6oraEwz8zPzn6HefSvdLA'][0]);
        $this->assertArrayHasKey('script_hex', $result['2NA7zpiq5PcYUx6oraEwz8zPzn6HefSvdLA'][0]);
        $this->assertEquals(10000000, $result['2NA7zpiq5PcYUx6oraEwz8zPzn6HefSvdLA'][0]['value']);
        $this->assertEquals(10000000, $result['2NA7zpiq5PcYUx6oraEwz8zPzn6HefSvdLA'][1]['value']);

        $total = $result['2NG3QEhJc1xzN5qxPdNAZfGaTdGAv3ixMbH'][0]['value'] + $result['2N9ijhGSX3kGbe16RMCQ2hviH8RLAVdaqZg'][0]['value']
                + $result['2NA7zpiq5PcYUx6oraEwz8zPzn6HefSvdLA'][0]['value'] + $result['2NA7zpiq5PcYUx6oraEwz8zPzn6HefSvdLA'][1]['value'];
        $this->assertEquals(40000000, $total);
    }

    public function testWalletSweep() {
        /*
         * We have set up a testnet wallet with known unspent outputs in certain addresses for this test
         */
        $increment = 10;            //using a search increment of 10 for speed, as we know our funds are no more than 10 addresses apart from each other
        $primaryPassphrase = "password";
        $primaryMnemonic = "olive six drill desk jealous nice chronic draw reveal super already stick wear hurt aunt crazy step mechanic derive already kangaroo render tenant honey large cabin better guitar biology metal angry tide boat father slam title maple notice salmon shy mass shock dog cream twelve strong marble sudden";
        $backupMnemonic = "adapt finger below junk slam power opinion finish vapor measure code know stove mom confirm design chaos goat cradle mansion target fuel empty fox pill recycle brisk flush swap chimney dance mind brass moral stay shoulder slide shove march wise animal frame shed require alien moral onion auto";
        $blocktrailKeys = array(
            [
                'keyIndex'=> 0,
                'path' => "M/0'",
                'pubkey' => '<KEY>',
            ],
            [
                'keyIndex'=> 9999,
                'path' => "M/9999'",
                'pubkey' => '<KEY>',
            ]
        );
        $bitcoinClient = new BlocktrailBitcoinService("MY_APIKEY", "MY_APISECRET", "BTC", true, 'v1');

        //create the wallet sweeper and do fund discovery
        $walletSweeper = new WalletSweeper($primaryMnemonic, $primaryPassphrase, $backupMnemonic, $blocktrailKeys, $bitcoinClient, 'btc', true);
        //$walletSweeper->enableLogging();    //can enable logging if test is taking too long or something seems to be wrong. NB: this test will take a long time - be patient

        $results = $walletSweeper->discoverWalletFunds($increment);
        $this->assertEquals(4, $results['count'], "expected utxo count to be 4");
        $this->assertEquals(40000000, $results['balance'], "unexpected balance amount");
        $this->assertGreaterThanOrEqual(50, $results['addressesSearched'], "expected at least 50 addresses to be searched");
        $this->assertEquals(3, count($results['utxos']), "expected 3 addresses to be found to have unspent outputs");
        $this->assertEquals(2, count($results['utxos']['2NA7zpiq5PcYUx6oraEwz8zPzn6HefSvdLA']['utxos']), "expected particular address to have 2 unspent outputs");
        $this->assertArrayHasKey('hash', $results['utxos']['2NA7zpiq5PcYUx6oraEwz8zPzn6HefSvdLA']['utxos'][0]);
        $this->assertArrayHasKey('index', $results['utxos']['2NA7zpiq5PcYUx6oraEwz8zPzn6HefSvdLA']['utxos'][0]);
        $this->assertArrayHasKey('value', $results['utxos']['2NA7zpiq5PcYUx6oraEwz8zPzn6HefSvdLA']['utxos'][0]);
        $this->assertArrayHasKey('script_hex', $results['utxos']['2NA7zpiq5PcYUx6oraEwz8zPzn6HefSvdLA']['utxos'][0]);
        $this->assertArrayHasKey('path', $results['utxos']['2NA7zpiq5PcYUx6oraEwz8zPzn6HefSvdLA']);
        $this->assertArrayHasKey('redeem', $results['utxos']['2NA7zpiq5PcYUx6oraEwz8zPzn6HefSvdLA']);

        //do fund sweeping - will carry out fund discovery if needed (already completed above) and then create and sign a transaction
        $destination = '2NA7zpiq5PcYUx6oraEwz8zPzn6HefSvdLA';
        $results = $walletSweeper->sweepWallet($destination, $increment);
        $this->assertArrayHasKey('hex', $results);
        $this->assertEquals('true', $results['complete']);
        $this->assertEquals(8, $results['req_sigs']);
        $this->assertEquals(8, $results['sign_count']);
    }
}
{'fraction_non_alphanumeric': 0.11407662505380974, 'fraction_numerical': 0.02746448557899268, 'mean_word_length': 3.281607077036491, 'pattern_counts': {'":': 0, '<': 12, '<?xml version=': 0, '>': 73, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 6, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2202448', 'n_tokens_mistral': 3911, 'n_tokens_neox': 3746, 'n_words': 880}