Pushing initial attempt at a docs site

This commit is contained in:
Lee *!* Clagett
2026-03-16 23:38:11 -04:00
parent fe3f4099bb
commit b3ac47705b
19 changed files with 2609 additions and 189 deletions
+29
View File
@@ -0,0 +1,29 @@
name: docs
on:
push:
branches: [ "master" ]
paths: [ "docs/**" ]
pull_request:
branches: [ "develop" ]
paths: [ "docs/**" ]
jobs:
deploy:
steps:
- name: Checkout LWS Source
uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v6
- name: Install dependencies
run: |
python3 -m pip install --upgrade pip
python3 -m pip install mkdocs
python3 -m pip install mkdocs-swagger-ui-tag
python3 -m pip install mkdocs-schema-reader
python3 mkdocs build
- name: Deploy
uses: peaceiris/actions-gh-pages@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./site
+1
View File
@@ -0,0 +1 @@
<swagger-ui src="admin.yaml" />
+941
View File
@@ -0,0 +1,941 @@
openapi: 3.0.4
info:
title: monero-lws Admin API
description: |-
This document describes the admin API for the [monero-lws](https://github.com/vtnerd/monero-lws) project.
An admin account can be created running the executable `monero-lws-admin create_admin` only (this command is not available via REST for security purposes). The key value returned in the create_admin JSON object becomes the `auth` parameter in the admin REST API. A new admin account is put into the hidden state - the account is not scanned for transactions and is not available to the normal REST API, but is available to the admin REST API.
version: 1.0.0
tags:
- name: account
description: Account administration
- name: webhook
description: Webhook administration
paths:
/accept_requests:
post:
tags:
- account
summary: Accept import+create account requests
description: |
This endpoint can perform two account actions:
* Accept new wallets requests created with the `/login` endpoint of the LWS client API.
* Accept "import" (from earlier block height) wallet requests created with the `/import_wallet_request` endpoint of the LWS client API.
operationId: accept_requests
requestBody:
content:
application/json:
schema:
type: object
properties:
params:
type: object
properties:
type:
type: string
enum:
- import
- create
addresses:
type: array
items:
$ref: '#/components/schemas/base58-address'
required:
- type
- addresses
allOf:
- $ref: '#/components/schemas/auth'
required:
- params
required: true
responses:
'200':
description: Success
content:
application/json:
schema:
$ref: '#/components/schemas/updated'
'400':
description: Invalid JSON.
'403':
description: Invalid `auth` parameter
'405':
description: Not `POST` method.
'500':
description: Invalid JSON schema, and all other general errors.
'503':
description: Unable to read or write from database.
/add_account:
post:
tags:
- account
summary: Add a new (client) account
description: Add a new account to be used by the client API.
operationId: add_account
requestBody:
content:
application/json:
schema:
type: object
properties:
params:
type: object
properties:
address:
$ref: '#/components/schemas/base58-address'
key:
description: The view-key corresponding to `address`
allOf:
- $ref: '#/components/schemas/binary32'
required:
- address
- key
allOf:
- $ref: '#/components/schemas/auth'
required:
- params
required: true
responses:
'200':
description: Success
content:
application/json:
schema:
$ref: '#/components/schemas/updated'
'400':
description: Invalid JSON.
'403':
description: Invalid `auth` parameter
'405':
description: Not `POST` method.
'500':
description: Invalid JSON schema, invalid key/address pair, and all other general errors.
'503':
description: Unable to read or write from database.
/list_accounts:
post:
tags:
- account
summary: List all accounts
operationId: list_accounts
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/auth'
required: true
responses:
'200':
description: Success
content:
application/json:
schema:
type: object
properties:
active:
description: Accounts that are being scanned and viewable in the client API
allOf:
- $ref: '#/components/schemas/account'
inactive:
description: Accounts that are _not_ being scanned, but are viewable in the client API
allOf:
- $ref: '#/components/schemas/account'
hidden:
description: Accounts that are neither being scanned nor viewable in the client API. This includes `auth` accounts that access the admin API.
allOf:
- $ref: '#/components/schemas/account'
'400':
description: Invalid JSON.
'403':
description: Invalid `auth` parameter
'405':
description: Not `POST` method.
'500':
description: Invalid JSON schema, and all other general errors.
'503':
description: Unable to read from database.
/list_requests:
post:
tags:
- account
summary: List all pending create+import requests
operationId: list_requests
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/auth'
required: true
responses:
'200':
description: Success
content:
application/json:
schema:
type: object
properties:
create:
$ref: '#/components/schemas/account-request'
import:
$ref: '#/components/schemas/account-request'
'400':
description: Invalid JSON.
'403':
description: Invalid `auth` parameter
'405':
description: Not `POST` method.
'500':
description: Invalid JSON schema, and all other general errors.
'503':
description: Unable to read from database.
/modify_account_status:
post:
tags:
- account
summary: Move account(s) to another state.
description: |
An account can have 3 states:
* `active`: Accounts that are being scanned and viewable in the client API
* `inactive`: Accounts that are _not_ being scanned, but are viewable in the client API
* `hidden`: Accounts that are neither being scanned nor viewable in the client API.
operationId: modify_account_status
requestBody:
content:
application/json:
schema:
type: object
properties:
params:
type: object
properties:
status:
type: string
enum:
- active
- inactive
- hidden
addresses:
type: array
items:
$ref: '#/components/schemas/base58-address'
required:
- status
- addresses
allOf:
- $ref: '#/components/schemas/auth'
required:
- params
required: true
responses:
'200':
description: Success
content:
application/json:
schema:
$ref: '#/components/schemas/updated'
'400':
description: Invalid JSON.
'403':
description: Invalid `auth` parameter
'405':
description: Not `POST` method.
'500':
description: Invalid JSON schema, and all other general errors.
'503':
description: Unable to read or write from database.
/reject_requests:
post:
tags:
- account
summary: Reject import+create account requests
description: |
This endpoint can perform two account actions:
* Reject new wallets requests created with the `/login` endpoint of the LWS client API.
* Reject "import" (from earlier block height) wallet requests created with the `/import_wallet_request` endpoint of the LWS client API.
operationId: reject_requests
requestBody:
content:
application/json:
schema:
type: object
properties:
params:
type: object
properties:
type:
type: string
enum:
- import
- create
addresses:
type: array
items:
$ref: '#/components/schemas/base58-address'
required:
- type
- addresses
allOf:
- $ref: '#/components/schemas/auth'
required:
- params
required: true
responses:
'200':
description: Success
content:
application/json:
schema:
$ref: '#/components/schemas/updated'
'400':
description: Invalid JSON.
'403':
description: Invalid `auth` parameter
'405':
description: Not `POST` method.
'500':
description: Invalid JSON schema, and all other general errors.
'503':
description: Unable to read or write from database.
/rescan:
post:
tags:
- account
summary: Force account(s) rescan from specific block height
operationId: rescan
requestBody:
content:
application/json:
schema:
type: object
properties:
params:
type: object
properties:
height:
$ref: '#/components/schemas/uint64'
addresses:
type: array
items:
$ref: '#/components/schemas/base58-address'
required:
- height
- addresses
allOf:
- $ref: '#/components/schemas/auth'
required:
- params
required: true
responses:
'200':
description: Success
content:
application/json:
schema:
$ref: '#/components/schemas/updated'
'400':
description: Invalid JSON.
'403':
description: Invalid `auth` parameter
'405':
description: Not `POST` method.
'500':
description: Invalid JSON schema, and all other general errors.
'503':
description: Unable to read or write from database.
/validate:
post:
summary: Validate components of a Monero wallet
operationId: validate
requestBody:
content:
application/json:
schema:
type: object
properties:
params:
type: object
properties:
spend_public_hex:
$ref: '#/components/schemas/binary32'
view_public_hex:
$ref: '#/components/schemas/binary32'
view_key_hex:
$ref: '#/components/schemas/binary32'
required:
- spend_public_hex
- view_public_hex
- view_key_hex
allOf:
- $ref: '#/components/schemas/auth'
required:
- params
required: true
responses:
'200':
description: Success
content:
application/json:
schema:
oneOf:
- type: object
properties:
address:
$ref: '#/components/schemas/base58-address'
required:
- address
- type: object
properties:
error:
type: object
properties:
field:
type: string
enum:
- spend_public_hex
- view_public_hex
- view_key_hex
details:
type: string
required:
- field
- details
required:
- error
'400':
description: Invalid JSON.
'403':
description: Invalid `auth` parameter
'405':
description: Not `POST` method.
'500':
description: Invalid JSON schema, and all other general errors.
/webhook_add:
post:
tags:
- webhook
summary: List all pending create+import requests
operationId: webhook_add
requestBody:
content:
application/json:
schema:
type: object
properties:
params:
oneOf:
- type: object
properties:
type:
type: string
enum:
- tx-confirmation
- tx-spend
url:
$ref: '#/components/schemas/webhook-url'
address:
$ref: '#/components/schemas/base58-address'
payment_id:
$ref: '#/components/schemas/payment-id'
token:
type: string
minLength: 1
confirmations:
$ref: '#/components/schemas/uint32'
required:
- type
- url
- address
- type: object
properties:
type:
type: string
enum:
- new-account
url:
$ref: '#/components/schemas/webhook-url'
token:
type: string
minLength: 1
required:
- type
- url
allOf:
- $ref: '#/components/schemas/auth'
required:
- params
required: true
responses:
'200':
description: Success
content:
application/json:
schema:
$ref: '#/components/schemas/webhook-value'
'400':
description: Invalid JSON.
'403':
description: Invalid `auth` parameter
'405':
description: Not `POST` method.
'500':
description: Invalid JSON schema, invalid URL, and all other general errors.
'503':
description: Unable to read or write from database.
callbacks:
onEvent:
'{$requestBody.params.url}':
post:
requestBody:
content:
application/json:
schema:
oneOf:
- type: object
description: Sent on tx-confirmation events
properties:
payment_id:
$ref: '#/components/schemas/payment-id'
token:
description: "The same token passed in the initial request"
type: string
confirmations:
$ref: '#/components/schemas/uint32'
event_id:
$ref: '#/components/schemas/uuid'
tx_info:
$ref: '#/components/schemas/tx-output'
required:
- payment_id
- token
- confirmations
- event_id
- tx_info
- type: object
description: Sent on tx-spend events
properties:
token:
description: "The same token passed in the initial request"
type: string
event_id:
$ref: '#/components/schemas/uuid'
tx_info:
$ref: '#/components/schemas/tx-spend'
required:
- token
- event_id
- tx_info
- type: object
description: Sent on new-account events
properties:
token:
description: "The same token passed in the initial request"
type: string
event_id:
$ref: '#/components/schemas/uuid'
address:
$ref: '#/components/schemas/base58-address'
required:
- token
- event_id
- address
responses:
201:
description: On success
/webhook_delete:
post:
tags:
- webhook
summary: Delete webhooks associated with Monero address(es)
operationId: webhook_delete
requestBody:
content:
application/json:
schema:
type: object
properties:
params:
type: object
properties:
addresses:
type: array
items:
$ref: '#/components/schemas/base58-address'
required:
- addresses
allOf:
- $ref: '#/components/schemas/auth'
required:
- params
required: true
responses:
'200':
description: Success
content:
application/json:
schema:
type: object
'400':
description: Invalid JSON.
'403':
description: Invalid `auth` parameter
'405':
description: Not `POST` method.
'500':
description: Invalid JSON schema, and all other general errors.
'503':
description: Unable to read or write from database.
/webhook_delete_uuid:
post:
tags:
- webhook
summary: Delete webhooks associated with UUID(s)
operationId: webhook_delete_uuid
requestBody:
content:
application/json:
schema:
type: object
properties:
params:
type: object
properties:
event_ids:
type: array
items:
$ref: '#/components/schemas/uuid'
required:
- event_ids
allOf:
- $ref: '#/components/schemas/auth'
required:
- params
required: true
responses:
'200':
description: Success
content:
application/json:
schema:
type: object
'400':
description: Invalid JSON.
'403':
description: Invalid `auth` parameter
'405':
description: Not `POST` method.
'500':
description: Invalid JSON schema, and all other general errors.
'503':
description: Unable to read or write from database.
/webhook_list:
post:
tags:
- webhook
summary: List all registered webhooks
operationId: webhook_list
requestBody:
content:
application/json:
schema:
type: object
allOf:
- $ref: '#/components/schemas/auth'
required:
- params
required: true
responses:
'200':
description: Success
content:
application/json:
schema:
type: object
properties:
webhooks:
type: object
properties:
key:
type: object
properties:
user:
$ref: '#/components/schemas/uint32'
type:
type: string
enum:
- tx-confirmation
- tx-send
- new-account
value:
$ref: '#/components/schemas/webhook-value'
required:
- key
- value
required:
- webhooks
'400':
description: Invalid JSON.
'403':
description: Invalid `auth` parameter
'405':
description: Not `POST` method.
'500':
description: Invalid JSON schema, and all other general errors.
'503':
description: Unable to read from database.
components:
schemas:
uint16:
type: integer
minimum: 0
maximum: 65535
uint32:
type: integer
minimum: 0
maximum: 4294967295
int64:
type: integer
minimum: -9223372036854775808
maximum: 9223372036854775807
uint64:
type: integer
minimum: 0
maximum: 18446744073709551615
timestamp:
description: Seconds since Unix epoch (1970-01-01 00:00:00)
allOf:
- $ref: '#/components/schemas/int64'
base58-address:
type: string
description: "Standard Monero address in base58"
minLength: 95
maxLength: 95
pattern: "^[0-9A-Za-z]{95}$"
example: "47nPhxp2cJeKN2NjamupNUNA13XgzcYPzQBCzzsKcj717s8M2UpFVmmdwSuYwgyy8kPDwU7hpEqTTDvfe5LAb9Aj6nwmEzf"
binary:
type: string
description: "binary data as hex (arbitrary length)"
pattern: "^([0-9A-Fa-f]{2})+$"
example: "0abcd9dcf0bca63310bb4d7e120918d1"
binary8:
type: string
description: "8-bytes binary data as hex"
minLength: 16
maxLength: 16
pattern: "^[0-9A-Fa-f]{16}$"
example: "6d26cac5c9d74f4e"
binary16:
type: string
description: "16-bytes binary data as hex"
minLength: 32
maxLength: 32
pattern: "^[0-9A-Fa-f]{32}$"
example: "67adfa30c9504e12955b9ae3ad3cd53b"
binary32:
type: string
description: "32-bytes binary data as hex"
minLength: 64
maxLength: 64
pattern: "^[0-9A-Fa-f]{64}$"
example: "ee171270296bbc26d5be4455b6313e1a2086a92080e205f77d6f861f8e5fd205"
payment-id:
$ref: '#/components/schemas/binary8'
uuid:
description: "A randomly generated, _unique_, UUID"
allOf:
- $ref: '#/components/schemas/binary16'
webhook-url:
description: A HTTP address OR `zmq` to indicate the notification happens over ZMQ PUB/SUB only.
type: string
pattern: "^(zmq|http://.+|https://.+)$"
auth:
type: object
properties:
auth:
description: |
A key generated via `./monero-lws-admin create_admin`. Not needed if server is started with `--disable-admin-auth`.
allOf:
- $ref: '#/components/schemas/binary32'
address-meta:
description: Subaddress index
type: object
properties:
maj_i:
$ref: '#/components/schemas/uint32'
min_i:
$ref: '#/components/schemas/uint32'
required:
- maj_i
- min_i
updated:
description: List of updated addresses
type: object
properties:
updated:
type: array
items:
$ref: '#/components/schemas/base58-address'
required:
- updated
account:
type: object
properties:
address:
$ref: '#/components/schemas/base58-address'
scan_height:
$ref: '#/components/schemas/uint64'
access_time:
$ref: '#/components/schemas/timestamp'
required:
- address
- scan_height
- access_time
account-request:
type: object
properties:
address:
$ref: '#/components/schemas/base58-address'
start_height:
$ref: '#/components/schemas/uint64'
required:
- address
- start_height
tx-output-id:
description: Blockchain unique identifier for the output. Changes on reorg.
type: object
properties:
high:
$ref: '#/components/schemas/uint32'
low:
$ref: '#/components/schemas/uint32'
required:
- high
- low
tx-spend-meta:
type: object
properties:
id:
$ref: '#/components/schemas/tx-output-id'
amount:
$ref: '#/components/schemas/uint64'
mixin:
$ref: '#/components/schemas/uint32'
index:
description: Index within vout, required for calculating spend key
allOf:
- $ref: '#/components/schemas/uint32'
tx_public:
description: The ephermal key used for the ECDH portion of transaction scanning
allOf:
- $ref: '#/components/schemas/binary32'
required:
- id
- amount
- mixin
- index
- tx_public
tx-output:
type: object
allOf:
- $ref: '#/components/schemas/tx-spend-meta'
properties:
block:
$ref: '#/components/schemas/uint64'
timestamp:
$ref: '#/components/schemas/timestamp'
tx_hash:
$ref: '#/components/schemas/binary32'
tx_prefix_hash:
$ref: '#/components/schemas/binary32'
rct_mask:
description: The encrypted ringct mask associated with output
allOf:
- $ref: '#/components/schemas/binary32'
payment_id:
$ref: '#/components/schemas/payment-id'
unlock_time:
$ref: '#/components/schemas/uint64'
mixin_count:
$ref: '#/components/schemas/uint32'
coinbase:
type: boolean
pub:
description: The unique public key for the output (which must be used in signature for spending)
allOf:
- $ref: '#/components/schemas/binary32'
recipient:
$ref: '#/components/schemas/address-meta'
required:
- block
- timestamp
- tx_hash
- tx_prefix_hash
- unlock_time
- mixin_count
- coinbase
- pub
- recipient
tx-spend:
type: object
properties:
input:
type: object
properties:
height:
$ref: '#/components/schemas/uint64'
tx_hash:
$ref: '#/components/schemas/binary32'
image:
$ref: '#/components/schemas/binary32'
source:
$ref: '#/components/schemas/tx-output-id'
timestamp:
$ref: '#/components/schemas/timestamp'
unlock_time:
$ref: '#/components/schemas/uint64'
mixin_count:
$ref: '#/components/schemas/uint32'
payment_id:
$ref: '#/components/schemas/payment-id'
sender:
$ref: '#/components/schemas/address-meta'
required:
- height
- tx_hash
- image
- source
- timestamp
- unlock_time
- mixin_count
- sender
output:
$ref: '#/components/schemas/tx-spend-meta'
required:
- input
- source
webhook-value:
type: object
properties:
event_id:
$ref: '#/components/schemas/uuid'
payment_id:
description: The `payment_id` sent in the request or all zeroes.
allOf:
- $ref: '#/components/schemas/payment-id'
token:
description: The token sent in the request or empty string.
type: string
confirmations:
description: The confirmations value sent in the request or `1`.
allOf:
- $ref: '#/components/schemas/uint32'
url:
description: The URL sent in the request.
allOf:
- $ref: '#/components/schemas/webhook-url'
required:
- event_id
- payment_id
- token
- confirmations
- url
+2 -2
View File
@@ -1,5 +1,5 @@
# monero-lws RabbitMQ Usage
Monero-lws uses RabbitMQ to provide JSON notifications of payment_id
# RabbitMQ
`monero-lws-daemon` uses RabbitMQ to provide JSON notifications of payment_id
(web)hooks. The feature is optional - by default LWS is _not_ compiled with
RabbitMQ support. The cmake option -DWITH_RMQ=ON must be specified during the
configuration stage to enable the feature.
+1
View File
@@ -0,0 +1 @@
<swagger-ui src="wallet.yaml" />
+1210
View File
File diff suppressed because it is too large Load Diff
+154
View File
@@ -0,0 +1,154 @@
# Webhooks / ZeroMQ
monero-lws can report scanner events via HTTP/1.1 webhooks or ZeroMQ PUB/SUB.
The ZeroMQ PUB is distinct from the `monerod` PUB socket;
`monero-lws-daemon --zmq-pub` creates a socket just for `monero-lws-daemon`
scanner updates. Webhooks can be "http" or "https" - the latter performing
standard system certificate authority checks (self-signed certificates NOT
allowed).
Events are ALWAYS published over ZMQ-PUB, whereas webhooks are only used when
a specific URL is given to `/webhook_add`. If the provided URL is `zmq` then
only ZMQ-PUB is used to push the event. All other URLs must start with
`http://` or `https://` as per [admin api spec](/api/admin).
## Registration
Registering for events requires `/webhook_add` from the
[admin api](/api/admin). Examples and full schema are provided on that page.
## Events
Every callback for an event has this structure:
```json
{
"index": 0,
"event": {...}
}
```
The `index` field is per event type, and tracks the number of events in that
type. This is useful only for ZeroMQ, where events can be dropped.
### Payments
A payment event occurs from 0-confirmations up to the user requested number of
confirmations. A payment event, even when using ZeroMQ, only occurs when one is
registered via `/webhook_add`. Payment registerations can only be done on
primary addresses and optionally a payment id. Registering a primary address
automatically registers all subaddresses; specifying a payment id only
registers that payment id. Leaving the payment id field blank during
registeration enables hooks from all payment ids.
The relevant topics for ZeroMQ-PUB are: `json-full-payment_hook`, and
`msgpack-full-payment_hook`.
Example payload of a webhook callback:
```json
{
"index": 2,
"event": {
"event": "tx-confirmation",
"payment_id": "4f695d197f2a3c54",
"token": "single zmq wallet",
"confirmations": 1,
"event_id": "3894f98f5dd54af5857e4f8a961a4e57",
"tx_info": {
"id": {
"high": 0,
"low": 5666768
},
"block": 2265961,
"index": 1,
"amount": 3117324236131,
"timestamp": 1687301600,
"tx_hash": "ef3187775584351cc5109de124b877bcc530fb3fdbf77895329dd447902cc566",
"tx_prefix_hash": "064884b8a8f903edcfebab830707ed44b633438b47c95a83320f4438b1b28626",
"tx_public": "54dce1a6eebafa2fdedcea5e373ef9de1c3d2737ae9f809e80958d1ba4590d74",
"rct_mask": "4cdc4c4e340aacb4741ba20f9b0b859242ecdad2fcc251f71d81123a47db3400",
"payment_id": "4f695d197f2a3c54",
"unlock_time": 0,
"mixin_count": 15,
"coinbase": false
}
}
}
```
### Spends
All of the information in the [payments](#payments) section is relevant to
here, except instead of payment confirmations, spend confirmations are
published. The relevant ZeroMQ-PUB topics are: `json-full-spend_hook` and
`msgpack-full_spend_hook`. Example payload of a webhook callback:
```json
{
"index": 0,
"event": {
"event": "tx-spend",
"token": "spend-xmr",
"event_id": "7ff047aa74e14f4aa978469bc0eec8ec",
"tx_info": {
"input": {
"height": 2464207,
"tx_hash": "97d4e66c4968b16fec7662adc9f8562c49108d3c5e7030c4d6dd32d97fb62540",
"image": "b0fe7acd9e17bb8b9ac2daae36d4cb607ac60ed8a101cc9b2e1f74016cf80b24",
"source": {
"high": 0,
"low": 6246316
},
"timestamp": 1711902214,
"unlock_time": 0,
"mixin_count": 15,
"sender": {
"maj_i": 0,
"min_i": 0
}
},
"source": {
"id": {
"high": 0,
"low": 6246316
},
"amount": 10000000000,
"mixin": 15,
"index": 0,
"tx_public": "426ccd6d39535a1ee8636d14978581e580fcea35c8d3843ceb32eb688a0197f7"
}
}
}
}
```
### New Accounts
When a new account is registered, regardless of the `--auto-accept-creation`
flag for `monero-lws-daemon`, the system will publish events. Registration
occurs in the [admin api](/api/admin). The ZeroMQ-PUB topics are
`json_full-new_account` and `msgpack-full-new_account`. Example of callback:
```json
{
"index": 2,
"event": {
"event": "new-account",
"event_id": "c5a735e71b1e4f0a8bfaeff661d0b38a",
"token": "",
"address": "9zGwnfWRMTF9nFVW9DNKp46aJ43CRtQBWNFvPqFVSN3RUKHuc37u2RDi2GXGp1wRdSRo5juS828FqgyxkumDaE4s9qyyi9B"
}
}
```
### Updated Accounts
You can register to be notified when the scanner has updated _any_ account,
and the event will batch the notifications per-thread. The ZeroMQ-PUB topics
are `json-minimal-scanned` and `msgpack-minimal-scanned`. Example of
callback:
```json
{
"index": 13,
"event": {
"height": 2438536,
"id": "9197e1c6f3de28a98dfc579325903e5416ef1ba2681043c54b5fff0d39645a7f",
"addresses": [
"9xkhhJSa7ZhS5sAcTix6ozL14RwdgxbV7JZVFW4rCghN7GidutaykfxDHfgW45UPiCTXncuvZ91GNSGgxs3b2Cin9TU8nP3"
]
}
}
```
+10 -9
View File
@@ -1,11 +1,11 @@
# monero-lws Administration
# Admin
The `monero-lws-admin` executable or `--admin-rest-server` option in the
`monero-lws-daemon` executable can be used to administer the database
used by `monero-lws-daemon`. Any number of `monero-lws-admin` instances can run
concurrently with a single `monero-lws-daemon` instance on the same database.
Administration is necessary to authorize new accounts and rescan requests
submitted from the REST API. The admin executable can also be used to list
the contents of the LMDB file for debugging purposes.
submitted from the [wallet API](/api/wallet). The admin executable can also be
used to list the contents of the LMDB file for debugging purposes.
# monero-lws-admin
@@ -21,14 +21,14 @@ search+filter the JSON output from the command.
# Admin REST API
The `monero-lws-daemon` can be started with 1+ `--admin-rest-server` parameters
that specify a listening location for admin REST clients. By default, there is
no admin REST server and no available admin accounts.
that specify a listening location for [admin API](/api/admin) clients. By
default, there is no admin REST server and no available admin accounts.
An admin REST server can be merged with a regular REST server if path prefixes
are specified, such as
`--rest-server https://0.0.0.0:8443/basic --admin-rest-server https://0.0.0.0:8443/admin`.
This will start a server listening on one port, 8443, and requires clients to
specify `/basic/command` or `/admin/admin_command` when making a
specify `/basic/command` or `/admin/admin/command` when making a
request.
An admin account account can be created via `monero-lws-admin create_admin`
@@ -58,9 +58,10 @@ if `--disable-admin-auth` is specified in the CLI arguments for the REST
server.
## Commands (of Admin REST API)
A subset of admin commands are available via admin REST API - the remainder
are initially omitted for security purposes. The commands available via REST
are:
A subset of admin commands are available via [admin REST API](/api/admin) - the
remainder are initially omitted for security purposes. The commands available
via REST are:
* [**accept_requests**](#accept_requests): `{"type": "import"|"create", "addresses":[...]}`
* [**add_account**](#add_account): `{"address": ..., "key": ...}`
* [**list_accounts**](#list_accounts): `{}`
View File
+81
View File
@@ -0,0 +1,81 @@
# monero-lws-daemon
`monero-lws-daemon` hosts the HTTP/1.1 server components of the
[wallet](/api/wallet) and [admin](/api/admin) API.
The wallet API is enabled by default on `http://127.0.0.1:8443`, and the admin
API is disabled by default. The daemon will listen for wallet API requests on
every `--rest-server` argument (multiple can be supplied). The same properties
apply to `--admin-rest-server` with the admin API.
The wallet API and admin API can be merged into one server instance through a
shared prefix: `--rest-server http://127.0.0.1:8443/wallet` combined with
` --admin-rest-server http://127.0.0.1:8443/admin` will listen on one port for
both APIs, and the client software must use `/wallet` or `/admin` to access
the correct API.
## SSL/TLS
Every REST endpoint that starts with `https://` will only communicate via
SSL/TLS. By default, a new certificate is created each time the lws daemon
starts. The commands `--rest-ssl-key` and `--rest-ssl-certificate` allow for
explicit server keys to be used, and they are applied to _every_ `https://`
REST argument (both wallet API and admin API).
## Subaddresses
Subaddresses are disabled by default in the lws daemon - all relevant endpoints
will fail. The option `--max-subaddresses`, when specified with a non-zero
value, will enable subaddress endpoints and impose restrictions on their
creation. If the value is lowered in the future, existing subaddresses are not
retroactively removed, so the limit is enforced purely at creation time.
If `--max-subaddresses` is zero or left unspecified, it will always disable
subaddresses, even if a user previously created some. So it is generally
recommended that once enabled, they always be enabled, even if the value
is lowered to `1` to discourage their use.
## ZeroMQ Sub
The daemon supports ZeroMQ SUB from `monerod` for instant mempool and block
notification. The `monerod` instance must use the option `--zmq-pub` and
`monero-lws-daemon` must use the `--sub` option. Both executables support
`tcp://` and `ipc://` for the rendevous location.
When a new block is processed by `monerod`, the lws daemon will immediately
begin processing as a result of the notification. Without proper `--sub`
usage, the lws daemon will poll the `monerod` instance at 20 second intervals.
The wallet API will **NOT** report mempool transactions due to a limitation
of the design. Webhooks **will** report mempool ("0-conf") transactions.
## Webhooks
The [admin API](/api/admin) has an endpoint, `/webhook_add`, with an `url`
field that must start with `http://`, `https://`, or `zmq`. See the link to
the API for specs/schema.
Every webhook is "simulcast" over an optional ZeroZQ PUB socket specified with
`--zmq-pub` (which is different from `monerod --zmq-pub`). If the webhook was
created with `params.url == zmq` then the notification occurs only over ZeroMQ.
The `params.address` field of `/webhook_add`, when needed as per spec, must
be a primary address. Subaddresses registered with the wallet API are
automatically reported to any primary address webhook. Omit `payment_id` to
report on _every_ transaction to that account.
See [webhooks documentation](/usage/webhooks) for more information.
## Remote Scanning
The view-key scanning process can be spread to multiple machines with the
`--lws-server-addr` option. The remote side should use the
[`monero-lws-client`](#monero-lws-client) executable, and connect back to the
`monero-lws-daemon` location. Usage of `--lws-server-pass` is highly
recommended when doing remote scanning, as it will prevent rogue processes
from hijacking the scan process. Also consider specifying the password in a
`--config-file`, otherwise the process list will leak the password.
The protocol is a custom unencrypted binary format, so `ssh -L ...` should be
used on the `monero-lws-client` side to provide proper encryption, and
additional authentication).
+53
View File
@@ -0,0 +1,53 @@
# monero-lws Overview
[monero-lws](https://github.com/vtnerd/monero-lws) is a Monero light-wallet
server that adheres to the community ratified
[LWS spec](https://github.com/monero-project/meta/blob/master/api/lightwallet_rest.md).
The server does all "cryptographic scanning" that is required of a Monero
wallet, and is non-custodial (the "spend" keys are never sent to server). It is
compatible with [Skylight wallet](https://skylight.magicgrants.org), and
[lwcli](https://github.com/cifro-codes/lwcli).
## Background
Monero wallets require complex scanning/decryption against _every_ transaction
to determine if funds were sent to that wallet. This process can be offloaded
to an outside process **without** giving up the "spend" keys of the wallet. The
LWS API provides a standard mechanism for splitting the "scanning" process from
the "spend" process.
The only negative of splitting this process is privacy - the "LWS server" knows
all incoming funds and can typically infer outgoing funds as well. This privacy
issue can be mitigated by self-hosting a LWS server. `monero-lws` and
[OpenMonero](https://github.com/moneroexamples/openmonero)
are the two options for self-hosting.
## Clients
The two available wallets are [lwcli](/lwcli/) and
[Skylight wallet](https://skylight.magicgrants.org). `lwcli` is a TUI wallet
aimed at advanced users, whereas `Skylight` is a beginner wallet.
Programmers wishing to create a new LWS wallet should investigate the
[lwsf](https://github.com/vtnerd/lwsf) project which provides a simple C++
interface of typical wallet functions while performing all of the heavy lifting
of communicating to the server and creating transactions.
## Versions
The `develop` branch is considered "nightly", and the `master` branch is
considered the "alpha" branch. Only developers should use `develop` because
DB changes could be incompatible from commit to commit.
After changes are well tested, they are moved to the `master` branch which
should rarely see incompatible DB changes. Users of this branch should
check the `src/lws_version.h.in` file - a major (first) number change indicates
that a incompatible DB change has been made. You will be unable to "roll-back"
to a prior `master` commit unless you save your DB and re-use it with that
older commited.
The `release-v` branches indicate beta/stable versions of the software. The
major (first) number indicates the DB version. Upgrades from lower numbers
to higher numbers is possible, but the reverse is never true. The minor
(second) number refers to stability: new features are never imported into a
release branch, instead a new release with higher major/minor number are used.
+15
View File
@@ -0,0 +1,15 @@
# Docker
Docker is the easiest way to get a recent copy of `monero-lws`. The paths are:
```bash
docker pull vtnerd/monero-lws
docker pull ghcr.io/vtnerd/monero-lws
```
which will download the latest stable release. A bleeding edge version can be
retrieved with:
```bash
docker pull vtnerd/monero-lws:master
docker pull ghcr.io/vtnerd/monero-lws:master
```
which is considered "alpha" software. The docker build comes with
`monero-lws-daemon` and `monero-lws-admin`.
+80
View File
@@ -0,0 +1,80 @@
# From Source
## Branches
Building from source requires deciding on a branch to compile:
* `develop` is where all merges go first. So this the "nightly" branch, and
is generally only recommended for developers. This should compile against
the `master` branch of `monerod`.
* `master` is where tested merges go - making this the "alpha" branch.
Recommended only if some new feature(s) are needed. This should compile
against the `master` branch of `monerod`.
* `release-v...` - The first number specifies the `monero-lws` version and
the second number specifies the `monerod` version. Example:
`release-v0.3_0.18` is the v0.3 version of `monero-lws` to be compiled
against the v0.18 version of `monerod`. The most recent release branch is
recommended for the bulk of users. The supported release branches are:
* release-v0.3_0.18
## Dependencies
After deciding on a branch, the next step is dependency installation. The only
dependencies are those required by `monerod` - go to
the [`monerod` dependency section](https://github.com/monero-project/monero/?tab=readme-ov-file#dependencies)
and follow those instructions for installing dependencies. Then come back to
this guide.
## Building
### Beginner
The "beginner" method for compilation lets the git submodules do all of the
hard work, but is only available on `develop` and `master` branches. The
process is simply:
```bash
git clone https://github.com/vtnerd/monero-lws.git
git checkout master
git submodule update --init --recursive
mkdir monero-lws/build && cd monero-lws/build
cmake -DCMAKE_BUILD_TYPE=Release ..
make -j$(nproc)
```
If on macOS, replace `-j$(nproc)` with `-j8` (or the number of cores on your
system). This should produce three binaries in the `monero/build/src` folder:
`monero-lws-daemon`, `monero-lws-admin`, and `monero-lws-client`. You can now
move onto [usage](/monero-lws/usage/).
### Advanced
If you already have the `monerod` source tree on your system, you can save some
space by re-using that copy. You need to manually ensure that the `monerod`
branch is the one needed by `monero-lws`. The
[first instruction](#building-from-source) specifies the expected `monerod`
branch foreach `monero-lws` branch.
The process skips the submodule init and specifies the monero tree manually:
```bash
git clone https://github.com/vtnerd/monero-lws.git
git checkout origin/release-v0.3_0.18
mkdir monero-lws/build && cd monero-lws/build
cmake -DMONERO_SOURCE_DIR=/path/to/monero_0.18/source -DCMAKE_BUILD_TYPE=Release ..
make -j$(nproc)
```
Again, replace `-j$(nproc)` on macOS with appropriate core count. This should
produce three executables in the `monero-lws/build/src` directory. Move onto
[usage](/monero-lws/usage/) portion.
### Other Build Options
Advanced users/developers may wish to specify additional build-time options
supported by the project. The easiest is specifying `-DSTATIC=ON` at the
cmake stage, which tries to use static libraries where possible.
The other available option is `-DBUILD_TESTS=ON` which can also be specified at
the cmake stage. This creates an executable `tests/unit/monero-lws-unit`.
The last option is `-DSANITIZER=address` which can be specified at the cmake
stage. This builds both monero source tree and lws source tree with the address
sanitizer.
+5
View File
@@ -0,0 +1,5 @@
# Round-Robin
This is the default scan algorithm used by `monero-lws-daemon`. Each account
is sorted by height, and then distributed evenly across threads. Older accounts
will typically end up on the first thread, however, some accounts are stuck
"waiting" for the old accounts to "catch-up".
-178
View File
@@ -1,178 +0,0 @@
# monero-lws ZeroMQ Usage
Monero-lws uses ZeroMQ-RPC to retrieve information from a Monero daemon,
ZeroMQ-SUB to get immediate notifications of blocks and transactions from a
Monero daemon, and ZeroMQ-PUB to notify external applications of payment_id
and new account (web)hooks.
## External "pub" socket
The bind location of the ZMQ-PUB socket is specified with the `--zmq-pub`
option. Users are still required to "subscribe" to topics:
* `json-full-payment_hook`: A JSON object of a single webhook payment event
that has recently triggered (identical output as webhook).
* `msgpack-full-payment_hook`: A msgpack object of a webhook payment events
that have recently triggered (identical output as webhook).
* `json-full-new_account_hook`: A JSON object of a single new account
creation that has recently triggered (identical output as webhook).
* `msgpack-full-new_account_hook`: A msgpack object of a single new account
creation that has recently triggered (identical output as webhook).
* `json-minimal-scanned`: A JSON object of a list of user primary addresses,
with their new height and block hash.
* `msgpack-minimal-scanned:` A msgpack object of a list of user primary
addresses with their new height and block hash.
* `json-full-spend_hook': A JSON object of a webhook spend event that has
recently triggerd (identical output as webhook).
* `msgpack-full-spend_hook`: A msgpack object of a single new account
creation that has recently triggered (identical output as webhook).
### `json-full-payment_hook`/`msgpack-full-payment_hook`
These topics receive PUB messages when a webhook ([`webhook_add`](administration.md)),
event is triggered for a payment (`tx-confirmation`). If the specified URL is
`zmq`, then notifications are only done over the ZMQ-PUB socket, otherwise the
notification is sent over ZMQ-PUB socket AND the specified URL. Invoking
`webhook_add` with a `payment_id` of zeroes (the field is optional in
`webhook_add`), will match on all transactions that lack a `payment_id`.
Example of the "raw" output from ZMQ-SUB side:
```json
json-full-payment_hook:{
"index": 2,
"event": {
"event": "tx-confirmation",
"payment_id": "4f695d197f2a3c54",
"token": "single zmq wallet",
"confirmations": 1,
"event_id": "3894f98f5dd54af5857e4f8a961a4e57",
"tx_info": {
"id": {
"high": 0,
"low": 5666768
},
"block": 2265961,
"index": 1,
"amount": 3117324236131,
"timestamp": 1687301600,
"tx_hash": "ef3187775584351cc5109de124b877bcc530fb3fdbf77895329dd447902cc566",
"tx_prefix_hash": "064884b8a8f903edcfebab830707ed44b633438b47c95a83320f4438b1b28626",
"tx_public": "54dce1a6eebafa2fdedcea5e373ef9de1c3d2737ae9f809e80958d1ba4590d74",
"rct_mask": "4cdc4c4e340aacb4741ba20f9b0b859242ecdad2fcc251f71d81123a47db3400",
"payment_id": "4f695d197f2a3c54",
"unlock_time": 0,
"mixin_count": 15,
"coinbase": false
}
}
}
```
Notice the `json-full-payment_hook:` prefix - this is required for the ZMQ PUB/SUB
subscription model. The subscriber requests data from a certain "topic" where
matching is done by string prefixes.
> `index` is a counter used to detect dropped messages.
> The `block` and `id` fields in the above example are NOT present when
`confirmations == 0`.
### `json-full-new_account_hook`/`msgpack-full-new_account_hook`
These topics receive PUB messages when a webhook ([`webhook_add`](administration.md)),
event is triggered for a new account (`new-account`). If the specified URL is
`zmq`, then notifications are only done over the ZMQ-PUB socket, otherwise the
notification is sent over ZMQ-PUB socket AND the specified URL. Invoking
`webhook_add` with a `payment_id` of zeroes (the field is optional in
`webhook_add`), will match on all transactions that lack a `payment_id`.
Example of the "raw" output from ZMQ-SUB side:
```json
json-full-new_account_hook:{
"index": 2,
"event": {
"event": "new-account",
"event_id": "c5a735e71b1e4f0a8bfaeff661d0b38a",
"token": "",
"address": "9zGwnfWRMTF9nFVW9DNKp46aJ43CRtQBWNFvPqFVSN3RUKHuc37u2RDi2GXGp1wRdSRo5juS828FqgyxkumDaE4s9qyyi9B"
}
}
```
Notice the `json-full-new_account_hook:` prefix - this is required for the ZMQ
PUB/SUB subscription model. The subscriber requests data from a certain "topic"
where matching is done by string prefixes.
> `index` is a counter used to detect dropped messages.
### `json-minimal-scanned`/`msgpack-minimal-scanned`
These topics receive PUB messages when a thread has finished scanning 1+
accounts. The last block height and hash is sent.
Example of the "raw" output from ZMQ-SUB side:
```json
json-minimal-scanned:{
"index": 13,
"event": {
"height": 2438536,
"id": "9197e1c6f3de28a98dfc579325903e5416ef1ba2681043c54b5fff0d39645a7f",
"addresses": [
"9xkhhJSa7ZhS5sAcTix6ozL14RwdgxbV7JZVFW4rCghN7GidutaykfxDHfgW45UPiCTXncuvZ91GNSGgxs3b2Cin9TU8nP3"
]
> `index` is a counter used to detect dropped messages.
### `json-full-spend_hook`/`msgpack-full-spend_hook`
These topics receive PUB messages when a webhook ([`webhook_add`](administration.md)),
event is triggered for a spend (`tx-spend`). If the specified URL is
`zmq`, then notifications are only done over the ZMQ-PUB socket, otherwise the
notification is sent over ZMQ-PUB socket AND the specified URL. Invoking
`webhook_add` with a `payment_id` or `confirmation` results in a NOP because
both fields are unused for spends. This event is only triggered on
confirmation==1 (`confirmation` field on `webhook_add`s have no effect, and
mempool spends are not scanned). The intent is to notify the user of unexpected
spend operations. The end user will need to use `tx_info.input.image`,
`tx_info.source.index`, and `tx_info.source.tx_public` to determine if the
output was actually spent or being used as a decoy.
Example of the "raw" output from ZMQ-SUB side:
```json
json-full-spend_hook:{
"index": 0,
"event": {
"event": "tx-spend",
"token": "spend-xmr",
"event_id": "7ff047aa74e14f4aa978469bc0eec8ec",
"tx_info": {
"input": {
"height": 2464207,
"tx_hash": "97d4e66c4968b16fec7662adc9f8562c49108d3c5e7030c4d6dd32d97fb62540",
"image": "b0fe7acd9e17bb8b9ac2daae36d4cb607ac60ed8a101cc9b2e1f74016cf80b24",
"source": {
"high": 0,
"low": 6246316
},
"timestamp": 1711902214,
"unlock_time": 0,
"mixin_count": 15,
"sender": {
"maj_i": 0,
"min_i": 0
}
},
"source": {
"id": {
"high": 0,
"low": 6246316
},
"amount": 10000000000,
"mixin": 15,
"index": 0,
"tx_public": "426ccd6d39535a1ee8636d14978581e580fcea35c8d3843ceb32eb688a0197f7"
}
}
}
}
```
> `index` is a counter used to detect dropped messages
+27
View File
@@ -0,0 +1,27 @@
site_name: docs.monerolws.com
site_url: https://docs.monerolws.com
site_description: Documentation for Monero-LWS
nav:
- Overview: index.md
- Installation:
- From Source: installation/source.md
- Docker: installation/docker.md
- Processes:
- daemon: apps/daemon.md
- admin: apps/admin.md
- client: apps/client.md
- Scan Algorithms:
- Round Robin: scan/round_robin.md
- Balance New Addresses: scan/balance_new_addresses.md
- Block Depth Threading: scan/block_depth_threading.md
- Split Synced Threads: scan/split_synced_threads.md
- API:
- Wallet: api/wallet.md
- Admin: api/admin.md
- Webhooks/ZeroMQ: api/zmq.md
- RabbitMQ: api/rmq.md
plugins:
- swagger-ui-tag
theme: readthedocs
repo_url: https://github.com/vtnerd/monero-lws
edit_uri: edit/develop/docs