Compare commits

...

1 Commits

Author SHA1 Message Date
BitcoinMitchell
03a4432535 dev: Added proper development setup 2026-01-21 22:55:35 +01:00
17 changed files with 927 additions and 415 deletions

View File

@ -7,20 +7,25 @@ on:
permissions: {}
jobs:
linting:
name: "Release a new ZIP"
release:
name: "Build & Publish Release"
runs-on: "ubuntu-latest"
steps:
# Checkout repository
- name: "Checkout"
uses: "actions/checkout@c2d88d3ecc89a9ef08eebf45d9637801dcee7eb5" # v6.0.0
with:
persist-credentials: false
- name: "Setup PHP, with composer and extensions"
# Setup PHP & Composer
- name: "Setup PHP with Composer and extensions"
uses: "shivammathur/setup-php@44454db4f0199b8b9685a5d763dc37cbf79108e1" # v2.36.0
with:
php-version: "8.0"
extensions: "mbstring, xml, ctype, iconv, intl, gd"
tools: "composer:v2"
tools: "composer:v2, symfony-cli"
# Cache Composer dependencies
- name: "Get composer cache directory"
id: "composer-cache"
run: 'echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT'
@ -31,17 +36,19 @@ jobs:
key: "${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}"
restore-keys: "${{ runner.os }}-composer-"
lookup-only: true
- name: "Validate composer"
run: "composer validate"
# Validate & install dependencies
- name: "Validate Composer configuration"
run: "symfony composer validate --no-interaction"
- name: "Install Composer dependencies"
run: "composer install --prefer-dist --no-progress --no-suggest --optimize-autoloader"
run: "symfony composer install --prefer-dist --no-progress --optimize-autoloader --no-interaction"
# Zip the module
- name: "Make zip"
run: "make"
# Build ZIP using Makefile
- name: "Build ZIP artifact"
run: "make build"
# Make a release from the tag and upload the zip
- name: "Create Release"
# Create GitHub Release & upload ZIP
- name: "Create GitHub Release"
id: "create_release"
uses: "softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b" # v2.5.0
env:

View File

@ -17,18 +17,24 @@ jobs:
strategy:
matrix:
php-versions: [ '8.0', '8.1' ]
steps:
# Checkout repository
- name: "Checkout"
uses: "actions/checkout@c2d88d3ecc89a9ef08eebf45d9637801dcee7eb5" # v6.0.0
with:
persist-credentials: false
# Setup PHP & Composer (with Symfony CLI)
- name: "Setup PHP, with composer and extensions"
uses: "shivammathur/setup-php@44454db4f0199b8b9685a5d763dc37cbf79108e1" # v2.36.0
with:
php-version: "${{ matrix.php-versions }}"
extensions: "mbstring, xml, ctype, iconv, intl, gd"
tools: "composer:v2"
- name: "Get composer cache directory"
tools: "composer:v2, symfony-cli"
# Cache Composer dependencies
- name: "Get Composer cache directory"
id: "composer-cache"
run: 'echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT'
- name: "Cache composer dependencies"
@ -38,11 +44,14 @@ jobs:
key: "${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}"
restore-keys: "${{ runner.os }}-composer-"
lookup-only: true
- name: "Validate composer"
run: "composer validate"
- name: "Install Composer dependencies"
run: "composer install --prefer-dist --no-progress --no-suggest --optimize-autoloader"
# Ensure our code looks proper
- name: "Lint the code"
# Validate & install dependencies
- name: "Validate Composer configuration"
run: "symfony composer validate --no-interaction"
- name: "Install Composer dependencies"
run: "symfony composer install --prefer-dist --no-progress --optimize-autoloader --no-interaction"
# Run linter
- name: "Lint codebase"
run: "make lint"

5
.gitignore vendored
View File

@ -13,8 +13,9 @@ btcpay.zip
# Ignore phpcs cache
.phpcs-cache
# Ignore developer specific docker-compose
docker-compose.override.yml
# Ignore developer specific stuff
/development/.env
/development/docker-compose.override.yml
# Ignore files in the module that are added via `make`
/modules/btcpay/LICENSE

174
Makefile
View File

