/**
  * Process incomming request.
  */
 public function process($payload)
 {
     if ($payload["type"] != "address") {
         return;
     }
     $data = $payload["data"];
     if (!$data["txid"]) {
         throw new Exception("No transaction id");
     }
     if (!$data["address"]) {
         throw new Exception("No address");
     }
     if (!$data["balance_change"]) {
         throw new Exception("No amount data");
     }
     $transaction = Transaction::findOneBy("transactionHash", $data["txid"]);
     if (!$transaction) {
         $account = Account::findOneBy("depositAddress", $data["address"]);
         if (!$account) {
             throw new Exception("No matching account.");
         }
         $transaction = new Transaction();
         $transaction->notice = "Deposit";
         $transaction->transactionHash = $data["txid"];
         $transaction->toAccountId = $account->id;
         $transaction->state = Transaction::CONFIRMING;
         $transaction->amount = BitcoinUtil::toSatoshi("btc", $data["balance_change"]);
         $transaction->save();
         $account->getPubSub()->publish();
     }
     if ($transaction->getState() == Transaction::COMPLETE) {
         return;
     }
     $transaction->confirmations = intval($data["confirmations"]);
     $account = $transaction->getToAccount();
     if (!$account) {
         throw new Exception("unable to find account");
     }
     if ($transaction->confirmations >= get_option("blockchainaccounts_notifications")) {
         $account->balance += $transaction->amount;
         $account->save();
         $transaction->toAccountBalance = $account->balance;
         $transaction->timestamp = time();
         $transaction->state = Transaction::COMPLETE;
         $transaction->save();
     }
     $transaction->save();
     $account->getPubSub()->publish();
 }
 /**
  * Send to address.
  */
 public function send($address, $amount)
 {
     if (!$this->password) {
         throw new Exception("Password for block.io not set");
     }
     $curl = $this->createRequest("withdraw");
     $curl->setParam("amounts", BitcoinUtil::fromSatoshi("btc", $amount));
     $curl->setParam("to_addresses", $address);
     $curl->setParam("pin", $this->password);
     $res = $curl->exec();
     if ($res["status"] != "success") {
         error_log(print_r($res, TRUE));
         throw new Exception("Unable to contact block.io: " . $res["error_message"]);
     }
     error_log(json_encode($res, TRUE));
 }
 /**
  * Get amount.
  */
 public function getAmount($denomination)
 {
     return BitcoinUtil::fromSatoshi($denomination, $this->amount);
 }
 /**
  * Withdraw funds.
  * If withdraw processing is manual, the transaction will
  * be stored as scheduled. If withdraw processing is automatic
  * the transaction will be performed immediately.
  */
 public function withdraw($denomination, $address, $amount)
 {
     if ($amount < 0 || $amount > $this->getBalance($denomination)) {
         throw new Exception("Insufficient funds on account.");
     }
     if ($this->hasConfirming()) {
         throw new Exception("There are unconfirmed transactions for the account.");
     }
     if ($this->entity_type != "user") {
         throw new Exception("Can only withdraw from user accounts.");
     }
     $this->balance -= BitcoinUtil::toSatoshi($denomination, $amount);
     $t = new Transaction();
     $t->withdrawAddress = $address;
     $t->fromAccountId = $this->id;
     $t->fromAccountBalance = $this->balance;
     $t->setAmount($denomination, $amount);
     $t->state = Transaction::SCHEDULED;
     $t->notice = "Withdraw";
     $t->save();
     $this->save();
     if (get_option("blockchainaccounts_withdraw_processing") == "auto") {
         $t->performWithdraw();
     }
     return $t;
 }