require_once __DIR__ . "/../vendor/autoload.php";
/*
    This simple example shows how to get the payload when your webhook is called.

    Set up the webhook before hand (see simple_webhooks_setup_example.php) with the webhook url pointing to this script,
    either through an ngrok tunnel or with a publically accessible development server.
    -----
    $client = new BlocktrailSDK("YOUR_APIKEY_HERE", "YOUR_APISECRET_HERE", "BTC", true, 'v1');
    $client->setupWebhook("http://oisin.ngrok.com/examples/simple_webhooks_receive_example.php", "oisin-ngrok-webhooks-example");


    Then you can either use the BlockTrail webhook tester (access from the dashboard when you login), or you could
    subscribe to block events, address transactions or a particular transaction hash and have your webhook fire naturally.
    -----
    $client->subscribeAddressTransactions("oisin-ngrok-webhooks-example", "2N6Fg6T74Fcv1JQ8FkPJMs8mYmbm9kitTxy");
    $client->subscribeNewBlocks("oisin-ngrok-webhooks-example");

    (Alternatively you can create a wallet webhook and receive notifications on your wallet activity.)
*/
// get the data POSTed to us when this webhook is fired
$payload = BlocktrailSDK::getWebhookPayload();
// we now have access to a block payload or transaction payload. See the API Docs for the full schemas.
if ($payload['event_type'] == "block") {
    //do stuff with the newly found block data
} elseif ($payload['event_type'] == "address-transactions") {
    //do stuff with the transaction data for the subscribed address(es)
} elseif ($payload['event_type'] == "transaction") {
    //do stuff with the transaction data for the subscribed transaction
}
// use the BlockTrail webhook tester and you'll see the full payload printed out
print_r($payload);
 /**
  * generate multisig address for given path
  *
  * @param $path
  * @return array
  * @throws \Exception
  */
 protected function createAddress($path)
 {
     $path = BIP32Path::path($path);
     //build public keys for this path
     $primaryPubKey = $this->primaryPrivateKey->buildKey($path)->publicKey();
     $backupPubKey = $this->backupPrivateKey->buildKey($path->unhardenedPath())->publicKey();
     $blocktrailPubKey = $this->getBlocktrailPublicKey($path)->buildKey($path)->publicKey();
     //sort the keys
     $multisigKeys = BlocktrailSDK::sortMultisigKeys([$primaryPubKey, $backupPubKey, $blocktrailPubKey]);
     //create the multisig address
     $multiSig = RawTransaction::create_multisig(2, $multisigKeys);
     return [$multiSig['address'], $multiSig['redeemScript']];
 }
 public function testSatoshiConversion()
 {
     $toSatoshi = [["0.00000001", "1", 1], [1.0E-8, "1", 1], ["0.29560000", "29560000", 29560000], [0.2956, "29560000", 29560000], ["1.0000009", "100000090", 100000090], [1.0000009, "100000090", 100000090], ["1.00000009", "100000009", 100000009], [1.00000009, "100000009", 100000009], ["21000000.00000001", "2100000000000001", 2100000000000001.0], [21000000.00000001, "2100000000000001", 2100000000000001.0], ["21000000.0000009", "2100000000000090", 2100000000000090.0], [21000000.0000009, "2100000000000090", 2100000000000090.0], ["21000000.00000009", "2100000000000009", 2100000000000009.0], [21000000.00000009, "2100000000000009", 2100000000000009.0], ["210000000.00000009", "21000000000000009", 2.100000000000001E+16], [210000000.0000001, "21000000000000009", 2.100000000000001E+16]];
     $toBTC = [["1", "0.00000001"], [1, "0.00000001"], ["29560000", "0.29560000"], [29560000, "0.29560000"], ["100000090", "1.00000090"], [100000090, "1.00000090"], ["100000009", "1.00000009"], [100000009, "1.00000009"], ["2100000000000001", "21000000.00000001"], [2100000000000001.0, "21000000.00000001"], ["2100000000000090", "21000000.00000090"], [2100000000000090.0, "21000000.00000090"], ["2100000000000009", "21000000.00000009"], [2100000000000009.0, "21000000.00000009"], ["21000000000000009", "210000000.00000009"], [2.100000000000001E+16, "210000000.00000009"], ["210000000000000009", "2100000000.00000009"], [2.1E+17, "2100000000.00000009"], ["2100000000000000009", "21000000000.00000009"], [2.1E+18, "21000000000.00000009"]];
     foreach ($toSatoshi as $i => $test) {
         $btc = $test[0];
         $satoshiString = $test[1];
         $satoshiInt = $test[2];
         $string = BlocktrailSDK::toSatoshiString($btc);
         $this->assertEquals($satoshiString, $string, "[{$i}] {$btc} => {$satoshiString} =? {$string}");
         $this->assertTrue($satoshiString === $string, "[{$i}] {$btc} => {$satoshiString} ==? {$string}");
         $int = BlocktrailSDK::toSatoshi($btc);
         $this->assertEquals($satoshiInt, $int, "[{$i}] {$btc} => {$satoshiInt} =? {$int}");
         $this->assertTrue($satoshiInt === $int, "[{$i}] {$btc} => {$satoshiInt} ==? {$int}");
     }
     foreach ($toBTC as $i => $test) {
         $satoshi = $test[0];
         $btc = $test[1];
         $this->assertEquals($btc, BlocktrailSDK::toBTC($satoshi), "[{$i}] {$satoshi} => {$btc}");
         $this->assertTrue($btc === BlocktrailSDK::toBTC($satoshi), "[{$i}] {$satoshi} => {$btc}");
     }
     $this->markTestIncomplete("@TODO: test toBTCString");
 }