@ -1,126 +1,74 @@
MODULE := "btcpay"
MODULE_FOLDER := "./modules"
# --- Variables ---
MODULE := btcpay
MODULE_FOLDER := ./modules
MODULE_PATH := $(MODULE_FOLDER)/$(MODULE)
BUILD_FOLDER := "./build"
ZIP_NAME := "${MODULE}.zip"
ZIP_DEBUG_NAME := "${MODULE}_debug.zip"
MODULE_OUT := "${BUILD_FOLDER}/${ZIP_NAME}"
BUILD_FOLDER := ./build
ZIP_NAME := $(MODULE).zip
MODULE_OUT := $(BUILD_FOLDER)/$(ZIP_NAME)
.PHONY: all build install update upgrade clean lint lint-fix
# --- Colors ---
BLUE := \033[36m
RESET := \033[0m
# --- Targets ---
.PHONY: all deps build bump update upgrade clean lint lint-fix help
all: build
build: ## Build the bastard binary file
# Installing all dependencies
@cd "$(MODULE_FOLDER)/$(MODULE)" \
&& composer install --no-dev
deps: ## Install and prepare all dependencies
@echo "$(BLUE)==> Installing dependencies...$(RESET)"
@cd "$(MODULE_PATH)" && symfony composer install
@echo "$(BLUE)==> Dumping autoloader...$(RESET)"
@cd "$(MODULE_PATH)" && symfony composer dump-autoload -o --no-dev
# Dump autoloader
@cd "$(MODULE_FOLDER)/$(MODULE)" \
&& composer dump-autoload -o --no-dev
build: deps ## Build the module and create ZIP
@echo "$(BLUE)==> Building module...$(RESET)"
@rm -f "$(MODULE_OUT)"
@mkdir -p "$(BUILD_FOLDER)"
@cp ./LICENSE "$(MODULE_PATH)"
@cp ./README.md "$(MODULE_PATH)"
@cd "$(MODULE_FOLDER)" && zip -r "$(ZIP_NAME)" "$(MODULE)" && mv "$(ZIP_NAME)" "../$(BUILD_FOLDER)"
@echo "$(BLUE)==> Build complete: $(MODULE_OUT)$(RESET)"
# Removing the old ZIP if present
@rm -f $(MODULE_OUT)
bump: ## Bump all PHP dependencies
@echo "$(BLUE)==> Bumping root dependencies...$(RESET)"
@symfony composer bump
@echo "$(BLUE)==> Bumping module dependencies...$(RESET)"
@cd "$(MODULE_PATH)" && symfony composer bump
# Make the build folder
@mkdir -p $(BUILD_FOLDER)
update: ## Update all dependencies (including dev)
@echo "$(BLUE)==> Updating root dependencies...$(RESET)"
@symfony composer update
@echo "$(BLUE)==> Updating module dependencies...$(RESET)"
@cd "$(MODULE_PATH)" && symfony composer update
# Copy the license to the module
@cp ./LICENSE "$(MODULE_FOLDER)/$(MODULE)"
upgrade: ## Upgrade all dependencies (including dev, with constraints)
@echo "$(BLUE)==> Upgrading root dependencies...$(RESET)"
@symfony composer upgrade -W
@echo "$(BLUE)==> Upgrading module dependencies...$(RESET)"
@cd "$(MODULE_PATH)" && symfony composer upgrade -W
# Copy the README to the module root and docs
@cp ./README.md "$(MODULE_FOLDER)/$(MODULE)"
@cp ./README.md "$(MODULE_FOLDER)/$(MODULE)/docs"
clean: ## Remove previous builds and vendor files
@echo "$(BLUE)==> Cleaning build artifacts...$(RESET)"
@rm -f "$(MODULE_OUT)"
@rm -rf "$(MODULE_PATH)/vendor"
@find "$(MODULE_FOLDER)" -mindepth 1 -maxdepth 1 -type d ! -name "$(MODULE)" -exec rm -rf {} +
# Zip the module
@cd $(MODULE_FOLDER) \
&& zip -r $(ZIP_NAME) $(MODULE) \
&& mv $(ZIP_NAME) "../$(BUILD_FOLDER)"
lint: ## Run linter (dry-run mode)
@echo "$(BLUE)==> Running PHP CS Fixer (dry-run)...$(RESET)"
@symfony php ./vendor/bin/php-cs-fixer fix --diff --dry-run -v
@echo "$(BLUE)==> Running PHPCS...$(RESET)"
@symfony php ./vendor/bin/phpcs -p
debug: ## Build the bastard binary file as debug file
# Installing all dependencies
@cd "$(MODULE_FOLDER)/$(MODULE)" \
&& composer install
lint-fix: ## Auto-fix linter issues
@echo "$(BLUE)==> Fixing code style with PHP CS Fixer...$(RESET)"
@symfony php ./vendor/bin/php-cs-fixer fix -v
@echo "$(BLUE)==> Running PHPCBF...$(RESET)"
@symfony php ./vendor/bin/phpcbf -p
# Dump autoloader
@cd "$(MODULE_FOLDER)/$(MODULE)" \
&& composer dump-autoload -o
# Removing the old ZIP if present
@rm -f $(MODULE_OUT)
# Make the build folder
@mkdir -p $(BUILD_FOLDER)
# Copy the license to the module
@cp ./LICENSE "$(MODULE_FOLDER)/$(MODULE)"
# Copy the README to the module
@cp ./README.md "$(MODULE_FOLDER)/$(MODULE)"
# Zip the module
@cd $(MODULE_FOLDER) \
&& zip -r $(ZIP_DEBUG_NAME) $(MODULE) \
&& mv $(ZIP_DEBUG_NAME) "../$(BUILD_FOLDER)"
bump: ## Bump all package versions
# Bump all root dependencies
@composer install
# Bump all module dependencies
@cd "$(MODULE_FOLDER)/$(MODULE)" \
&& composer install
install: ## Install everything for development
# Installing all root dependencies
@composer install
# Installing all module dependencies
@cd "$(MODULE_FOLDER)/$(MODULE)" \
&& composer install
update: ## Update all dependencies (including development)
# Upgrading all root dependencies
@composer update
# Upgrading all module dependencies
@cd "$(MODULE_FOLDER)/$(MODULE)" \
&& composer update
upgrade: ## Upgrade all dependencies (including development)
# Upgrading all root dependencies
@composer upgrade
# Upgrading all module dependencies
@cd "$(MODULE_FOLDER)/$(MODULE)" \
&& composer upgrade
clean: ## Remove previous builds
# Removing the ZIP
@rm -f $(MODULE_OUT)
# Remove the vendor
@rm -rf "$(MODULE_FOLDER)/$(MODULE)/vendor"
# Remove all unnecessary modules
@ls -d $(MODULE_FOLDER)/* | grep -v $(MODULE) | xargs rm -rf
lint: ## Lints the module
# Run PHP CS Fixer
@./vendor/bin/php-cs-fixer fix --diff --dry-run -v
# Run PHPCS
@./vendor/bin/phpcs --cache -p
# Run PHP Parallel Lint
@./vendor/bin/parallel-lint --exclude ./modules/btcpay/vendor ./modules/btcpay
lint-fix: ## Resolves linter issues
# Run PHP CS Fixer
@./vendor/bin/php-cs-fixer fix -v
# Run PHPCBF
@./vendor/bin/phpcbf --cache -p
help: ## Display this help screen
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
help: ## Show this help message
@echo "$(BLUE)Available targets:$(RESET)"
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) \
| sort \
| awk 'BEGIN {FS = ":.*?## "}; {printf " $(BLUE)%-15s$(RESET) %s\n", $$1, $$2}'

View File

@ -21,10 +21,8 @@
</div>
<div align="center">
<sub>"This is lies, my trust in you is broken, I will make you obsolete" 💚
</a>
<sub>"This is lies, my trust in you is broken, I will make you obsolete" 💚</sub>
</div>
<br/>
<p align="center">
<a href="https://github.com/btcpayserver/prestashop-plugin/issues/new/choose">Report a bug</a>
@ -36,6 +34,8 @@
---
BTCPay Servers PrestaShop plugin lets you accept Bitcoin payments directly in your PrestaShop store, with no intermediaries or fees. Secure, open-source, and easy to set up.
## 🔧 Requirements
Please ensure that you meet the following requirements before installing this plugin.
@ -50,8 +50,9 @@ Please ensure that you meet the following requirements before installing this pl
- [You've a wallet connected to your store](https://docs.btcpayserver.org/WalletSetup)
### Tested successfully
- Prestashop v8.0, v8.0.1, v8.0.4, v8.1.0, v8.1.3, v8.1.4, v8.2.1, v9.0.0
- BTCPay server v1.7.0, v1.7.3.0, v1.12.5, v1.13.0, v1.13.5, v2.1.5, v2.2.1
- BTCPay server v1.7.0, v1.7.3.0, v1.12.5, v1.13.0, v1.13.5, v2.1.5, v2.2.1
- BTCPay server v2 is supported as of module version v6.3.0.
### Multistore
@ -78,9 +79,13 @@ BTCPay Server is built and maintained entirely by volunteer contributors around
Contributors looking to help out, before opening a pull request, please join [our community chat](https://chat.btcpayserver.org/) or [start a GitHub discussion](https://github.com/btcpayserver/btcpayserver/discussions) to get early feedback, discuss the best ways to tackle the problem, and ensure there is no work duplication.
### 🔧 Development
## 🔧 Development
We recommend using [PrestaShop Kickstarter](https://github.com/PrestaShopCorp/docker-compose-kickstarter) (which supports [ngrok](https://ngrok.com/)) and a dockerized [BTCPay Server instance](https://github.com/btcpayserver/btcpayserver-docker/blob/master/Production/docker-compose.btc.yml) (or [an online testnet instance](https://testnet.demo.btcpayserver.org/)) for testing locally.
If you want to work on the plugin, it is recommended to install/use the following:
- [Symfony CLI](https://symfony.com/doc/current/setup/symfony_cli.html) is required for Makefile and makes life easier.
- [PrestaShop Flashlight](https://github.com/PrestaShop/prestashop-flashlight)
- This is a newer, maintained version of [PrestaShop Kickstarter](https://github.com/PrestaShopCorp/docker-compose-kickstarter).
- Checkout the development [README](./development/README.md) for more information.
## 🏪 PrestaShop Support

View File

@ -35,20 +35,20 @@
"composer/installers": "^1.12.0"
},
"require-dev": {
"dealerdirect/phpcodesniffer-composer-installer": "^1.0.0",
"ergebnis/composer-normalize": "^2.43.0",
"dealerdirect/phpcodesniffer-composer-installer": "^1.1.2",
"ergebnis/composer-normalize": "^2.48.2",
"ezyang/htmlpurifier": "dev-master as 4.17.0",
"friendsofphp/php-cs-fixer": "^3.4.0",
"lcobucci/jwt": "dev-3.4.6-patch as 3.4.6",
"php-parallel-lint/php-console-highlighter": "^1.0",
"php-parallel-lint/php-parallel-lint": "^1.4.0",
"phpoffice/phpspreadsheet": "^1.29.1",
"phpoffice/phpspreadsheet": "^1.30.0",
"prestashop/autoindex": "^2.1",
"prestashop/php-dev-tools": "^5",
"prestashop/prestashop": "^8.1.7",
"roave/security-advisories": "dev-latest",
"slevomat/coding-standard": "^8.15.0",
"squizlabs/php_codesniffer": "^3.10.2"
"squizlabs/php_codesniffer": "^3.13.4"
},
"replace": {
"prestashop/blockreassurance": "^5.1.4",

4
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "341828a5d3777291ef0fda5cab8c7da5",
"content-hash": "ca61b719d71fccae62dc4a0f8176af9a",
"packages": [
{
"name": "composer/installers",
@ -10341,7 +10341,7 @@
"ext-mbstring": "*",
"ext-zip": "*"
},
"platform-dev": {},
"platform-dev": [],
"platform-overrides": {
"php": "8.0"
},

13
development/.env.dist Normal file
View File

@ -0,0 +1,13 @@
# Ngrok configuration
NGROK_AUTHTOKEN=XXXXXXXXXXX
# Shop Verions
PS_VERSION=9.0.2-alpine-nginx
#PS_VERSION=9.0.0-8.1-fpm-alpine-nginx
#PS_VERSION=8.2.0-8.1-fpm-alpine
#PS_VERSION=8.1.1-8.1-fpm-alpine
#PS_VERSION=8.0.5-8.0-fpm-alpine
#PS_VERSION=8.0.5-8.1-fpm-alpine
#PS_VERSION=1.7.7.8-7.2-fpm-alpine
#PS_VERSION=1.7.8.11-7.2-fpm-alpine
#PS_VERSION=1.6.1.11-7.1-fpm-alpine

109
development/README.md Normal file
View File

@ -0,0 +1,109 @@
# BTCPayServer Plugin - Development Environment
This repository provides a development environment for this plugin, including Docker-based services and helper scripts.
## TOC
<!-- toc -->
- [Prerequisites](#prerequisites)
- [Getting Started](#getting-started)
- [Autocomplete](#autocomplete)
- [Troubleshooting](#troubleshooting)
- [Directory Structure](#directory-structure)
- [Bitcoin CLI Helper](#bitcoin-cli-helper)
- [License](#license)
<!-- tocstop -->
## Prerequisites
- [Docker](https://docs.docker.com/get-started/get-docker/) and [Docker Compose](https://docs.docker.com/compose/install) installed
## Getting Started
1. **Clone the repository:**
```sh
git clone https://github.com/btcpayserver/prestashop-plugin.git
cd prestashop-plugin
```
2. **Configure environment variables:**
- Copy `.env.dist` to `.env` and adjust values as needed:
```sh
cp development/.env.dist development/.env
# Edit development/.env as required
```
- For PrestaShop, edit `development/prestashop/prestashop.env` if needed.
3. **Choosing PrestaShop Flashlight Version:**
- The development environment uses the [PrestaShop Flashlight](https://github.com/PrestaShop/prestashop-flashlight) Docker image.
- You can select the version by setting the `PS_VERSION` variable in your `.env` file.
- For example options see commented lines in `.env.dist` or [Docker Hub](https://hub.docker.com/r/prestashop/prestashop-flashlight/tags).
- Adjust the version to match your testing needs.
4. **Start the development environment:**
```sh
cd development
docker compose up --d
```
This will pull and start all required containers (e.g., PrestaShop, MariaDB, Ngrok).
5. **Access the services:**
- PrestaShop: [http://localhost:8080](http://localhost:8080) (will redirect you to the proper Ngrok URL)
- Default username/password, see [prestashop.env](./prestashop/prestashop.env)
- BTCPay Server: [http://localhost:49392](http://localhost:49392)
- Check the logs for the proper Ngrok URL.
6. PrestaShop expects the Ngrok URL to stay the same, if it doesn't you have to stop it, remove the volume and recreate it.
## Autocomplete
- `development/autocomplete.php` provides PHP autocompletion for IDEs.
## Troubleshooting
- Ensure all environment variables are set correctly.
- Check Docker logs for errors: `docker compose logs`
- For permission issues, try running Docker as administrator.
## Directory Structure
This folder contains the following files and subfolders:
- `.env.dist`: Example environment variables for development.
- `autocomplete.php`: Helper for IDE autocompletion.
- `bitcoin-cli.sh`: Helper script to interact with Bitcoin Core inside the Docker environment.
- `docker-compose.yml`: Docker Compose file to spin up the development environment.
- `btcpayserver/`: Contains BTCPay Server-specific environment files and configs:
- `btcpayserver.env`: Environment variables for BTCPay Server container.
- `ngrok/ngrok.yml`: Contains Ngrok specific configuration.
- `prestashop/`: Contains PrestaShop-specific environment files and configs:
- `prestashop.env`: Environment variables for PrestaShop container.
## Bitcoin CLI Helper
The `development/bitcoin-cli.sh` script is a helper for interacting with the Bitcoin node running in Docker (default: regtest mode).
It wraps common `bitcoin-cli` commands for development and testing.
**Usage:**
```sh
./bitcoin-cli.sh COMMAND [ARGS]
```
**Supported commands:**
- `getnewaddress` - Generate a new Bitcoin address.
- `generatetoaddress BLOCKS ADDRESS` - Mine blocks to a specific address.
- `generate NUM_BLOCKS` - Mine a number of blocks (regtest only)
- `settxfee FEE` - Set transaction fee per kB
- `sendtoaddress ADDRESS AMOUNT` - Send funds to an address
- `getbalance` - Get wallet balance
- `listtransactions` - List recent transactions
The script automatically runs the commands inside the `bitcoind` Docker container.
## License
See [LICENSE](../LICENSE) for details.

View File

@ -1,76 +1,140 @@
#!/bin/bash
# Helper to connect to the running bitcoind (by default running regtest).
#!/usr/bin/env bash
# Enhanced Bitcoin CLI Helper for Docker-based bitcoind (regtest by default)
# Function to show usage instructions
set -euo pipefail
# Colors
RED="\033[1;31m"
GREEN="\033[1;32m"
YELLOW="\033[1;33m"
BLUE="\033[1;34m"
CYAN="\033[1;36m"
MAGENTA="\033[1;35m"
WHITE="\033[1;37m"
RESET="\033[0m"
error() { echo -e "\n${RED}[ERROR]${RESET} $*\n" >&2; }
# Defaults
CONTAINER_NAME="${BITCOIND_CONTAINER:-bitcoind}"
DATA_DIR="${BITCOIND_DATA_DIR:-/data}"
# Usage
show_usage() {
cat <<EOF
Usage: bitcoin-cli-helper COMMAND [ARGS]
echo -e "----------------------------------------"
echo -e "${MAGENTA}Bitcoin CLI Helper${RESET}\n"
echo -e "${MAGENTA}Usage:${RESET} $(basename "$0") ${BLUE}COMMAND${RESET} [ARGS...]\n"
Commands:
getnewaddress Generate a new address
generatetoaddress BLOCKS ADDRESS Generate new blocks and send the reward to the specified address
generate NUM_BLOCKS Generate a specified number of blocks
settxfee FEE Set the transaction fee for this network
sendtoaddress ADDRESS AMOUNT Send funds to an address
EOF
echo -e "${GREEN}Commands:${RESET}"
echo -e " ${GREEN}getnewaddress${RESET} Generate a new address"
echo -e " ${GREEN}generatetoaddress${RESET} ${YELLOW}BLOCKS ADDRESS${RESET} Generate blocks to address"
echo -e " ${GREEN}generate${RESET} ${YELLOW}NUM_BLOCKS${RESET} Generate NUM_BLOCKS (regtest only)"
echo -e " ${GREEN}settxfee${RESET} ${YELLOW}FEE${RESET} Set transaction fee per kB"
echo -e " ${GREEN}sendtoaddress${RESET} ${YELLOW}ADDRESS AMOUNT${RESET} Send funds to an address"
echo -e " ${GREEN}getbalance${RESET} Get wallet balance"
echo -e " ${GREEN}listtransactions${RESET} List recent transactions\n"
echo -e "${CYAN}Environment Variables:${RESET}"
echo -e " ${CYAN}BITCOIND_CONTAINER${RESET} Name of the container running bitcoind (default: ${CONTAINER_NAME})"
echo -e " ${CYAN}BITCOIND_DATA_DIR${RESET} Data directory inside the container (default: ${DATA_DIR})"
echo -e "----------------------------------------"
}
# Check if a valid command is provided
# Command Validation
VALID_COMMANDS=("getnewaddress" "generatetoaddress" "generate" "settxfee" "sendtoaddress" "getbalance" "listtransactions")
validate_command() {
local valid_commands=("getnewaddress" "generatetoaddress" "generate" "settxfee" "sendtoaddress")
local command=$1
for valid_cmd in "${valid_commands[@]}"; do
if [ "$valid_cmd" = "$command" ]; then
return 0
fi
local cmd=$1
for valid_cmd in "${VALID_COMMANDS[@]}"; do
[[ "$cmd" == "$valid_cmd" ]] && return 0
done
return 1
}
# Validate the number of arguments
if [ "$#" -lt 1 ]; then
echo "Error: Missing command."
# Argument Validators
is_positive_number() {
[[ $1 =~ ^[0-9]+$ ]]
}
is_valid_amount() {
[[ $1 =~ ^[0-9]+(\.[0-9]+)?$ ]]
}
# JSON Pretty-Print
pretty_json() {
local data="$1"
if [[ "$data" =~ ^[[:space:]]*[\{\[] ]]; then
if command -v jq >/dev/null 2>&1 && echo "$data" | jq . >/dev/null 2>&1; then
echo "$data" | jq .
elif command -v python3 >/dev/null 2>&1 && echo "$data" | python3 -m json.tool >/dev/null 2>&1; then
echo "$data" | python3 -m json.tool
elif command -v python >/dev/null 2>&1 && echo "$data" | python -m json.tool >/dev/null 2>&1; then
echo "$data" | python -m json.tool
else
echo "$data"
fi
else
echo "$data"
fi
}
# Docker Execution Wrapper
run_bitcoin_cli() {
local output
if ! output=$(docker compose exec -T "$CONTAINER_NAME" bitcoin-cli -datadir="$DATA_DIR" "$@" 2>&1); then
local msg
msg=$(echo "$output" | awk '/error message:/ {flag=1; next} flag {print}' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
if [[ -n "$msg" ]]; then
echo -e "${RED}${msg}${RESET}" >&2
else
echo -e "${RED}${output}${RESET}" >&2
fi
exit 2
else
if [[ "$output" == "true" ]]; then
echo -e "${GREEN}✅ Command executed successfully${RESET}"
else
pretty_json "$output"
fi
fi
}
# Argument Checks
if [[ $# -lt 1 ]]; then
error "Missing command."
show_usage
exit 1
fi
# Check if the provided command is valid
if ! validate_command "$1"; then
echo "Error: Invalid command."
COMMAND=$1
shift
if ! validate_command "$COMMAND"; then
error "Invalid command '$COMMAND'."
show_usage
exit 1
fi
# Execute the command with docker
if [ "$1" = "generate" ]; then
if [ "$#" -lt 2 ]; then
echo "Error: Missing number of blocks to generate."
show_usage
exit 1
fi
case "$COMMAND" in
generate)
[[ $# -lt 1 ]] && { error "Missing number of blocks."; show_usage; exit 1; }
! is_positive_number "$1" && { error "Blocks must be a positive integer."; exit 1; }
run_bitcoin_cli -generate "$1"
exit
;;
generatetoaddress)
[[ $# -lt 2 ]] && { error "Missing blocks to mine and/or address."; show_usage; exit 1; }
! is_positive_number "$1" && { error "Blocks must be a positive integer."; exit 1; }
;;
settxfee)
[[ $# -lt 1 ]] && { error "Missing transaction fee value."; show_usage; exit 1; }
! is_valid_amount "$1" && { error "Fee must be a valid number."; exit 1; }
;;
sendtoaddress)
[[ $# -lt 2 ]] && { error "Missing address and/or amount to send."; show_usage; exit 1; }
! is_valid_amount "$2" && { error "Amount must be a valid number."; exit 1; }
;;
esac
# Execute it right away, as we must pass `-`
docker exec prestashop_bitcoind bitcoin-cli -datadir="/data" -generate "$2"
exit 0
elif [ "$1" = "generatetoaddress" ]; then
if [ "$#" -lt 3 ]; then
echo "Error: Missing blocks to mine and/or address."
show_usage
exit 1
fi
elif [ "$1" = "settxfee" ]; then
if [ "$#" -lt 2 ]; then
echo "Error: Missing transaction fee value."
show_usage
exit 1
fi
elif [ "$1" = "sendtoaddress" ]; then
if [ "$#" -lt 3 ]; then
echo "Error: Missing address and/or amount to send."
show_usage
exit 1
fi
fi
# Execute the command with docker
docker exec prestashop_bitcoind bitcoin-cli -datadir="/data" "$@"
# Execute Command
run_bitcoin_cli "$COMMAND" "$@"

View File

@ -0,0 +1,2 @@
# BTCPayServer configuration
NBITCOIN_NETWORK="regtest"

View File

@ -0,0 +1,131 @@
name: prestashop
services:
# PrestaShop
prestashop:
image: prestashop/prestashop-flashlight:${PS_VERSION:-latest}
env_file: [ prestashop/prestashop.env ]
environment: { NGROK_TUNNEL_AUTO_DETECT: "http://ngrok:4040" }
depends_on:
- ngrok
- mysql
ports: [ "8000:80" ]
# MariaDB (PrestaShop Database)
mysql:
image: mariadb:lts
environment:
MYSQL_USER: prestashop
MYSQL_PASSWORD: prestashop
MYSQL_ROOT_PASSWORD: prestashop
MYSQL_DATABASE: prestashop
ports: [ "3306:3306" ]
volumes: [ "mysql_data:/var/lib/mysql" ]
healthcheck:
test: [ "CMD-SHELL", "mariadb-admin ping -h localhost -pprestashop --silent" ]
interval: 5s
retries: 10
timeout: 3s
# Ngrok (Tunnel)
ngrok:
image: ngrok/ngrok:latest
env_file: [ .env ]
ports: [ "4040:4040" ]
volumes: [ "./ngrok/ngrok.yml:/var/lib/ngrok/ngrok.yml" ]
# BTCPayServer
btcpayserver:
image: btcpayserver/btcpayserver:2.3.3
platform: linux/amd64
restart: always
env_file: [ btcpayserver/btcpayserver.env ]
environment:
BTCPAY_POSTGRES: User ID=postgres;Host=postgres;Port=5432;Application Name=btcpayserver;Database=btcpayserver${NBITCOIN_NETWORK:-regtest}
BTCPAY_EXPLORERPOSTGRES: User ID=postgres;Host=postgres;Port=5432;Application Name=btcpayserver;MaxPoolSize=80;Database=nbxplorer${NBITCOIN_NETWORK:-regtest}
BTCPAY_NETWORK: ${NBITCOIN_NETWORK:-regtest}
BTCPAY_BIND: 0.0.0.0:49392
BTCPAY_ROOTPATH: /
BTCPAY_DEBUGLOG: btcpay.log
BTCPAY_UPDATEURL: https://api.github.com/repos/btcpayserver/btcpayserver/releases/latest
BTCPAY_DOCKERDEPLOYMENT: "true"
BTCPAY_CHAINS: "btc"
BTCPAY_BTCEXPLORERURL: http://nbxplorer:32838/
ports: [ "49392:49392" ]
links:
- postgres
volumes:
- "btcpay_datadir:/datadir"
- "nbxplorer_datadir:/root/.nbxplorer"
# Bitcoin Daemon (Regtest)
bitcoind:
image: btcpayserver/bitcoin:29.1
platform: linux/amd64
environment:
BITCOIN_NETWORK: ${NBITCOIN_NETWORK:-regtest}
CREATE_WALLET: "false"
BITCOIN_WALLETDIR: "/walletdata"
BITCOIN_EXTRA_ARGS: |
rpcport=43782
rpcbind=0.0.0.0:43782
rpcallowip=0.0.0.0/0
port=39388
whitelist=0.0.0.0/0
maxmempool=500
prune=50000
ports: [ "18443:43782" ]
volumes:
- "bitcoin_datadir:/data"
- "bitcoin_wallet_datadir:/walletdata"
healthcheck:
test: [ "CMD", "bitcoin-cli", "-regtest", "-rpcconnect=127.0.0.1", "-rpcport=43782", "-rpccookiefile=/data/regtest/.cookie", "getblockchaininfo" ]
interval: 10s
retries: 20
timeout: 5s
# NBXplorer (Bitcoin Indexer)
nbxplorer:
image: nicolasdorier/nbxplorer:2.5.30-1
platform: linux/amd64
environment:
NBXPLORER_NETWORK: ${NBITCOIN_NETWORK:-regtest}
NBXPLORER_BIND: 0.0.0.0:32838
NBXPLORER_TRIMEVENTS: 10000
NBXPLORER_SIGNALFILESDIR: /datadir
NBXPLORER_POSTGRES: User ID=postgres;Host=postgres;Port=5432;Application Name=nbxplorer;MaxPoolSize=20;Database=nbxplorer${NBITCOIN_NETWORK:-regtest}
NBXPLORER_CHAINS: "btc"
NBXPLORER_BTCRPCURL: http://bitcoind:43782/
NBXPLORER_BTCNODEENDPOINT: bitcoind:39388
links:
- postgres
volumes:
- "nbxplorer_datadir:/datadir"
- "bitcoin_datadir:/root/.bitcoin"
depends_on:
postgres:
condition: service_healthy
bitcoind:
condition: service_healthy
# PostgreSQL (for BTCPay + NBXplorer)
postgres:
image: btcpayserver/postgres:13.18
platform: linux/amd64
environment: { POSTGRES_HOST_AUTH_METHOD: trust }
volumes: [ "postgres_datadir:/var/lib/postgresql/data" ]
healthcheck:
test: [ "CMD-SHELL", "pg_isready -U postgres" ]
interval: 5s
retries: 10
timeout: 3s
# Named Volumes
volumes:
btcpay_datadir:
btcpay_pluginsdir:
bitcoin_datadir:
bitcoin_wallet_datadir:
postgres_datadir:
nbxplorer_datadir:
mysql_data:

View File

@ -0,0 +1,17 @@
version: 2
region: eu
log_level: debug
web_addr: 0.0.0.0:4040
tunnels:
prestashop:
proto: http
addr: prestashop:80
inspect: true
schemes:
- https
btcpayserver:
proto: http
addr: btcpayserver:49392
inspect: true
schemes:
- https

View File

@ -0,0 +1,12 @@
# Prestashop configuration
ADMIN_MAIL=admin@prestashop.com
ADMIN_PASSWD=prestashop
DEBUG_MODE=true
PS_LANGUAGE=en
PS_COUNTRY=GB
PS_FOLDER_ADMIN=admin-dev
DUMP_ON_RESTART=true
INIT_ON_RESTART=true
INIT_SCRIPTS_ON_RESTART=true
INSTALL_MODULES_ON_RESTART=true
POST_SCRIPTS_ON_RESTART=true

View File

@ -26,11 +26,11 @@
"ext-json": "*",
"ext-mbstring": "*",
"btcpayserver/btcpayserver-greenfield-php": "^2.8.1",
"composer/semver": "^3.4.2",
"stechstudio/backoff": "^1.4"
"composer/semver": "^3.4.4",
"stechstudio/backoff": "^1.6"
},
"require-dev": {
"ergebnis/composer-normalize": "^2.43",
"ergebnis/composer-normalize": "^2.48.2",
"roave/security-advisories": "dev-latest",
"symfony/debug-bundle": "~5.4.40",
"symfony/var-dumper": "~5.4.43"

File diff suppressed because it is too large Load Diff

View File

@ -56,7 +56,6 @@
<!-- Force whitespace after a type cast -->
<rule ref="Generic.Formatting.SpaceAfterCast"/>
<rule ref="Generic.Functions.CallTimePassByReference"/>
<rule ref="Generic.Metrics.NestingLevel"/>
<!-- Forbid PHP 4 constructors -->
@ -92,6 +91,9 @@
</properties>
</rule>
<!-- Require space after language constructs -->
<rule ref="Generic.WhiteSpace.LanguageConstructSpacing"/>
<!-- Forbid comments starting with # -->
<rule ref="PEAR.Commenting.InlineComment"/>
<rule ref="PEAR.Files.IncludingFile"/>
@ -149,14 +151,28 @@
<!-- Forbid useless annotations - Git and LICENCE file provide more accurate information -->
<rule ref="SlevomatCodingStandard.Commenting.ForbiddenAnnotations">
<properties>
<property name="forbiddenAnnotations" type="array" value="@api,@author,@category,@created,@license,@package,@since,@subpackage,@version"/>
<property name="forbiddenAnnotations" type="array">
<element value="@api"/>
<element value="@author"/>
<element value="@category"/>
<element value="@created"/>
<element value="@license"/>
<element value="@package"/>
<element value="@since"/>
<element value="@subpackage"/>
<element value="@version"/>
</property>
</properties>
</rule>
<!-- Forbid useless comments -->
<rule ref="SlevomatCodingStandard.Commenting.ForbiddenComments">
<properties>
<property name="forbiddenCommentPatterns" type="array" value="~^Created by \S+\.\z~i,~^\S+ [gs]etter\.\z~i,~(\S+\s+)?constructor\.~"/>
<property name="forbiddenCommentPatterns" type="array">
<element value="~^Created by \S+\.\z~i"/>
<element value="~^\S+ [gs]etter\.\z~i"/>
<element value="~(\S+\s+)?constructor\.~"/>
</property>
</properties>
</rule>
@ -266,9 +282,6 @@
<exclude name="Squiz.Arrays.ArrayDeclaration.ValueNotAligned"/>
</rule>
<!-- Forbid duplicate properties -->
<rule ref="Squiz.Classes.DuplicateProperty"/>
<!-- Force `self::` for self-reference, force lower-case self, forbid spaces around `::` -->
<rule ref="Squiz.Classes.SelfMemberReference"/>
@ -325,9 +338,6 @@
<!-- Forbid blank line after function opening brace -->
<rule ref="Squiz.WhiteSpace.FunctionOpeningBraceSpace"/>
<!-- Require space after language constructs -->
<rule ref="Squiz.WhiteSpace.LanguageConstructSpacing"/>
<!-- Require space around logical operators -->
<rule ref="Squiz.WhiteSpace.LogicalOperatorSpacing"/>