generated from nathanwoodburn/python-webserver-template
Nathan Woodburn
1b7a35e51f
All checks were successful
Build Docker / BuildImage (push) Successful in 33s
343 lines
14 KiB
HTML
343 lines
14 KiB
HTML
<!DOCTYPE html>
|
|
<html data-bs-theme="dark" lang="en-au">
|
|
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
|
|
<title>Home - Vault | Woodburn</title>
|
|
<meta name="twitter:description" content="Woodburn Vault">
|
|
<meta name="twitter:image" content="https://vault.woodburn.au/assets/img/favicon.png">
|
|
<meta property="og:description" content="Woodburn Vault">
|
|
<meta property="og:type" content="website">
|
|
<meta property="og:title" content="Vault | Woodburn">
|
|
<meta name="twitter:card" content="summary">
|
|
<meta name="twitter:title" content="Vault | Woodburn">
|
|
<meta name="description" content="Woodburn Vault">
|
|
<meta property="og:image" content="https://vault.woodburn.au/assets/img/favicon.png">
|
|
<script type="application/ld+json">
|
|
{
|
|
"@context": "http://schema.org",
|
|
"@type": "WebSite",
|
|
"name": "Vault | Woodburn",
|
|
"url": "https://vault.woodburn.au"
|
|
}
|
|
</script>
|
|
<link rel="icon" type="image/png" sizes="512x512" href="assets/img/favicon.png">
|
|
<link rel="stylesheet" href="assets/bootstrap/css/bootstrap.min.css">
|
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Catamaran:100,200,300,400,500,600,700,800,900&display=swap">
|
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Lato:100,100i,300,300i,400,400i,700,700i,900,900i&display=swap">
|
|
</head>
|
|
|
|
<body>
|
|
<nav class="navbar navbar-expand-lg fixed-top bg-dark navbar-custom navbar-dark">
|
|
<div class="container"><a class="navbar-brand" href="#">Vault | Woodburn</a></div>
|
|
</nav>
|
|
<header class="text-center text-white masthead">
|
|
<div class="masthead-content">
|
|
<div class="container">
|
|
<h1 class="masthead-heading mb-0">Woodburn Vault</h1>
|
|
<h2 class="masthead-subheading mb-0">An easy way to buy into a diverse crypto portfolio.</h2>
|
|
<p>Woodburn Vault Balance: {{vault}} USD<br>stWDBRN Token Supply: {{supply}}<br>Current Token Value: {{value}} USD</p>
|
|
</div>
|
|
</div>
|
|
<div class="bg-circle-1 bg-circle"></div>
|
|
<div class="bg-circle-2 bg-circle"></div>
|
|
<div class="bg-circle-3 bg-circle"></div>
|
|
<div class="bg-circle-4 bg-circle"></div>
|
|
</header>
|
|
<section style="margin-top: 50px;margin-bottom: 50px;max-width: 100vw;overflow: hidden;">
|
|
<div class="text-center">
|
|
<h1 data-bs-toggle="tooltip" data-bss-tooltip="" id="chart-header" title="Toggle per token view" style="border-bottom: 5px dashed var(--bs-body-color);width: fit-content;margin: auto;margin-bottom: 20px;">Current Vault Contents</h1>
|
|
<div class="text-center" id="data-table"></div>
|
|
<div class="d-xl-flex justify-content-xl-center" id="pie-chart" style="margin: auto;"><script type="text/javascript">
|
|
window.onload = function () {
|
|
google.charts.load('current', { packages: ['corechart'] });
|
|
|
|
// Set a callback to run when the API is loaded.
|
|
google.charts.setOnLoadCallback(drawChart);
|
|
|
|
let isPerTokenView = false; // Track the current view state
|
|
let chart; // Declare the chart instance globally to reuse it
|
|
let options = {
|
|
pieSliceText: 'label',
|
|
tooltip: { isHtml: false },
|
|
legend: {
|
|
position: 'right',
|
|
textStyle: { color: 'white' }
|
|
},
|
|
backgroundColor: '#212529',
|
|
sliceVisibilityThreshold: 0.02
|
|
};
|
|
|
|
async function fetchData(apiUrl) {
|
|
try {
|
|
const response = await fetch(apiUrl);
|
|
if (!response.ok) throw new Error('Failed to fetch data from API');
|
|
return await response.json();
|
|
} catch (error) {
|
|
console.error('Error fetching data:', error);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
function transformDataForChart(data) {
|
|
const chartData = [];
|
|
for (const token in data) {
|
|
if (token !== 'total') {
|
|
chartData.push([
|
|
token, // Label for the chart
|
|
data[token].value, // Value for the chart
|
|
data[token].tooltip, // Tooltip for the chart
|
|
]);
|
|
}
|
|
}
|
|
return chartData;
|
|
}
|
|
|
|
async function drawChart() {
|
|
const apiUrl = '/api/v1/vault';
|
|
const data = await fetchData(apiUrl);
|
|
|
|
if (!data) return; // Exit if data fetch fails
|
|
|
|
const chartDataTable = new google.visualization.DataTable();
|
|
chartDataTable.addColumn('string', 'Token');
|
|
chartDataTable.addColumn('number', 'Value');
|
|
chartDataTable.addColumn({ type: 'string', role: 'tooltip', 'p': { 'html': false } });
|
|
chartDataTable.addRows(transformDataForChart(data));
|
|
|
|
chart = new google.visualization.PieChart(document.getElementById('pie-chart'));
|
|
resizeAndDraw(chart, chartDataTable, options);
|
|
updateText(true);
|
|
populateTable(data);
|
|
}
|
|
|
|
function updateText(isVault) {
|
|
let headerText = document.getElementById('chart-header');
|
|
if (isVault) {
|
|
headerText.innerText = 'Current Vault Contents';
|
|
} else {
|
|
headerText.innerText = 'Current Per Token Holding';
|
|
}
|
|
}
|
|
|
|
function populateTable(data) {
|
|
const tableContainer = document.getElementById('data-table');
|
|
tableContainer.innerHTML = ''; // Clear previous table data
|
|
|
|
// Create table elements
|
|
const table = document.createElement('table');
|
|
table.style.margin = 'auto';
|
|
table.style.borderCollapse = 'collapse';
|
|
table.style.maxWidth = '100%';
|
|
|
|
const thead = document.createElement('thead');
|
|
const tbody = document.createElement('tbody');
|
|
|
|
// Create table header
|
|
const headerRow = document.createElement('tr');
|
|
['Name', 'Amount', 'USD Value'].forEach((headerText, index) => {
|
|
const th = document.createElement('th');
|
|
th.textContent = headerText;
|
|
th.style.border = '1px solid #ccc';
|
|
th.style.padding = '8px 20px';
|
|
th.style.backgroundColor = '#333';
|
|
th.style.color = 'white';
|
|
|
|
if (headerText === 'USD Value') {
|
|
th.style.cursor = 'pointer'; // Make it clear this header is clickable
|
|
th.addEventListener('click', () => sortTableByValue(tbody));
|
|
}
|
|
|
|
headerRow.appendChild(th);
|
|
});
|
|
thead.appendChild(headerRow);
|
|
|
|
// Create table rows
|
|
for (const token in data) {
|
|
if (token !== 'total') {
|
|
const row = document.createElement('tr');
|
|
|
|
const nameCell = document.createElement('td');
|
|
nameCell.textContent = data[token].name;
|
|
nameCell.style.border = '1px solid #ccc';
|
|
nameCell.style.padding = '8px 20px';
|
|
|
|
const amountCell = document.createElement('td');
|
|
amountCell.textContent = `${data[token].amount} ${token}`;
|
|
amountCell.style.border = '1px solid #ccc';
|
|
amountCell.style.padding = '8px 20px';
|
|
|
|
const valueCell = document.createElement('td');
|
|
valueCell.textContent = data[token].value;
|
|
valueCell.style.border = '1px solid #ccc';
|
|
valueCell.style.padding = '8px 20px';
|
|
|
|
row.appendChild(nameCell);
|
|
row.appendChild(amountCell);
|
|
row.appendChild(valueCell);
|
|
tbody.appendChild(row);
|
|
}
|
|
}
|
|
|
|
table.appendChild(thead);
|
|
table.appendChild(tbody);
|
|
tableContainer.appendChild(table);
|
|
sortTableByValue(tbody);
|
|
}
|
|
|
|
// Function to sort table rows by the "Value" column
|
|
function sortTableByValue(tbody) {
|
|
const rows = Array.from(tbody.querySelectorAll('tr'));
|
|
const sortedRows = rows.sort((a, b) => {
|
|
const valueA = parseFloat(a.children[2].textContent) || 0;
|
|
const valueB = parseFloat(b.children[2].textContent) || 0;
|
|
return valueA - valueB;
|
|
});
|
|
|
|
// Reverse order if already sorted in ascending order
|
|
const isDecending = tbody.getAttribute('data-sort-order') === 'desc';
|
|
if (!isDecending) {
|
|
sortedRows.reverse();
|
|
tbody.setAttribute('data-sort-order', 'desc');
|
|
} else {
|
|
tbody.setAttribute('data-sort-order', 'asc');
|
|
}
|
|
|
|
// Append sorted rows back to the tbody
|
|
tbody.innerHTML = '';
|
|
sortedRows.forEach(row => tbody.appendChild(row));
|
|
}
|
|
|
|
|
|
|
|
async function toggleChart() {
|
|
isPerTokenView = !isPerTokenView;
|
|
const apiUrl = isPerTokenView ? '/api/v1/token' : '/api/v1/vault';
|
|
const data = await fetchData(apiUrl);
|
|
|
|
if (!data) return; // Exit if data fetch fails
|
|
|
|
const chartDataTable = new google.visualization.DataTable();
|
|
chartDataTable.addColumn('string', 'Token');
|
|
chartDataTable.addColumn('number', 'Value');
|
|
chartDataTable.addColumn({ type: 'string', role: 'tooltip', 'p': { 'html': false } });
|
|
chartDataTable.addRows(transformDataForChart(data));
|
|
|
|
resizeAndDraw(chart, chartDataTable, options);
|
|
updateText(!isPerTokenView);
|
|
populateTable(data);
|
|
}
|
|
|
|
function resizeAndDraw(chart, chartDataTable, options) {
|
|
function resizeChart() {
|
|
const width = window.innerWidth * 0.8;
|
|
const height = window.innerHeight * 0.5;
|
|
|
|
const dynamicOptions = { ...options };
|
|
if (width >= 700) {
|
|
dynamicOptions.width = width;
|
|
dynamicOptions.height = height;
|
|
}
|
|
|
|
chart.draw(chartDataTable, dynamicOptions);
|
|
}
|
|
|
|
resizeChart();
|
|
window.addEventListener('resize', resizeChart);
|
|
}
|
|
|
|
// Set button event listener
|
|
document.getElementById('chart-header').addEventListener('click', toggleChart);
|
|
};
|
|
</script>
|
|
</div><a class="btn btn-secondary" role="button" href="https://www.coingecko.com/en/portfolios/public/vault" target="_blank" style="margin: 10px;">View on Coingecko</a>
|
|
</div>
|
|
</section>
|
|
<section>
|
|
<div class="container">
|
|
<div class="row align-items-center">
|
|
<div class="col-lg-6 order-lg-2">
|
|
<div class="p-5"><img class="rounded-circle img-fluid" src="assets/img/01.jpg"></div>
|
|
</div>
|
|
<div class="col-lg-6 order-lg-1">
|
|
<div class="p-5">
|
|
<h2 class="display-4">1. Buy tokens</h2>
|
|
<p>To get started buy stWDBRN tokens at the current price to buy a percent of the vault value. The buy in value is then invested in various projects in order to increase the token's value.<br><br>Send USDC or SOL to vault.woodburn.sol and receive stWDBRN in exchange. (Note automated swaps only happen for deposits over 1 USDC)</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
<section>
|
|
<div class="container">
|
|
<div class="row align-items-center">
|
|
<div class="col-lg-6 order-lg-1">
|
|
<div class="p-5"><img class="rounded-circle img-fluid" src="assets/img/02.jpg"></div>
|
|
</div>
|
|
<div class="col-lg-6 order-lg-2">
|
|
<div class="p-5">
|
|
<h2 class="display-4">2. HODL and check price</h2>
|
|
<p>Hodl your stWDBRN while the value fluctuates. Check this site to see the current value.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
<section>
|
|
<div class="container">
|
|
<div class="row align-items-center">
|
|
<div class="col-lg-6 order-lg-2">
|
|
<div class="p-5"><img class="rounded-circle img-fluid" src="assets/img/03.jpg"></div>
|
|
</div>
|
|
<div class="col-lg-6 order-lg-1">
|
|
<div class="p-5">
|
|
<h2 class="display-4">3. Sell your tokens</h2>
|
|
<p>When you want to cash out just sell your tokens back to us at the current token price.</p><a class="btn btn-primary" role="button" href="mailto:vault@woodburn.au">Sell Tokens</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
<section>
|
|
<div class="container">
|
|
<div class="p-5">
|
|
<h2 class="display-4">Vault addresses</h2>
|
|
<div class="table-responsive">
|
|
<table class="table">
|
|
<thead>
|
|
<tr>
|
|
<th>Chain</th>
|
|
<th>Address</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td>Solana</td>
|
|
<td>NWywvhcqdkJsm1s9VVviPm9UfyDtyCW9t8kDb24PDPN</td>
|
|
</tr>
|
|
<tr>
|
|
<td>Cardano</td>
|
|
<td>stake1uy4qd785pcds7ph2jue2lrhhxa698c5959375lqdv3yphcgwc8qna</td>
|
|
</tr>
|
|
<tr>
|
|
<td>Sui</td>
|
|
<td>0x7e4fa1592e4fad084789f9fe1a4d7631a2e6477b658e777ae95351681bcbe8da</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
<footer class="py-5 bg-black">
|
|
<div class="container">
|
|
<p class="text-center text-white m-0 small">Copyright © Vault | Woodburn 2024</p>
|
|
</div>
|
|
</footer>
|
|
<script src="assets/bootstrap/js/bootstrap.min.js"></script>
|
|
<script src="assets/js/bs-init.js"></script>
|
|
<script src="https://www.gstatic.com/charts/loader.js"></script>
|
|
</body>
|
|
|
|
</html> |