<?php

use Blocktrail\SDK\BlocktrailSDK;
use Blocktrail\SDK\Connection\Exceptions\ObjectNotFound;
use Blocktrail\SDK\Wallet;
use Blocktrail\SDK\WalletInterface;
require_once __DIR__ . "/../vendor/autoload.php";
$client = new BlocktrailSDK("MY_APIKEY", "MY_APISECRET", "BTC", true, 'v1');
// $client->setVerboseErrors();
// $client->setCurlDebugging();
/**
 * @var $wallet             \Blocktrail\SDK\WalletInterface
 * @var $backupMnemonic     string
 */
try {
    /** @var Wallet $wallet */
    $wallet = $client->initWallet(["identifier" => "example-wallet", "passphrase" => "example-strong-password"]);
} catch (ObjectNotFound $e) {
    list($wallet, $primaryMnemonic, $backupMnemonic, $blocktrailPublicKeys) = $client->createNewWallet(["identifier" => "example-wallet", "passphrase" => "example-strong-password", "key_index" => 9999]);
    $wallet->doDiscovery();
}
// var_dump($wallet->deleteWebhook());
// var_dump($wallet->setupWebhook("http://www.example.com/wallet/webhook/example-wallet"));
// print some new addresses
var_dump($wallet->getAddressByPath("M/9999'/0/0"), $wallet->getAddressByPath("M/9999'/0/1"));
// print the balance
list($confirmed, $unconfirmed) = $wallet->getBalance();
var_dump($confirmed, BlocktrailSDK::toBTC($confirmed));
var_dump($unconfirmed, BlocktrailSDK::toBTC($unconfirmed));
// send a payment (will fail unless you've send some BTC to an address part of this wallet)
$addr = $wallet->getNewAddress();
 public function testBuildTx()
 {
     $client = $this->setupBlocktrailSDK();
     $wallet = $client->initWallet(["identifier" => "unittest-transaction", "passphrase" => "password"]);
     /*
      * test simple (real world TX) scenario
      */
     list($inputs, $outputs) = $wallet->buildTx((new TransactionBuilder())->spendOutput("ed6458f2567c3a6847e96ca5244c8eb097efaf19fd8da2d25ec33d54a49b4396", 0, BlocktrailSDK::toSatoshi(0.0001), "2N6DJMnoS3xaxpCSDRMULgneCghA1dKJBmT", "a9148e3c73aaf758dc4f4186cd49c3d523954992a46a87", "M/9999'/0/1537", "5221025a341fad401c73eaa1ee40ba850cc7368c41f7a29b3c6e1bbb537be51b398c4d210331801794a117dac34b72d61262aa0fcec7990d72a82ddde674cf583b4c6a5cdf21033247488e521170da034e4d8d0251530df0e0d807419792492af3e54f6226441053ae")->addRecipient("2N6DJMnoS3xaxpCSDRMULgneCghA1dKJBmT", BlocktrailSDK::toSatoshi(0.0001))->setFeeStrategy(Wallet::FEE_STRATEGY_BASE_FEE));
     $inputTotal = array_sum(array_column($inputs, 'value'));
     $outputTotal = array_sum(array_column($outputs, 'value'));
     $fee = $inputTotal - $outputTotal;
     // assert the output(s)
     $this->assertEquals(BlocktrailSDK::toSatoshi(0.0001), $inputTotal);
     $this->assertEquals(BlocktrailSDK::toSatoshi(0.0001), $outputTotal);
     $this->assertEquals(BlocktrailSDK::toSatoshi(0), $fee);
     // assert the input(s)
     $this->assertEquals(1, count($inputs));
     $this->assertEquals("ed6458f2567c3a6847e96ca5244c8eb097efaf19fd8da2d25ec33d54a49b4396", $inputs[0]['txid']);
     $this->assertEquals(0, $inputs[0]['vout']);
     $this->assertEquals("2N6DJMnoS3xaxpCSDRMULgneCghA1dKJBmT", $inputs[0]['address']);
     $this->assertEquals("a9148e3c73aaf758dc4f4186cd49c3d523954992a46a87", $inputs[0]['scriptPubKey']);
     $this->assertEquals(10000, $inputs[0]['value']);
     $this->assertEquals("M/9999'/0/1537", $inputs[0]['path']);
     $this->assertEquals("5221025a341fad401c73eaa1ee40ba850cc7368c41f7a29b3c6e1bbb537be51b398c4d210331801794a117dac34b72d61262aa0fcec7990d72a82ddde674cf583b4c6a5cdf21033247488e521170da034e4d8d0251530df0e0d807419792492af3e54f6226441053ae", $inputs[0]['redeemScript']);
     // assert the output(s)
     $this->assertEquals(1, count($outputs));
     $this->assertEquals("2N6DJMnoS3xaxpCSDRMULgneCghA1dKJBmT", $outputs[0]['address']);
     $this->assertEquals(10000, $outputs[0]['value']);
     /*
      * test trying to spend too much
      */
     $e = null;
     try {
         list($inputs, $outputs) = $wallet->buildTx((new TransactionBuilder())->spendOutput("ed6458f2567c3a6847e96ca5244c8eb097efaf19fd8da2d25ec33d54a49b4396", 0, BlocktrailSDK::toSatoshi(0.0001), "2N6DJMnoS3xaxpCSDRMULgneCghA1dKJBmT", "a9148e3c73aaf758dc4f4186cd49c3d523954992a46a87", "M/9999'/0/1537", "5221025a341fad401c73eaa1ee40ba850cc7368c41f7a29b3c6e1bbb537be51b398c4d210331801794a117dac34b72d61262aa0fcec7990d72a82ddde674cf583b4c6a5cdf21033247488e521170da034e4d8d0251530df0e0d807419792492af3e54f6226441053ae")->addRecipient("2N6DJMnoS3xaxpCSDRMULgneCghA1dKJBmT", BlocktrailSDK::toSatoshi(0.0002))->setFeeStrategy(Wallet::FEE_STRATEGY_BASE_FEE));
     } catch (\Exception $e) {
     }
     $this->assertTrue(!!$e);
     /*
      * test change
      */
     list($inputs, $outputs) = $wallet->buildTx((new TransactionBuilder())->spendOutput("ed6458f2567c3a6847e96ca5244c8eb097efaf19fd8da2d25ec33d54a49b4396", 0, BlocktrailSDK::toSatoshi(1), "2N6DJMnoS3xaxpCSDRMULgneCghA1dKJBmT", "a9148e3c73aaf758dc4f4186cd49c3d523954992a46a87", "M/9999'/0/1537", "5221025a341fad401c73eaa1ee40ba850cc7368c41f7a29b3c6e1bbb537be51b398c4d210331801794a117dac34b72d61262aa0fcec7990d72a82ddde674cf583b4c6a5cdf21033247488e521170da034e4d8d0251530df0e0d807419792492af3e54f6226441053ae")->addRecipient("2NAUFsSps9S2mEnhaWZoaufwyuCaVPUv8op", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2NE2uSqCktMXfe512kTPrKPhQck7vMNvaGK", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2NFK27bVrNfDHSrcykALm29DTi85TLuNm1A", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2N3y477rv4TwAwW1t8rDxGQzrWcSqkzheNr", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2N3SEVZ8cpT8zm6yiQphgxCL3wLfQ75f7wK", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2MyCfumM2MwnCfMAqLFQeRzaovetvpV63Pt", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2N7ZNbgb6kEPuok2L8KwAEGnHq7Y8k6XR8B", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2MtamUPcc8U12sUQ2zhgoXg34c31XRd9h2E", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2N1jJJxEHnQfdKMh2wor7HQ9aHp6KfpeSgw", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2Mx5ZJEdJus7TekzM8Jr9H2xaKH1iy4775y", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2MzzvxQNZtE4NP5U2HGgLhFzsRQJaRQouKY", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2N8inYmbUT9wM1ewvtEy6RW4zBQstgPkfCQ", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2N7TZBUcr7dTJaDFPN6aWtWmRsh5MErv4nu", BlocktrailSDK::toSatoshi(0.0001))->setChangeAddress("2N6DJMnoS3xaxpCSDRMULgneCghA1dKJBmT")->randomizeChangeOutput(false)->setFeeStrategy(Wallet::FEE_STRATEGY_BASE_FEE));
     $inputTotal = array_sum(array_column($inputs, 'value'));
     $outputTotal = array_sum(array_column($outputs, 'value'));
     $fee = $inputTotal - $outputTotal;
     // assert the output(s)
     $this->assertEquals(BlocktrailSDK::toSatoshi(1), $inputTotal);
     $this->assertEquals(BlocktrailSDK::toSatoshi(0.9999), $outputTotal);
     $this->assertEquals(BlocktrailSDK::toSatoshi(0.0001), $fee);
     $this->assertEquals(14, count($outputs));
     $this->assertEquals("2N6DJMnoS3xaxpCSDRMULgneCghA1dKJBmT", $outputs[13]['address']);
     $this->assertEquals(99860000, $outputs[13]['value']);
     /*
      * 1 input (1 * 294b) = 294b
      * 19 recipients (19 * 34b) = 646b
      *
      * size = 8b + 294b + 646b = 948b
      * + change output (34b) = 982b
      *
      * fee = 0.0001
      *
      * 1 - (19 * 0.0001) = 0.9981
      * change = 0.9980
      */
     list($inputs, $outputs) = $wallet->buildTx((new TransactionBuilder())->spendOutput("ed6458f2567c3a6847e96ca5244c8eb097efaf19fd8da2d25ec33d54a49b4396", 0, BlocktrailSDK::toSatoshi(1), "2N6DJMnoS3xaxpCSDRMULgneCghA1dKJBmT", "a9148e3c73aaf758dc4f4186cd49c3d523954992a46a87", "M/9999'/0/1537", "5221025a341fad401c73eaa1ee40ba850cc7368c41f7a29b3c6e1bbb537be51b398c4d210331801794a117dac34b72d61262aa0fcec7990d72a82ddde674cf583b4c6a5cdf21033247488e521170da034e4d8d0251530df0e0d807419792492af3e54f6226441053ae")->addRecipient("2NAUFsSps9S2mEnhaWZoaufwyuCaVPUv8op", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2NFK27bVrNfDHSrcykALm29DTi85TLuNm1A", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2N3y477rv4TwAwW1t8rDxGQzrWcSqkzheNr", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2N3SEVZ8cpT8zm6yiQphgxCL3wLfQ75f7wK", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2MyCfumM2MwnCfMAqLFQeRzaovetvpV63Pt", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2N7ZNbgb6kEPuok2L8KwAEGnHq7Y8k6XR8B", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2MtamUPcc8U12sUQ2zhgoXg34c31XRd9h2E", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2N1jJJxEHnQfdKMh2wor7HQ9aHp6KfpeSgw", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2Mx5ZJEdJus7TekzM8Jr9H2xaKH1iy4775y", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2MzzvxQNZtE4NP5U2HGgLhFzsRQJaRQouKY", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2N8inYmbUT9wM1ewvtEy6RW4zBQstgPkfCQ", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2N7TZBUcr7dTJaDFPN6aWtWmRsh5MErv4nu", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2Mw34qYu3rCmFkzZeNsDJ9aQri8HjmUZ6wY", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2MsTtsupHuqy6JvWUscn5HQ54EscLiXaPSF", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2MtR3Qa9eeYEpBmw3kLNywWGVmUuGjwRGXk", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2N6GmkegBNA1D8wbHMLZFwxMPoNRjVnZgvv", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2NBCPVQ6xX3KAVPKmGENH1eHhPwJzmN1Bpf", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2NAHY321fSVz4wKnE4eWjyLfRmoauCrQpBD", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2N2anz2GmZdrKNNeEZD7Xym8djepwnTqPXY", BlocktrailSDK::toSatoshi(0.0001))->setChangeAddress("2N6DJMnoS3xaxpCSDRMULgneCghA1dKJBmT")->randomizeChangeOutput(false)->setFeeStrategy(Wallet::FEE_STRATEGY_BASE_FEE));
     $inputTotal = array_sum(array_column($inputs, 'value'));
     $outputTotal = array_sum(array_column($outputs, 'value'));
     $fee = $inputTotal - $outputTotal;
     // assert the output(s)
     $this->assertEquals(BlocktrailSDK::toSatoshi(1), $inputTotal);
     $this->assertEquals(BlocktrailSDK::toSatoshi(0.9999), $outputTotal);
     $this->assertEquals(BlocktrailSDK::toSatoshi(0.0001), $fee);
     $this->assertEquals(20, count($outputs));
     $this->assertEquals("2N6DJMnoS3xaxpCSDRMULgneCghA1dKJBmT", $outputs[19]['address']);
     $this->assertEquals(BlocktrailSDK::toSatoshi(0.998), $outputs[19]['value']);
     /*
      * test change output bumps size over 1kb, fee += 0.0001
      *
      * 1 input (1 * 294b) = 294b
      * 20 recipients (19 * 34b) = 680b
      *
      * size = 8b + 294b + 680b = 982b
      * + change output (34b) = 1006b
      *
      * fee = 0.0002
      * input = 1.0000
      * 1.0000 - (20 * 0.0001) = 0.9980
      * change = 0.9978
      */
     list($inputs, $outputs) = $wallet->buildTx((new TransactionBuilder())->spendOutput("ed6458f2567c3a6847e96ca5244c8eb097efaf19fd8da2d25ec33d54a49b4396", 0, BlocktrailSDK::toSatoshi(1), "2N6DJMnoS3xaxpCSDRMULgneCghA1dKJBmT", "a9148e3c73aaf758dc4f4186cd49c3d523954992a46a87", "M/9999'/0/1537", "5221025a341fad401c73eaa1ee40ba850cc7368c41f7a29b3c6e1bbb537be51b398c4d210331801794a117dac34b72d61262aa0fcec7990d72a82ddde674cf583b4c6a5cdf21033247488e521170da034e4d8d0251530df0e0d807419792492af3e54f6226441053ae")->addRecipient("2NAUFsSps9S2mEnhaWZoaufwyuCaVPUv8op", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2NFK27bVrNfDHSrcykALm29DTi85TLuNm1A", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2N3y477rv4TwAwW1t8rDxGQzrWcSqkzheNr", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2N3SEVZ8cpT8zm6yiQphgxCL3wLfQ75f7wK", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2MyCfumM2MwnCfMAqLFQeRzaovetvpV63Pt", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2N7ZNbgb6kEPuok2L8KwAEGnHq7Y8k6XR8B", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2MtamUPcc8U12sUQ2zhgoXg34c31XRd9h2E", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2N1jJJxEHnQfdKMh2wor7HQ9aHp6KfpeSgw", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2Mx5ZJEdJus7TekzM8Jr9H2xaKH1iy4775y", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2MzzvxQNZtE4NP5U2HGgLhFzsRQJaRQouKY", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2N8inYmbUT9wM1ewvtEy6RW4zBQstgPkfCQ", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2N7TZBUcr7dTJaDFPN6aWtWmRsh5MErv4nu", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2Mw34qYu3rCmFkzZeNsDJ9aQri8HjmUZ6wY", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2MsTtsupHuqy6JvWUscn5HQ54EscLiXaPSF", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2MtR3Qa9eeYEpBmw3kLNywWGVmUuGjwRGXk", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2N6GmkegBNA1D8wbHMLZFwxMPoNRjVnZgvv", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2NBCPVQ6xX3KAVPKmGENH1eHhPwJzmN1Bpf", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2NAHY321fSVz4wKnE4eWjyLfRmoauCrQpBD", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2N2anz2GmZdrKNNeEZD7Xym8djepwnTqPXY", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2Mvs5ik3nC9RBho2kPcgi5Q62xxAE2Aryse", BlocktrailSDK::toSatoshi(0.0001))->setChangeAddress("2N6DJMnoS3xaxpCSDRMULgneCghA1dKJBmT")->randomizeChangeOutput(false)->setFeeStrategy(Wallet::FEE_STRATEGY_BASE_FEE));
     $inputTotal = array_sum(array_column($inputs, 'value'));
     $outputTotal = array_sum(array_column($outputs, 'value'));
     $fee = $inputTotal - $outputTotal;
     // assert the output(s)
     $this->assertEquals(BlocktrailSDK::toSatoshi(1), $inputTotal);
     $this->assertEquals(BlocktrailSDK::toSatoshi(0.9998), $outputTotal);
     $this->assertEquals(BlocktrailSDK::toSatoshi(0.0002), $fee);
     $this->assertEquals(21, count($outputs));
     $this->assertEquals("2N6DJMnoS3xaxpCSDRMULgneCghA1dKJBmT", $outputs[20]['address']);
     $this->assertEquals(BlocktrailSDK::toSatoshi(0.9978), $outputs[20]['value']);
     /*
      * test change
      *
      * 1 input (1 * 294b) = 294b
      * 20 recipients (19 * 34b) = 680b
      *
      * size = 8b + 294b + 680b = 982b
      * + change output (34b) = 1006b
      *
      * fee = 0.0001
      * input = 0.0021
      * 0.0021 - (20 * 0.0001) = 0.0001
      */
     list($inputs, $outputs) = $wallet->buildTx((new TransactionBuilder())->spendOutput("ed6458f2567c3a6847e96ca5244c8eb097efaf19fd8da2d25ec33d54a49b4396", 0, BlocktrailSDK::toSatoshi(0.0021), "2N6DJMnoS3xaxpCSDRMULgneCghA1dKJBmT", "a9148e3c73aaf758dc4f4186cd49c3d523954992a46a87", "M/9999'/0/1537", "5221025a341fad401c73eaa1ee40ba850cc7368c41f7a29b3c6e1bbb537be51b398c4d210331801794a117dac34b72d61262aa0fcec7990d72a82ddde674cf583b4c6a5cdf21033247488e521170da034e4d8d0251530df0e0d807419792492af3e54f6226441053ae")->addRecipient("2NAUFsSps9S2mEnhaWZoaufwyuCaVPUv8op", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2NFK27bVrNfDHSrcykALm29DTi85TLuNm1A", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2N3y477rv4TwAwW1t8rDxGQzrWcSqkzheNr", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2N3SEVZ8cpT8zm6yiQphgxCL3wLfQ75f7wK", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2MyCfumM2MwnCfMAqLFQeRzaovetvpV63Pt", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2N7ZNbgb6kEPuok2L8KwAEGnHq7Y8k6XR8B", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2MtamUPcc8U12sUQ2zhgoXg34c31XRd9h2E", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2N1jJJxEHnQfdKMh2wor7HQ9aHp6KfpeSgw", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2Mx5ZJEdJus7TekzM8Jr9H2xaKH1iy4775y", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2MzzvxQNZtE4NP5U2HGgLhFzsRQJaRQouKY", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2N8inYmbUT9wM1ewvtEy6RW4zBQstgPkfCQ", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2N7TZBUcr7dTJaDFPN6aWtWmRsh5MErv4nu", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2Mw34qYu3rCmFkzZeNsDJ9aQri8HjmUZ6wY", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2MsTtsupHuqy6JvWUscn5HQ54EscLiXaPSF", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2MtR3Qa9eeYEpBmw3kLNywWGVmUuGjwRGXk", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2N6GmkegBNA1D8wbHMLZFwxMPoNRjVnZgvv", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2NBCPVQ6xX3KAVPKmGENH1eHhPwJzmN1Bpf", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2NAHY321fSVz4wKnE4eWjyLfRmoauCrQpBD", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2N2anz2GmZdrKNNeEZD7Xym8djepwnTqPXY", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2Mvs5ik3nC9RBho2kPcgi5Q62xxAE2Aryse", BlocktrailSDK::toSatoshi(0.0001))->setChangeAddress("2N6DJMnoS3xaxpCSDRMULgneCghA1dKJBmT")->randomizeChangeOutput(false)->setFeeStrategy(Wallet::FEE_STRATEGY_BASE_FEE));
     $inputTotal = array_sum(array_column($inputs, 'value'));
     $outputTotal = array_sum(array_column($outputs, 'value'));
     $fee = $inputTotal - $outputTotal;
     // assert the output(s)
     $this->assertEquals(BlocktrailSDK::toSatoshi(0.0021), $inputTotal);
     $this->assertEquals(BlocktrailSDK::toSatoshi(0.002), $outputTotal);
     $this->assertEquals(BlocktrailSDK::toSatoshi(0.0001), $fee);
     $this->assertEquals(20, count($outputs));
     /*
      * test change output bumps size over 1kb, fee += 0.0001
      *  but change was < 0.0001 so better to just fee it all
      *
      * 1 input (1 * 294b) = 294b
      * 20 recipients (19 * 34b) = 680b
      *
      * input = 0.00219
      *
      * size = 8b + 294b + 680b = 982b
      * fee = 0.0001
      * 0.00219 - (20 * 0.0001) = 0.00019
      *
      * + change output (0.00009) (34b) = 1006b
      * fee = 0.0002
      * 0.00219 - (20 * 0.0001) = 0.00019
      */
     list($inputs, $outputs) = $wallet->buildTx((new TransactionBuilder())->spendOutput("ed6458f2567c3a6847e96ca5244c8eb097efaf19fd8da2d25ec33d54a49b4396", 0, BlocktrailSDK::toSatoshi(0.00219), "2N6DJMnoS3xaxpCSDRMULgneCghA1dKJBmT", "a9148e3c73aaf758dc4f4186cd49c3d523954992a46a87", "M/9999'/0/1537", "5221025a341fad401c73eaa1ee40ba850cc7368c41f7a29b3c6e1bbb537be51b398c4d210331801794a117dac34b72d61262aa0fcec7990d72a82ddde674cf583b4c6a5cdf21033247488e521170da034e4d8d0251530df0e0d807419792492af3e54f6226441053ae")->addRecipient("2NAUFsSps9S2mEnhaWZoaufwyuCaVPUv8op", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2NFK27bVrNfDHSrcykALm29DTi85TLuNm1A", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2N3y477rv4TwAwW1t8rDxGQzrWcSqkzheNr", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2N3SEVZ8cpT8zm6yiQphgxCL3wLfQ75f7wK", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2MyCfumM2MwnCfMAqLFQeRzaovetvpV63Pt", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2N7ZNbgb6kEPuok2L8KwAEGnHq7Y8k6XR8B", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2MtamUPcc8U12sUQ2zhgoXg34c31XRd9h2E", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2N1jJJxEHnQfdKMh2wor7HQ9aHp6KfpeSgw", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2Mx5ZJEdJus7TekzM8Jr9H2xaKH1iy4775y", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2MzzvxQNZtE4NP5U2HGgLhFzsRQJaRQouKY", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2N8inYmbUT9wM1ewvtEy6RW4zBQstgPkfCQ", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2N7TZBUcr7dTJaDFPN6aWtWmRsh5MErv4nu", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2Mw34qYu3rCmFkzZeNsDJ9aQri8HjmUZ6wY", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2MsTtsupHuqy6JvWUscn5HQ54EscLiXaPSF", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2MtR3Qa9eeYEpBmw3kLNywWGVmUuGjwRGXk", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2N6GmkegBNA1D8wbHMLZFwxMPoNRjVnZgvv", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2NBCPVQ6xX3KAVPKmGENH1eHhPwJzmN1Bpf", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2NAHY321fSVz4wKnE4eWjyLfRmoauCrQpBD", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2N2anz2GmZdrKNNeEZD7Xym8djepwnTqPXY", BlocktrailSDK::toSatoshi(0.0001))->addRecipient("2Mvs5ik3nC9RBho2kPcgi5Q62xxAE2Aryse", BlocktrailSDK::toSatoshi(0.0001))->setChangeAddress("2N6DJMnoS3xaxpCSDRMULgneCghA1dKJBmT")->randomizeChangeOutput(false)->setFeeStrategy(Wallet::FEE_STRATEGY_BASE_FEE));
     $inputTotal = array_sum(array_column($inputs, 'value'));
     $outputTotal = array_sum(array_column($outputs, 'value'));
     $fee = $inputTotal - $outputTotal;
     // assert the output(s)
     $this->assertEquals(BlocktrailSDK::toSatoshi(0.00219), $inputTotal);
     $this->assertEquals(BlocktrailSDK::toSatoshi(0.002), $outputTotal);
     $this->assertEquals(BlocktrailSDK::toSatoshi(0.00019), $fee);
     $this->assertEquals(20, count($outputs));
     /*
      * custom fee
      */
     list($inputs, $outputs) = $wallet->buildTx((new TransactionBuilder())->spendOutput("ed6458f2567c3a6847e96ca5244c8eb097efaf19fd8da2d25ec33d54a49b4396", 0, BlocktrailSDK::toSatoshi(0.002001), "2N6DJMnoS3xaxpCSDRMULgneCghA1dKJBmT", "a9148e3c73aaf758dc4f4186cd49c3d523954992a46a87", "M/9999'/0/1537", "5221025a341fad401c73eaa1ee40ba850cc7368c41f7a29b3c6e1bbb537be51b398c4d210331801794a117dac34b72d61262aa0fcec7990d72a82ddde674cf583b4c6a5cdf21033247488e521170da034e4d8d0251530df0e0d807419792492af3e54f6226441053ae")->addRecipient("2NAUFsSps9S2mEnhaWZoaufwyuCaVPUv8op", BlocktrailSDK::toSatoshi(0.002))->setFee(BlocktrailSDK::toSatoshi(1.0E-6))->setFeeStrategy(Wallet::FEE_STRATEGY_BASE_FEE));
     $inputTotal = array_sum(array_column($inputs, 'value'));
     $outputTotal = array_sum(array_column($outputs, 'value'));
     $fee = $inputTotal - $outputTotal;
     // assert the output(s)
     $this->assertEquals(BlocktrailSDK::toSatoshi(0.002001), $inputTotal);
     $this->assertEquals(BlocktrailSDK::toSatoshi(0.002), $outputTotal);
     $this->assertEquals(BlocktrailSDK::toSatoshi(1.0E-6), $fee);
     /*
      * multiple outputs same address
      */
     list($inputs, $outputs) = $wallet->buildTx((new TransactionBuilder())->spendOutput("ed6458f2567c3a6847e96ca5244c8eb097efaf19fd8da2d25ec33d54a49b4396", 0, BlocktrailSDK::toSatoshi(0.002), "2N6DJMnoS3xaxpCSDRMULgneCghA1dKJBmT", "a9148e3c73aaf758dc4f4186cd49c3d523954992a46a87", "M/9999'/0/1537", "5221025a341fad401c73eaa1ee40ba850cc7368c41f7a29b3c6e1bbb537be51b398c4d210331801794a117dac34b72d61262aa0fcec7990d72a82ddde674cf583b4c6a5cdf21033247488e521170da034e4d8d0251530df0e0d807419792492af3e54f6226441053ae")->addRecipient("2NAUFsSps9S2mEnhaWZoaufwyuCaVPUv8op", BlocktrailSDK::toSatoshi(0.0005))->addRecipient("2NAUFsSps9S2mEnhaWZoaufwyuCaVPUv8op", BlocktrailSDK::toSatoshi(0.0005))->setChangeAddress("2N6DJMnoS3xaxpCSDRMULgneCghA1dKJBmT")->randomizeChangeOutput(false)->setFeeStrategy(Wallet::FEE_STRATEGY_BASE_FEE));
     $inputTotal = array_sum(array_column($inputs, 'value'));
     $outputTotal = array_sum(array_column($outputs, 'value'));
     $fee = $inputTotal - $outputTotal;
     // assert the output(s)
     $this->assertEquals(BlocktrailSDK::toSatoshi(0.002), $inputTotal);
     $this->assertEquals(BlocktrailSDK::toSatoshi(0.0019), $outputTotal);
     $this->assertEquals(BlocktrailSDK::toSatoshi(0.0001), $fee);
     $this->assertEquals("2NAUFsSps9S2mEnhaWZoaufwyuCaVPUv8op", $outputs[0]['address']);
     $this->assertEquals("2NAUFsSps9S2mEnhaWZoaufwyuCaVPUv8op", $outputs[1]['address']);
 }
<?php

use Blocktrail\SDK\BlocktrailSDK;
require_once __DIR__ . "/../vendor/autoload.php";
$client = new BlocktrailSDK("YOUR_APIKEY_HERE", "YOUR_APISECRET_HERE", "BTC", true, 'v1');
$client->setupWebhook("http://rubensayshi.ngrok.com/webhook", "rubensayshi-ngrok");
$client->subscribeAddressTransactions("rubensayshi-ngrok", "2N6Fg6T74Fcv1JQ8FkPJMs8mYmbm9kitTxy");
<?php

use Blocktrail\SDK\BlocktrailSDK;
use Blocktrail\SDK\Connection\Exceptions\ObjectNotFound;
require_once __DIR__ . "/../vendor/autoload.php";
$client = new BlocktrailSDK("MY_APIKEY", "MY_APISECRET", "BTC", true, 'v1');
// $client->setVerboseErrors();
// $client->setCurlDebugging();
$primaryPrivateKey = ["tprv8ZgxMBicQKsPdMD2AYgpezVQZNi5kxsRJDpQWc5E9mxp747KgzekJbCkvhqv6sBTDErTjkWqZdY14rLP1YL3cJawEtEp2dufHxPhr1YUoeS", "m"];
$backupPublicKey = ["tpubD6NzVbkrYhZ4Y6Ny2VF2o5wkBGuZLQAsGPn88Y4JzKZH9siB85txQyYq3sDjRBFwnE1YhdthmHWWAurJu7EetmdeJH9M5jz3Chk7Ymw2oyf", "M"];
/**
 * @var $wallet             \Blocktrail\SDK\WalletInterface
 * @var $backupMnemonic     string
 */
try {
    $wallet = $client->initWallet(["identifier" => "example-wallet", "primary_private_key" => $primaryPrivateKey, "primary_mnemonic" => false]);
} catch (ObjectNotFound $e) {
    list($wallet, $primaryMnemonic, $backupMnemonic, $blocktrailPublicKeys) = $client->createNewWallet(["identifier" => "example-wallet", "primary_private_key" => $primaryPrivateKey, "backup_public_key" => $backupPublicKey, "key_index" => 9999]);
    $wallet->doDiscovery();
}
// var_dump($wallet->deleteWebhook());
// var_dump($wallet->setupWebhook("http://www.example.com/wallet/webhook/example-wallet"));
// print some new addresses
var_dump($wallet->getAddressByPath("M/9999'/0/0"), $wallet->getAddressByPath("M/9999'/0/1"));
// print the balance
list($confirmed, $unconfirmed) = $wallet->getBalance();
var_dump($confirmed, BlocktrailSDK::toBTC($confirmed));
var_dump($unconfirmed, BlocktrailSDK::toBTC($unconfirmed));
// send a payment (will fail unless you've send some BTC to an address part of this wallet)
$addr = $wallet->getNewAddress();
var_dump($wallet->pay([$addr => BlocktrailSDK::toSatoshi(0.001)]));
<?php

use Blocktrail\SDK\BackupGenerator;
use Blocktrail\SDK\BlocktrailSDK;
require_once __DIR__ . "/../vendor/autoload.php";
$client = new BlocktrailSDK("MY_APIKEY", "MY_APISECRET", "BTC", true, 'v1');
$client->setVerboseErrors(true);
//create a new wallet
$bytes = openssl_random_pseudo_bytes(10);
$identifier = bin2hex($bytes);
list($wallet, $primaryMnemonic, $backupMnemonic, $blocktrailPublicKeys) = $client->createNewWallet($identifier, "example-strong-password", $_account = 9999);
//generate the backup document
$backupGenerator = new BackupGenerator($primaryMnemonic, $backupMnemonic, $blocktrailPublicKeys);
$pdfStream = $backupGenerator->generatePDF();
//we can either save the pdf file locally
file_put_contents("my wallet backup.pdf", $pdfStream);
//or output the pdf to the browser
header("Content-type:application/pdf");
echo $pdfStream;
//html and img documents can also be generated for saving/returning to the browser
//$backupHTML = $backupGenerator->generateHTML();
//echo $backupHTML;
//$backupGenerator->generateImg('my wallet backup.png');    //save image to disk
//$backupGenerator->generateImg();                          //stream image to browser
 /**
  * @param BIP32Key          $key
  * @param string|BIP32Path  $path
  * @return string[]                 [address, redeemScript]
  * @throws \Exception
  */
 protected function getRedeemScriptFromKey(BIP32Key $key, $path)
 {
     $path = BIP32Path::path($path)->publicPath();
     $blocktrailPublicKey = $this->getBlocktrailPublicKey($path);
     $multiSig = RawTransaction::create_multisig(2, BlocktrailSDK::sortMultisigKeys([$key->buildKey($path)->publicKey(), $this->backupPublicKey->buildKey($path->unhardenedPath())->publicKey(), $blocktrailPublicKey->buildKey($path)->publicKey()]));
     return [$multiSig['address'], $multiSig['redeemScript']];
 }
<?php

use Blocktrail\SDK\BlocktrailSDK;
require_once __DIR__ . "/../vendor/autoload.php";
$client = new BlocktrailSDK("YOUR_APIKEY_HERE", "YOUR_APISECRET_HERE");
// $client->setCurlDebugging();
// GET request
echo "\n -- Get Address Data -- \n";
$address = $client->address("1dice8EMZmqKvrGE4Qc9bUFf9PX3xaYDp");
var_dump($address['address'], $address['balance'], BlocktrailSDK::toBTC($address['balance']));
// POST Request
echo "\n -- Verify Address -- \n";
$address = "16dwJmR4mX5RguGrocMfN9Q9FR2kZcLw2z";
$signature = "HPMOHRgPSMKdXrU6AqQs/i9S7alOakkHsJiqLGmInt05Cxj6b/WhS7kJxbIQxKmDW08YKzoFnbVZIoTI2qofEzk=";
$result = $client->verifyAddress($address, $signature);
var_dump($result);
// Dealing with numbers
echo "\n -- 123456789 Satoshi to BTC -- \n";
var_dump(BlocktrailSDK::toBTC(123456789));
echo "\n -- 1.23456789 BTC to Satoshi -- \n";
var_dump(BlocktrailSDK::toSatoshi(1.23456789));