/** * Vazin Pay → Google Sheets rate logger * Source: https://pay.vazin.online/v3/portal/rates * * Setup: * 1) Open your Google Sheet → Extensions → Apps Script * 2) Paste this whole file, Save * 3) Run setupVazinRates once (authorize when asked) * 4) Optional: Triggers → verify hourly trigger exists */ var VAZIN_RATES_URL = 'https://pay.vazin.online/v3/portal/rates'; var SHEET_WALLET = 'wallet_rates'; var SHEET_TOMAN = 'toman_ref'; var SHEET_META = 'meta'; function setupVazinRates() { var ss = SpreadsheetApp.getActive(); ensureSheet_(ss, SHEET_WALLET, [ 'logged_at_utc', 'asset', 'units_per_usd', 'deposit_units_per_usd', 'withdrawal_units_per_usd', 'deposit_enabled', 'withdrawal_enabled', 'stale', 'exchange_available', 'rate_updated_at' ]); ensureSheet_(ss, SHEET_TOMAN, [ 'logged_at_utc', 'asset', 'toman', 'source', 'age_seconds', 'ref_updated_at' ]); ensureSheet_(ss, SHEET_META, ['key', 'value']); upsertMeta_('source_url', VAZIN_RATES_URL); upsertMeta_('setup_at_utc', new Date().toISOString()); // remove old triggers for this function, then create hourly ScriptApp.getProjectTriggers().forEach(function (t) { if (t.getHandlerFunction() === 'logVazinRates') ScriptApp.deleteTrigger(t); }); ScriptApp.newTrigger('logVazinRates').timeBased().everyHours(1).create(); // also run once now logVazinRates(); SpreadsheetApp.getUi().alert('Vazin rates: setup OK. Hourly logging is on.'); } function logVazinRates() { var ss = SpreadsheetApp.getActive(); var res = UrlFetchApp.fetch(VAZIN_RATES_URL, { muteHttpExceptions: true, followRedirects: true, validateHttpsCertificates: true }); var code = res.getResponseCode(); var body = res.getContentText(); if (code !== 200) { upsertMeta_('last_error', code + ' ' + body.slice(0, 200)); throw new Error('Rates fetch failed: HTTP ' + code); } var data = JSON.parse(body); var now = new Date().toISOString(); var wallet = ss.getSheetByName(SHEET_WALLET); var toman = ss.getSheetByName(SHEET_TOMAN); if (!wallet || !toman) { throw new Error('Run setupVazinRates first'); } var walletRows = (data.rates || []).map(function (r) { return [ now, String(r.asset || '').toUpperCase(), num_(r.units_per_usd), num_(r.deposit_units_per_usd), num_(r.withdrawal_units_per_usd), !!r.deposit_enabled, !!r.withdrawal_enabled, !!r.stale, !!r.exchange_available, r.updated_at || '' ]; }); if (walletRows.length) { wallet.getRange(wallet.getLastRow() + 1, 1, walletRows.length, walletRows[0].length).setValues(walletRows); } var tomanRows = (data.reference || []).map(function (r) { return [ now, String(r.asset || '').toUpperCase(), num_(r.toman), r.source || '', r.age_seconds == null ? '' : Number(r.age_seconds), r.updated_at || '' ]; }); if (tomanRows.length) { toman.getRange(toman.getLastRow() + 1, 1, tomanRows.length, tomanRows[0].length).setValues(tomanRows); } upsertMeta_('last_ok_utc', now); upsertMeta_('last_wallet_rows', String(walletRows.length)); upsertMeta_('last_toman_rows', String(tomanRows.length)); upsertMeta_('last_error', ''); } function ensureSheet_(ss, name, headers) { var sh = ss.getSheetByName(name); if (!sh) sh = ss.insertSheet(name); if (sh.getLastRow() === 0) { sh.getRange(1, 1, 1, headers.length).setValues([headers]); sh.setFrozenRows(1); } return sh; } function upsertMeta_(key, value) { var ss = SpreadsheetApp.getActive(); var sh = ensureSheet_(ss, SHEET_META, ['key', 'value']); var values = sh.getDataRange().getValues(); for (var i = 1; i < values.length; i++) { if (String(values[i][0]) === key) { sh.getRange(i + 1, 2).setValue(value); return; } } sh.appendRow([key, value]); } function num_(v) { var n = Number(v); return isFinite(n) ? n : ''; }