Atompek Swap & CORs

Words
86
Reading
1 min
Listen
Play
1y

When I'm trying to make swaps work... but I keep getting CORs errors.

Minimal fun.

So these gosh darn CORs's, lol.

Am I not calling for it correctly? It's been a few months of work to build this thing. I'm a bit of an ADD type of character, so I am all over the place but still trying to get shit done.

Help!!

I may end up having this fixed, but right now I'm at my wits' end. So slide some knowledge on me, folks.

// script.js - Handles the frontend logic for atomic swap UI (Keychain & Hivesigner DEX version)

// List of Hive Engine API endpoints (primary and backups)
const HIVE_ENGINE_APIS = [
    'https://api.hive-engine.com/rpc',
    'https://herpc.dtools.dev',
    'https://heapi.inleo.io',
    'https://api.primersion.com',
    'https://api.ausbit.dev',
    'https://api.tribaldex.com/rpc'
];

// Helper: Try all APIs in order until one succeeds
async function fetchWithBackups(options) {
    for (let i = 0; i < HIVE_ENGINE_APIS.length; i++) {
        try {
            const res = await fetch(HIVE_ENGINE_APIS[i], options);
            if (res.ok) return await res.json();
        } catch (e) {}
    }
    return null;
}

async function fetchSwapHiveRate(token) {
    // Try buyBook (best ask)
    try {
        const data = await fetchWithBackups({
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({
                jsonrpc: '2.0',
                id: 1,
                method: 'find',
                params: {
                    contract: 'market',
                    table: 'buyBook',
                    query: { symbol: token, baseSymbol: 'SWAP.HIVE' },
                    limit: 1,
                    indexes: [{ index: 'price', descending: true }]
                }
            })
        });
        if (data && data.result && data.result.length > 0 && data.result[0].price && !isNaN(data.result[0].price)) {
            return parseFloat(data.result[0].price);
        }
    } catch (e) {}
    // Try metrics as fallback
    try {
        const data = await fetchWithBackups({
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({
                jsonrpc: '2.0',
                id: 1,
                method: 'findOne',
                params: {
                    contract: 'market',
                    table: 'metrics',
                    query: { symbol: token }
                }
            })
        });
        if (data && data.result && data.result.lastPrice && !isNaN(data.result.lastPrice)) {
            return parseFloat(data.result.lastPrice);
        }
    } catch (e) {}
    return null;
}

