<!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>Vault | Woodburn</title>
    <meta name="theme-color" content="#ffffff">
    <meta name="twitter:description" content="Woodburn Vault">
    <meta name="twitter:image" content="https://sol.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://sol.woodburn.au/assets/img/favicon.png">
    <script type="application/ld+json">
        {
            "@context": "http://schema.org",
            "@type": "WebSite",
            "name": "Vault | Woodburn",
            "url": "https://sol.woodburn.au"
        }
    </script>
    <link rel="icon" type="image/png" sizes="192x192" href="assets/img/favicon-192.png">
    <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="manifest" href="manifest.json" crossorigin="use-credentials">
    <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Catamaran:100,200,300,400,500,600,700,800,900&amp;display=swap">
    <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Lato:100,100i,300,300i,400,400i,700,700i,900,900i&amp;display=swap">
    <link rel="stylesheet" href="assets/fonts/font-awesome.min.css">
</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 ({{vault_aud}} AUD)<br>stWDBRN Token Supply: {{supply}}<br>Current Token Value: {{value}} USD ({{value_aud}} AUD)</p>
                <div style="display: inline-flex;">
                    <div class="input-group" style="width: fit-content;margin: 10px;"><span class="input-group-text">USD</span><input class="form-control" type="text" id="fiat-input" name="fiat" oninput="convert(&#39;fiat&#39;)" value="1"><button class="btn btn-primary" id="toggle-currency" type="button" onclick="toggleCurrency()">AUD</button></div><span class="fs-1 text-center d-xl-flex align-items-xl-center"><i class="fa fa-arrows-h"></i></span>
                    <div class="input-group" style="width: fit-content;margin: 10px;"><span class="input-group-text">stWDBRN</span><input class="form-control" type="text" id="stwdbrn-input" name="stwdbrn" oninput="convert(&#39;stwdbrn&#39;)"></div><script>
    let currentFiat = 'USD';

    function toggleCurrency() {
        document.getElementById('toggle-currency').textContent = currentFiat;
        currentFiat = currentFiat === 'USD' ? 'AUD' : 'USD';        
        document.querySelector('.input-group span').textContent = currentFiat;
        convert('fiat');
    }

    async function convert(source) {
        const fiatInput = document.getElementById('fiat-input');
        const stwdbrnInput = document.getElementById('stwdbrn-input');

        let endpoint = '';

        if (source === 'fiat') {
            const fiatAmount = parseFloat(fiatInput.value);
            if (isNaN(fiatAmount) || fiatAmount <= 0) {
                stwdbrnInput.value = '';
                return;
            }
            endpoint = `/api/v1/${currentFiat.toLowerCase()}/${fiatAmount}`;
        } else if (source === 'stwdbrn') {
            const stwdbrnAmount = parseFloat(stwdbrnInput.value);
            if (isNaN(stwdbrnAmount) || stwdbrnAmount <= 0) {
                fiatInput.value = '';
                return;
            }
            endpoint = `/api/v1/token/${stwdbrnAmount}`;
        } else {
            return;
        }

        try {
            const response = await fetch(endpoint);
            if (!response.ok) {
                throw new Error('Error fetching data');
            }

            const data = await response.json();
            if (source === 'fiat') {
                stwdbrnInput.value = parseFloat(data.stWDBRN).toFixed(2);
            } else if (source === 'stwdbrn') {
                fiatInput.value = parseFloat(data[currentFiat.toLowerCase()]).toFixed(2);
            }
        } catch (error) {
            console.error('Failed to fetch conversion data:', error);
        }
    }

    // on window load set the initial value of the input fields
    convert('fiat');

