diff --git a/.gitignore b/.gitignore index 927b838..2e1118c 100644 --- a/.gitignore +++ b/.gitignore @@ -131,6 +131,7 @@ dmypy.json # Data data/ go-ipfs/ +avalanchego-v1.7.3 *jpg *png *svg diff --git a/Makefile b/Makefile index 3ab93d6..31f24cd 100644 --- a/Makefile +++ b/Makefile @@ -20,5 +20,18 @@ install-ipfs: tar -xvzf go-ipfs_v0.10.0_linux-amd64.tar.gz cd go-ipfs && bash install.sh +install-avax: + wget https://github.com/ava-labs/avalanchego/releases/download/v1.7.3/avalanchego-linux-amd64-v1.7.3.tar.gz + tar -xzvf avalanchego-linux-amd64-v1.7.3.tar.gz + +run-ipfs: + ipfs daemon + +run-avax: + ./avalanchego-v1.7.3/avalanchego + +run-avax-test: + ./avalanchego-v1.7.3/avalanchego --network-id fuji + kill: pkill -e -f suchwowx diff --git a/suchwowx/config.py b/suchwowx/config.py index 7c93088..a646150 100644 --- a/suchwowx/config.py +++ b/suchwowx/config.py @@ -18,6 +18,656 @@ ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif', 'svg', 'mp4', 'webp'} MAX_CONTENT_LENGTH = 32 * 1024 * 1024 TEMPLATES_AUTO_RELOAD = getenv('TEMPLATES_AUTO_RELOAD', True) +# Contract +CONTRACT_ADDRESS = '0xBAb68B24068D21Fa862908818054c7e4d921db5A' # rinkeby ETH +CONTRACT_ABI = [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": False, + "inputs": [ + { + "indexed": True, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": True, + "internalType": "address", + "name": "approved", + "type": "address" + }, + { + "indexed": True, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": False, + "inputs": [ + { + "indexed": True, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": True, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": False, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "ApprovalForAll", + "type": "event" + }, + { + "anonymous": False, + "inputs": [ + { + "indexed": True, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": True, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": False, + "inputs": [ + { + "indexed": True, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": True, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": True, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function", + "constant": True + }, + { + "inputs": [], + "name": "contractCreator", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function", + "constant": True + }, + { + "inputs": [], + "name": "contractVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function", + "constant": True + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "creatorTips", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function", + "constant": True + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "creatorTokensMinted", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function", + "constant": True + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "creatorWowneroAddress", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function", + "constant": True + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "getApproved", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function", + "constant": True + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "isApprovedForAll", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function", + "constant": True + }, + { + "inputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "name": "metadataTokenId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function", + "constant": True + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function", + "constant": True + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function", + "constant": True + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ownerOf", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function", + "constant": True + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setApprovalForAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function", + "constant": True + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function", + "constant": True + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "tipperTips", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function", + "constant": True + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "tokenCreator", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function", + "constant": True + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "tokenMetadata", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function", + "constant": True + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "tokenTips", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function", + "constant": True + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function", + "constant": True + }, + { + "inputs": [ + { + "internalType": "string", + "name": "wowneroAddress", + "type": "string" + } + ], + "name": "set_wownero_address", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "metadataIPFSHash", + "type": "string" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "tip", + "outputs": [], + "stateMutability": "payable", + "type": "function", + "payable": True + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "tokenURI", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function", + "constant": True + } +] + # Logging LOGGING_CONFIG = { 'version': 1, diff --git a/suchwowx/routes.py b/suchwowx/routes.py index 15fd0df..8c29583 100644 --- a/suchwowx/routes.py +++ b/suchwowx/routes.py @@ -1,11 +1,12 @@ -import ipfsApi from os import path from secrets import token_urlsafe from json import loads, dumps -from requests.exceptions import HTTPError +import ipfsApi from flask import Blueprint, render_template, request, current_app from flask import send_from_directory, redirect, flash, url_for +from requests.exceptions import HTTPError +from web3 import Web3 from suchwowx.models import Meme from suchwowx.factory import db @@ -17,7 +18,15 @@ bp = Blueprint('meta', 'meta') @bp.route('/') def index(): memes = Meme.query.filter().order_by(Meme.create_date.desc()) - return render_template('index.html', memes=memes) + w3 = Web3(Web3.HTTPProvider('http://127.0.0.1:9650')) + contract_address = w3.toChecksumAddress(config.CONTRACT_ADDRESS) + contract_abi = config.CONTRACT_ABI + contract = w3.eth.contract( + address=contract_address, + abi=contract_abi + ) + # total_supply = contract.functions.totalSupply().call() + return render_template('index.html', memes=memes, contract=contract) @bp.route('/new', methods=['GET', 'POST']) def new(): @@ -100,3 +109,7 @@ def meme(meme_id): if not meme: return redirect('/') return render_template('meme.html', meme=meme) + +@bp.route('/creator/') +def creator(handle): + return render_template('includes/creator.html') diff --git a/suchwowx/static/css/custom.css b/suchwowx/static/css/custom.css new file mode 100644 index 0000000..5f1b3c0 --- /dev/null +++ b/suchwowx/static/css/custom.css @@ -0,0 +1,9 @@ +.screen { + padding-bottom: 1em; + max-width: 500px; + margin: 0 auto; +} + +/* #memeImage { + cursor: zoom-in; +} */ diff --git a/suchwowx/templates/includes/creator.html b/suchwowx/templates/includes/creator.html new file mode 100644 index 0000000..acdabd2 --- /dev/null +++ b/suchwowx/templates/includes/creator.html @@ -0,0 +1,11 @@ + + + + + +

Wownero Address: ?

+
+ × +
+
+
diff --git a/suchwowx/templates/includes/head.html b/suchwowx/templates/includes/head.html index 540a660..9cb5c47 100644 --- a/suchwowx/templates/includes/head.html +++ b/suchwowx/templates/includes/head.html @@ -8,5 +8,6 @@ + diff --git a/suchwowx/templates/includes/navbar.html b/suchwowx/templates/includes/navbar.html new file mode 100644 index 0000000..4749c85 --- /dev/null +++ b/suchwowx/templates/includes/navbar.html @@ -0,0 +1,13 @@ +
+

+ SuchWowX. +

+

+ Memes. Interplanetary! +

+ {% if request.path == '/' %} + New Meme + {% else %} + Go Home + {% endif %} +
diff --git a/suchwowx/templates/index.html b/suchwowx/templates/index.html index b57a42a..b9ce8e8 100644 --- a/suchwowx/templates/index.html +++ b/suchwowx/templates/index.html @@ -4,13 +4,7 @@
-

- SuchWowX. -

-

- Memes. Interplanetary! -

- New Meme + {% include 'includes/navbar.html' %} {% if get_flashed_messages(with_categories=true) %}

@@ -20,19 +14,16 @@ try installing the software and running the following:

$ ipfs daemon +

{% endif %} {% if memes %} -
- {% for meme in memes %} -
-

Meme: {{ meme }}

-

Upload path: {{ meme.upload_path }}

-

Meta IPFS: {{ meme.meta_ipfs_hash }}

-

Meme IPFS: {{ meme.meme_ipfs_hash }}

-

Title: {{ meme.title }}

-

Description: {{ meme.description }}

-

Creator handle: {{ meme.creator_handle }}

+ {% for _meme in memes | batch(4) %} + + {% endfor %} {% endif %}
diff --git a/suchwowx/templates/meme.html b/suchwowx/templates/meme.html index 9974579..5eb3906 100644 --- a/suchwowx/templates/meme.html +++ b/suchwowx/templates/meme.html @@ -4,37 +4,33 @@
-

- SuchWowX. -

-

- Memes. Interplanetary! -

- Go Home + + {% include 'includes/navbar.html' %} {% if meme %} -
-
-

Meme: {{ meme }}

-

Upload path: {{ meme.upload_path }}

-

Meta IPFS: {{ meme.meta_ipfs_hash }}

-

Meme IPFS: {{ meme.meme_ipfs_hash }}

-

Title: {{ meme.title }}

-

Description: {{ meme.description }}

-

Creator handle: {{ meme.creator_handle }}

+
+
{% if meme.upload_path.endswith('mp4') %} {% else %} - + {% endif %} +
+

Title: {{ meme.title }}

+

Description: {{ meme.description }}

+

Creator handle: {{ meme.creator_handle }}

+

Meta IPFS: {{ meme.meta_ipfs_hash }}

+

Meme IPFS: {{ meme.meme_ipfs_hash }}

+

Meme ID: {{ meme }}

{% endif %}
+