diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..5b7c32d --- /dev/null +++ b/.dockerignore @@ -0,0 +1,3 @@ +.venv +.git +/data diff --git a/Dockerfile-monero b/Dockerfile-monero new file mode 100644 index 0000000..1d5a7d0 --- /dev/null +++ b/Dockerfile-monero @@ -0,0 +1,38 @@ +FROM ubuntu:21.10 + +ENV MONERO_HASH 59e16c53b2aff8d9ab7a8ba3279ee826ac1f2480fbb98e79a149e6be23dd9086 +ENV MONERO_DL_URL https://downloads.getmonero.org/cli/monero-linux-x64-v0.17.2.0.tar.bz2 +ENV MONERO_DL_FILE monero.tar.bz2 +ENV MONERO_SUMS_FILE sha256sums + +WORKDIR /opt/monero + +# Update system and install dependencies +# Download Monero binaries from Github +# Confirm hashes match +# Install binaries to system path +# Clean up + +RUN apt-get update +RUN apt-get upgrade -y +RUN apt-get install -y tar wget bzip2 + +RUN wget -qO ${MONERO_DL_FILE} ${MONERO_DL_URL} +RUN echo "${MONERO_HASH} ${MONERO_DL_FILE}" > ${MONERO_SUMS_FILE} \ + && sha256sum -c ${MONERO_SUMS_FILE}; \ + if [ "$?" -eq 0 ]; \ + then \ + echo -e "[+] Hashes match - proceeding with container build"; \ + else \ + echo -e "[!] Hashes do not match - exiting"; \ + exit 5; \ + fi \ + && mkdir ./tmp \ + && tar xvf ${MONERO_DL_FILE} -C ./tmp --strip 1 \ + && mv ./tmp/* /usr/local/bin/ \ + && rm -rf ./tmp ${MONERO_SUMS_FILE} ${MONERO_DL_FILE} + +WORKDIR /tmp +COPY bin/run_wallet.sh /run_wallet.sh + +WORKDIR /data diff --git a/bin/run_wallet.sh b/bin/run_wallet.sh new file mode 100644 index 0000000..fa6b6dc --- /dev/null +++ b/bin/run_wallet.sh @@ -0,0 +1,38 @@ +#!/bin/sh + +export RPC_CREDS="${2}" +export DAEMON_ADDRESS=singapore.node.xmr.pm + +# Define the network we plan to operate our wallet in +if [[ "${1}" == "stagenet" ]]; then + export NETWORK=--stagenet + export PORT=38081 +elif [[ "${1}" == "testnet" ]]; then + export NETWORK=--testnet + export PORT=28081 +else + export NETWORK= + export PORT=18089 +fi + +# Create new wallet if it doesn't exist +if [[ ! -d /data/wallet ]]; then + monero-wallet-cli ${NETWORK} \ + --generate-new-wallet /data/wallet \ + --daemon-address http://${DAEMON_ADDRESS}:${PORT} \ + --trusted-daemon \ + --use-english-language-names \ + --mnemonic-language English +fi + +# Run RPC wallet +monero-wallet-rpc ${NETWORK} \ + --daemon-address http://${DAEMON_ADDRESS}:${PORT} \ + --wallet-file /data/wallet \ + --password "" \ + --rpc-login ${RPC_CREDS} \ + --rpc-bind-port 8000 \ + --rpc-bind-ip 0.0.0.0 \ + --confirm-external-bind \ + --log-file /data/wallet-rpc.log \ + --trusted-daemon diff --git a/docker-compose.yaml b/docker-compose.yaml index 9f2ff89..2e6b6eb 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -14,3 +14,13 @@ services: image: redis:latest ports: - 127.0.0.1:6379:6379 + wallet: + build: + context: . + dockerfile: Dockerfile-monero + ports: + - 127.0.0.1:8000:8000 + volumes: + - ./data/wallet:/data + command: + bash /run_wallet.sh "${XMR_WALLET_NETWORK}" "${XMR_WALLET_RPC_USER}:${XMR_WALLET_RPC_PASS}" diff --git a/env-example b/env-example index c90285b..5f9282d 100644 --- a/env-example +++ b/env-example @@ -9,6 +9,7 @@ XMR_WALLET_RPC_USER=xxxxxxxxxx XMR_WALLET_RPC_PASS=xxxxxxxxxxxxxxxxxxx XMR_WALLET_RPC_ENDPOINT=http://localhost:9090 XMR_DAEMON_URI=http://super.fast.node.xmr.pm:38089 +XMR_WALLET_NETWORK=stagenet SITE_NAME=xmrbackers SECRET_KEY=xxxxxxxxxxxxxxxxxxx diff --git a/xmrbackers/helpers.py b/xmrbackers/helpers.py new file mode 100644 index 0000000..8047b55 --- /dev/null +++ b/xmrbackers/helpers.py @@ -0,0 +1,17 @@ +from monero.wallet import Wallet +from monero.exceptions import WrongAddress + +from xmrbackers import config + +def check_tx_key(tx_id, tx_key, wallet_address): + try: + check_data = { + 'txid': tx_id, + 'tx_key': tx_key, + 'address': wallet_address + } + w = Wallet(port=8000, user=config.XMR_WALLET_RPC_USER, password=config.XMR_WALLET_RPC_PASS) + res = w._backend.raw_request('check_tx_key', check_data) + return res + except: + raise Exception('there was a problem i dont feel like writing good code for right now') diff --git a/xmrbackers/library/cache.py b/xmrbackers/library/cache.py index 3372afa..6109882 100644 --- a/xmrbackers/library/cache.py +++ b/xmrbackers/library/cache.py @@ -4,8 +4,9 @@ from datetime import timedelta from redis import Redis -from app.library.market import get_market_data -from app import config +# from xmrbackers.helpers import get_market_data +from xmrbackers.library.market import get_market_data +from xmrbackers import config class Cache(object): diff --git a/xmrbackers/routes/creator.py b/xmrbackers/routes/creator.py index a40365d..e550363 100644 --- a/xmrbackers/routes/creator.py +++ b/xmrbackers/routes/creator.py @@ -1,7 +1,12 @@ from quart import Blueprint, render_template, flash, redirect, url_for +from flask_login import current_user, login_required +from monero.wallet import Wallet from xmrbackers.forms import ConfirmSubscription -from xmrbackers.models import User, CreatorProfile, TextPost, SubscriptionMeta +from xmrbackers.models import User, CreatorProfile, BackerProfile, TextPost +from xmrbackers.models import Subscription, SubscriptionMeta +from xmrbackers.helpers import check_tx_key +from xmrbackers import config bp = Blueprint('creator', 'creator') @@ -53,12 +58,43 @@ async def subscription(username): await flash('That creator does not exist.') return redirect(url_for('meta.index')) -@bp.route('/subscription//confirm', methods=['POST']) -async def confirm_subscription(creator_id): +@bp.route('/subscription//confirm', methods=['POST']) +async def confirm_subscription(subscription_id): + # do checks here for SubscriptionMeta assumption + sm = SubscriptionMeta.get_or_none(subscription_id) form = ConfirmSubscription() if form.validate_on_submit(): - - return redirect(url_for('meta.index')) + w = Wallet( + port=8000, + user=config.XMR_WALLET_RPC_USER, + password=config.XMR_WALLET_RPC_PASS + ) + check_data = { + 'txid': form.tx_id.data, + 'tx_key': form.tx_key.data, + 'address': form.wallet_address.data + } + try: + res = w._backend.raw_request('check_tx_key', check_data) + except: + await flash(f'Invalid transaction! No subscription for you!') + return redirect(url_for('creator.show', username=sm.creator.user.username)) + + if res['received'] >= sm.atomic_xmr: + backer_profile = BackerProfile.select().where( + BackerProfile.user == current_user + ).first() + s = Subscription( + creator=sm.creator.id, + backer=backer_profile.id, + meta=sm.id, + ) + s.save() + await flash(f'Found valid transaction! You are now subscribed to {sm.creator.user.username}!') + return redirect(url_for('creator.show', username=sm.creator.user.username)) + else: + await flash('Not enough XMR sent! No subscription for you!') + return redirect(url_for('creator.show', username=sm.creator.user.username)) else: await flash('Unable to accept form POST.') return redirect(url_for('meta.index')) diff --git a/xmrbackers/templates/creator/subscription.html b/xmrbackers/templates/creator/subscription.html index c426d01..b337e22 100644 --- a/xmrbackers/templates/creator/subscription.html +++ b/xmrbackers/templates/creator/subscription.html @@ -15,7 +15,7 @@

XMR: {{ subscription_meta.atomic_xmr | from_atomic }}

Address: {{ subscription_meta.wallet_address }}

Hours: {{ subscription_meta.number_hours }}

-
+ {% for f in form %} {% if f.name == 'csrf_token' %} {{ f }}