</script>
                </div>
            </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.05
        };

        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');

                    // If token in other investments
                    otherInvestments = ["Lending"]
                    if (otherInvestments.includes(token)) {
                        amountCell.textContent = `${data[token].amount} Positions`;
                    }
                    else {
                        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.toFixed(2)}`;
                    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) => {
                // Remove `$` and parse the value as float
                const valueA = parseFloat(a.children[2].textContent.replace('$', '')) || 0;
                const valueB = parseFloat(b.children[2].textContent.replace('$', '')) || 0;
                return valueA - valueB;
            });

            // Reverse order if already sorted in ascending order
            const isDescending = tbody.getAttribute('data-sort-order') === 'desc';
            if (!isDescending) {
                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 SOL or approved tokens to vault.woodburn.sol and receive stWDBRN in exchange. (Note automated swaps only happen for deposits over 1 USDC)</p><button class="btn btn-primary" id="video-button" type="button" style="margin: 20px;">See how</button><button class="btn btn-primary" id="approved-tokens-button" type="button" style="margin: 20px;">Approved Tokens</button><div id="video-div" style="margin-top: 20px; display: none;">
    <video id="video" style="max-width: 75%; height: auto;border-radius: 25px;" controls>
        <source src="https://cloud.woodburn.au/s/dsaF9MHMz9s5H2q/download/Screen_Recording_20241205_235805_Phantom.mp4"
            type="video/mp4">
    </video>
</div>

<div id="approved-tokens" style="margin-top: 20px; display: none;">
    <h2>Approved Tokens</h2>
    <p>The following tokens are approved to be used with the stWDBRN Vault.</p>
    <ul id="approvedTokenList"></ul>
</div>
<script>
    function toggleVideo() {
        var video = document.getElementById("video-div");
        var approvedtokens = document.getElementById("approved-tokens");
        if (video.style.display === "none") {
            video.style.display = "block";
            approvedtokens.style.display = "none";
        } else {
            video.style.display = "none";
        }
    }
    async function fetchAndRenderTokens() {
        try {
            // Fetch data from the API
            const response = await fetch('/api/v1/tokens');
            if (!response.ok) {
                throw new Error(`HTTP error! Status: ${response.status}`);
            }
            const tokens = await response.json();

            // Select the container where the list will be appended
            const tokenList = document.getElementById('approvedTokenList');

            // Loop through the tokens and create HTML for each
            tokens.forEach(token => {
                const listItem = document.createElement('li'); // Create a list item
                const anchor = document.createElement('a'); // Create a link element

                anchor.href = token.url; // Set the URL
                anchor.target = '_blank'; // Open the link in a new tab
                anchor.textContent = `${token.name} (${token.symbol.toUpperCase()})`; // Set the text

                listItem.appendChild(anchor); // Append the anchor to the list item
                tokenList.appendChild(listItem); // Append the list item to the container
            });
        } catch (error) {
            console.error('Error fetching or rendering tokens:', error);
        }
    }

    function toggleApprovedTokens() {
        // Fill in the approved tokens list if it isn't already
        if (document.getElementById("approvedTokenList").innerHTML === "") {
            fetchAndRenderTokens();
        }
        var approvedtokens = document.getElementById("approved-tokens");
        var video = document.getElementById("video-div");
        if (approvedtokens.style.display === "none") {
            approvedtokens.style.display = "block";
            video.style.display = "none";
        } else {
            approvedtokens.style.display = "none";
        }
    }

    document.getElementById("video-button").onclick = function () {
        toggleVideo();
    };
    document.getElementById("approved-tokens-button").onclick = function () {
        toggleApprovedTokens();
    };
</script>
                    </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 me at the current token price.</p><a class="btn btn-primary" role="button" href="mailto:vault@woodburn.au" target="_blank">Contact to 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><a href="https://explorer.solana.com/address/NWywvhcqdkJsm1s9VVviPm9UfyDtyCW9t8kDb24PDPN" target="_blank">NWywvhcqdkJsm1s9VVviPm9UfyDtyCW9t8kDb24PDPN</a></td>
                            </tr>
                            <tr>
                                <td>Cardano</td>
                                <td><a href="https://cardanoscan.io/stakekey/e12a06f8f40e1b0f06ea9732af8ef7377453e285a163ea7c0d64481be1" target="_blank">stake1uy4qd785pcds7ph2jue2lrhhxa698c5959375lqdv3yphcgwc8qna</a></td>
                            </tr>
                            <tr>
                                <td>Sui</td>
                                <td><a href="https://suivision.xyz/account/0x7e4fa1592e4fad084789f9fe1a4d7631a2e6477b658e777ae95351681bcbe8da" target="_blank">0x7e4fa1592e4fad084789f9fe1a4d7631a2e6477b658e777ae95351681bcbe8da</a></td>
                            </tr>
                            <tr>
                                <td>dYdX</td>
                                <td><a href="https://www.mintscan.io/dydx/address/dydx1ugraczuyfmxy8k38nps4fu7e5derryzx95fs8n" target="_blank">dydx1ugraczuyfmxy8k38nps4fu7e5derryzx95fs8n</a></td>
                            </tr>
                        </tbody>
                    </table>
                </div>
            </div>
            <div class="p-5">
                <h2 class="display-4">DeFi Positions</h2>
                <div class="table-responsive" id="defi-table">
                    <table class="table">
                        <thead>
                            <tr>
                                <th>Type</th>
                                <th>Initial Value</th>
                                <th>Date bought</th>
                                <th>Current Value</th>
                                <th>APY</th>
                                <th>Info</th>
                                <th>Last Updated</th>
                            </tr>
                        </thead>
                        <tbody>
                            <tr>
                                <td>Position Name</td>
                                <td>$0</td>
                                <td>00/00/00</td>
                                <td>$0</td>
                                <td>0%</td>
                                <td>Find out more</td>
                                <td>00/00/00</td>
                            </tr>
                        </tbody>
                    </table>
                </div><script type="text/javascript">
    async function fetchAndInjectDefiData() {
    try {
        // Fetch data from the API
        const response = await fetch('/api/v1/defi');
        if (!response.ok) {
            throw new Error('Network response was not ok' + response.statusText);
        }
        
        const data = await response.json();

        // Locate the table where the data will be injected
        const tableBody = document.querySelector('#defi-table tbody');

        if (!tableBody) {
            console.error('Table body not found. Make sure your table has an id "defi-table" with a <tbody> element.');
            return;
        }

        // Clear existing rows (optional, depending on use case)
        tableBody.innerHTML = '';

        const formatDate = (timestamp) => {
            const date = new Date(timestamp * 1000); // Convert seconds to milliseconds
            const day = String(date.getDate()).padStart(2, '0');
            const month = String(date.getMonth() + 1).padStart(2, '0'); // Months are zero-based
            const year = String(date.getFullYear()).slice(-2); // Get last two digits of the year
            return `${day}/${month}/${year}`;
        };

        // Iterate over the data and create table rows
        data.forEach(item => {
            const row = document.createElement('tr');

            row.innerHTML = `
                <td>${item.name}</td>
                <td>$${item.initial}</td>
                <td>${formatDate(item.bought)}</td>
                <td>$${item.value}</td>
                <td>~${item.apy}%</td>
                <td><a href="${item.url}" target="_blank">Find out more</a></td>
                <td>${formatDate(item.updated)}</td>
            `;

            tableBody.appendChild(row);
        });

    } catch (error) {
        console.error('Error fetching or injecting data:', error);
    }
}

// Set on page load event listener
window.addEventListener('load', fetchAndInjectDefiData);
</script>
            </div>
            <div class="p-5">
                <h2 class="display-4">Other</h2>
                <div class="table-responsive" id="other-table">
                    <table class="table">
                        <thead>
                            <tr>
                                <th>Asset</th>
                                <th>APY</th>
                                <th>Info</th>
                                <th>Last Updated</th>
                            </tr>
                        </thead>
                        <tbody>
                            <tr>
                                <td>Asset Name</td>
                                <td>0%</td>
                                <td>Find out more</td>
                                <td>00/00/00</td>
                            </tr>
                        </tbody>
                    </table>
                </div><script type="text/javascript">
    async function fetchAndInjectDefiData() {
    try {
        // Fetch data from the API
        const response = await fetch('/api/v1/apy');
        if (!response.ok) {
            throw new Error('Network response was not ok' + response.statusText);
        }
        
        const data = await response.json();

        // Locate the table where the data will be injected
        const tableBody = document.querySelector('#other-table tbody');

        if (!tableBody) {
            console.error('Table body not found. Make sure your table has an id "other-table" with a <tbody> element.');
            return;
        }

        // Clear existing rows (optional, depending on use case)
        tableBody.innerHTML = '';

        const formatDate = (timestamp) => {
            const date = new Date(timestamp * 1000); // Convert seconds to milliseconds
            const day = String(date.getDate()).padStart(2, '0');
            const month = String(date.getMonth() + 1).padStart(2, '0'); // Months are zero-based
            const year = String(date.getFullYear()).slice(-2); // Get last two digits of the year
            return `${day}/${month}/${year}`;
        };

        // Iterate over the data and create table rows
        data.forEach(item => {
            const row = document.createElement('tr');

            row.innerHTML = `
                <td>${item.name}</td>
                <td>~${item.apy}%</td>
                <td><a href="${item.url}" target="_blank">Find out more</a></td>
                <td>${formatDate(item.updated)}</td>
            `;

            tableBody.appendChild(row);
        });

    } catch (error) {
        console.error('Error fetching or injecting data:', error);
    }
}

// Set on page load event listener
window.addEventListener('load', fetchAndInjectDefiData);
</script>
            </div>
        </div>
    </section>
    <footer class="py-5 bg-black">
        <div class="container">
            <p class="text-center text-white m-0 small">Copyright&nbsp;©&nbsp;<a href="https://nathan.woodburn.au" target="_blank">Nathan.Woodburn/</a> 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>