// --- UI Rate Display Logic (modified) ---
async function updateRateDisplay() {
    const token = document.getElementById('hiveToken').value;
    const tokenAmount = parseFloat(document.getElementById('hiveAmount').value);
    const rateDisplay = document.getElementById('rateDisplay');
    if (tokenAmount > 0) {
        const swapHiveRate = await fetchSwapHiveRate(token);
        if (swapHiveRate) {
            const pekAmount = tokenAmount * swapHiveRate;
            rateDisplay.innerHTML = `Estimated: ${pekAmount.toFixed(6)} PEK for ${tokenAmount} ${token}
Final swap rate is determined by the market at the time of each transaction.`
; } else { rateDisplay.textContent = 'Unable to fetch live SWAP.HIVE rate.'; } } else { rateDisplay.textContent = ''; } } document.getElementById('hiveAmount').addEventListener('input', updateRateDisplay); document.getElementById('hiveToken').addEventListener('change', updateRateDisplay); window.addEventListener('DOMContentLoaded', updateRateDisplay); // --- Helper: Build Hive Engine custom_json for marketSell/marketBuy --- function buildMarketSellJson(account, symbol, quantity) { return { contractName: "market", contractAction: "marketSell", contractPayload: { symbol: symbol, quantity: String(quantity) } }; } function buildMarketBuyJson(account, symbol, quantity) { return { contractName: "market", contractAction: "marketBuy", contractPayload: { symbol: symbol, quantity: String(quantity) } }; } // --- Helper: Hivesigner custom_json link --- function buildHivesignerCustomJsonLink(account, json, authority = 'Active') { const op = [ 'custom_json', { required_auths: [account], required_posting_auths: [], id: 'ssc-mainnet-hive', json: JSON.stringify(json) } ]; const ops = encodeURIComponent(JSON.stringify([op])); return `https://hivesigner.com/sign/tx?operations=${ops}&authority=${authority}`; } // --- Combined Swap: Sell Token for SWAP.HIVE, then Buy PEK --- async function performSwap(useKeychain) { const account = document.getElementById('hiveSender').value.trim(); const symbol = document.getElementById('hiveToken').value; const quantity = parseFloat(document.getElementById('hiveAmount').value); const swapResult = document.getElementById('swapResult'); swapResult.innerHTML = ''; if (!account || !symbol || !quantity || quantity <= 0) { swapResult.innerHTML = "Please fill in all fields."; return; } // Step 1: Sell selected token for SWAP.HIVE const sellJson = buildMarketSellJson(account, symbol, quantity); if (useKeychain) { if (!window.hive_keychain) { swapResult.innerHTML = "Hive Keychain extension not detected."; return; } // Use a non-async callback for Keychain (Keychain expects a regular function, not async) window.hive_keychain.requestCustomJson( account, 'ssc-mainnet-hive', 'Active', JSON.stringify(sellJson), `Sell ${quantity} ${symbol} for SWAP.HIVE`, function(response) { if (response.success) { swapResult.innerHTML = "Sell order broadcasted! Waiting for your SWAP.HIVE payout..."; // Poll for payout up to 30s, every 2s let payout = 0; let pollCount = 0; const pollPayout = async function() { payout = await getLastSwapHivePayoutFromLogs(account, symbol); if (payout > 0.000001) { performBuyPEK(account, payout, true); } else if (++pollCount < 15) { setTimeout(pollPayout, 2000); } else { swapResult.innerHTML = "No SWAP.HIVE payout detected from your sale after 30 seconds. Please check your wallet and try again."; } }; setTimeout(pollPayout, 2000); } else { swapResult.innerHTML = "Keychain error: " + (response.message || "Unknown error"); } } ); } else { const url = buildHivesignerCustomJsonLink(account, sellJson, 'Active'); window.open(url, '_blank'); swapResult.innerHTML = "Sell order link opened in Hivesigner. Waiting for your SWAP.HIVE payout..."; // Poll for payout up to 30s, every 2s let pollCount = 0; let payout = 0; const pollPayout = async function() { payout = await getLastSwapHivePayoutFromLogs(account, symbol); if (payout > 0.000001) { performBuyPEK(account, payout, false); } else if (++pollCount < 15) { setTimeout(pollPayout, 2000); } else { swapResult.innerHTML = "No SWAP.HIVE payout detected from your sale after 30 seconds. Please check your wallet and try again."; } }; setTimeout(pollPayout, 2000); } } // Fetch the user's SWAP.HIVE balance from Hive Engine async function getSwapHiveBalance(account) { try { const res = await fetch('https://api.hive-engine.com/rpc', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ jsonrpc: '2.0', id: 1, method: 'findOne', params: { contract: 'tokens', table: 'balances', query: { account: account, symbol: 'SWAP.HIVE' } } }) }); const data = await res.json(); if (data && data.result && data.result.balance) { return parseFloat(data.result.balance); } } catch (e) {} return 0; } // Fetch the most recent SWAP.HIVE payout from a marketSell for the selected token async function getLastSwapHivePayout(account, symbol) { try { const res = await fetch('https://api.hive-engine.com/rpc', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ jsonrpc: '2.0', id: 1, method: 'find', params: { contract: 'market', table: 'trades', query: { account: account, symbol: symbol, market: 'SWAP.HIVE' }, limit: 10, indexes: [{ index: 'timestamp', descending: true }] } }) }); const data = await res.json(); if (data && data.result && data.result.length > 0) { // Find the most recent trade where the user was the seller and payoutSymbol is SWAP.HIVE for (const trade of data.result) { if (trade.account === account && trade.symbol === symbol && trade.payoutSymbol === 'SWAP.HIVE') { return parseFloat(trade.payoutQuantity); } } } } catch (e) {} return 0; } // Fetch the most recent SWAP.HIVE payout from a marketSell for the selected token using logs/events async function getLastSwapHivePayoutFromLogs(account, symbol) { try { // Query the last 10 blocks for marketSell actions by the user const res = await fetch('https://api.hive-engine.com/rpc', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ jsonrpc: '2.0', id: 1, method: 'find', params: { contract: 'blockLog', table: 'blocks', query: {}, limit: 10, indexes: [{ index: 'blockNumber', descending: true }] } }) }); const data = await res.json(); if (data && data.result && data.result.length > 0) { for (const block of data.result) { if (block.transactions) { for (const tx of block.transactions) { if (tx.sender === account && tx.contract === 'market' && tx.action === 'marketSell' && tx.payload && tx.payload.symbol === symbol) { // Look for a transferFromContract event for SWAP.HIVE to the user if (tx.logs && tx.logs.events) { for (let i = 0; i < tx.logs.events.length; i++) { const event = tx.logs.events[i]; if (event.contract === 'tokens' && event.event === 'transferFromContract' && event.data && event.data.to === account && event.data.symbol === 'SWAP.HIVE') { return parseFloat(event.data.quantity); } } } } } } } } } catch (e) {} return 0; } // --- Combined Swap: Sell Token for SWAP.HIVE, then Buy PEK --- async function performBuyPEK(account, swapHiveAmount, useKeychain) { const swapResult = document.getElementById('swapResult'); // Subtract Hive Engine multiTransaction fee (0.001 SWAP.HIVE) const MULTI_TX_FEE = 0.001; let buyAmount = swapHiveAmount - MULTI_TX_FEE; if (buyAmount <= 0) { swapResult.innerHTML = "Insufficient SWAP.HIVE amount after fee deduction."; return; } const buyJson = buildMarketBuyJson(account, 'PEK', buyAmount); if (useKeychain) { if (!window.hive_keychain) { swapResult.innerHTML = "Hive Keychain extension not detected."; return; } window.hive_keychain.requestCustomJson( account, 'ssc-mainnet-hive', 'Active', JSON.stringify(buyJson), `Buy PEK with ${buyAmount} SWAP.HIVE`, function(response) { if (response.success) { swapResult.innerHTML = "Buy order broadcasted!"; } else { swapResult.innerHTML = "Keychain error: " + (response.message || "Unknown error"); } } ); } else { const url = buildHivesignerCustomJsonLink(account, buyJson, 'Active'); window.open(url, '_blank'); swapResult.innerHTML = "Buy order link opened in Hivesigner."; } }
Atompek Swap & CORs | Ecency