705 lines
14 KiB
Bash
Executable File
705 lines
14 KiB
Bash
Executable File
#!/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
|
|
echo "docker compose is not installed"
|
|
echo "installation instructions are here: https://docs.docker.com/desktop/"
|
|
exit 0
|
|
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 "$@"
|
|
}
|
|
|
|
docker__exec() {
|
|
if [ ! -x "$(command -v docker)" ]; then
|
|
echo "docker is not installed"
|
|
echo "installation instructions are here: https://docs.docker.com/desktop/"
|
|
exit 0
|
|
fi
|
|
|
|
DOCKER_CLI_HINTS=false command docker exec -i "$@"
|
|
}
|
|
|
|
docker__sn_lnd() {
|
|
t=$1
|
|
if [ "$t" = "-t" ]; then
|
|
shift
|
|
else
|
|
t=""
|
|
fi
|
|
|
|
docker__exec $t -u lnd sn_lnd lncli "$@"
|
|
}
|
|
|
|
docker__stacker_lnd() {
|
|
t=$1
|
|
if [ "$t" = "-t" ]; then
|
|
shift
|
|
else
|
|
t=""
|
|
fi
|
|
|
|
docker__exec $t -u lnd stacker_lnd lncli "$@"
|
|
}
|
|
|
|
docker__stacker_cln() {
|
|
t=$1
|
|
|
|
if [ "$t" = "-t" ]; then
|
|
shift
|
|
else
|
|
t=""
|
|
fi
|
|
|
|
if [ "$1" = "get_onion" ]; then
|
|
onion="$(docker__exec -t stacker_cln cat /home/clightning/.tor/hidden_service/hostname | tr -d '[:space:]')"
|
|
echo "$onion:3010"
|
|
exit 0
|
|
fi
|
|
|
|
docker__exec $t -u clightning stacker_cln lightning-cli --regtest "$@"
|
|
}
|
|
|
|
sndev__start() {
|
|
shift
|
|
|
|
if [ $# -eq 0 ]; then
|
|
docker__compose up --build
|
|
exit 0
|
|
fi
|
|
|
|
docker__compose up "$@"
|
|
}
|
|
|
|
sndev__help_start() {
|
|
help="
|
|
start the sndev env
|
|
|
|
USAGE
|
|
$ sndev start [OPTIONS] [SERVICE...]
|
|
|
|
OPTIONS"
|
|
|
|
echo "$help"
|
|
docker__compose up --help | awk '/Options:/{y=1;next}y'
|
|
}
|
|
|
|
sndev__stop() {
|
|
shift
|
|
docker__compose down "$@"
|
|
}
|
|
|
|
sndev__help_stop() {
|
|
help="
|
|
stop the sndev env
|
|
|
|
USAGE
|
|
$ sndev stop [OPTIONS] [SERVICE...]
|
|
|
|
OPTIONS"
|
|
|
|
echo "$help"
|
|
docker__compose down --help | awk '/Options:/{y=1;next}y'
|
|
}
|
|
|
|
sndev__open() {
|
|
shift
|
|
service=$(docker__compose ps $1 --format '{{.Label "CONNECT"}}')
|
|
if [ -z "$service" ]; then
|
|
echo "no url found for $1"
|
|
exit 1
|
|
fi
|
|
service="http://$service"
|
|
|
|
echo "opening $1 ... $service"
|
|
if [ "$(uname)" = "Darwin" ]; then
|
|
open $service
|
|
elif [ "$(uname)" = "Linux" ]; then
|
|
xdg-open $service
|
|
elif [ "$(uname)" = "Windows_NT" ]; then
|
|
start $service
|
|
fi
|
|
}
|
|
|
|
sndev__help_open() {
|
|
help="
|
|
open a container's url if it has one
|
|
|
|
USAGE
|
|
$ sndev open SERVICE
|
|
|
|
OPTIONS
|
|
no options currently exist
|
|
"
|
|
|
|
echo "$help"
|
|
}
|
|
|
|
sndev__restart() {
|
|
shift
|
|
docker__compose restart "$@"
|
|
}
|
|
|
|
sndev__help_restart() {
|
|
help="
|
|
restart the sndev env
|
|
|
|
USAGE
|
|
$ sndev restart [OPTIONS] [SERVICE...]
|
|
|
|
OPTIONS"
|
|
|
|
echo "$help"
|
|
docker__compose restart --help | awk '/Options:/{y=1;next}y'
|
|
}
|
|
|
|
sndev__logs() {
|
|
shift
|
|
if [ $# -eq 1 ]; then
|
|
docker__compose logs -t --tail=1000 -f "$@"
|
|
exit 0
|
|
fi
|
|
|
|
docker__compose logs "$@"
|
|
}
|
|
|
|
sndev__help_logs() {
|
|
help="
|
|
get logs from sndev env
|
|
|
|
USAGE
|
|
$ sndev logs [OPTIONS] [SERVICE...]
|
|
|
|
OPTIONS"
|
|
|
|
echo "$help"
|
|
docker__compose logs --help | awk '/Options:/{y=1;next}y'
|
|
}
|
|
|
|
sndev__status() {
|
|
shift
|
|
if [ $# -eq 0 ]; then
|
|
docker__compose ps -a --format 'table {{.Service}}\t{{.State}}\t{{.Status}}\t{{.Label "CONNECT"}}'
|
|
exit 0
|
|
fi
|
|
docker__compose ps "$@"
|
|
}
|
|
|
|
sndev__help_status() {
|
|
help="
|
|
show container status of sndev env
|
|
|
|
USAGE
|
|
$ sndev status [OPTIONS] [SERVICE...]
|
|
|
|
OPTIONS"
|
|
|
|
echo "$help"
|
|
docker__compose ps --help | awk '/Options:/{y=1;next}y'
|
|
}
|
|
|
|
sndev__delete() {
|
|
printf "this deletes containers, volumes, and orphans - are you sure? [y/N] "
|
|
read -r answer
|
|
if [ "$answer" = "y" ]; then
|
|
docker__compose down --volumes --remove-orphans
|
|
else
|
|
echo "delete cancelled"
|
|
fi
|
|
}
|
|
|
|
sndev__help_delete() {
|
|
help="
|
|
remove orphans and volumes from sndev env
|
|
equivalent to sndev stop --volumes --remove-orphans
|
|
|
|
USAGE
|
|
$ sndev delete
|
|
"
|
|
|
|
echo "$help"
|
|
}
|
|
|
|
sndev__fund_user() {
|
|
shift
|
|
if [ -z "$1" ]; then
|
|
echo "<nym> argument required"
|
|
sndev__help_fund_user
|
|
exit 1
|
|
fi
|
|
if [ -z "$2" ]; then
|
|
echo "<msats> argument required"
|
|
sndev__help_fund_user
|
|
exit 2
|
|
fi
|
|
re='^[0-9]+$'
|
|
if ! [[ $2 =~ $re ]]; then
|
|
echo "<msats> is not a positive integer"
|
|
sndev__help_fund_user
|
|
exit 3
|
|
fi
|
|
docker__exec db psql -U sn -d stackernews -q <<EOF
|
|
UPDATE users set msats = $2 where name = '$1';
|
|
EOF
|
|
}
|
|
|
|
sndev__help_fund_user() {
|
|
help="
|
|
fund a nym without using an LN invoice (local only)
|
|
|
|
USAGE
|
|
$ sndev fund_user <nym> <msats>
|
|
|
|
<nym> - the name of the user you want to fund
|
|
<msats> - the amount of millisatoshis to set the account to. Must be >= 0
|
|
"
|
|
|
|
echo "$help"
|
|
}
|
|
|
|
sndev__fund() {
|
|
shift
|
|
docker__stacker_lnd -t payinvoice "$@"
|
|
}
|
|
|
|
sndev__help_fund() {
|
|
help="
|
|
pay a bolt11 for funding
|
|
|
|
USAGE
|
|
$ sndev fund <bolt11> [OPTIONS]
|
|
|
|
OPTIONS"
|
|
|
|
echo "$help"
|
|
docker__stacker_lnd payinvoice -h | awk '/OPTIONS:/{y=1;next}y' | awk '!/^[\t ]+--pay_req value/'
|
|
}
|
|
|
|
sndev__cln_fund() {
|
|
shift
|
|
docker__stacker_cln -t pay "$@"
|
|
}
|
|
|
|
sndev__help_cln_fund() {
|
|
help="
|
|
pay a bolt11 for funding with CLN
|
|
|
|
USAGE
|
|
$ sndev cln_fund <bolt11>"
|
|
echo "$help"
|
|
}
|
|
|
|
sndev__cln_withdraw() {
|
|
shift
|
|
label=$(date +%s)
|
|
docker__stacker_cln -t invoice "$1" "$label" sndev | jq -r '.bolt11'
|
|
}
|
|
|
|
sndev__help_cln_withdraw() {
|
|
help="
|
|
create a bolt11 for withdrawal with CLN
|
|
|
|
USAGE
|
|
$ sndev cln_withdraw <amount msats>"
|
|
echo "$help"
|
|
}
|
|
|
|
sndev__withdraw() {
|
|
shift
|
|
docker__stacker_lnd addinvoice --amt "$@" | jq -r '.payment_request'
|
|
}
|
|
|
|
sndev__help_withdraw() {
|
|
help="
|
|
create a bolt11 for withdrawal
|
|
|
|
USAGE
|
|
$ sndev withdraw <amount sats> [OPTIONS]
|
|
|
|
OPTIONS"
|
|
|
|
echo "$help"
|
|
docker__stacker_lnd addinvoice -h | awk '/OPTIONS:/{y=1;next}y' | awk '!/^[\t ]+(--amt|--amt_msat) value/'
|
|
}
|
|
|
|
sndev__psql() {
|
|
shift
|
|
docker__exec -t db psql "$@" -U sn -d stackernews
|
|
}
|
|
|
|
sndev__help_psql() {
|
|
help="
|
|
open psql on db
|
|
|
|
USAGE
|
|
$ sndev psql [OPTIONS]
|
|
|
|
OPTIONS"
|
|
|
|
echo "$help"
|
|
docker__exec db psql --help | awk '/General options:/{y=1;next}y' | sed -n '/Connection options:/q;p' |
|
|
awk '!/^([\t ]+-l, --list)|([\t ]+-d, --dbname)|([\t ]+-\?, --help)|([\t ]--help=)/'
|
|
}
|
|
|
|
sndev__prisma() {
|
|
shift
|
|
docker__exec -t -u apprunner app npx prisma "$@"
|
|
}
|
|
|
|
sndev__help_prisma() {
|
|
help="
|
|
run prisma commands
|
|
|
|
USAGE
|
|
$ sndev prisma [COMMAND]
|
|
|
|
COMMANDS"
|
|
|
|
echo "$help"
|
|
sndev__prisma --help | awk '/Commands/{y=1;next}y' | awk '!/^([\t ]+init)|([\t ]+studio)/' | sed -n '/Flags/q;p'
|
|
}
|
|
|
|
sndev__lint() {
|
|
shift
|
|
docker__exec -t -u apprunner app npm run lint
|
|
}
|
|
|
|
sndev__help_lint() {
|
|
help="
|
|
run linters
|
|
|
|
USAGE
|
|
$ sndev lint
|
|
"
|
|
|
|
echo "$help"
|
|
}
|
|
|
|
sndev__compose() {
|
|
shift
|
|
docker__compose "$@"
|
|
}
|
|
|
|
sndev__help_compose() {
|
|
docker__compose --help
|
|
}
|
|
|
|
sndev__sn_lndcli() {
|
|
shift
|
|
docker__sn_lnd -t "$@"
|
|
}
|
|
|
|
sndev__help_sn_lndcli() {
|
|
docker__sn_lnd --help
|
|
}
|
|
|
|
sndev__stacker_lndcli() {
|
|
shift
|
|
docker__stacker_lnd -t "$@"
|
|
}
|
|
|
|
sndev__help_stacker_lndcli() {
|
|
docker__stacker_lnd --help
|
|
}
|
|
|
|
sndev__stacker_clncli() {
|
|
shift
|
|
docker__stacker_cln -t "$@"
|
|
}
|
|
|
|
sndev__help_stacker_clncli() {
|
|
docker__stacker_cln help
|
|
echo
|
|
echo "EXTRA:"
|
|
echo " get_onion get the onion address"
|
|
}
|
|
|
|
sndev__stacker_litcli() {
|
|
shift
|
|
docker__exec -t litd litcli -n regtest --rpcserver localhost:8444 "$@"
|
|
}
|
|
|
|
sndev__help_stacker_litcli() {
|
|
docker__exec -t litd litcli -h
|
|
}
|
|
|
|
__sndev__pr_track() {
|
|
json=$(curl -fsSH "Accept: application/vnd.github.v3+json" "https://api.github.com/repos/stackernews/stacker.news/pulls/$1")
|
|
case $(git config --get remote.origin.url) in
|
|
"http"*) url=$(echo "$json" | grep -e '"clone_url"' | head -n1 | sed -e 's/^.*"clone_url":[[:space:]]*"//; s/",[[:space:]]*$//') ;;
|
|
*) url=$(echo "$json" | grep -e '"ssh_url"' | head -n1 | sed -e 's/^.*"ssh_url":[[:space:]]*"//; s/",[[:space:]]*$//') ;;
|
|
esac
|
|
|
|
push=$(git remote -v | grep -e "$url .*push" | head -n1) || true
|
|
if [ -n "$push" ]; then
|
|
remote=$(echo "$push" | cut -f 1)
|
|
else
|
|
remote=$(echo "$json" | grep -e '"login"' | head -n1 | sed -e 's/^.*"login":[[:space:]]*"//; s/",[[:space:]]*$//')
|
|
git remote remove "$remote" 1>/dev/null 2>&1 || true
|
|
git remote add "$remote" "$url"
|
|
fi
|
|
|
|
ref=$(echo "$json" | grep -e '"ref"' | head -n1 | sed -e 's/^.*"ref":[[:space:]]*"//; s/",[[:space:]]*$//')
|
|
git fetch "$remote" "$ref"
|
|
git checkout -t -b "pr/$1" "$remote/$ref"
|
|
git config --local "remote.$remote.push" pr/$1:$ref
|
|
exit 0
|
|
}
|
|
|
|
__sndev__pr_detach() {
|
|
refspec="+refs/pull/$1/head:refs/remotes/pr/$1"
|
|
case $(git config --get remote.origin.url) in
|
|
"http"*) git fetch https://github.com/stackernews/stacker.news.git "$refspec" ;;
|
|
*) git fetch git@github.com:stackernews/stacker.news.git "$refspec" ;;
|
|
esac
|
|
git checkout "pr/$1"
|
|
exit 0
|
|
}
|
|
|
|
sndev__pr() {
|
|
shift
|
|
|
|
case $1 in
|
|
-t|--track)
|
|
call "__sndev__pr_track" "$2" ;;
|
|
*)
|
|
call "__sndev__pr_detach" "$1" ;;
|
|
esac
|
|
}
|
|
|
|
sndev__help_pr() {
|
|
help="
|
|
fetch and checkout a pr
|
|
|
|
USAGE
|
|
$ sndev pr [OPTIONS] <pr number>
|
|
|
|
OPTIONS
|
|
-t, --track track the pr in a new branch, creating a remote if necessary
|
|
defaults to checking out the pr in a detached state
|
|
"
|
|
|
|
echo "$help"
|
|
}
|
|
|
|
sndev__login() {
|
|
shift
|
|
if [ -z "$1" ]; then
|
|
echo "<nym> argument required"
|
|
sndev__help_login
|
|
exit 1
|
|
fi
|
|
# hardcode token for which is the hex digest of the sha256 of
|
|
# "SNDEV-TOKEN3_0W_PhDRZVanbeJsZZGIEljexkKoGbL6qGIqSwTjjI"
|
|
# next-auth concats the token with the secret from env and then sha256's it
|
|
token="d5fce54babffcb070c39f78d947761fd9ec37647fafcecb9734a3085a78e5c5e"
|
|
salt="202c90943c313b829e65e3f29164fb5dd7ea3370d7262c4159691c2f6493bb8b"
|
|
# upsert user with nym and nym@sndev.team
|
|
email="$1@sndev.team"
|
|
docker__exec db psql -U sn -d stackernews -q <<EOF
|
|
INSERT INTO users (name) VALUES ('$1') ON CONFLICT DO NOTHING;
|
|
UPDATE users SET email = '$email', "emailHash" = encode(digest(LOWER('$email')||'$salt', 'sha256'), 'hex') WHERE name = '$1';
|
|
INSERT INTO verification_requests (identifier, token, expires)
|
|
VALUES ('$email', '$token', NOW() + INTERVAL '1 day')
|
|
ON CONFLICT (token) DO UPDATE
|
|
SET identifier = '$email', expires = NOW() + INTERVAL '1 day';
|
|
EOF
|
|
|
|
echo
|
|
echo "open url in browser"
|
|
echo "http://localhost:3000/api/auth/callback/email?token=SNDEV-TOKEN&email=$1%40sndev.team"
|
|
echo
|
|
}
|
|
|
|
sndev__help_login() {
|
|
help="
|
|
login as a nym
|
|
|
|
USAGE
|
|
$ sndev login <nym>
|
|
"
|
|
|
|
echo "$help"
|
|
}
|
|
|
|
sndev__help_stacker_lnd() {
|
|
help="
|
|
|
|
USAGE
|
|
$ sndev stacker_lnd get_cert get the tls cert
|
|
$ sndev stacker_lnd get_onion get the onion address
|
|
"
|
|
|
|
echo "$help"
|
|
}
|
|
|
|
sndev__stacker_lnd() {
|
|
shift
|
|
if [ -z "$1" ]; then
|
|
echo "no command provided"
|
|
sndev__help_stacker_lnd
|
|
exit 1
|
|
fi
|
|
if [ "$1" = "get_cert" ]; then
|
|
echo $(docker__exec -t stacker_lnd openssl base64 -A -in /home/lnd/.lnd/tls.cert)
|
|
elif [ "$1" = "get_onion" ];
|
|
then
|
|
onion="$(docker__exec -t stacker_lnd cat /home/lnd/.tor/hidden_service/hostname | tr -d '[:space:]')"
|
|
echo "$onion:10009"
|
|
fi
|
|
}
|
|
|
|
sndev__help_lnbits() {
|
|
help="
|
|
|
|
USAGE
|
|
$ sndev stacker_lnbits get_onion get the onion address
|
|
"
|
|
}
|
|
|
|
sndev__lnbits() {
|
|
shift
|
|
if [ -z "$1" ]; then
|
|
echo "no command provided"
|
|
sndev__help_lnbits
|
|
exit 1
|
|
fi
|
|
if [ "$1" = "get_onion" ];
|
|
then
|
|
onion="$(docker__exec -t lnbits cat /app/.tor/hidden_service/hostname | tr -d '[:space:]')"
|
|
echo "$onion:5000"
|
|
fi
|
|
}
|
|
|
|
|
|
sndev__help_tor() {
|
|
help="
|
|
|
|
USAGE
|
|
$ sndev tor get_onion get the onion address
|
|
"
|
|
|
|
echo "$help"
|
|
}
|
|
|
|
sndev__tor() {
|
|
shift
|
|
if [ -z "$1" ]; then
|
|
echo "no command provided"
|
|
sndev__help_tor
|
|
exit 1
|
|
fi
|
|
if [ "$1" = "get_onion" ];
|
|
then
|
|
onion="$(docker__exec -t stacker_lnd cat /home/lnd/.tor/hidden_service/hostname | tr -d '[:space:]')"
|
|
echo "$onion"
|
|
fi
|
|
}
|
|
|
|
sndev__help() {
|
|
if [ $# -eq 2 ]; then
|
|
call "sndev__$1_$2" "$@"
|
|
exit 0
|
|
fi
|
|
|
|
help="
|
|
888
|
|
888
|
|
888
|
|
.d8888b 88888b. .d88888 .d88b. 888 888
|
|
88K 888 '88b d88' 888 d8P Y8b 888 888
|
|
'Y8888b. 888 888 888 888 88888888 Y88 88P
|
|
X88 888 888 Y88b 888 Y8b. Y8bd8P
|
|
88888P' 888 888 'Y88888 'Y8888 Y88P
|
|
|
|
manages a docker based stacker news development environment
|
|
|
|
USAGE
|
|
$ sndev [COMMAND]
|
|
$ sndev help [COMMAND]
|
|
|
|
COMMANDS
|
|
help show help
|
|
|
|
env:
|
|
start start env
|
|
stop stop env
|
|
restart restart env
|
|
status status of env
|
|
logs logs from env
|
|
delete delete env
|
|
|
|
sn:
|
|
login login as a nym
|
|
fund_user fund a nym without using an LN invoice
|
|
|
|
lnd:
|
|
fund pay a bolt11 for funding
|
|
withdraw create a bolt11 for withdrawal
|
|
|
|
cln:
|
|
cln_fund pay a bolt11 for funding with CLN
|
|
cln_withdraw create a bolt11 for withdrawal with CLN
|
|
|
|
db:
|
|
psql open psql on db
|
|
prisma run prisma 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
|
|
tor get_onion get the onion address
|
|
stacker_lnd get_cert get the tls cert
|
|
stacker_lnd get_onion get the onion address
|
|
stacker_cln get_onion get the onion address
|
|
lndbits get_onion get the onion address
|
|
"
|
|
echo "$help"
|
|
}
|
|
|
|
call() {
|
|
func=$1
|
|
if type "$func" 1>/dev/null 2>&1; then
|
|
# if it's sndev COMMAND help, then call help for that command
|
|
case $3 in
|
|
-h|--help|help)
|
|
call "sndev__help_$2"
|
|
exit 0
|
|
;;
|
|
esac
|
|
shift # remove func from args
|
|
"$func" "$@" # invoke our named function w/ all remaining arguments
|
|
else
|
|
# if it's sndev -h COMMAND, then call help for that command
|
|
case $2 in
|
|
-h|--help)
|
|
call "sndev__help_$3"
|
|
exit 0
|
|
;;
|
|
esac
|
|
sndev__help
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
call "sndev__$1" "$@" |