Skip to content

Commit

Permalink
full code commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Ekliptor authored and Ekliptor committed Jun 29, 2019
1 parent 48a0d76 commit c66ed05
Show file tree
Hide file tree
Showing 24 changed files with 2,700 additions and 4 deletions.
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ Homestead.json
.svn
.project
.buildpath
.settings

# Logs
logs
Expand All @@ -52,4 +53,8 @@ pids
.yarn-integrity


# PHP packages
phpqrcode

# private files
examples/example-qr.png
120 changes: 119 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,16 @@ This is a PHP library to enable [BitCoin Cash (BCH)](https://www.bitcoincash.org
You can easily use this with WordPress, Laravel and other PHP frameworks.

#### Installation
With composer (recommended):
```
composer require "ekliptor/cashp"
```

Manual installation:

1. Download the source code and include `cashp.php` from the root directory of this library.
2. Download the source of this [PHP QR-code package](https://github.com/Ekliptor/qr-code) and extract it to `src/phpqrcode`

#### Requirements
```
PHP >= 7.1
Expand All @@ -19,11 +25,123 @@ PHP >= 7.1
* generate QR codes with BCH and SLP payment URIs

## Docs
* ...
Take a look at [code examples](https://github.com/Ekliptor/cashp/tree/master/examples).

#### CashP class
##### __construct(CashpOptions $options = null)
Create the main API class.
* `CashpOptions $options` - (optional) API options (see below)

##### getRate(): ExchangeRate
Return the exchange rate API.

##### getBlockchain(): AbstractBlockchainApi
Return the Blockchain API to generate addresses, check balances, transactions,...

##### generateQrCodeForAddress(string $fileLocal, string $address, float $amountBCH, float $amountToken = 0.0, string $tokenID = ""): bool
Generate a QR code for a payment.
* `string $fileLocal` - A path on your local filesystem to store the QR code file. This should be accessible from the web if you want to display the QR code to users.
If the given file already exists it will NOT be overwritten (QR codes are meant to be generated & cached in your web temp directory).
* `string $address` - The (1-time) BCH (or SLP) address created for this payment.
* `float $amountBCH` - The amount in BCH. Can be 0 if the user pays the full amount in SLP tokens.
* `float $amountToken` - (optional) The amount of the optional token to be received.
* `string $tokenID` - (optional) The hex ID of the SLP token. Required if $amountToken > 0.
---
returns `bool` - true on success, false otherwise

##### createPaymentURI(string $address, float $amountBCH, float $amountToken = 0.0, string $tokenID = ""): string
Return a payment URI (starting with "bitcoincash:" or "simpleledger:" if $amountToken > 0) for the given $address.
* `string $address` - The receiving BCH (or SLP) address.
* `float $amountBCH` - The amount in BCH to receive.
* `float $amountToken` - (optional) The amount of SLP tokens to receive.
* `string $tokenID` - (optional) The hex ID of the SLP token. Required if $amountToken > 0.
---
returns `string`


#### CashpOptions class
A set of advanced config properties.
* `$httpAgent = null` - The HTTP implementation used to make HTTP requests.
Values: BasicHttpAgent|CurlHttpAgent|WordpressHttpAgent
Defaults to BasicHttpAgent, but you should use a better one according to your PHP setup.
* `$exchangeRateExpirationMin = 60` - How long the crawled exchange rate shall stay in cache. Currently rates are not saved beyond script execution.
* `$httpTimeoutSec = 10` - The timeout for HTTP requests to the REST API backend.
* `$blockchainApiImplementation = "BitcoinComRestApi"` - The REST API backend implementation to use. Allowed values: BitcoinComRestApi


#### ExchangeRate class
An API to get BCH exchanges rates to fiat currencies.

##### getRate(string $currency = "USD"): float
Get the current exchange rate for BCH.
* `string $currency` - A fiat currency such as USD|EUR|JPY
---
returns `float`


#### BlockchainApi class
The Blockchain API to generate addresses, check balances, transactions,...

##### static setLogger(callable $loggerFn): void
Set a logger function for errors and debug output. Use this to write to a logfile or database.
If no function is provided everything will be printed using 'echo'.
* `callable $loggerFn(string $subject, mixed $error, mixed $data = null)` - parameters of the PHP callable

##### setHttpAgent(AbstractHttpAgent $agent): void
Set a a HTTP implementation for requests (cURL, Wordpress HTTP API,...)
* `AbstractHttpAgent $agent` -

##### getConfirmationCount(string $transactionID): int
Return the number of confirmation for the given blockchain transaction ID.
* `string $transactionID`
---
returns `int` - The number of confirmations or -1 if the $transactionID doesn't exist.

##### createNewAddress(string $xPub, int $addressCount, string $hdPathFormat = '0/%d'): ?BchAddress
Creates a new address from the xPub. It will automatically increment the counter in the hdPath parameter to derive the next deterministic address.
* `string $xPub` - The extended public key. Called 'Master Public Key' in Electron Cash.
* `int $addressCount` - The number of the next address to generate a unique address. Usually this should be an incrementing integer.
* `string $hdPathFormat` - (optional) The HD path to be used for creating address children.
---
returns `BchAddress` - the address or `null` on failure

##### getTokenInfo(string $tokenID): ?SlpToken
Get general (network-wide) info about a SLP token.
* `string $tokenID` -
---
returns `SlpToken` - The token or `null` on failure

##### getAddressBalance(string $address): float
Return the BCH balance of the given address (including unconfirmed transactions).
* `string $address` - The BCH address in CashAddress format.
---
returns `float` - The balance or -1 if the address doesn't exist.

##### getAddressTokenBalance(string $address, string $tokenID): float
Return the token balance of the given SLP address (including unconfirmed transactions).
* `string $address` -
* `string $tokenID` -
---
returns `float` - The balance or -1 if the address doesn't exist.

##### getAddressDetails(string $address): ?BchAddress
Return the BCH Address with all its properties such as balance, TXIDs,...
* `string $address` - The BCH address in CashAddress format.
---
returns `BchAddress` - the address or `null` on failure

##### getSlpAddressDetails(string $address, string $tokenID): ?SlpTokenAddress
Return the SLP token details of a given address include balance, TXIDs,...
* `string $address` -
* `string $tokenID` -
---
returns `SlpTokenAddress` - The token or `null` on failure


## ToDo
* add SLP address verification
* add BadgerWallet HTML & JavaScript output
* implement more functions of the REST API


## Contact
Expand Down
102 changes: 102 additions & 0 deletions autoload.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
<?php
namespace Ekliptor\CashP;
// Copyright @Ekliptor 2016-2019
// based on: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-4-autoloader-examples.md
// and Composer ClassLoader.php https://getcomposer.org/

class AppAutoload {
const DEBUG = false;
private static $loader = null;

private $namespaceMap;
private $fallbackDirs;

public static function getAppAutoload() {
if (static::$loader !== null)
return static::$loader;

$appAutoload = new AppAutoload();
spl_autoload_register(function ($class) use ($appAutoload) {
// class only has the namespace if called from outside that namespace like: new Name1\Class()
// or within the namespace declaration, but NOT with 'use Name1;' (see composer fallbackDirsPsr4 variable)

// base directory for all our autoload classes
//$srcDir = __DIR__ . '/src/'; // set inside map.php
$classPath = str_replace('\\', '/', $class);

// closure also prevents accessing self/$this if we move this to a class
$includeFile = function($file) {
if (file_exists($file)) {
// require_once not needed. 2 classes with different names can not have the same path
// use include instead of require to throw only a warning?
require $file;
return true;
}
return false;
};

// try our known namespaces first
// composer optiizes performance by using a map of maps with the first letter of the namespace as key
$namespaceMap = $appAutoload->getNamespaceMap();
foreach ($namespaceMap as $namespace => $paths)
{
$namespacePath = str_replace('\\', '/', $namespace);
$length = strlen($namespacePath);
if (substr($classPath, 0, $length) !== $namespacePath)
continue;
foreach ($paths as $path)
{
$file = $path . substr($classPath, $length) . '.php';
if ($includeFile($file))
return;
}
}

// try the root src dir as fallback (for 'use' keyword or not registered/global namespace)
$fallbackDirs = $appAutoload->getFallbackDirs();
foreach ($fallbackDirs as $dir)
{
$file = $dir . $classPath . '.php';
if ($includeFile($file))
return;
}
if (static::DEBUG) // happens on production when we upload a new file with OPCache enabled
notifyError("Class Autoload failed", "File does not exist: $file");
});

// files to always include (config, global functions,...)
$includeFiles = require __DIR__ . '/mapFiles.php';
foreach ($includeFiles as $fileIdentifier => $file)
$appAutoload->requireFile($fileIdentifier, $file);

static::$loader = $appAutoload;
return static::$loader;
}

public function __construct() {
$this->namespaceMap = require __DIR__ . '/map.php';
// last resort for loading classes are the paths specified here (the root /src/ dir)
// we have to merge all namespace paths into this, in case $class in the callback does not hold the namespace
$this->fallbackDirs = array(__DIR__ . '/src/');
foreach ($this->namespaceMap as $namespace => $paths)
$this->fallbackDirs = array_merge($paths, $this->fallbackDirs); // try namespace paths first
}

public function getNamespaceMap() {
return $this->namespaceMap;
}

public function getFallbackDirs() {
return $this->fallbackDirs;
}

public function requireFile($fileIdentifier, $file) {
// use check via globals instead of require_once because it's faster, no context change (see Laravel autoloader)
if (empty($GLOBALS['__ekliptor_autoload_files'][$fileIdentifier])) {
require $file;
$GLOBALS['__ekliptor_autoload_files'][$fileIdentifier] = true;
}
}
}
AppAutoload::getAppAutoload();
?>
4 changes: 4 additions & 0 deletions cashp.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?php
// Include this file in your project if you are not using Composer.
include __DIR__ . '/autoload.php';
?>
41 changes: 41 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"name" : "ekliptor/cashp",
"description" : "PHP library for Bitcoin Cash (BCH) and SLP token payments",
"keywords" : [
"bitcoin",
"cryptocurrency",
"billing",
"ecommerce",
"payment"
],
"type" : "library",
"license" : "MIT",
"support" : {
"issues" : "https://github.com/Ekliptor/cashp/issues",
"source" : "https://github.com/Ekliptor/cashp"
},
"authors" : [{
"name" : "Ekliptor",
"email" : "[email protected]"
}
],
"require": {
"ekliptor/qr-code": "^1"
},
"require-dev" : {
"phpunit/phpunit" : "^8"
},
"autoload" : {
"psr-4" : {
"Ekliptor\\CashP\\" : "src/"
},
"files" : []
},
"autoload-dev" : {
"psr-4" : {
"Ekliptor\\CashP\\Tests\\" : "tests/"
}
},
"minimum-stability" : "stable",
"prefer-stable" : true
}
Loading

0 comments on commit c66ed05

Please sign in to comment.