A simple, yet powerful Electrum class for PHP which allows you to receive cryptocurrency payments without any third party integrations nor KYC verification. Works with Linux, Windows and OSX installations. Latest SegWit address format is supported as well.
composer require zaczero/php-electrum-class
Get composer here - getcomposer.org
Let's start with setting up an electrum installation on your machine. Please follow the instructions at the electrum.org/#download. Alternatively if you are using Linux you can execute the following list of commands. Make sure to change the download URL to match the latest version of electrum.
# Install dependencies
sudo apt install python3-pyqt5 libsecp256k1-0 python3-cryptography
# Download package
wget https://download.electrum.org/3.3.8/Electrum-3.3.8.tar.gz
# Extract package
tar -xvf Electrum-3.3.8.tar.gz
# Install electrum command
sudo ln -s $(pwd)/Electrum-3.3.8/run_electrum /usr/bin/electrum
# Check if everything works properly
electrum help
Now you have to set the username, password and port for the RPC connection. You can do that by running those commands. Make sure that the password is hard to guess and that the port is unreachable from behind the firewall.
electrum setconfig rpcuser "user"
electrum setconfig rpcpassword "S3CR3T_password"
electrum setconfig rpcport 7777
electrum setconfig rpcuser "user" --testnet
electrum setconfig rpcpassword "S3CR3T_password" --testnet
electrum setconfig rpcport 7777 --testnet
To create the wallet execute the command:
- SegWit wallet
electrum create --segwit
- Legacy wallet
electrum create
electrum create --segwit --testnet
# or
electrum create --testnet
There are two commands you have to run in order to have our electrum daemon function properly.
# Start the daemon
electrum daemon start
# Load the wallet
electrum daemon load_wallet
Please note that you will have to load the wallet every time you start the daemon. The same applies for the autostart procedure.
# Start the daemon
electrum daemon start --testnet
# Load the wallet
electrum daemon load_wallet --testnet
The last step would be to make electrum daemon autostart itself on the system boot. You can achieve that by adding a @reboot
entry to the cron service. To edit the cron tasks execute the following command.
sudo crontab -e
Then simply create a reboot entry in a new line:
@reboot electrum daemon start; electrum daemon load_wallet
@reboot electrum daemon start --testnet; electrum daemon load_wallet --testnet
First of all make sure to require
the php-electrum-class file. Then you can initialize the class with the default constructor which requires rpcuser and rpcpassword variables. If you are planning to use the testnet please provide the testnet connection settings. Optionally you can also pass a custom rpchost and rpcport values (by default it's localhost:7777).
require_once "electrum.php";
$rpcuser = "user";
$rpcpass = "CHANGE_ME_PASSWORD";
$electrum = new Electrum($rpcuser, $rpcpass);
var_dump($electrum->getbalance());
- btc2sat(float $btc) : float
- $btc - bitcoin value
- return - satoshi value
Converts bitcoin to satoshi unit.
- sat2btc(float $sat) : float
- $sat - satoshi value
- return - bitcoin value
Converts satoshi to bitcoin unit.
- broadcast(string $tx) : string
- $tx - hex-encoded transaction
- return - transaction hash (txid)
Broadcasts the hex-encoded transaction to the network.
- getfeerate(float $fee_level = 0.5) : string
- $fee_level - transaction priority (range from 0.0 to 1.0)
- return - sat/byte fee rate
Returns recommended sat/byte fee rate for chosen priority. $fee_level = 0 means that you don't care when the transaction will be going through. You just want to save as much as possible on the fee. $fee_level = 1 means that you want to process the transaction as soon as possible.
- createnewaddress() : string
- return - new receiving address
Generates a new receiving address.
- getbalance(bool $confirmed_only = false) : float
- $confirmed_only - include only confirmed transactions
- return - confirmed account balance
This one is obvious. However please keep in mind that if you decide to include only confirmed transactions even if you send some amount from the wallet you will not see a change until the outgoing transaction gets confirmed.
- history(int $min_confirmations = 1, int $from_height = 1, &$last_height) : array
- $min_confirmations - only include transaction with X confirmations or above
- $from_height - only include transaction from block X or above
- &$last_height - returns lastly processed block height
- return - an array of receiving addresses and total transactions value
Iterates through all of the transactions which met the provided criteria and returns an array of addresses and total transaction value. Addresses are receiving addresses (not sending). Those are the same which got generated using createnewaddress()
function.
- ismine(string $address) : bool
- $address - address to check
- return - true or false
Checks if provided address is owned by the local wallet.
- payto(string $destination, float $amount, float $amount_fee = 0.0) : string
- $destination - destination address to send to
- $amount - amount to send in bitcoin unit
- $amount_fee - fee amount in bitcoin unit (0 is dynamic)
- return - hex-encoded transaction ready to broadcast
Generates and signs a new transaction with provided parameters.
- payto_max(string $destination, float $amount_fee = 0.0) : string
- $destination - destination address to send to
- $amount_fee - fee amount in bitcoin unit (0 is dynamic)
- return - hex-encoded transaction ready to broadcast
Generates and signs a new transaction with provided parameters. Sends all funds which are available.
- validateaddress(string $address) : bool
- $address - address which should be validated
- return - true or false
Checks if provided address is valid or not.
Simply use a createnewaddress() function to generate the address and save it in the database alongside with the payment amount and the customer ID for later processing. A new address shall be generated for each payment request.
require_once "electrum.php";
$rpcuser = "user";
$rpcpass = "CHANGE_ME_PASSWORD";
$electrum = new Electrum($rpcuser, $rpcpass);
$receive_address = $electrum->createnewaddress();
$price = 0.001;
// pseudo code
db_save_smart($receive_address, $price, $user_id);
render_view();
Iterate through receive_address->amount dictionary returned by history() function which contains all newly received payments. Then fetch the payment data by querying the database provided the receive_address. Add the amount to total received and then finalize the payment if total received is greater or equal than the required amount.
Finally remember to save the $last_height returned by history() function so we don't process the same block twice or more. Please note that if there are no transactions returned then the $last_height will remain the same as provided initially.
require_once "electrum.php";
$rpcuser = "user";
$rpcpass = "CHANGE_ME_PASSWORD";
$electrum = new Electrum($rpcuser, $rpcpass);
$min_confirmations = 1;
$last_height = db_load("last_height");
$from_height = $last_height + 1;
// iterate through all receive transactions
foreach ($electrum->history(
$min_confrimations,
$from_height,
$last_height) as $receive_address => $amount) {
// fetch data by receive_address as a unique key
db_where("receive_address", $receive_address);
$price = db_load("price");
$user_id = db_load("user_id");
$amount_paid = db_load("amount_paid");
$completed = db_load("completed");
$amount_paid += $amount;
// check if user paid the total amount
if ($amount_paid >= $price && !$completed) {
deliver_product($user_id);
db_where("receive_address", $receive_address);
db_save("amount_paid", $amount_paid);
db_save("completed", true);
}
else {
// wait for more money or already delivered
db_where("receive_address", $receive_address);
db_save("amount_paid", $amount_paid);
}
}
// we have to store the last_height to make sure
// we don't process the same transaction twice
db_save($last_height);
require_once "electrum.php";
$rpcuser = "user";
$rpcpass = "CHANGE_ME_PASSWORD";
$electrum = new Electrum($rpcuser, $rpcpass);
// generate transaction for sending all available funds
$tx = $electrum->payto_max("BTC_ADDRESS");
// and broadcast it to the network
$txid = $electrum->broadcast($tx);
// browse the transaction on blockchair.com
$redirect_url = "https://blockchair.com/bitcoin/transaction/".$txid;
header("Location: ".$redirect_url);
require_once "electrum.php";
$rpcuser = "user";
$rpcpass = "CHANGE_ME_PASSWORD";
$electrum = new Electrum($rpcuser, $rpcpass);
// get recommended fee rate as sat/byte
// you can hard-code this value (eg. 1 will be 1 sat/byte)
$fee_rate = $electrum->getfeerate(0.3);
// generate a temporary transaction to estaminate the size
// we don't broadcast it, just use for calculations
$tx_tmp = $electrum->payto("BTC_ADDRESS", 0.2);
// calculate a fee rate in bitcoin for given transaction
// we divide by two because tx is hex-encoded this means 2 chars = 1 byte
$fee = $electrum->sat2btc($fee_rate * strlen($tx_tmp) / 2);
// send 0.2 BTC and include the bitcoin fee as a third parameter
$tx = $electrum->payto("BTC_ADDRESS", 0.2, $fee);
$txid = $electrum->broadcast($tx);
// browse the transaction on blockchair.com
$redirect_url = "https://blockchair.com/bitcoin/transaction/".$txid;
header("Location: ".$redirect_url);
- Email: kamil@monicz.pl