Introduction
Welcome to the MoneroPay documentation. Here you will find information on how to deploy it and API specification.
.-"""-.
/ \
|__/\_/\__|
\ /
'-...-'
_
\('v')/
/ \
(\_ _/)
^^ ^^
- Project main repository: https://gitlab.com/moneropay/moneropay
- Matrix: https://matrix.to/#/#moneropay:kernal.eu
- GitHub mirror: https://github.com/moneropay/moneropay
- Commercial support: Contact us at info@digilol.net
Feel free to open a PR, raise an issue or request a new feature.
For related discussions join our Matrix room.
What is this?
A backend service for receiving, sending and tracking status of Monero payments.
MoneroPay provides a simple HTTP API for merchants or individuals who want to accept XMR.
MoneroPay supports optional status updates via HTTP Callbacks.
MoneroPay is not a plugin for an existing e-commerce solution. It is a standalone backend daemon that can be used for any purpose. Some use cases are:
- Online stores/e-commerce
- Donation/fundraiser websites
- ATMs
- Paid services like parking or bus ticket applications
- Shell scripts and programs for any purpose
MoneroPay utilizes:
- Monero Wallet RPC
- PostgreSQL (or SQLite)
Installation
Docker Compose
The MoneroPay repository contains docker-compose.yaml which is a complete setup of MoneroPay + PostgreSQL + monero-wallet-rpc.
Create the .env
, docker-compose.override.yaml
files from the .env.example
, docker-compose.override.yaml.example
and configure it.
cp .env.example .env
cp docker-compose.override.yaml.example docker-compose.override.yaml
vim .env
vim docker-compose.override.yaml
Create the data directory and add your wallet files.
mkdir -p data/wallet
cp wallet{,.keys} data/wallet
touch data/wallet/wallet.passwd # if your wallet is password protected, write it in this file. Else leave empty.
chown -R 1000:1000 data/wallet # change owner to prevent permission errors
Docker compose configuration expects the wallet keys file to be called
wallet.keys
. You can choose to rename your wallet keys file or change the name in thedocker-compose.yaml
file.
Now you should have 3 files under data/wallet
directory: wallet
, wallet.keys
and wallet.passwd
.
Bring it up.
docker compose up -d
You can check the logs using:
docker compose logs -f
Native
Running MoneroPay without Docker.
Prerequisites
- Go compiler
- PostgreSQL server (and an empty database)
- monero-wallet-rpc server
- A Monero wallet (view-only or full)
Compilation
git clone https://gitlab.com/moneropay/moneropay.git
cd moneropay
go build ./cmd/moneropay
Now MoneroPay help page can be checked via ./moneropay -h
Security
MoneroPay is meant to be run inside local network and should not be exposed to the public internet. If it needs to be exposed, we suggest reverse proxying using a web server. This way authentication and SSL encryption can be used to secure your connection.
Below is an example configuration for reverse proxying and enabling basic authentication on top of MoneroPay using Caddy2 web server.
/etc/caddy/Caddyfile
:
moneropay.example.net {
basicauth {
admin your_password_hash
}
reverse_proxy localhost:5000
}
Generate the your_password_hash
field using the caddy hash-password
command.
Scalability
It is possible differentiate MoneroPay instances based on their X-Moneropay-Address
HTTP header. This header contains the wallet's primary address.
Merchant workflow
Here is a sequence diagram that displays the interaction between the merchant and MoneroPay.
Table of Endpoints
Method | URI | Input |
---|---|---|
GET | /balance | |
GET | /health | |
POST | /receive | {"amount": 123000000, "description": "Stickers", "callback_url": "http://merchant"} |
GET | /receive/:address?min=&max= | |
POST | /transfer | {"destinations": [{"amount": 1337000000, "address": "47stn..."}]} |
GET | /transfer/:tx_hash |
All the amount fields are in atomic units, also known as piconero.
GET /balance
Get the entire wallet balance.
Request
curl -s -X GET "${endpoint}/balance"
Response
{
"total": 2513444800,
"unlocked": 800000000,
}
For querying received amounts to subaddresses take a look at
GET /receive/:address
endpoint.
GET /health
Check if required services are up.
Request
curl -s -X GET "${endpoint}/health"
Response
200 OK
{
"status": 200,
"services": {
"walletrpc": true,
"postgresql": true
}
}
503 Service Unavailable
{
"status": 503,
"services": {
"walletrpc": false,
"postgresql": true
}
}
POST /receive
Create a subaddress for incoming transfers.
Request
curl -s -X POST "${endpoint}/receive" \
-H 'Content-Type: application/json' \
-d '{"amount": 123000000, "description": "Server expenses", "callback_url": "http://merchant/callback/moneropay_tio2foogaaLo9olaew4o"}'
"complete"
will be set totrue
inside callback andGET /receive/:subaddress
payload, when unlocked amount is equal or more to the one specified in"amount"
.
"description"
and"callback_url"
are optional. If"callback_url"
is set, MoneroPay will send a POST request to URL specified with a payload described here.
Response
{
"address": "84WsptnLmjTYQjm52SMkhQWsepprkcchNguxdyLkURTSW1WLo3tShTnCRvepijbc2X8GAKPGxJK9hfQhLHzoKSxh7y8Yqrg",
"amount": 123000000,
"description": "Server expenses",
"created_at": "2022-07-18T11:54:49.780542861Z"
}
GET /receive/:address
View incoming transfers for a subaddress.
Request
curl -s -X GET "${endpoint}/receive/${address}?min=${min_height}&max=${max_height}"
Optionally filter
"transactions"
bymin
andmax
block height.
Response
{
"amount": {
"expected": 200000000,
"covered": {
"total": 200000000,
"unlocked": 200000000
}
},
"complete": true,
"description": "Donation to Kernal",
"created_at": "2022-07-11T19:04:24.574583Z",
"transactions": [
{
"amount": 200000000,
"confirmations": 10,
"double_spend_seen": false,
"fee": 9200000,
"height": 2402648,
"timestamp": "2022-07-11T19:19:05Z",
"tx_hash": "0c9a7b40b15596fa9a06ba32463a19d781c075120bb59ab5e4ed2a97ab3b7f33",
"unlock_time": 0,
"locked": false
}
]
}
POST /transfer
Transfer to a single or multiple recipients. If necessary, split the transfer into multiple transactions.
Request
curl -s -X POST "${endpoint}/transfer" \
-H 'Content-Type: application/json' \
-d '{"destinations": [{"amount": 1337000000, "address": "47stn..."}]}'
This transaction uses balance of the wallet's Primary Account.
Response
{
"amount": 1337000000,
"fee": 87438594,
"tx_hash": "5ca34...",
"tx_hash_list": ["5ca34...", "cf448..."],
"destinations": [
{
"amount": 1337000000,
"address": "47stn..."
}
]
}
Deprecated: TxHash (tx_hash) field will be removed the next major release (3.0.0). Please use TxHashList (tx_hash_list) instead. See here for more details.
GET /transfer/:tx_hash
Get information about transaction via its hash.
Request
curl -s -X GET "${endpoint}/transfer/${tx_hash}"
Response
{
"amount": 79990000,
"fee": 9110000,
"state": "completed",
"transfer": [
{
"amount": 79990000,
"address": "453biCQpM6oSSr7jgTwmtC9YfiXUWZY1wEfSZJD4r6rf7mPqPj8NZpp7WYpAHVq7p69SYa1B1zMN6SeRc8exYi1WEenqu2c"
}
],
"confirmations": 15,
"double_spend_seen": false,
"height": 2407445,
"timestamp": "2022-07-18T11:37:50Z",
"unlock_time": 10,
"tx_hash": "cf448effb86f24f81476c0012a6636700488e13accd91f8f43302ae90fed25ce"
}
Callback payload
MoneroPay contains a goroutine which checks for new incoming transactions every 5 seconds and sends a POST
request to "callback_url"
specified in the POST /receive
endpoint with the following payload:
{
"amount": {
"expected": 0,
"covered": {
"total": 200000000,
"unlocked": 200000000
}
},
"complete": true,
"description": "Donation to Kernal",
"created_at": "2022-07-11T19:04:24.574583Z",
"transaction": {
"amount": 200000000,
"confirmations": 10,
"double_spend_seen": false,
"fee": 9200000,
"height": 2402648,
"timestamp": "2022-07-11T19:19:05Z",
"tx_hash": "0c9a7b40b15596fa9a06ba32463a19d781c075120bb59ab5e4ed2a97ab3b7f33",
"unlock_time": 0,
"locked": false
}
}
Additionally the same data can be retrieved via
GET /receive/:address
endpoint and is encouraged to check once in a while at the higher end application in case of a downtime or failed callback delivery.
Options
The configuration parameters for MoneroPay are as follows:
$ ./moneropay -h
Usage of ./moneropay:
-bind="localhost:5000": Bind address:port for moneropayd
-config="": Path to configuration file
-log-format="pretty": Log format (pretty or json)
-poll-frequency=5s: Interval for checking new incoming and pool payments.
-postgresql="postgresql://moneropay:s3cret@localhost:5432/moneropay": PostgreSQL connection string
-rpc-address="http://localhost:18082/json_rpc": Wallet RPC server address
-rpc-password="": Password for monero-wallet-rpc
-rpc-username="": Username for monero-wallet-rpc
-sqlite="": SQLite3 connection string
-transfer-mixin=8: Number of outputs from the blockchain to mix with (0 means no mixing)
-transfer-priority=0: Set a priority for transactions
-transfer-unlock-time=10: Number of blocks before the monero can be spent (0 to not add a lock)
-zero-conf=false: Enable 0-conf mode. Sends 3 callbacks (0-conf, 1-conf, 10-conf).
These parameters are also available as environment variables. For example, --log-format
can be configured by setting LOG_FORMAT
.
0-conf
When enabled, MoneroPay sends 3 callbacks in total: 0-conf, 1-conf and unlock (default 10-conf). Support for 0-conf was added in version 2.6.0.
Set --zero-conf=true
(ZERO_CONF=true
) to enable 0 confirmation mode.