mirror of
https://github.com/Cameri/nostream.git
synced 2025-09-17 19:13:35 +02:00
fix: confirm invoice function ambiguous unit variable (#221)
* fix: dont crash when SECRET is not set * docs: add semisol to contributors * docs: improve readme * docs: add payment info to readme * docs: add zebedee_api_key to configuration.md * fix: confirm_invoice unit var * chore: remove unused code * chore: improve error logging for payments * chore: use instead of changeme * chore: fix typo * chore: improve get invoice status ctrl * fix: csp bug * chore: remove rate limits * chore: improve invoice page logging * chore: prevent root with start_local * chore: revert to redis 4.5.1
This commit is contained in:
committed by
GitHub
parent
e99ac5d02b
commit
fd3294929a
@@ -6,6 +6,7 @@ The following environment variables can be set:
|
||||
|
||||
| Name | Description | Default |
|
||||
|----------------------------------|--------------------------------|------------------------|
|
||||
| SECRET | Long random secret. | changeme |
|
||||
| RELAY_PORT | Relay's server port | 8008 |
|
||||
| RELAY_PRIVATE_KEY | Relay's private key in hex | (auto-generated) |
|
||||
| WORKER_COUNT | Number of workers override | No. of available CPUs |
|
||||
@@ -38,6 +39,7 @@ The following environment variables can be set:
|
||||
| REDIS_PASSWORD | Redis Password | nostr_ts_relay |
|
||||
| NOSTR_CONFIG_DIR | Configuration directory | <project_root>/.nostr/ |
|
||||
| DEBUG | Debugging filter | |
|
||||
| ZEBEDEE_API_KEY | Zebedee Project API Key | |
|
||||
|
||||
# Settings
|
||||
|
||||
|
58
README.md
58
README.md
@@ -50,6 +50,7 @@ NIPs with a relay-specific implementation are listed here.
|
||||
- [x] NIP-04: Encrypted Direct Message
|
||||
- [x] NIP-09: Event deletion
|
||||
- [x] NIP-11: Relay information document
|
||||
- [x] NIP-11a: Relay Information Document Extensions
|
||||
- [x] NIP-12: Generic tag queries
|
||||
- [x] NIP-13: Proof of Work
|
||||
- [x] NIP-15: End of Stored Events Notice
|
||||
@@ -60,7 +61,6 @@ NIPs with a relay-specific implementation are listed here.
|
||||
- [x] NIP-28: Public Chat
|
||||
- [x] NIP-33: Parameterized Replaceable Events
|
||||
- [x] NIP-40: Expiration Timestamp
|
||||
- [x] NIP-111: Relay Information Document Extensions
|
||||
|
||||
## Requirements
|
||||
|
||||
@@ -86,24 +86,6 @@ Install Docker from their [official guide](https://docs.docker.com/engine/instal
|
||||
- [Set up a Paid Nostr relay with Nostream and ZBD](https://andreneves.xyz/p/how-to-setup-a-paid-nostr-relay) by [André Neves](https://snort.social/p/npub1rvg76s0gz535txd9ypg2dfqv0x7a80ar6e096j3v343xdxyrt4ksmkxrck) (CTO & Co-Founder at [ZEBEDEE](https://zebedee.io/))
|
||||
- [Set up a Nostr relay in under 5 minutes](https://andreneves.xyz/p/set-up-a-nostr-relay-server-in-under) by [André Neves](https://twitter.com/andreneves) (CTO & Co-Founder at [ZEBEDEE](https://zebedee.io/))
|
||||
|
||||
## Local Quick Start (Docker Compose)
|
||||
|
||||
Install Docker Desktop following the [official guide](https://docs.docker.com/desktop/).
|
||||
You may have to uninstall Docker on your machine if you installed it using a different guide.
|
||||
|
||||
Clone repository and enter directory:
|
||||
```
|
||||
git clone git@github.com:Cameri/nostream.git
|
||||
cd nostream
|
||||
```
|
||||
|
||||
Start:
|
||||
```
|
||||
./scripts/start_local
|
||||
```
|
||||
|
||||
This will run in the foreground of the terminal until you stop it with Ctrl+C.
|
||||
|
||||
## Quick Start (Docker Compose)
|
||||
|
||||
Install Docker following the [official guide](https://docs.docker.com/engine/install/).
|
||||
@@ -184,15 +166,17 @@ Set the following environment variables:
|
||||
```
|
||||
DB_URI="postgresql://postgres:postgres@localhost:5432/nostr_ts_relay_test"
|
||||
DB_USER=postgres
|
||||
|
||||
```
|
||||
or
|
||||
|
||||
```
|
||||
DB_HOST=localhost
|
||||
DB_PORT=5432
|
||||
DB_NAME=nostr_ts_relay
|
||||
DB_USER=postgres
|
||||
DB_PASSWORD=postgres
|
||||
```
|
||||
|
||||
```
|
||||
REDIS_URI="redis://default:nostr_ts_relay@localhost:6379"
|
||||
|
||||
REDIS_HOST=localhost
|
||||
@@ -201,6 +185,19 @@ Set the following environment variables:
|
||||
REDIS_PASSWORD=nostr_ts_relay
|
||||
```
|
||||
|
||||
If enabling payments, generate a long random secret and set SECRET:
|
||||
You may want to use `openssl rand -hex 128` to generate a secret.
|
||||
|
||||
```
|
||||
SECRET=aaabbbccc...dddeeefff
|
||||
# Secret shortened for brevity
|
||||
```
|
||||
|
||||
In addition, if using Zebedee for payments, you must also set ZEBEDEE_API_KEY with
|
||||
an API Key from one of your projects in your Zebedee Developer Dashboard. Contact
|
||||
@foxp2zeb on Telegram or npub1rvg76s0gz535txd9ypg2dfqv0x7a80ar6e096j3v343xdxyrt4ksmkxrck on Nostr requesting
|
||||
access to the Zebedee Developer Dashboard.
|
||||
|
||||
Create `nostr_ts_relay` database:
|
||||
|
||||
```
|
||||
@@ -261,6 +258,24 @@ To clean up the build, coverage and test reports run:
|
||||
```
|
||||
npm run clean
|
||||
```
|
||||
## Development Quick Start (Docker Compose)
|
||||
|
||||
Install Docker Desktop following the [official guide](https://docs.docker.com/desktop/).
|
||||
You may have to uninstall Docker on your machine if you installed it using a different guide.
|
||||
|
||||
Clone repository and enter directory:
|
||||
```
|
||||
git clone git@github.com:Cameri/nostream.git
|
||||
cd nostream
|
||||
```
|
||||
|
||||
Start:
|
||||
```
|
||||
./scripts/start_local
|
||||
```
|
||||
|
||||
This will run in the foreground of the terminal until you stop it with Ctrl+C.
|
||||
|
||||
## Tests
|
||||
|
||||
### Unit tests
|
||||
@@ -391,6 +406,7 @@ I'm Cameri on most social networks. You can find me on Nostr by npub1qqqqqqyz0la
|
||||
- Saransh Sharma
|
||||
- swissrouting
|
||||
- André Neves
|
||||
- Semisol
|
||||
|
||||
## License
|
||||
|
||||
|
@@ -3,7 +3,7 @@ services:
|
||||
build: .
|
||||
container_name: nostream
|
||||
environment:
|
||||
SECRET: changeme
|
||||
SECRET: ${SECRET}
|
||||
RELAY_PORT: 8008
|
||||
# Master
|
||||
NOSTR_CONFIG_DIR: /home/node/.nostr
|
||||
|
62
migrations/20230220_002700_fix_unit_confirm_invoice_func.js
Normal file
62
migrations/20230220_002700_fix_unit_confirm_invoice_func.js
Normal file
@@ -0,0 +1,62 @@
|
||||
exports.up = function (knex) {
|
||||
return knex.schema
|
||||
.raw('DROP FUNCTION confirm_invoice(invoice_id UUID, amount_received BIGINT, confirmation_date TIMESTAMP WITHOUT TIME ZONE)')
|
||||
.raw('DROP FUNCTION confirm_invoice(invoice_id TEXT, amount_received BIGINT, confirmation_date TIMESTAMP WITHOUT TIME ZONE)')
|
||||
.raw(`CREATE OR REPLACE FUNCTION confirm_invoice(invoice_id TEXT, amount_received BIGINT, confirmation_date TIMESTAMP WITHOUT TIME ZONE)
|
||||
RETURNS INTEGER
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
DECLARE
|
||||
payee BYTEA;
|
||||
confirmed_date TIMESTAMP WITHOUT TIME ZONE;
|
||||
invoice_unit TEXT;
|
||||
BEGIN
|
||||
PERFORM ASSERT_SERIALIZED();
|
||||
|
||||
SELECT "pubkey", "confirmed_at", "unit" INTO payee, confirmed_date, invoice_unit FROM "invoices" WHERE id = invoice_id;
|
||||
IF confirmed_date IS NULL THEN
|
||||
UPDATE invoices
|
||||
SET
|
||||
"confirmed_at" = confirmation_date,
|
||||
"amount_paid" = amount_received,
|
||||
"updated_at" = now_utc()
|
||||
WHERE id = invoice_id;
|
||||
IF invoice_unit = 'sats' THEN
|
||||
UPDATE users SET balance = balance + amount_received * 1000 WHERE "pubkey" = payee;
|
||||
ELSIF invoice_unit = 'msats' THEN
|
||||
UPDATE users SET balance = balance + amount_received WHERE "pubkey" = payee;
|
||||
ELSIF invoice_unit = 'btc' THEN
|
||||
UPDATE users SET balance = balance + amount_received * 100000000 * 1000 WHERE "pubkey" = payee;
|
||||
END IF;
|
||||
END IF;
|
||||
RETURN 0;
|
||||
END;
|
||||
$$;`)
|
||||
}
|
||||
|
||||
exports.down = function (knex) {
|
||||
return knex.schema
|
||||
.raw(`CREATE OR REPLACE FUNCTION confirm_invoice(invoice_id TEXT, amount_received BIGINT, confirmation_date TIMESTAMP WITHOUT TIME ZONE)
|
||||
RETURNS INTEGER
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
DECLARE
|
||||
payee BYTEA;
|
||||
confirmed_date TIMESTAMP WITHOUT TIME ZONE;
|
||||
BEGIN
|
||||
PERFORM ASSERT_SERIALIZED();
|
||||
|
||||
SELECT "pubkey", "confirmed_at" INTO payee, confirmed_date FROM "invoices" WHERE id = invoice_id;
|
||||
IF confirmed_date IS NULL THEN
|
||||
UPDATE invoices
|
||||
SET
|
||||
"confirmed_at" = confirmation_date,
|
||||
"amount_paid" = amount_received,
|
||||
"updated_at" = now_utc()
|
||||
WHERE id = invoice_id;
|
||||
UPDATE users SET balance = balance + amount_received WHERE "pubkey" = payee;
|
||||
END IF;
|
||||
RETURN 0;
|
||||
END;
|
||||
$$;`)
|
||||
}
|
96
package-lock.json
generated
96
package-lock.json
generated
@@ -10,7 +10,7 @@
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@noble/secp256k1": "1.7.1",
|
||||
"axios": "^1.2.6",
|
||||
"axios": "1.2.6",
|
||||
"bech32": "2.0.0",
|
||||
"body-parser": "1.20.1",
|
||||
"debug": "4.3.4",
|
||||
@@ -24,7 +24,7 @@
|
||||
"pg": "8.9.0",
|
||||
"pg-query-stream": "4.3.0",
|
||||
"ramda": "0.28.0",
|
||||
"redis": "4.6.2",
|
||||
"redis": "4.5.1",
|
||||
"rxjs": "7.8.0",
|
||||
"tor-control-ts": "^1.0.0",
|
||||
"ws": "8.12.0"
|
||||
@@ -1517,9 +1517,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@redis/bloom": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@redis/bloom/-/bloom-1.2.0.tgz",
|
||||
"integrity": "sha512-HG2DFjYKbpNmVXsa0keLHp/3leGJz1mjh09f2RLGGLQZzSHpkmZWuwJbAvo3QcRY8p80m5+ZdXZdYOSBLlp7Cg==",
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@redis/bloom/-/bloom-1.1.0.tgz",
|
||||
"integrity": "sha512-9QovlxmpRtvxVbN0UBcv8WfdSMudNZZTFqCsnBszcQXqaZb/TVe30ScgGEO7u1EAIacTPAo7/oCYjYAxiHLanQ==",
|
||||
"peerDependencies": {
|
||||
"@redis/client": "^1.0.0"
|
||||
}
|
||||
@@ -1528,6 +1528,7 @@
|
||||
"version": "1.5.3",
|
||||
"resolved": "https://registry.npmjs.org/@redis/client/-/client-1.5.3.tgz",
|
||||
"integrity": "sha512-kPad3QmWyRcmFj1gnb+SkzjXBV7oPpyTJmasVA+ocgNClxqZaTJjLFReqxm9cZQiCtqZK9vrcTISNrgzQXFpLg==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"cluster-key-slot": "1.1.2",
|
||||
"generic-pool": "3.9.0",
|
||||
@@ -1554,9 +1555,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@redis/search": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@redis/search/-/search-1.1.1.tgz",
|
||||
"integrity": "sha512-pqCXTc5e7wJJgUuJiC3hBgfoFRoPxYzwn0BEfKgejTM7M/9zP3IpUcqcjgfp8hF+LoV8rHZzcNTz7V+pEIY7LQ==",
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@redis/search/-/search-1.1.0.tgz",
|
||||
"integrity": "sha512-NyFZEVnxIJEybpy+YskjgOJRNsfTYqaPbK/Buv6W2kmFNaRk85JiqjJZA5QkRmWvGbyQYwoO5QfDi2wHskKrQQ==",
|
||||
"peerDependencies": {
|
||||
"@redis/client": "^1.0.0"
|
||||
}
|
||||
@@ -3182,6 +3183,7 @@
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz",
|
||||
"integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
@@ -11209,18 +11211,39 @@
|
||||
}
|
||||
},
|
||||
"node_modules/redis": {
|
||||
"version": "4.6.2",
|
||||
"resolved": "https://registry.npmjs.org/redis/-/redis-4.6.2.tgz",
|
||||
"integrity": "sha512-Xoh7UyU6YnT458xA8svaZAJu6ZunKeW7Z/7GXrLWGGwhVLTsDX6pr3u7ENAoV+DHBPO+9LwIu45ClwUwpIjAxw==",
|
||||
"version": "4.5.1",
|
||||
"resolved": "https://registry.npmjs.org/redis/-/redis-4.5.1.tgz",
|
||||
"integrity": "sha512-oxXSoIqMJCQVBTfxP6BNTCtDMyh9G6Vi5wjdPdV/sRKkufyZslDqCScSGcOr6XGR/reAWZefz7E4leM31RgdBA==",
|
||||
"dependencies": {
|
||||
"@redis/bloom": "1.2.0",
|
||||
"@redis/client": "1.5.3",
|
||||
"@redis/bloom": "1.1.0",
|
||||
"@redis/client": "1.4.2",
|
||||
"@redis/graph": "1.1.0",
|
||||
"@redis/json": "1.0.4",
|
||||
"@redis/search": "1.1.1",
|
||||
"@redis/search": "1.1.0",
|
||||
"@redis/time-series": "1.0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/redis/node_modules/@redis/client": {
|
||||
"version": "1.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@redis/client/-/client-1.4.2.tgz",
|
||||
"integrity": "sha512-oUdEjE0I7JS5AyaAjkD3aOXn9NhO7XKyPyXEyrgFDu++VrVBHUPnV6dgEya9TcMuj5nIJRuCzCm8ZP+c9zCHPw==",
|
||||
"dependencies": {
|
||||
"cluster-key-slot": "1.1.1",
|
||||
"generic-pool": "3.9.0",
|
||||
"yallist": "4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/redis/node_modules/cluster-key-slot": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.1.tgz",
|
||||
"integrity": "sha512-rwHwUfXL40Chm1r08yrhU3qpUvdVlgkKNeyeGPOxnW8/SyVDvgRaed/Uz54AqWNaTCAThlj6QAs3TZcKI0xDEw==",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/reflect-metadata": {
|
||||
"version": "0.1.13",
|
||||
"resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz",
|
||||
@@ -14389,15 +14412,16 @@
|
||||
}
|
||||
},
|
||||
"@redis/bloom": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@redis/bloom/-/bloom-1.2.0.tgz",
|
||||
"integrity": "sha512-HG2DFjYKbpNmVXsa0keLHp/3leGJz1mjh09f2RLGGLQZzSHpkmZWuwJbAvo3QcRY8p80m5+ZdXZdYOSBLlp7Cg==",
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@redis/bloom/-/bloom-1.1.0.tgz",
|
||||
"integrity": "sha512-9QovlxmpRtvxVbN0UBcv8WfdSMudNZZTFqCsnBszcQXqaZb/TVe30ScgGEO7u1EAIacTPAo7/oCYjYAxiHLanQ==",
|
||||
"requires": {}
|
||||
},
|
||||
"@redis/client": {
|
||||
"version": "1.5.3",
|
||||
"resolved": "https://registry.npmjs.org/@redis/client/-/client-1.5.3.tgz",
|
||||
"integrity": "sha512-kPad3QmWyRcmFj1gnb+SkzjXBV7oPpyTJmasVA+ocgNClxqZaTJjLFReqxm9cZQiCtqZK9vrcTISNrgzQXFpLg==",
|
||||
"peer": true,
|
||||
"requires": {
|
||||
"cluster-key-slot": "1.1.2",
|
||||
"generic-pool": "3.9.0",
|
||||
@@ -14417,9 +14441,9 @@
|
||||
"requires": {}
|
||||
},
|
||||
"@redis/search": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@redis/search/-/search-1.1.1.tgz",
|
||||
"integrity": "sha512-pqCXTc5e7wJJgUuJiC3hBgfoFRoPxYzwn0BEfKgejTM7M/9zP3IpUcqcjgfp8hF+LoV8rHZzcNTz7V+pEIY7LQ==",
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@redis/search/-/search-1.1.0.tgz",
|
||||
"integrity": "sha512-NyFZEVnxIJEybpy+YskjgOJRNsfTYqaPbK/Buv6W2kmFNaRk85JiqjJZA5QkRmWvGbyQYwoO5QfDi2wHskKrQQ==",
|
||||
"requires": {}
|
||||
},
|
||||
"@redis/time-series": {
|
||||
@@ -15673,7 +15697,8 @@
|
||||
"cluster-key-slot": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz",
|
||||
"integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA=="
|
||||
"integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==",
|
||||
"peer": true
|
||||
},
|
||||
"color-convert": {
|
||||
"version": "2.0.1",
|
||||
@@ -21627,16 +21652,33 @@
|
||||
}
|
||||
},
|
||||
"redis": {
|
||||
"version": "4.6.2",
|
||||
"resolved": "https://registry.npmjs.org/redis/-/redis-4.6.2.tgz",
|
||||
"integrity": "sha512-Xoh7UyU6YnT458xA8svaZAJu6ZunKeW7Z/7GXrLWGGwhVLTsDX6pr3u7ENAoV+DHBPO+9LwIu45ClwUwpIjAxw==",
|
||||
"version": "4.5.1",
|
||||
"resolved": "https://registry.npmjs.org/redis/-/redis-4.5.1.tgz",
|
||||
"integrity": "sha512-oxXSoIqMJCQVBTfxP6BNTCtDMyh9G6Vi5wjdPdV/sRKkufyZslDqCScSGcOr6XGR/reAWZefz7E4leM31RgdBA==",
|
||||
"requires": {
|
||||
"@redis/bloom": "1.2.0",
|
||||
"@redis/client": "1.5.3",
|
||||
"@redis/bloom": "1.1.0",
|
||||
"@redis/client": "1.4.2",
|
||||
"@redis/graph": "1.1.0",
|
||||
"@redis/json": "1.0.4",
|
||||
"@redis/search": "1.1.1",
|
||||
"@redis/search": "1.1.0",
|
||||
"@redis/time-series": "1.0.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"@redis/client": {
|
||||
"version": "1.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@redis/client/-/client-1.4.2.tgz",
|
||||
"integrity": "sha512-oUdEjE0I7JS5AyaAjkD3aOXn9NhO7XKyPyXEyrgFDu++VrVBHUPnV6dgEya9TcMuj5nIJRuCzCm8ZP+c9zCHPw==",
|
||||
"requires": {
|
||||
"cluster-key-slot": "1.1.1",
|
||||
"generic-pool": "3.9.0",
|
||||
"yallist": "4.0.0"
|
||||
}
|
||||
},
|
||||
"cluster-key-slot": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.1.tgz",
|
||||
"integrity": "sha512-rwHwUfXL40Chm1r08yrhU3qpUvdVlgkKNeyeGPOxnW8/SyVDvgRaed/Uz54AqWNaTCAThlj6QAs3TZcKI0xDEw=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"reflect-metadata": {
|
||||
|
@@ -130,10 +130,10 @@
|
||||
"pg": "8.9.0",
|
||||
"pg-query-stream": "4.3.0",
|
||||
"ramda": "0.28.0",
|
||||
"redis": "4.6.2",
|
||||
"redis": "4.5.1",
|
||||
"rxjs": "7.8.0",
|
||||
"ws": "8.12.0",
|
||||
"tor-control-ts": "^1.0.0"
|
||||
"tor-control-ts": "^1.0.0",
|
||||
"ws": "8.12.0"
|
||||
},
|
||||
"config": {
|
||||
"commitizen": {
|
||||
|
@@ -36,9 +36,9 @@ limits:
|
||||
invoice:
|
||||
rateLimits:
|
||||
- period: 60000
|
||||
rate: 6
|
||||
rate: 12
|
||||
- period: 3600000
|
||||
rate: 16
|
||||
rate: 30
|
||||
ipWhitelist:
|
||||
- "::1"
|
||||
- "10.10.10.1"
|
||||
@@ -49,8 +49,6 @@ limits:
|
||||
rate: 12
|
||||
- period: 60000
|
||||
rate: 48
|
||||
- period: 3600000
|
||||
rate: 300
|
||||
ipWhitelist:
|
||||
- "::1"
|
||||
- "10.10.10.1"
|
||||
@@ -101,14 +99,6 @@ limits:
|
||||
- 42
|
||||
period: 60000
|
||||
rate: 12
|
||||
- description: 360 events/hour for event kinds 1, 2, 4 and 42
|
||||
kinds:
|
||||
- 1
|
||||
- 2
|
||||
- 4
|
||||
- 42
|
||||
period: 3600000
|
||||
rate: 360
|
||||
- description: 30 events/min for event kind ranges 5-7 and 43-49
|
||||
kinds:
|
||||
- - 5
|
||||
@@ -135,9 +125,6 @@ limits:
|
||||
- description: 720 events/hour for all events
|
||||
period: 3600000
|
||||
rate: 720
|
||||
- description: 2880 events/day for all events
|
||||
period: 86400000
|
||||
rate: 2880
|
||||
whitelists:
|
||||
pubkeys: []
|
||||
ipAddresses:
|
||||
@@ -153,9 +140,6 @@ limits:
|
||||
- description: 240 raw messages/min
|
||||
period: 60000
|
||||
rate: 240
|
||||
- description: 3600 raw messages/hour
|
||||
period: 3600000
|
||||
rate: 4800
|
||||
ipWhitelist:
|
||||
- "::1"
|
||||
- "10.10.10.1"
|
||||
|
@@ -108,6 +108,8 @@
|
||||
var paid = false
|
||||
var fallbackTimeout
|
||||
|
||||
console.log('invoice id', reference)
|
||||
|
||||
function getBackoffTime() {
|
||||
return 5000 + Math.floor(Math.random() * 5000)
|
||||
}
|
||||
@@ -125,6 +127,8 @@
|
||||
hide('pending')
|
||||
show('expired')
|
||||
return
|
||||
} else {
|
||||
console.log('invoice status', status)
|
||||
}
|
||||
|
||||
paid = true
|
||||
|
@@ -5,6 +5,11 @@ PROJECT_ROOT="$(dirname $(readlink -f "${BASH_SOURCE[0]}"))/.."
|
||||
DOCKER_COMPOSE_FILE="${PROJECT_ROOT}/docker-compose.yml"
|
||||
DOCKER_COMPOSE_LOCAL_FILE="${PROJECT_ROOT}/docker-compose.local.yml"
|
||||
|
||||
if [ "$EUID" -eq 0 ]
|
||||
then echo "Error: Nostream should not be run as root."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! type "mkcert" &> /dev/null; then
|
||||
echo "Could not find mkcert, which is required for generating locally-trusted TLS certificates. Follow the installation instructions at https://github.com/FiloSottile/mkcert, then run this script again."
|
||||
exit 1
|
||||
|
@@ -59,10 +59,13 @@ export class App implements IRunnable {
|
||||
}
|
||||
logCentered(`v${packageJson.version}`, width)
|
||||
logCentered(`NIPs implemented: ${packageJson.supportedNips}`, width)
|
||||
logCentered(`Pay-to-relay ${pathEq(['payments', 'enabled'], true, settings) ? 'enabled' : 'disabled'}`, width)
|
||||
logCentered(`Payments provider: ${path(['payments', 'processor'], settings)}`, width)
|
||||
const paymentsEnabled = pathEq(['payments', 'enabled'], true, settings)
|
||||
logCentered(`Pay-to-relay ${paymentsEnabled ? 'enabled' : 'disabled'}`, width)
|
||||
if (paymentsEnabled) {
|
||||
logCentered(`Payments provider: ${path(['payments', 'processor'], settings)}`, width)
|
||||
}
|
||||
|
||||
if (typeof this.process.env.SECRET !== 'string' || this.process.env.SECRET === 'changeme') {
|
||||
if (paymentsEnabled && (typeof this.process.env.SECRET !== 'string' || this.process.env.SECRET === '' || this.process.env.SECRET === 'changeme')) {
|
||||
console.error('Please configure the secret using the SECRET environment variable.')
|
||||
this.process.exit(1)
|
||||
}
|
||||
@@ -82,11 +85,13 @@ export class App implements IRunnable {
|
||||
WORKER_TYPE: 'worker',
|
||||
})
|
||||
}
|
||||
logCentered(`${workerCount} client workers started`, width)
|
||||
|
||||
createWorker({
|
||||
WORKER_TYPE: 'maintenance',
|
||||
})
|
||||
|
||||
logCentered('1 maintenance worker started', width)
|
||||
const mirrors = settings?.mirroring?.static
|
||||
|
||||
if (Array.isArray(mirrors) && mirrors.length) {
|
||||
@@ -96,11 +101,9 @@ export class App implements IRunnable {
|
||||
MIRROR_INDEX: i.toString(),
|
||||
})
|
||||
}
|
||||
logCentered(`${mirrors.length} maintenance worker started`, width)
|
||||
}
|
||||
|
||||
logCentered(`${workerCount} client workers started`, width)
|
||||
logCentered('1 maintenance worker started', width)
|
||||
|
||||
debug('settings: %O', settings)
|
||||
|
||||
const host = `${hostname()}:${port}`
|
||||
|
@@ -1,7 +1,10 @@
|
||||
import { Request, Response } from 'express'
|
||||
import { createLogger } from '../../factories/logger-factory'
|
||||
import { IController } from '../../@types/controllers'
|
||||
import { IInvoiceRepository } from '../../@types/repositories'
|
||||
|
||||
const debug = createLogger('get-invoice-status-controller')
|
||||
|
||||
export class GetInvoiceStatusController implements IController {
|
||||
public constructor(
|
||||
private readonly invoiceRepository: IInvoiceRepository,
|
||||
@@ -12,22 +15,25 @@ export class GetInvoiceStatusController implements IController {
|
||||
response: Response,
|
||||
): Promise<void> {
|
||||
const invoiceId = request.params.invoiceId
|
||||
if (!invoiceId) {
|
||||
if (typeof invoiceId !== 'string' || !invoiceId) {
|
||||
debug('invalid invoice id: %s', invoiceId)
|
||||
response
|
||||
.status(400)
|
||||
.setHeader('content-type', 'text/plain; charset=utf8')
|
||||
.send('Invalid invoice')
|
||||
.send({ id: invoiceId, status: 'invalid invoice' })
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
const invoice = await this.invoiceRepository.findById(request.params.invoiceId)
|
||||
debug('fetching invoice: %s', invoiceId)
|
||||
const invoice = await this.invoiceRepository.findById(invoiceId)
|
||||
|
||||
if (!invoice) {
|
||||
debug('invoice not found: %s', invoiceId)
|
||||
response
|
||||
.status(404)
|
||||
.setHeader('content-type', 'text/plain; charset=utf8')
|
||||
.send('Invoice not found')
|
||||
.send({ id: invoiceId, status: 'not found' })
|
||||
return
|
||||
}
|
||||
|
||||
@@ -44,7 +50,7 @@ export class GetInvoiceStatusController implements IController {
|
||||
response
|
||||
.status(500)
|
||||
.setHeader('content-type', 'text/plain; charset=utf8')
|
||||
.send('Unable to get invoice status')
|
||||
.send({ id: invoiceId, status: 'error' })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -10,11 +10,13 @@ import { PaymentsProcessor } from '../payments-processors/payments-procesor'
|
||||
import { Settings } from '../@types/settings'
|
||||
import { ZebedeePaymentsProcesor } from '../payments-processors/zebedee-payments-processor'
|
||||
|
||||
const debug = createLogger('create-zebedee-payments-processor')
|
||||
const debug = createLogger('create-payments-processor')
|
||||
|
||||
const getZebedeeAxiosConfig = (settings: Settings): CreateAxiosDefaults<any> => {
|
||||
if (!process.env.ZEBEDEE_API_KEY) {
|
||||
throw new Error('ZEBEDEE_API_KEY must be set.')
|
||||
const error = new Error('ZEBEDEE_API_KEY must be set.')
|
||||
console.error('Unable to get Zebedee config.', error)
|
||||
throw error
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -45,14 +47,20 @@ const getLNbitsAxiosConfig = (settings: Settings): CreateAxiosDefaults<any> => {
|
||||
const createZebedeePaymentsProcessor = (settings: Settings): IPaymentsProcessor => {
|
||||
const callbackBaseURL = path(['paymentsProcessors', 'zebedee', 'callbackBaseURL'], settings) as string | undefined
|
||||
if (typeof callbackBaseURL === 'undefined' || callbackBaseURL.indexOf('nostream.your-domain.com') >= 0) {
|
||||
throw new Error('Unable to create payments processor: Setting paymentsProcessor.zebedee.callbackBaseURL is not configured.')
|
||||
const error = new Error('Setting paymentsProcessor.zebedee.callbackBaseURL is not configured.')
|
||||
console.error('Unable to create payments processor.', error)
|
||||
|
||||
throw error
|
||||
}
|
||||
|
||||
if (
|
||||
!Array.isArray(settings.paymentsProcessors?.zebedee?.ipWhitelist)
|
||||
|| !settings.paymentsProcessors?.zebedee?.ipWhitelist?.length
|
||||
) {
|
||||
throw new Error('Unable to create payments processor: Setting paymentsProcessor.zebedee.ipWhitelist is empty.')
|
||||
const error = new Error('Setting paymentsProcessor.zebedee.ipWhitelist is empty.')
|
||||
console.error('Unable to create payments processor.', error)
|
||||
|
||||
throw error
|
||||
}
|
||||
|
||||
const config = getZebedeeAxiosConfig(settings)
|
||||
@@ -67,7 +75,10 @@ const createZebedeePaymentsProcessor = (settings: Settings): IPaymentsProcessor
|
||||
const createLNbitsPaymentProcessor = (settings: Settings): IPaymentsProcessor => {
|
||||
const callbackBaseURL = path(['paymentsProcessors', 'lnbits', 'callbackBaseURL'], settings) as string | undefined
|
||||
if (typeof callbackBaseURL === 'undefined' || callbackBaseURL.indexOf('nostream.your-domain.com') >= 0) {
|
||||
throw new Error('Unable to create payments processor: Setting paymentsProcessor.lnbits.callbackBaseURL is not configured.')
|
||||
const error = new Error('Setting paymentsProcessor.lnbits.callbackBaseURL is not configured.')
|
||||
console.error('Unable to create payments processor.', error)
|
||||
|
||||
throw error
|
||||
}
|
||||
|
||||
const config = getLNbitsAxiosConfig(settings)
|
||||
@@ -80,12 +91,12 @@ const createLNbitsPaymentProcessor = (settings: Settings): IPaymentsProcessor =>
|
||||
}
|
||||
|
||||
export const createPaymentsProcessor = (): IPaymentsProcessor => {
|
||||
debug('create payments processor')
|
||||
const settings = createSettings()
|
||||
if (!settings.payments?.enabled) {
|
||||
return new NullPaymentsProcessor()
|
||||
}
|
||||
|
||||
|
||||
switch (settings.payments?.processor) {
|
||||
case 'zebedee':
|
||||
return createZebedeePaymentsProcessor(settings)
|
||||
|
@@ -24,7 +24,7 @@ export const createWebApp = () => {
|
||||
*/
|
||||
'img-src': ["'self'", 'data:', 'https://cdn.zebedee.io/an/nostr/'],
|
||||
'connect-src': ["'self'", settings.info.relay_url as string, webRelayUrl.toString()],
|
||||
'default-src': ['"self"'],
|
||||
'default-src': ["'self'"],
|
||||
'script-src-attr': ["'unsafe-inline'"],
|
||||
'script-src': ["'self'", "'unsafe-inline'", 'https://cdn.jsdelivr.net/npm/', 'https://unpkg.com/', 'https://cdnjs.cloudflare.com/ajax/libs/'],
|
||||
'style-src': ["'self'", 'https://cdn.jsdelivr.net/npm/'],
|
||||
|
@@ -10,6 +10,7 @@ export const postInvoiceRequestHandler = async (
|
||||
try {
|
||||
await controller.handleRequest(req, res)
|
||||
} catch (error) {
|
||||
console.error('Unable handle request.', error)
|
||||
res
|
||||
.status(500)
|
||||
.setHeader('content-type', 'text-plain')
|
||||
|
@@ -56,7 +56,7 @@ export const rootRequestHandler = (request: Request, response: Response, next: N
|
||||
}
|
||||
|
||||
response
|
||||
.setHeader('conten-type', 'application/nostr+json')
|
||||
.setHeader('content-type', 'application/nostr+json')
|
||||
.setHeader('access-control-allow-origin', '*')
|
||||
.status(200)
|
||||
.send(relayInformationDocument)
|
||||
|
@@ -1,5 +1,4 @@
|
||||
import { Router, urlencoded } from 'express'
|
||||
import { createPaymentsProcessor } from '../../factories/payments-processor-factory'
|
||||
|
||||
import { getInvoiceRequestHandler } from '../../handlers/request-handlers/get-invoice-request-handler'
|
||||
import { getInvoiceStatusRequestHandler } from '../../handlers/request-handlers/get-invoice-status-request-handler'
|
||||
@@ -8,10 +7,6 @@ import { postInvoiceRequestHandler } from '../../handlers/request-handlers/post-
|
||||
const invoiceRouter = Router()
|
||||
|
||||
invoiceRouter
|
||||
.use((req, _res, next) => {
|
||||
req['paymentsProcessor'] = createPaymentsProcessor()
|
||||
next()
|
||||
})
|
||||
.get('/', getInvoiceRequestHandler)
|
||||
.get('/:invoiceId/status', getInvoiceStatusRequestHandler)
|
||||
.post('/', urlencoded({ extended: true }), postInvoiceRequestHandler)
|
||||
|
Reference in New Issue
Block a user