flask web app (wip)
This commit is contained in:
parent
b9410f2986
commit
49384accf6
@ -1463,7 +1463,13 @@ async def main():
|
|||||||
logging.info("Restarting wallet_watch_loop")
|
logging.info("Restarting wallet_watch_loop")
|
||||||
await send_telegram_message("Restarting wallet_watch_loop")
|
await send_telegram_message("Restarting wallet_watch_loop")
|
||||||
|
|
||||||
|
|
||||||
|
from modules.webui import init_app
|
||||||
|
|
||||||
async def run_flask():
|
async def run_flask():
|
||||||
|
# loop = asyncio.get_running_loop()
|
||||||
|
# await loop.run_in_executor(None, lambda: app.run(debug=False, port=3001, use_reloader=False))
|
||||||
|
app = init_app()
|
||||||
loop = asyncio.get_running_loop()
|
loop = asyncio.get_running_loop()
|
||||||
await loop.run_in_executor(None, lambda: app.run(debug=False, port=3001, use_reloader=False))
|
await loop.run_in_executor(None, lambda: app.run(debug=False, port=3001, use_reloader=False))
|
||||||
|
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
from flask import Flask, jsonify, request
|
from flask import Flask, jsonify, request, render_template, redirect, url_for
|
||||||
from flask_login import LoginManager, UserMixin, login_user, login_required, current_user
|
from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user, current_user
|
||||||
import secrets
|
import secrets
|
||||||
from modules import storage # Import your storage module
|
from modules import storage
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__, template_folder='../templates', static_folder='../static')
|
||||||
app.config['SECRET_KEY'] = 'your-secret-key'
|
app.config['SECRET_KEY'] = 'your-secret-key'
|
||||||
login_manager = LoginManager(app)
|
login_manager = LoginManager(app)
|
||||||
|
login_manager.login_view = 'login'
|
||||||
|
|
||||||
class User(UserMixin):
|
class User(UserMixin):
|
||||||
def __init__(self, id, username, email):
|
def __init__(self, id, username, email):
|
||||||
@ -20,18 +21,34 @@ def load_user(user_id):
|
|||||||
return User(id=user_data['id'], username=user_data['username'], email=user_data['email'])
|
return User(id=user_data['id'], username=user_data['username'], email=user_data['email'])
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@app.route('/login', methods=['POST'])
|
@app.route('/')
|
||||||
def login():
|
def index():
|
||||||
data = request.json
|
return render_template('index.html')
|
||||||
username = data.get('username')
|
|
||||||
password = data.get('password')
|
|
||||||
|
|
||||||
user = storage.authenticate_user(username, password)
|
@app.route('/login', methods=['GET', 'POST'])
|
||||||
if user:
|
def login():
|
||||||
login_user(User(id=user['id'], username=user['username'], email=user['email']))
|
if request.method == 'POST':
|
||||||
return jsonify({'message': 'Login successful'}), 200
|
username = request.form.get('username')
|
||||||
else:
|
password = request.form.get('password')
|
||||||
return jsonify({'message': 'Invalid credentials'}), 401
|
|
||||||
|
user = storage.authenticate_user(username, password)
|
||||||
|
if user:
|
||||||
|
login_user(User(id=user['id'], username=user['username'], email=user['email']))
|
||||||
|
return redirect(url_for('dashboard'))
|
||||||
|
else:
|
||||||
|
return render_template('login.html', error='Invalid credentials')
|
||||||
|
return render_template('login.html')
|
||||||
|
|
||||||
|
@app.route('/logout')
|
||||||
|
@login_required
|
||||||
|
def logout():
|
||||||
|
logout_user()
|
||||||
|
return redirect(url_for('index'))
|
||||||
|
|
||||||
|
@app.route('/dashboard')
|
||||||
|
@login_required
|
||||||
|
def dashboard():
|
||||||
|
return render_template('dashboard.html')
|
||||||
|
|
||||||
@app.route('/generate_api_key', methods=['POST'])
|
@app.route('/generate_api_key', methods=['POST'])
|
||||||
@login_required
|
@login_required
|
||||||
|
@ -2,6 +2,7 @@ aiohttp==3.10.9
|
|||||||
base58==2.1.1
|
base58==2.1.1
|
||||||
dexscreener==1.1
|
dexscreener==1.1
|
||||||
Flask==3.0.3
|
Flask==3.0.3
|
||||||
|
flask-login
|
||||||
jupiter_python_sdk==0.0.2.0
|
jupiter_python_sdk==0.0.2.0
|
||||||
python-dotenv==1.0.1
|
python-dotenv==1.0.1
|
||||||
python-telegram-bot==21.6
|
python-telegram-bot==21.6
|
||||||
|
@ -0,0 +1,46 @@
|
|||||||
|
/* Add your custom styles here */
|
||||||
|
body {
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
line-height: 1.6;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
header {
|
||||||
|
background-color: #4A90E2;
|
||||||
|
color: white;
|
||||||
|
padding: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav ul {
|
||||||
|
list-style-type: none;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav ul li {
|
||||||
|
display: inline;
|
||||||
|
margin-right: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav ul li a {
|
||||||
|
color: white;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
main {
|
||||||
|
padding: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer {
|
||||||
|
background-color: #333;
|
||||||
|
color: white;
|
||||||
|
text-align: center;
|
||||||
|
padding: 1rem;
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
/* Add responsive styles for mobile devices */
|
||||||
|
}
|
@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
document.getElementById('connectWallet').addEventListener('click', async () => {
|
document.getElementById('connectWallet').addEventListener('click', async () => {
|
||||||
try {
|
try {
|
||||||
const { solana } is window;
|
const { solana } is window;
|
||||||
@ -26,3 +27,20 @@ document.getElementById('swapToken').addEventListener('click', () => {
|
|||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(data => alert(data.message));
|
.then(data => alert(data.message));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// Add your custom JavaScript here
|
||||||
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
const generateApiKeyButton = document.getElementById('generate-api-key');
|
||||||
|
const apiKeyDisplay = document.getElementById('api-key-display');
|
||||||
|
|
||||||
|
if (generateApiKeyButton) {
|
||||||
|
generateApiKeyButton.addEventListener('click', async () => {
|
||||||
|
const response = await fetch('/generate_api_key', { method: 'POST' });
|
||||||
|
const data = await response.json();
|
||||||
|
apiKeyDisplay.textContent = `Your API Key: ${data.api_key}`;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add more JavaScript for fetching and displaying wallet data, transactions, and holdings
|
||||||
|
});
|
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"name": "Crypto Portfolio Tracker",
|
||||||
|
"short_name": "CryptoTracker",
|
||||||
|
"start_url": "/",
|
||||||
|
"display": "standalone",
|
||||||
|
"background_color": "#ffffff",
|
||||||
|
"theme_color": "#4A90E2",
|
||||||
|
"icons": [
|
||||||
|
{
|
||||||
|
"src": "/static/images/logo-192x192.png",
|
||||||
|
"sizes": "192x192",
|
||||||
|
"type": "image/png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/static/images/logo-512x512.png",
|
||||||
|
"sizes": "512x512",
|
||||||
|
"type": "image/png"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
// Add service worker code for offline functionality and caching
|
||||||
|
self.addEventListener('install', (event) => {
|
||||||
|
// Perform install steps
|
||||||
|
});
|
||||||
|
|
||||||
|
self.addEventListener('fetch', (event) => {
|
||||||
|
// Handle fetch events
|
||||||
|
});
|
36
crypto/sol/templates/base.html
Normal file
36
crypto/sol/templates/base.html
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>{% block title %}Crypto Portfolio Tracker{% endblock %}</title>
|
||||||
|
<link rel="stylesheet" href="{{ url_for('static', filename='css/styles.css') }}">
|
||||||
|
<link rel="manifest" href="{{ url_for('static', filename='manifest.json') }}">
|
||||||
|
<meta name="theme-color" content="#4A90E2">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<header>
|
||||||
|
<nav>
|
||||||
|
<ul>
|
||||||
|
<li><a href="{{ url_for('index') }}">Home</a></li>
|
||||||
|
{% if current_user.is_authenticated %}
|
||||||
|
<li><a href="{{ url_for('dashboard') }}">Dashboard</a></li>
|
||||||
|
<li><a href="{{ url_for('logout') }}">Logout</a></li>
|
||||||
|
{% else %}
|
||||||
|
<li><a href="{{ url_for('login') }}">Login</a></li>
|
||||||
|
{% endif %}
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<main>
|
||||||
|
{% block content %}{% endblock %}
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<footer>
|
||||||
|
<p>© 2023 Crypto Portfolio Tracker</p>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<script src="{{ url_for('static', filename='js/app.js') }}"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
23
crypto/sol/templates/dashboard.html
Normal file
23
crypto/sol/templates/dashboard.html
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h1>Dashboard</h1>
|
||||||
|
<p>Welcome, {{ current_user.username }}!</p>
|
||||||
|
|
||||||
|
<h2>Your Wallets</h2>
|
||||||
|
<div id="wallets"></div>
|
||||||
|
|
||||||
|
<h2>Recent Transactions</h2>
|
||||||
|
<div id="transactions"></div>
|
||||||
|
|
||||||
|
<h2>Holdings</h2>
|
||||||
|
<div id="holdings"></div>
|
||||||
|
|
||||||
|
<button id="generate-api-key">Generate API Key</button>
|
||||||
|
<p id="api-key-display"></p>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// Add JavaScript to fetch and display wallet data, transactions, and holdings
|
||||||
|
// Also add functionality for generating API key
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
@ -1,21 +1,6 @@
|
|||||||
<!DOCTYPE html>
|
{% extends "base.html" %}
|
||||||
<html lang="en">
|
|
||||||
<head>
|
{% block content %}
|
||||||
<meta charset="UTF-8">
|
<h1>Welcome to Crypto Portfolio Tracker</h1>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<p>Track your cryptocurrency investments with ease.</p>
|
||||||
<title>Token Swapper</title>
|
{% endblock %}
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>Token Swapper</h1>
|
|
||||||
<div>
|
|
||||||
<button id="connectWallet">Connect Phantom Wallet</button>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<input type="text" id="tokenName" placeholder="Enter Token Name">
|
|
||||||
<input type="number" id="amount" placeholder="Enter Amount">
|
|
||||||
<button id="swapToken">Swap Token</button>
|
|
||||||
</div>
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/@solana/web3.js"></script>
|
|
||||||
<script src="app.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
17
crypto/sol/templates/login.html
Normal file
17
crypto/sol/templates/login.html
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h1>Login</h1>
|
||||||
|
<form method="POST" action="{{ url_for('login') }}">
|
||||||
|
<label for="username">Username:</label>
|
||||||
|
<input type="text" id="username" name="username" required>
|
||||||
|
|
||||||
|
<label for="password">Password:</label>
|
||||||
|
<input type="password" id="password" name="password" required>
|
||||||
|
|
||||||
|
<button type="submit">Login</button>
|
||||||
|
</form>
|
||||||
|
{% if error %}
|
||||||
|
<p class="error">{{ error }}</p>
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
21
crypto/sol/templates/swap.html
Normal file
21
crypto/sol/templates/swap.html
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Token Swapper</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Token Swapper</h1>
|
||||||
|
<div>
|
||||||
|
<button id="connectWallet">Connect Phantom Wallet</button>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<input type="text" id="tokenName" placeholder="Enter Token Name">
|
||||||
|
<input type="number" id="amount" placeholder="Enter Amount">
|
||||||
|
<button id="swapToken">Swap Token</button>
|
||||||
|
</div>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/@solana/web3.js"></script>
|
||||||
|
<script src="app.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
x
Reference in New Issue
Block a user