Compare commits

..

No commits in common. "8000886e72ca5c0c7dcdbd1fdf7892765c7776b1" and "dc0370ba1749c444cacb9c13d2179fa04c654ca5" have entirely different histories.

11 changed files with 39 additions and 58 deletions

View File

@ -1,7 +1,6 @@
PRISMA_SLOW_LOGS_MS=
GRAPHQL_SLOW_LOGS_MS=
NODE_ENV=development
COMPOSE_PROFILES='minimal,images,search,payments,wallets,email,capture'
############################################################################
# OPTIONAL SECRETS #
@ -115,6 +114,8 @@ POSTGRES_DB=stackernews
# opensearch container stuff
OPENSEARCH_INITIAL_ADMIN_PASSWORD=mVchg1T5oA9wudUh
plugins.security.disabled=true
discovery.type=single-node
DISABLE_SECURITY_DASHBOARDS_PLUGIN=true
# bitcoind container stuff

View File

@ -76,7 +76,6 @@ COMMANDS
sn:
login login as a nym
fund_user fund a nym without using an LN invoice
lnd:
fund pay a bolt11 for funding
@ -93,14 +92,12 @@ COMMANDS
dev:
pr fetch and checkout a pr
lint run linters
open open container url in browser
other:
compose docker compose passthrough
sn_lndcli lncli passthrough on sn_lnd
stacker_lndcli lncli passthrough on stacker_lnd
stacker_clncli lightning-cli passthrough on stacker_cln
stacker_litcli litcli passthrough on litd
```
@ -108,16 +105,23 @@ COMMANDS
#### Running specific services
By default all services will be run. If you want to exclude specific services from running, set `COMPOSE_PROFILES` in a `.env.local` file to one or more of `minimal,images,search,payments,wallets,email,capture`. To only run mininal necessary without things like payments in `.env.local`:
By default all services will be run. If you want to exclude specific services from running, set `COMPOSE_PROFILES` to use one or more of `minimal|images|search|payments|wallets|email|capture`. To only run mininal services without images, search, email, wallets, or payments:
```.env
COMPOSE_PROFILES=minimal
```sh
$ COMPOSE_PROFILES=minimal ./sndev start
```
Or, as I would recommend:
```sh
$ export COMPOSE_PROFILES=minimal
$ ./sndev start
```
To run with images and payments services:
```.env
COMPOSE_PROFILES=images,payments
```sh
$ COMPOSE_PROFILES=images,payments ./sndev start
```
#### Merging compose files
@ -456,9 +460,7 @@ In addition, we run other critical services the above services interact with lik
## Wallet transaction safety
To ensure stackers balances are kept sane, some wallet updates are run in [serializable transactions](https://www.postgresql.org/docs/current/transaction-iso.html#XACT-SERIALIZABLE) at the database level. Because early versions of prisma had relatively poor support for transactions most wallet touching code is written in [plpgsql](https://www.postgresql.org/docs/current/plpgsql.html) stored procedures and can be found in the `prisma/migrations` folder.
*UPDATE*: Most wallet updates are now run in [read committed](https://www.postgresql.org/docs/current/transaction-iso.html#XACT-READ-COMMITTED) transactions. See `api/paidAction/README.md` for more information.
To ensure stackers balances are kept sane, all wallet updates are run in [serializable transactions](https://www.postgresql.org/docs/current/transaction-iso.html#XACT-SERIALIZABLE) at the database level. Because early versions of prisma had relatively poor support for transactions most wallet touching code is written in [plpgsql](https://www.postgresql.org/docs/current/plpgsql.html) stored procedures and can be found in the `prisma/migrations` folder.
<br>

View File

@ -1,13 +1,11 @@
import lndService from 'ln-service'
import lnd from '@/api/lnd'
import { isServiceEnabled } from '@/lib/sndev'
const cache = new Map()
const expiresIn = 1000 * 30 // 30 seconds in milliseconds
async function fetchBlockHeight () {
let blockHeight = 0
if (!isServiceEnabled('payments')) return blockHeight
try {
const height = await lndService.getHeight({ lnd })
blockHeight = height.current_block_height

View File

@ -115,7 +115,3 @@ cointastical,issue,#1223,#107,medium,,2,,20k,cointastical@stacker.news,2024-06-2
kravhen,pr,#1215,#253,medium,,2,upgraded to medium,200k,nichro@getalby.com,2024-06-28
dillon-co,pr,#1140,#633,hard,,,requested advance,500k,bolt11,2024-07-02
takitakitanana,issue,,#1257,good-first-issue,,,,2k,takitakitanana@stacker.news,2024-07-11
SatsAllDay,pr,#1263,#1112,medium,,,1,225k,weareallsatoshi@getalby.com,2024-07-31
OneOneSeven117,issue,#1272,#1268,easy,,,,10k,OneOneSeven@stacker.news,2024-07-31
aniskhalfallah,pr,#1264,#1226,good-first-issue,,,,20k,aniskhalfallah@stacker.news,2024-07-31
Gudnessuche,issue,#1264,#1226,good-first-issue,,,,2k,???,???

1 name type pr id issue ids difficulty priority changes requested notes amount receive method date paid
115 kravhen pr #1215 #253 medium 2 upgraded to medium 200k nichro@getalby.com 2024-06-28
116 dillon-co pr #1140 #633 hard requested advance 500k bolt11 2024-07-02
117 takitakitanana issue #1257 good-first-issue 2k takitakitanana@stacker.news 2024-07-11
SatsAllDay pr #1263 #1112 medium 1 225k weareallsatoshi@getalby.com 2024-07-31
OneOneSeven117 issue #1272 #1268 easy 10k OneOneSeven@stacker.news 2024-07-31
aniskhalfallah pr #1264 #1226 good-first-issue 20k aniskhalfallah@stacker.news 2024-07-31
Gudnessuche issue #1264 #1226 good-first-issue 2k ??? ???

View File

@ -29,7 +29,7 @@ export default function Qr ({ asIs, value, useWallet: automated, statusVariant,
className='h-auto mw-100' value={qrValue} renderAs='svg' size={300}
/>
</a>
{description && <div className='mt-1 text-center text-muted'>{description}</div>}
{description && <div className='mt-1 fst-italic text-center text-muted'>{description}</div>}
<div className='mt-3 w-100'>
<CopyInput type='text' placeholder={value} readOnly noForm />
</div>

View File

@ -67,10 +67,10 @@ export function DropdownItemUpVote ({ item }) {
)
}
export const defaultTipIncludingRandom = ({ tipDefault, tipRandom, tipRandomMin, tipRandomMax } = {}) =>
export const defaultTipIncludingRandom = ({ tipDefault, tipRandom, tipRandomMin, tipRandomMax }) =>
tipRandom
? Math.floor((Math.random() * (tipRandomMax - tipRandomMin)) + tipRandomMin)
: (tipDefault || 100)
: (tipDefault || 1)
export const nextTip = (meSats, { tipDefault, turboTipping, tipRandom, tipRandomMin, tipRandomMax }) => {
// what should our next tip be?

View File

@ -150,8 +150,6 @@ services:
env_file: *env_file
environment:
- OPENSEARCH_INITIAL_ADMIN_PASSWORD=mVchg1T5oA9wudUh
- plugins.security.disabled=true
- discovery.type=single-node
ports:
- 9200:9200 # REST API
- 9600:9600 # Performance Analyzer

View File

@ -36,12 +36,12 @@ export const numWithUnits = (n, {
abbreviate = true,
unitSingular = 'sat',
unitPlural = 'sats',
format
format = false
} = {}) => {
if (isNaN(n)) {
return `${n} ${unitPlural}`
}
return `${abbreviate ? abbrNum(n) : !abbreviate || format === true ? new Intl.NumberFormat().format(n) : n} ${n === 1 ? unitSingular : unitPlural}`
return `${abbreviate ? abbrNum(n) : format ? new Intl.NumberFormat().format(n) : n} ${n === 1 ? unitSingular : unitPlural}`
}
export const fixedDecimal = (n, f) => {

View File

@ -1,6 +0,0 @@
export function isServiceEnabled (service) {
if (process.env.NODE_ENV !== 'development') return true
const services = (process.env.COMPOSE_PROFILES ?? '').split(',')
return services.includes(service)
}

11
sndev
View File

@ -1,11 +1,6 @@
#!/bin/sh
set -e
set -a # automatically export all variables
. .env.development
if [ -f .env.local ]; then
. .env.local
fi
docker__compose() {
if [ ! -x "$(command -v docker)" ]; then
@ -14,12 +9,16 @@ docker__compose() {
exit 0
fi
if [ -z "$COMPOSE_PROFILES" ]; then
COMPOSE_PROFILES="images,search,payments,wallets,email,capture"
fi
ENV_LOCAL=
if [ -f .env.local ]; then
ENV_LOCAL='--env-file .env.local'
fi
CURRENT_UID=$(id -u) CURRENT_GID=$(id -g) command docker compose --env-file .env.development $ENV_LOCAL "$@"
CURRENT_UID=$(id -u) CURRENT_GID=$(id -g) COMPOSE_PROFILES=$COMPOSE_PROFILES command docker compose --env-file .env.development $ENV_LOCAL "$@"
}
docker__exec() {

View File

@ -27,7 +27,6 @@ import { saltAndHashEmails } from './saltAndHashEmails.js'
import { remindUser } from './reminder.js'
import { holdAction, settleAction, settleActionError } from './paidAction.js'
import { thisDay } from './thisDay.js'
import { isServiceEnabled } from '@/lib/sndev.js'
const { loadEnvConfig } = nextEnv
const { ApolloClient, HttpLink, InMemoryCache } = apolloClient
@ -83,29 +82,17 @@ async function work () {
await boss.start()
if (isServiceEnabled('payments')) {
await subscribeToWallet(args)
await boss.work('finalizeHodlInvoice', jobWrapper(finalizeHodlInvoice))
await boss.work('checkPendingDeposits', jobWrapper(checkPendingDeposits))
await boss.work('checkPendingWithdrawals', jobWrapper(checkPendingWithdrawals))
await boss.work('autoDropBolt11s', jobWrapper(autoDropBolt11s))
await boss.work('autoWithdraw', jobWrapper(autoWithdraw))
await boss.work('settleActionError', jobWrapper(settleActionError))
await boss.work('settleAction', jobWrapper(settleAction))
await boss.work('checkInvoice', jobWrapper(checkInvoice))
await boss.work('holdAction', jobWrapper(holdAction))
}
if (isServiceEnabled('search')) {
await boss.work('indexItem', jobWrapper(indexItem))
await boss.work('indexAllItems', jobWrapper(indexAllItems))
}
if (isServiceEnabled('images')) {
await boss.work('imgproxy', jobWrapper(imgproxy))
await boss.work('deleteUnusedImages', jobWrapper(deleteUnusedImages))
}
await subscribeToWallet(args)
await boss.work('finalizeHodlInvoice', jobWrapper(finalizeHodlInvoice))
await boss.work('checkPendingDeposits', jobWrapper(checkPendingDeposits))
await boss.work('checkPendingWithdrawals', jobWrapper(checkPendingWithdrawals))
await boss.work('autoDropBolt11s', jobWrapper(autoDropBolt11s))
await boss.work('autoWithdraw', jobWrapper(autoWithdraw))
await boss.work('repin-*', jobWrapper(repin))
await boss.work('trust', jobWrapper(trust))
await boss.work('timestampItem', jobWrapper(timestampItem))
await boss.work('indexItem', jobWrapper(indexItem))
await boss.work('indexAllItems', jobWrapper(indexAllItems))
await boss.work('auction', jobWrapper(auction))
await boss.work('earn', jobWrapper(earn))
await boss.work('streak', jobWrapper(computeStreaks))
@ -113,12 +100,18 @@ async function work () {
await boss.work('nip57', jobWrapper(nip57))
await boss.work('views-*', jobWrapper(views))
await boss.work('rankViews', jobWrapper(rankViews))
await boss.work('imgproxy', jobWrapper(imgproxy))
await boss.work('deleteItem', jobWrapper(deleteItem))
await boss.work('deleteUnusedImages', jobWrapper(deleteUnusedImages))
await boss.work('territoryBilling', jobWrapper(territoryBilling))
await boss.work('territoryRevenue', jobWrapper(territoryRevenue))
await boss.work('ofac', jobWrapper(ofac))
await boss.work('saltAndHashEmails', jobWrapper(saltAndHashEmails))
await boss.work('reminder', jobWrapper(remindUser))
await boss.work('settleActionError', jobWrapper(settleActionError))
await boss.work('settleAction', jobWrapper(settleAction))
await boss.work('holdAction', jobWrapper(holdAction))
await boss.work('checkInvoice', jobWrapper(checkInvoice))
await boss.work('thisDay', jobWrapper(thisDay))
console.log('working jobs')