Skip to content

Instantly share code, notes, and snippets.

@rubensayshi
Created November 22, 2014 16:08
Show Gist options
  • Select an option

  • Save rubensayshi/aaaef09db4dd3451a21b to your computer and use it in GitHub Desktop.

Select an option

Save rubensayshi/aaaef09db4dd3451a21b to your computer and use it in GitHub Desktop.
BIPs
<?php
namespace BlockTrail\SDK;
/**
* Class BIP32Path
*
* BIP32 path, does not mutate itself but returns new instance everytime
*
* @package BlockTrail\SDK
*/
class BIP32Path {
protected $path;
public function __construct($path) {
$this->path = is_array($path) ? $path : explode("/", $path);
}
/**
* increase the last level of the path by 1 and return the new path
*
* @return BIP32Path
*/
public function next() {
$path = $this->path;
$last = array_pop($path);
if ($hardened = (strpos($last, "'") !== false)) {
$last = str_replace("'", "", $last);
}
$last = (int)$last;
$last += 1;
if ($hardened) {
$last .= "'";
}
$path[] = $last;
return new static($path);
}
/**
* pop off one level of the path and return the new path
*
* @return BIP32Path
*/
public function parent() {
$path = $this->path;
array_pop($path);
if (empty($path)) {
return false;
}
return new static($path);
}
/**
* get child $child of the current path and return the new path
*
* @param $child
* @return BIP32Path
*/
public function child($child) {
$path = $this->path;
$path[] = $child;
return new static($path);
}
/**
* harden the last level of the path and return the new pat
*
* @return BIP32Path
*/
public function hardened() {
$path = $this->path;
$last = array_pop($path);
if ($hardened = (strpos($last, "'") !== false)) {
return $this;
}
$last .= "'";
$path[] = $last;
return new static($path);
}
/**
* unharden the last level of the path and return the new pat
*
* @return BIP32Path
*/
public function unhardened() {
$path = $this->path;
$last = array_pop($path);
if (!($hardened = (strpos($last, "'") !== false))) {
return $this;
}
$last = str_replace("'", "", $last);
$path[] = $last;
return new static($path);
}
/**
* change the path to be for the public key (starting with M/) and return the new pat
*
* @return BIP32Path
*/
public function publicKey() {
$path = $this->path;
if ($path[0] == "M") {
return $this;
} else if ($path[0] == "m") {
array_shift($path);
array_unshift($path, "M");
return new static($path);
} else {
return false;
}
}
/**
* get the string representation of the path
*
* @return string
*/
public function getPath() {
return implode("/", $this->path);
}
/**
* check if the last level of the path is hardened
*
* @return bool
*/
public function isHardened() {
$path = $this->path;
$last = array_pop($path);
return strpos($last, "'") !== false;
}
/**
* static method to initialize class
*
* @param $path
* @return BIP32Path
*/
public static function path($path) {
if ($path instanceof static) {
return $path;
}
return new static($path);
}
/**
* count the levels in the path (including master)
*
* @return int
*/
public function count() {
return count($this->path);
}
/**
* @return string
*/
public function __toString() {
return $this->getPath();
}
}
<?php
namespace BlockTrail\SDK;
/**
* Class BIP44
*
* BIP44 state, does not mutate itself but returns new instance everytime
*
* @package BlockTrail\SDK
*/
class BIP44 {
protected $coin;
protected $account;
protected $external;
protected $address;
public function __construct($coin = 0, $account = 0, $external = true, $address = 0) {
$this->coin = $coin;
$this->account = $account;
$this->external = (int)$external;
$this->address = $address;
}
/**
* increase the address by 1 and return new BIP44
*
* @return BIP44
*/
public function next() {
return new static($this->coin, $this->account, $this->external, ($this->address ?: 0) + 1);
}
/**
* change the account (and reset external to TRUE and account to 0) and return new BIP44
*
* @param $account
* @return BIP44
*/
public function account($account) {
return new static($this->coin, $account);
}
/**
* change to the external chain (and reset account to 0) and return new BIP44
*
* @param bool $external
* @return BIP44
*/
public function external($external = true) {
if ($external == $this->external) {
return $this;
}
return new static($this->coin, $this->account, $external);
}
/**
* change to the internal chain (and reset account to 0) and return new BIP44
*
* @param bool $internal
* @return BIP44
*/
public function internal($internal = true) {
if ($internal != $this->external) {
return $this;
}
return new static($this->coin, $this->account, !$internal);
}
/**
* change to a different address and return new BIP44
*
* @param $address
* @return BIP44
*/
public function address($address) {
if ($address == $this->address) {
return $this;
}
return new static($this->coin, $this->account, $this->external, $address);
}
/**
* reset the address counter reset to 0 and return new BIP44
*
* @return BIP44
*/
public function reset() {
return $this->address(0);
}
/**
* get the BIP32Path for the current state
*
* @return BIP32Path
*/
public function path() {
return BIP32Path::path("m/{$this->coin}'/{$this->account}'/{$this->external}/{$this->address}");
}
/**
* static method to initialize class
*
* @param int $coin
* @param int $account
* @param bool $external
* @param int $address
* @return BIP44
*/
public static function BIP44($coin = 0, $account = 0, $external = true, $address = 0) {
return new static($coin, $account, $external, $address);
}
/**
* @return string
*/
public function __toString() {
return (string)$this->path();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment