getting some chain syncing going, still very rough

main
lza_menace 3 years ago
parent c6289bd816
commit 19738fccc5

3
.gitignore vendored

@ -132,9 +132,6 @@ dmypy.json
data/ data/
go-ipfs/ go-ipfs/
avalanchego-v1.7.3 avalanchego-v1.7.3
*jpg
*png
*svg
*mp4 *mp4
*webp *webp
*mkv *mkv

@ -1,6 +1,11 @@
import requests
from flask import Blueprint from flask import Blueprint
from secrets import token_urlsafe
from suchwowx.factory import db from suchwowx.factory import db
from suchwowx.helpers import get_eth_contract
from suchwowx.models import Meme, User
from suchwowx import config
bp = Blueprint('cli', 'cli', cli_group=None) bp = Blueprint('cli', 'cli', cli_group=None)
@ -9,3 +14,49 @@ bp = Blueprint('cli', 'cli', cli_group=None)
@bp.cli.command('init') @bp.cli.command('init')
def init(): def init():
db.create_all() db.create_all()
@bp.cli.command('sync-avax')
def sync_avax():
"""
Synchronize your local database with the tokens minted on Avalanche blockchain.
"""
contract = get_eth_contract()
total_supply = contract.functions.totalSupply().call()
# walk backwards through all tokens at top of supply
# until you've accounted for the last known
for i in range(total_supply, 0, -1):
# first get metadata ipfs hash
deets = contract.functions.tokenMeme(i).call()
try:
meme_exists = Meme.query.filter(Meme.meta_ipfs_hash == deets[5]).first() # noqa
user_exists = User.query.filter(User.public_address == deets[4].lower()).first() # noqa
if meme_exists:
if not meme_exists.minted:
meme_exists.minted = True
db.session.commit()
print(f'[+] Marked existing meme {meme_exists.id} as minted')
else:
print(deets)
if not user_exists:
user_exists = User(
public_address=deets[4].lower()
)
db.session.add(user_exists)
db.session.commit()
user_exists.handle = f'anon{user_exists.id}-{token_urlsafe(6)}'
db.session.commit()
print(f'[+] Created user {user_exists.handle}')
res = requests.get(f'{config.IPFS_SERVER}/ipfs/{deets[5]}', timeout=30).json()
meme = Meme(
title=res['name'],
description=res['description'],
user_id=user_exists.id,
meta_ipfs_hash=deets[5],
meme_ipfs_hash=res['image'].split('ipfs://')[1],
minted=True
)
db.session.add(meme)
db.session.commit()
print(f'[+] Added new meme {meme.id}')
except Exception as e:
print(e)

@ -8,6 +8,7 @@ SECRET_KEY = getenv('SECRET_KEY', 'yyyyyyyyyyyyy')
DATA_FOLDER = getenv('DATA_FOLDER', '/path/to/uploads') DATA_FOLDER = getenv('DATA_FOLDER', '/path/to/uploads')
SERVER_NAME = getenv('SERVER_NAME', '127.0.0.1:5000') SERVER_NAME = getenv('SERVER_NAME', '127.0.0.1:5000')
IPFS_SERVER = getenv('IPFS_SERVER', 'http://127.0.0.1:8080') IPFS_SERVER = getenv('IPFS_SERVER', 'http://127.0.0.1:8080')
AVAX_RPC = getenv('AVAX_RPC', 'https://api.avax-test.network/ext/bc/C/rpc')
# Cache # Cache
CACHE_HOST = getenv('CACHE_HOST', 'localhost') CACHE_HOST = getenv('CACHE_HOST', 'localhost')

@ -10,7 +10,7 @@ from suchwowx import config
db = SQLAlchemy() db = SQLAlchemy()
w3 = Web3(Web3.HTTPProvider('http://127.0.0.1:9650')) # noqa w3 = Web3(Web3.HTTPProvider(config.AVAX_RPC))
def setup_db(app: Flask, db: SQLAlchemy = db): def setup_db(app: Flask, db: SQLAlchemy = db):

@ -6,6 +6,19 @@ from suchwowx.factory import w3
from suchwowx import config from suchwowx import config
def get_eth_contract():
"""
Return a web3 contract object with the currently
deployed SuchWowX smart contract.
"""
contract_abi = config.CONTRACT_ABI
contract_address = w3.toChecksumAddress(config.CONTRACT_ADDRESS)
return w3.eth.contract(
address=contract_address,
abi=contract_abi
)
def verify_signature(message, signature, public_address): def verify_signature(message, signature, public_address):
msg = encode_defunct(text=message) msg = encode_defunct(text=message)
recovered = w3.eth.account.recover_message(msg, signature=signature) recovered = w3.eth.account.recover_message(msg, signature=signature)

@ -21,15 +21,7 @@ def index():
memes = Meme.query.filter( memes = Meme.query.filter(
Meme.approved == True Meme.approved == True
).order_by(Meme.create_date.desc()) ).order_by(Meme.create_date.desc())
w3 = Web3(Web3.HTTPProvider('http://127.0.0.1:9650')) return render_template('index.html', memes=memes)
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('/mod') @bp.route('/mod')

@ -27,3 +27,8 @@
.wrap { .wrap {
word-wrap: break-word; word-wrap: break-word;
} }
.mintedAVAX {
background-color: rgba(242,37,52,.2);
border: 2px solid rgba(243,37,52,1);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

@ -1,8 +1,9 @@
{# expects meme var #} {# expects meme var #}
<div class="card"> <div class="card {% if meme.minted %}mintedAVAX{% endif %}">
<div class="card-image"> <div class="card-image">
<figure class="image"> <figure class="image">
<a href="{{ url_for('meme.show', meme_id=meme.id) }}"> <a href="{{ url_for('meme.show', meme_id=meme.id) }}">
{% if meme.file_name %}
{% if meme.file_name.endswith('mp4') %} {% if meme.file_name.endswith('mp4') %}
<video class="img-fluid" {% if not request.MOBILE %}autoplay{% else %}controls{% endif %} muted loop> <video class="img-fluid" {% if not request.MOBILE %}autoplay{% else %}controls{% endif %} muted loop>
<source src="{{ url_for('meta.uploaded_file', filename=meme.file_name) }}" type="video/mp4"> <source src="{{ url_for('meta.uploaded_file', filename=meme.file_name) }}" type="video/mp4">
@ -11,6 +12,9 @@
{% else %} {% else %}
<img alt="{{ meme.title }}" src="{{ url_for('meta.uploaded_file', filename=meme.file_name) }}" width="200px" class="img-fluid" style="" /> <img alt="{{ meme.title }}" src="{{ url_for('meta.uploaded_file', filename=meme.file_name) }}" width="200px" class="img-fluid" style="" />
{% endif %} {% endif %}
{% else %}
<img alt="{{ meme.title }}" src="{{ config.IPFS_SERVER }}/ipfs/{{ meme.meme_ipfs_hash }}" width="200px" class="img-fluid" style="" />
{% endif %}
</a> </a>
</figure> </figure>
</div> </div>

@ -19,6 +19,7 @@
<div id="screen"> <div id="screen">
<div class="screen"> <div class="screen">
{% if meme.file_name %}
{% if meme.file_name.endswith('mp4') %} {% if meme.file_name.endswith('mp4') %}
<video style="max-height: 60vh!important;max-width:100%;" {% if not request.MOBILE %}autoplay{% else %}controls{% endif %} muted loop> <video style="max-height: 60vh!important;max-width:100%;" {% if not request.MOBILE %}autoplay{% else %}controls{% endif %} muted loop>
<source src="{{ meme_url }}" type="video/mp4"> <source src="{{ meme_url }}" type="video/mp4">
@ -27,10 +28,14 @@
{% else %} {% else %}
<img src="{{ meme_url }}" id="memeImage" /> <img src="{{ meme_url }}" id="memeImage" />
{% endif %} {% endif %}
{% endif %}
<br/> <br/>
<p>Title: <strong>{{ meme.title }}</strong></p> <p>Title: <strong>{{ meme.title }}</strong></p>
<p>Description: <strong>{{ meme.description }}</strong></p> <p>Description: <strong>{{ meme.description }}</strong></p>
<p>Poster Address: <a href="{{ url_for('user.show', handle=meme.user.handle) }}">{{ meme.user.handle }}</a></p> <p>Poster Address: <a href="{{ url_for('user.show', handle=meme.user.handle) }}">{{ meme.user.handle }}</a></p>
{% if meme.user.wownero_address %}
<p>Wownero Address: <strong><span style="word-wrap: break-word">{{ meme.user.wownero_address }}</strong></p>
{% endif %}
{% if meme.meta_ipfs_hash %} {% if meme.meta_ipfs_hash %}
<p>Meta IPFS: <a href="{{ meta_url }}" target=_self up-preload up-follow=".container">{{ meme.meta_ipfs_hash }}</a></p> <p>Meta IPFS: <a href="{{ meta_url }}" target=_self up-preload up-follow=".container">{{ meme.meta_ipfs_hash }}</a></p>
{% endif %} {% endif %}
@ -42,12 +47,14 @@
<div class="modal-background"></div> <div class="modal-background"></div>
<div class="modal-card"> <div class="modal-card">
<header class="modal-card-head"> <header class="modal-card-head">
<p class="modal-card-title">Modal title</p> <p class="modal-card-title">Tip meme in WOW</p>
<button class="delete" aria-label="close"></button> <button class="delete" aria-label="close" onclick="closeModal('profileModal')" id="closeModal"></button>
</header> </header>
<section class="modal-card-body"> <section class="modal-card-body">
<p style="word-wrap: break-word;">Wownero Address: {{ meme.user.wownero_address }}</p> <p style="word-wrap: break-word;">Wownero Address: <span id="wowneroAddress">{{ meme.user.wownero_address | default('?') }}</span></p>
</section> </section>
<footer class="modal-card-foot">
</footer>
</div> </div>
</div> </div>
{% if not meme.approved %} {% if not meme.approved %}
@ -63,19 +70,19 @@
{% else %} {% else %}
<br/> <br/>
<div id="tipButtons" class="columns" style="display:none;"> <div id="tipButtons" class="columns" style="display:none;">
<div class="column"> <!-- <div class="column">
<a class="button is-info is-12 column" onclick="tipAVAX()">Tip AVAX</a> <a class="button is-info is-12 column" onclick="tipAVAX()">Tip AVAX</a>
</div> </div>
<div class="column"> <div class="column">
<a class="button is-info is-12 column" onclick="tipWOWX()">Tip WOWX</a> <a class="button is-info is-12 column" onclick="tipWOWX()">Tip WOWX</a>
</div> </div> -->
<div class="column"> <div class="column">
<a class="button is-info is-12 column" onclick="tipWOW()">Tip WOW</a> <a class="button is-info is-12 column" onclick="tipWOW()">Tip</a>
</div> </div>
</div> </div>
<div id="mintButton" class="columns" style="display:none;"> <div id="mintButton" class="columns" style="display:none;">
<div class="column"> <div class="column">
<a class="button is-danger is-12 column" onclick="mint()">Mint</a> <a class="button is-danger is-12 column" onclick="mint()" id="mintButtonLoading">Mint</a>
</div> </div>
</div> </div>
{% endif %} {% endif %}
@ -96,8 +103,23 @@
} else { } else {
document.getElementById('mintButton').style.display = "flex"; document.getElementById('mintButton').style.display = "flex";
} }
try {
_walletAddress = w3.utils.toChecksumAddress('{{ meme.user.public_address }}');
const userProfile = await contract.methods.userProfile(_walletAddress).call();
console.log(userProfile)
if (userProfile.wowneroAddress){document.getElementById('wowneroAddress').innerHTML = userProfile.wowneroAddress};
} catch(e) {
console.log(e);
}
}); });
async function tipWOW() {
document.getElementById('profileModal').classList.add('is-active');
document.getElementById('closeModal').onclick = () => {
document.getElementById('profileModal').classList.remove('is-active');
}
}
async function tipAVAX() { async function tipAVAX() {
const tokenId = await getTokenID('{{ meme.meta_ipfs_hash }}'); const tokenId = await getTokenID('{{ meme.meta_ipfs_hash }}');
const walletAddress = await getMetamaskAccount(); const walletAddress = await getMetamaskAccount();
@ -110,7 +132,7 @@
notif(`Tipping meme "{{ meme.id | shorten_address }}" by "{{ meme.user.handle }} ({{ meme.user.public_address | shorten_address }})" to the Avalanche blockchain.`, 'info'); notif(`Tipping meme "{{ meme.id | shorten_address }}" by "{{ meme.user.handle }} ({{ meme.user.public_address | shorten_address }})" to the Avalanche blockchain.`, 'info');
let res = await contract.methods.tipAVAX(tokenId).send({ let res = await contract.methods.tipAVAX(tokenId).send({
from: walletAddress, from: walletAddress,
value: 1000000000000000, value: 1,
gasPrice: gasPrice, gasPrice: gasPrice,
gas: gasLimit gas: gasLimit
}); });
@ -126,6 +148,7 @@
notif('Already minted!', 'warning'); notif('Already minted!', 'warning');
return return
} }
document.getElementById('mintButtonLoading').classList.add('is-active');
const walletAddress = await getMetamaskAccount(); const walletAddress = await getMetamaskAccount();
const gasPrice = await w3.eth.getGasPrice(); const gasPrice = await w3.eth.getGasPrice();
const gasLimit = await contract.methods.mint("{{ meme.meta_ipfs_hash }}", "{{ meme.user.public_address }}").estimateGas({from: walletAddress}, function(err, gas){ const gasLimit = await contract.methods.mint("{{ meme.meta_ipfs_hash }}", "{{ meme.user.public_address }}").estimateGas({from: walletAddress}, function(err, gas){
@ -140,6 +163,7 @@
gas: gasLimit gas: gasLimit
}); });
console.log(res); console.log(res);
document.getElementById('mintButtonLoading').classList.remove('is-active');
window.location.href = ""; window.location.href = "";
} catch(e) { } catch(e) {
notif(e.message, 'warning'); notif(e.message, 'warning');

Loading…
Cancel
Save