diff --git a/app/background.js b/app/background.js index 66d04d2..a741014 100644 --- a/app/background.js +++ b/app/background.js @@ -403,6 +403,10 @@ const createWindow = async () => { mainWindow.loadURL('http://localhost:8080/index.html'); + mainWindow.webContents.setWindowOpenHandler(() => { + return { action: "deny" }; + }); + tray = new electron__WEBPACK_IMPORTED_MODULE_4__.Tray(path__WEBPACK_IMPORTED_MODULE_0___default().join(__dirname, "img", "tray.png")); const contextMenu = electron__WEBPACK_IMPORTED_MODULE_4__.Menu.buildFromTemplate([ { diff --git a/app/background.js.map b/app/background.js.map index cae9e26..84f307f 100644 --- a/app/background.js.map +++ b/app/background.js.map @@ -1 +1 @@ -{"version":3,"file":"background.js","mappings":";;;;;;;;;;;;;;;;AAAmC;AACnC;AACA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,WAAW;AACX,YAAY,iCAAiC;AAC7C,YAAY;AACZ;AACA;AACA;AACA,iBAAiB,0CAAI;AACrB,IAAI,0CAAI;AACR;;;;;;;;;;;;;;;;;;;;;ACvBsC;AACW;AACb;AACpC;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA,aAAa;AACb;AACA;AACA,aAAa;AACb;AACA;AACA,aAAa;AACb;AACA,KAAK;AACL;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA,aAAa;AACb;AACA;AACA,aAAa;AACb;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA,kBAAkB,gDAAI;AACtB;AACA;AACA;AACA,kBAAkB,yCAAyC;AAC3D,yCAAyC,OAAO;AAChD;AACA,UAAU;AACV,0BAA0B,wCAAwC;AAClE;AACA;AACA;AACA,uBAAuB,2DAAkB;AACzC,wBAAwB,uBAAuB;AAC/C;AACA;AACA;AACA;AACA;AACA,UAAU;AACV,0BAA0B,6CAA6C;AACvE;AACA;AACA;AACA;AACA;AACA;AACA,UAAU;AACV,0BAA0B,6CAA6C;AACvE;AACA;AACA;AACA;AACA;AACA;AACA,UAAU;AACV,0BAA0B,8CAA8C;AACxE;AACA;AACA;AACA;AACA;AACA;AACA,UAAU;AACV,0BAA0B,oCAAoC;AAC9D;AACA;AACA;AACA;AACA;AACA;AACA,uBAAuB,wCAAM;AAC7B,UAAU;AACV,0BAA0B,2CAA2C;AACrE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA;AACA;AACA;AACA,UAAU;AACV,0BAA0B,0CAA0C;AACpE;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;;;;;;;;;;;AC5HA;;;;;;;;;;ACAA;;;;;;;;;;ACAA;;;;;;;;;;ACAA;;;;;;;;;;ACAA;;;;;;;;;;ACAA;;;;;;;;;;ACAA;;;;;;;;;;ACAA;;;;;;UCAA;UACA;;UAEA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;;UAEA;UACA;;UAEA;UACA;UACA;;;;;WCtBA;WACA;WACA;WACA;WACA;WACA,iCAAiC,WAAW;WAC5C;WACA;;;;;WCPA;WACA;WACA;WACA;WACA,yCAAyC,wCAAwC;WACjF;WACA;WACA;;;;;WCPA;;;;;WCAA;WACA;WACA;WACA,uDAAuD,iBAAiB;WACxE;WACA,gDAAgD,aAAa;WAC7D;;;;;;;;;;;;;;;;;;;;;ACNwB;AACJ;AACE;AACQ;AAC9B;AASkB;AAClB;AAC+D;AACV;AACrD;AACA;AACA;AACA;AACA;AACA,YAAY,gBAAgB,EAAE,4CAAM;AACpC;AACA,qBAAqB,mDAAa;AAClC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,qBAAqB,gDAAS;AAC9B,SAAS;AACT;AACA,KAAK;AACL;AACA,uBAAuB,8CAAO;AAC9B;AACA;AACA,QAAQ,IAAsC;AAC9C;AACA,MAAM,KAAK,EAEN;AACL;AACA,mBAAmB,wDAAc;AACjC;AACA;AACA,KAAK;AACL;AACA,IAAI,4EAAmB;AACvB;AACA;AACA;AACA,eAAe,0CAAI,CAAC,gDAAS;AAC7B,wBAAwB,0CAAI;AAC5B;AACA;AACA;AACA;AACA,aAAa;AACb,SAAS;AACT;AACA;AACA;AACA;AACA,gBAAgB,yCAAG;AACnB,aAAa;AACb,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA,IAAI,6CAAO;AACX,gBAAgB,QAAQ;AACxB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAU;AACV,yBAAyB,MAAM;AAC/B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA,IAAI,6CAAO;AACX,gBAAgB,mBAAmB;AACnC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,qBAAqB;AACrB,mCAAmC,UAAU;AAC7C,8BAA8B,KAAK;AACnC,6BAA6B,KAAK;AAClC,kCAAkC,UAAU;AAC5C,gCAAgC,QAAQ;AACxC,gCAAgC,QAAQ;AACxC,6BAA6B,KAAK;AAClC,kCAAkC,UAAU;AAC5C;AACA;AACA;AACA,yCAAyC,eAAe;AACxD,UAAU;AACV,0BAA0B,OAAO;AACjC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA,IAAI,6CAAO;AACX,gBAAgB,mCAAmC;AACnD;AACA;AACA;AACA,6BAA6B,kEAAgB;AAC7C,UAAU;AACV,0BAA0B,OAAO;AACjC;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,6CAAO;AACX;AACA,kCAAkC,gDAAO;AACzC;AACA;AACA;AACA,+CAA+C,gDAAO;AACtD;AACA,aAAa;AACb;AACA;AACA,gBAAgB,2CAAK;AACrB,cAAc;AACd;AACA,gEAAgE,OAAO;AACvE;AACA;AACA,UAAU;AACV,iDAAiD,YAAY;AAC7D;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA,yCAAG;AACH;AACA,kBAAkB,kDAAW;AAC7B;AACA;AACA,uBAAuB,yCAAG;AAC1B;AACA;AACA,QAAQ,yCAAG;AACX;AACA;AACA,IAAI,yCAAG;AACP;AACA,KAAK;AACL,EAAE;AACF,IAAI,yCAAG;AACP;AACA,KAAK;AACL;AACA,IAAI,yCAAG;AACP;AACA,YAAY,yCAAG;AACf;AACA,KAAK;AACL;AACA,IAAI,yCAAG;AACP;AACA;AACA;AACA,KAAK;AACL","sources":["webpack://bitshares_astro_ui/./src/lib/applicationMenu.js","webpack://bitshares_astro_ui/./src/lib/deeplink.js","webpack://bitshares_astro_ui/external commonjs \"bitsharesjs\"","webpack://bitshares_astro_ui/external commonjs \"bitsharesjs-ws\"","webpack://bitshares_astro_ui/external commonjs \"electron\"","webpack://bitshares_astro_ui/external commonjs \"express\"","webpack://bitshares_astro_ui/external commonjs \"uuid\"","webpack://bitshares_astro_ui/external node-commonjs \"os\"","webpack://bitshares_astro_ui/external node-commonjs \"path\"","webpack://bitshares_astro_ui/external node-commonjs \"url\"","webpack://bitshares_astro_ui/webpack/bootstrap","webpack://bitshares_astro_ui/webpack/runtime/compat get default export","webpack://bitshares_astro_ui/webpack/runtime/define property getters","webpack://bitshares_astro_ui/webpack/runtime/hasOwnProperty shorthand","webpack://bitshares_astro_ui/webpack/runtime/make namespace object","webpack://bitshares_astro_ui/./src/background.js"],"sourcesContent":["import {app, Menu} from 'electron';\r\n\r\n/**\r\n * For configuring the electron window menu\r\n */\r\nexport function initApplicationMenu(mainWindow) {\r\n const template = [\r\n {\r\n label: 'View',\r\n submenu: [\r\n {\r\n label: 'Send to tray',\r\n click() {\r\n mainWindow.minimize();\r\n }\r\n },\r\n { label: 'Reload', role: 'reload' },\r\n { label: 'Dev tools', role: 'toggleDevTools' }\r\n ]\r\n }\r\n ];\r\n const menu = Menu.buildFromTemplate(template);\r\n Menu.setApplicationMenu(menu);\r\n}\r\n","import { Apis } from \"bitsharesjs-ws\";\r\nimport { TransactionBuilder } from \"bitsharesjs\";\r\nimport { v4 as uuidv4 } from \"uuid\";\r\n\r\nconst chains = {\r\n bitshares: {\r\n nodeList: [\r\n {\r\n url: \"wss://node.xbts.io/ws\",\r\n },\r\n {\r\n url: \"wss://api.bts.mobi/ws\",\r\n },\r\n {\r\n url: \"wss://api.bitshares.bhuz.info/ws\",\r\n },\r\n {\r\n url: \"wss://btsws.roelandp.nl/ws\",\r\n },\r\n ],\r\n },\r\n bitshares_testnet: {\r\n nodeList: [\r\n {\r\n url: \"wss://testnet.dex.trading/\",\r\n },\r\n {\r\n url: \"wss://testnet.xbts.io/ws\",\r\n },\r\n {\r\n url: \"wss://api-testnet.61bts.com/ws\",\r\n },\r\n ],\r\n },\r\n};\r\n\r\nasync function generateDeepLink(chain, opType, operations) {\r\n return new Promise(async (resolve, reject) => {\r\n const _node = chains[chain].nodeList[0].url\r\n\r\n try {\r\n await Apis.instance(\r\n _node,\r\n true,\r\n 4000,\r\n { enableCrypto: false, enableOrders: true },\r\n (error) => console.log({ error })\r\n ).init_promise;\r\n } catch (error) {\r\n console.log({ error, location: \"api instance failed\" });\r\n return reject(error);\r\n }\r\n\r\n const tr = new TransactionBuilder();\r\n for (let i = 0; i < operations.length; i++) {\r\n tr.add_type_operation(opType, operations[i]);\r\n }\r\n\r\n try {\r\n await tr.update_head_block();\r\n } catch (error) {\r\n console.log({ error, location: \"update head block failed\" });\r\n reject(error);\r\n return;\r\n }\r\n\r\n try {\r\n await tr.set_required_fees();\r\n } catch (error) {\r\n console.log({ error, location: \"set required fees failed\" });\r\n reject(error);\r\n return;\r\n }\r\n\r\n try {\r\n tr.set_expire_seconds(7200);\r\n } catch (error) {\r\n console.log({ error, location: \"set expire seconds failed\" });\r\n reject(error);\r\n return;\r\n }\r\n\r\n try {\r\n tr.finalize();\r\n } catch (error) {\r\n console.log({ error, location: \"finalize failed\" });\r\n reject(error);\r\n return;\r\n }\r\n\r\n let id;\r\n try {\r\n id = await uuidv4();\r\n } catch (error) {\r\n console.log({ error, location: \"uuid generation failed\" });\r\n reject(error);\r\n return;\r\n }\r\n\r\n const request = {\r\n type: \"api\",\r\n id: id,\r\n payload: {\r\n method: \"injectedCall\",\r\n params: [\"signAndBroadcast\", JSON.stringify(tr.toObject()), []],\r\n appName: \"Bitshares Astro UI\",\r\n chain: chain === \"bitshares\" ? \"BTS\" : \"BTS_TEST\",\r\n browser: \"web browser\",\r\n origin: \"localhost\",\r\n },\r\n };\r\n\r\n let encodedPayload;\r\n try {\r\n encodedPayload = encodeURIComponent(JSON.stringify(request));\r\n } catch (error) {\r\n console.log({ error, location: \"encode payload failed\" });\r\n reject(error);\r\n return;\r\n }\r\n\r\n resolve(encodedPayload);\r\n });\r\n}\r\n\r\nexport { generateDeepLink };","module.exports = require(\"bitsharesjs\");","module.exports = require(\"bitsharesjs-ws\");","module.exports = require(\"electron\");","module.exports = require(\"express\");","module.exports = require(\"uuid\");","module.exports = require(\"os\");","module.exports = require(\"path\");","module.exports = require(\"url\");","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","import path from \"path\";\r\nimport os from \"os\";\r\nimport url from \"url\";\r\nimport express from \"express\";\r\n\r\nimport {\r\n app,\r\n BrowserWindow,\r\n Menu,\r\n Tray,\r\n ipcMain,\r\n screen,\r\n shell,\r\n} from \"electron\";\r\n\r\nimport { initApplicationMenu } from \"./lib/applicationMenu.js\";\r\nimport { generateDeepLink } from \"./lib/deeplink.js\";\r\n\r\nlet mainWindow = null;\r\nlet tray = null;\r\n\r\nconst createWindow = async () => {\r\n const { width, height } = screen.getPrimaryDisplay().workAreaSize;\r\n\r\n mainWindow = new BrowserWindow({\r\n width: width,\r\n height: height,\r\n minWidth: 480,\r\n minHeight: 695,\r\n maxWidth: width,\r\n maximizable: true,\r\n maxHeight: height,\r\n useContentSize: true,\r\n autoHideMenuBar: true,\r\n webPreferences: {\r\n nodeIntegration: false,\r\n contextIsolation: true,\r\n sandbox: true,\r\n preload: path.join(__dirname, \"preload.js\"),\r\n },\r\n icon: __dirname + \"/img/taskbar.png\",\r\n });\r\n \r\n const expressApp = express();\r\n\r\n let astroDistPath;\r\n if (process.env.NODE_ENV === 'development') {\r\n astroDistPath = 'astroDist';\r\n } else {\r\n astroDistPath = path.join(process.resourcesPath, 'astroDist');\r\n }\r\n\r\n expressApp.use(express.static(astroDistPath));\r\n expressApp.listen(8080, () => {\r\n console.log(\"Express server listening on port 8080\");\r\n });\r\n\r\n initApplicationMenu(mainWindow);\r\n\r\n mainWindow.loadURL('http://localhost:8080/index.html');\r\n\r\n tray = new Tray(path.join(__dirname, \"img\", \"tray.png\"));\r\n const contextMenu = Menu.buildFromTemplate([\r\n {\r\n label: \"Show App\",\r\n click: function () {\r\n mainWindow?.show();\r\n },\r\n },\r\n {\r\n label: \"Quit\",\r\n click: function () {\r\n tray = null;\r\n app.quit();\r\n },\r\n },\r\n ]);\r\n\r\n tray.setToolTip(\"Bitshares Astro UI\");\r\n\r\n tray.on(\"right-click\", (event, bounds) => {\r\n tray?.popUpContextMenu(contextMenu);\r\n });\r\n\r\n ipcMain.handle(\"fetchTopMarkets\", async (event, arg) => {\r\n const { chain } = arg;\r\n\r\n let retrievedData;\r\n try {\r\n retrievedData = await fetch(\r\n chain === \"bitshares\"\r\n ? `https://api.bitshares.ws/openexplorer/top_markets?top_n=100`\r\n : `https://api.testnet.bitshares.ws/openexplorer/top_markets?top_n=50`\r\n );\r\n } catch (error) {\r\n console.log({error})\r\n }\r\n \r\n if (!retrievedData || !retrievedData.ok) {\r\n console.log(\"Failed to fetch top markets\");\r\n return;\r\n }\r\n \r\n const topMarkets = await retrievedData.json();\r\n return topMarkets ?? null;\r\n });\r\n\r\n ipcMain.handle(\"fetchAccountHistory\", async (event, arg) => {\r\n const { chain, accountID } = arg;\r\n\r\n const from = arg.from ?? 0;\r\n const size = arg.size ?? 100;\r\n const from_date = arg.from_date ?? \"2015-10-10\";\r\n const to_date = arg.to_date ?? \"now\";\r\n const sort_by = arg.sort_by ?? \"-operation_id_num\";\r\n const type = arg.type ?? \"data\";\r\n const agg_field = arg.agg_field ?? \"operation_type\";\r\n\r\n const url = `https://${\r\n chain === \"bitshares\" ? \"api\" : \"api.testnet\"\r\n }.bitshares.ws/openexplorer/es/account_history` +\r\n `?account_id=${accountID}` +\r\n `&from_=${from}` +\r\n `&size=${size}` +\r\n `&from_date=${from_date}` +\r\n `&to_date=${to_date}` +\r\n `&sort_by=${sort_by}` +\r\n `&type=${type}` +\r\n `&agg_field=${agg_field}`;\r\n\r\n let history;\r\n try {\r\n history = await fetch(url, { method: \"GET\" });\r\n } catch (error) {\r\n console.log({ error });\r\n return null;\r\n }\r\n\r\n if (!history || !history.ok) {\r\n console.log(\"Couldn't fetch account history.\");\r\n return null;\r\n }\r\n\r\n const accountHistory = await history.json(); \r\n return accountHistory ?? null;\r\n });\r\n\r\n ipcMain.handle(\"generateDeepLink\", async (event, arg) => {\r\n const { usrChain, operationName, trxJSON } = arg;\r\n\r\n let deeplink;\r\n try {\r\n deeplink = await generateDeepLink(usrChain, operationName, trxJSON);\r\n } catch (error) {\r\n console.log({ error });\r\n }\r\n\r\n return deeplink ?? null;\r\n });\r\n\r\n const safeDomains = [\r\n \"https://blocksights.info/\",\r\n \"https://bts.exchange/\",\r\n \"https://ex.xbts.io/\",\r\n \"https://kibana.bts.mobi/\",\r\n \"https://www.bitsharescan.info/\",\r\n \"https://github.com/bitshares/beet\",\r\n ];\r\n ipcMain.on(\"openURL\", (event, arg) => {\r\n try {\r\n const parsedUrl = new url.URL(arg);\r\n const domain = parsedUrl.hostname;\r\n\r\n const isSafeDomain = safeDomains.some(safeDomain => {\r\n const safeDomainHostname = new url.URL(safeDomain).hostname;\r\n return safeDomainHostname === domain;\r\n });\r\n\r\n if (isSafeDomain) {\r\n shell.openExternal(arg);\r\n } else {\r\n console.error(\r\n `Rejected opening URL with unsafe domain: ${domain}`\r\n );\r\n }\r\n } catch (err) {\r\n console.error(`Failed to open URL: ${err.message}`);\r\n }\r\n }); \r\n\r\n tray.on(\"click\", () => {\r\n mainWindow?.setAlwaysOnTop(true);\r\n mainWindow?.show();\r\n mainWindow?.focus();\r\n mainWindow?.setAlwaysOnTop(false);\r\n });\r\n\r\n tray.on(\"balloon-click\", () => {\r\n mainWindow?.setAlwaysOnTop(true);\r\n mainWindow?.show();\r\n mainWindow?.focus();\r\n mainWindow?.setAlwaysOnTop(false);\r\n });\r\n};\r\n\r\napp.disableHardwareAcceleration();\r\n\r\nconst currentOS = os.platform();\r\nif (currentOS === \"win32\" || currentOS === \"linux\") {\r\n // windows + linux setup phase\r\n const gotTheLock = app.requestSingleInstanceLock();\r\n\r\n if (!gotTheLock) {\r\n app.quit();\r\n }\r\n\r\n app.whenReady().then(() => {\r\n createWindow();\r\n });\r\n} else {\r\n app.whenReady().then(() => {\r\n createWindow();\r\n });\r\n\r\n app.on(\"window-all-closed\", () => {\r\n if (process.platform !== \"darwin\") {\r\n app.quit();\r\n }\r\n });\r\n\r\n app.on(\"activate\", () => {\r\n if (mainWindow === null) {\r\n createWindow();\r\n }\r\n });\r\n}\r\n"],"names":[],"sourceRoot":""} \ No newline at end of file +{"version":3,"file":"background.js","mappings":";;;;;;;;;;;;;;;;AAAmC;AACnC;AACA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,WAAW;AACX,YAAY,iCAAiC;AAC7C,YAAY;AACZ;AACA;AACA;AACA,iBAAiB,0CAAI;AACrB,IAAI,0CAAI;AACR;;;;;;;;;;;;;;;;;;;;;ACvBsC;AACW;AACb;AACpC;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA,aAAa;AACb;AACA;AACA,aAAa;AACb;AACA;AACA,aAAa;AACb;AACA,KAAK;AACL;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA,aAAa;AACb;AACA;AACA,aAAa;AACb;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA,kBAAkB,gDAAI;AACtB;AACA;AACA;AACA,kBAAkB,yCAAyC;AAC3D,yCAAyC,OAAO;AAChD;AACA,UAAU;AACV,0BAA0B,wCAAwC;AAClE;AACA;AACA;AACA,uBAAuB,2DAAkB;AACzC,wBAAwB,uBAAuB;AAC/C;AACA;AACA;AACA;AACA;AACA,UAAU;AACV,0BAA0B,6CAA6C;AACvE;AACA;AACA;AACA;AACA;AACA;AACA,UAAU;AACV,0BAA0B,6CAA6C;AACvE;AACA;AACA;AACA;AACA;AACA;AACA,UAAU;AACV,0BAA0B,8CAA8C;AACxE;AACA;AACA;AACA;AACA;AACA;AACA,UAAU;AACV,0BAA0B,oCAAoC;AAC9D;AACA;AACA;AACA;AACA;AACA;AACA,uBAAuB,wCAAM;AAC7B,UAAU;AACV,0BAA0B,2CAA2C;AACrE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA;AACA;AACA;AACA,UAAU;AACV,0BAA0B,0CAA0C;AACpE;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;;;;;;;;;;;AC5HA;;;;;;;;;;ACAA;;;;;;;;;;ACAA;;;;;;;;;;ACAA;;;;;;;;;;ACAA;;;;;;;;;;ACAA;;;;;;;;;;ACAA;;;;;;;;;;ACAA;;;;;;UCAA;UACA;;UAEA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;;UAEA;UACA;;UAEA;UACA;UACA;;;;;WCtBA;WACA;WACA;WACA;WACA;WACA,iCAAiC,WAAW;WAC5C;WACA;;;;;WCPA;WACA;WACA;WACA;WACA,yCAAyC,wCAAwC;WACjF;WACA;WACA;;;;;WCPA;;;;;WCAA;WACA;WACA;WACA,uDAAuD,iBAAiB;WACxE;WACA,gDAAgD,aAAa;WAC7D;;;;;;;;;;;;;;;;;;;;;ACNwB;AACJ;AACE;AACQ;AAC9B;AASkB;AAClB;AAC+D;AACV;AACrD;AACA;AACA;AACA;AACA;AACA,YAAY,gBAAgB,EAAE,4CAAM;AACpC;AACA,qBAAqB,mDAAa;AAClC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,qBAAqB,gDAAS;AAC9B,SAAS;AACT;AACA,KAAK;AACL;AACA,uBAAuB,8CAAO;AAC9B;AACA;AACA,QAAQ,IAAsC;AAC9C;AACA,MAAM,KAAK,EAEN;AACL;AACA,mBAAmB,wDAAc;AACjC;AACA;AACA,KAAK;AACL;AACA,IAAI,4EAAmB;AACvB;AACA;AACA;AACA;AACA,iBAAiB;AACjB,KAAK;AACL;AACA,eAAe,0CAAI,CAAC,gDAAS;AAC7B,wBAAwB,0CAAI;AAC5B;AACA;AACA;AACA;AACA,aAAa;AACb,SAAS;AACT;AACA;AACA;AACA;AACA,gBAAgB,yCAAG;AACnB,aAAa;AACb,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA,IAAI,6CAAO;AACX,gBAAgB,QAAQ;AACxB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAU;AACV,yBAAyB,MAAM;AAC/B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA,IAAI,6CAAO;AACX,gBAAgB,mBAAmB;AACnC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,qBAAqB;AACrB,mCAAmC,UAAU;AAC7C,8BAA8B,KAAK;AACnC,6BAA6B,KAAK;AAClC,kCAAkC,UAAU;AAC5C,gCAAgC,QAAQ;AACxC,gCAAgC,QAAQ;AACxC,6BAA6B,KAAK;AAClC,kCAAkC,UAAU;AAC5C;AACA;AACA;AACA,yCAAyC,eAAe;AACxD,UAAU;AACV,0BAA0B,OAAO;AACjC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA,IAAI,6CAAO;AACX,gBAAgB,mCAAmC;AACnD;AACA;AACA;AACA,6BAA6B,kEAAgB;AAC7C,UAAU;AACV,0BAA0B,OAAO;AACjC;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,6CAAO;AACX;AACA,kCAAkC,gDAAO;AACzC;AACA;AACA;AACA,+CAA+C,gDAAO;AACtD;AACA,aAAa;AACb;AACA;AACA,gBAAgB,2CAAK;AACrB,cAAc;AACd;AACA,gEAAgE,OAAO;AACvE;AACA;AACA,UAAU;AACV,iDAAiD,YAAY;AAC7D;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA,yCAAG;AACH;AACA,kBAAkB,kDAAW;AAC7B;AACA;AACA,uBAAuB,yCAAG;AAC1B;AACA;AACA,QAAQ,yCAAG;AACX;AACA;AACA,IAAI,yCAAG;AACP;AACA,KAAK;AACL,EAAE;AACF,IAAI,yCAAG;AACP;AACA,KAAK;AACL;AACA,IAAI,yCAAG;AACP;AACA,YAAY,yCAAG;AACf;AACA,KAAK;AACL;AACA,IAAI,yCAAG;AACP;AACA;AACA;AACA,KAAK;AACL","sources":["webpack://bitshares_astro_ui/./src/lib/applicationMenu.js","webpack://bitshares_astro_ui/./src/lib/deeplink.js","webpack://bitshares_astro_ui/external commonjs \"bitsharesjs\"","webpack://bitshares_astro_ui/external commonjs \"bitsharesjs-ws\"","webpack://bitshares_astro_ui/external commonjs \"electron\"","webpack://bitshares_astro_ui/external commonjs \"express\"","webpack://bitshares_astro_ui/external commonjs \"uuid\"","webpack://bitshares_astro_ui/external node-commonjs \"os\"","webpack://bitshares_astro_ui/external node-commonjs \"path\"","webpack://bitshares_astro_ui/external node-commonjs \"url\"","webpack://bitshares_astro_ui/webpack/bootstrap","webpack://bitshares_astro_ui/webpack/runtime/compat get default export","webpack://bitshares_astro_ui/webpack/runtime/define property getters","webpack://bitshares_astro_ui/webpack/runtime/hasOwnProperty shorthand","webpack://bitshares_astro_ui/webpack/runtime/make namespace object","webpack://bitshares_astro_ui/./src/background.js"],"sourcesContent":["import {app, Menu} from 'electron';\r\n\r\n/**\r\n * For configuring the electron window menu\r\n */\r\nexport function initApplicationMenu(mainWindow) {\r\n const template = [\r\n {\r\n label: 'View',\r\n submenu: [\r\n {\r\n label: 'Send to tray',\r\n click() {\r\n mainWindow.minimize();\r\n }\r\n },\r\n { label: 'Reload', role: 'reload' },\r\n { label: 'Dev tools', role: 'toggleDevTools' }\r\n ]\r\n }\r\n ];\r\n const menu = Menu.buildFromTemplate(template);\r\n Menu.setApplicationMenu(menu);\r\n}\r\n","import { Apis } from \"bitsharesjs-ws\";\r\nimport { TransactionBuilder } from \"bitsharesjs\";\r\nimport { v4 as uuidv4 } from \"uuid\";\r\n\r\nconst chains = {\r\n bitshares: {\r\n nodeList: [\r\n {\r\n url: \"wss://node.xbts.io/ws\",\r\n },\r\n {\r\n url: \"wss://api.bts.mobi/ws\",\r\n },\r\n {\r\n url: \"wss://api.bitshares.bhuz.info/ws\",\r\n },\r\n {\r\n url: \"wss://btsws.roelandp.nl/ws\",\r\n },\r\n ],\r\n },\r\n bitshares_testnet: {\r\n nodeList: [\r\n {\r\n url: \"wss://testnet.dex.trading/\",\r\n },\r\n {\r\n url: \"wss://testnet.xbts.io/ws\",\r\n },\r\n {\r\n url: \"wss://api-testnet.61bts.com/ws\",\r\n },\r\n ],\r\n },\r\n};\r\n\r\nasync function generateDeepLink(chain, opType, operations) {\r\n return new Promise(async (resolve, reject) => {\r\n const _node = chains[chain].nodeList[0].url\r\n\r\n try {\r\n await Apis.instance(\r\n _node,\r\n true,\r\n 4000,\r\n { enableCrypto: false, enableOrders: true },\r\n (error) => console.log({ error })\r\n ).init_promise;\r\n } catch (error) {\r\n console.log({ error, location: \"api instance failed\" });\r\n return reject(error);\r\n }\r\n\r\n const tr = new TransactionBuilder();\r\n for (let i = 0; i < operations.length; i++) {\r\n tr.add_type_operation(opType, operations[i]);\r\n }\r\n\r\n try {\r\n await tr.update_head_block();\r\n } catch (error) {\r\n console.log({ error, location: \"update head block failed\" });\r\n reject(error);\r\n return;\r\n }\r\n\r\n try {\r\n await tr.set_required_fees();\r\n } catch (error) {\r\n console.log({ error, location: \"set required fees failed\" });\r\n reject(error);\r\n return;\r\n }\r\n\r\n try {\r\n tr.set_expire_seconds(7200);\r\n } catch (error) {\r\n console.log({ error, location: \"set expire seconds failed\" });\r\n reject(error);\r\n return;\r\n }\r\n\r\n try {\r\n tr.finalize();\r\n } catch (error) {\r\n console.log({ error, location: \"finalize failed\" });\r\n reject(error);\r\n return;\r\n }\r\n\r\n let id;\r\n try {\r\n id = await uuidv4();\r\n } catch (error) {\r\n console.log({ error, location: \"uuid generation failed\" });\r\n reject(error);\r\n return;\r\n }\r\n\r\n const request = {\r\n type: \"api\",\r\n id: id,\r\n payload: {\r\n method: \"injectedCall\",\r\n params: [\"signAndBroadcast\", JSON.stringify(tr.toObject()), []],\r\n appName: \"Bitshares Astro UI\",\r\n chain: chain === \"bitshares\" ? \"BTS\" : \"BTS_TEST\",\r\n browser: \"web browser\",\r\n origin: \"localhost\",\r\n },\r\n };\r\n\r\n let encodedPayload;\r\n try {\r\n encodedPayload = encodeURIComponent(JSON.stringify(request));\r\n } catch (error) {\r\n console.log({ error, location: \"encode payload failed\" });\r\n reject(error);\r\n return;\r\n }\r\n\r\n resolve(encodedPayload);\r\n });\r\n}\r\n\r\nexport { generateDeepLink };","module.exports = require(\"bitsharesjs\");","module.exports = require(\"bitsharesjs-ws\");","module.exports = require(\"electron\");","module.exports = require(\"express\");","module.exports = require(\"uuid\");","module.exports = require(\"os\");","module.exports = require(\"path\");","module.exports = require(\"url\");","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","import path from \"path\";\r\nimport os from \"os\";\r\nimport url from \"url\";\r\nimport express from \"express\";\r\n\r\nimport {\r\n app,\r\n BrowserWindow,\r\n Menu,\r\n Tray,\r\n ipcMain,\r\n screen,\r\n shell,\r\n} from \"electron\";\r\n\r\nimport { initApplicationMenu } from \"./lib/applicationMenu.js\";\r\nimport { generateDeepLink } from \"./lib/deeplink.js\";\r\n\r\nlet mainWindow = null;\r\nlet tray = null;\r\n\r\nconst createWindow = async () => {\r\n const { width, height } = screen.getPrimaryDisplay().workAreaSize;\r\n\r\n mainWindow = new BrowserWindow({\r\n width: width,\r\n height: height,\r\n minWidth: 480,\r\n minHeight: 695,\r\n maxWidth: width,\r\n maximizable: true,\r\n maxHeight: height,\r\n useContentSize: true,\r\n autoHideMenuBar: true,\r\n webPreferences: {\r\n nodeIntegration: false,\r\n contextIsolation: true,\r\n sandbox: true,\r\n preload: path.join(__dirname, \"preload.js\"),\r\n },\r\n icon: __dirname + \"/img/taskbar.png\",\r\n });\r\n \r\n const expressApp = express();\r\n\r\n let astroDistPath;\r\n if (process.env.NODE_ENV === 'development') {\r\n astroDistPath = 'astroDist';\r\n } else {\r\n astroDistPath = path.join(process.resourcesPath, 'astroDist');\r\n }\r\n\r\n expressApp.use(express.static(astroDistPath));\r\n expressApp.listen(8080, () => {\r\n console.log(\"Express server listening on port 8080\");\r\n });\r\n\r\n initApplicationMenu(mainWindow);\r\n\r\n mainWindow.loadURL('http://localhost:8080/index.html');\r\n\r\n mainWindow.webContents.setWindowOpenHandler(() => {\r\n return { action: \"deny\" };\r\n });\r\n\r\n tray = new Tray(path.join(__dirname, \"img\", \"tray.png\"));\r\n const contextMenu = Menu.buildFromTemplate([\r\n {\r\n label: \"Show App\",\r\n click: function () {\r\n mainWindow?.show();\r\n },\r\n },\r\n {\r\n label: \"Quit\",\r\n click: function () {\r\n tray = null;\r\n app.quit();\r\n },\r\n },\r\n ]);\r\n\r\n tray.setToolTip(\"Bitshares Astro UI\");\r\n\r\n tray.on(\"right-click\", (event, bounds) => {\r\n tray?.popUpContextMenu(contextMenu);\r\n });\r\n\r\n ipcMain.handle(\"fetchTopMarkets\", async (event, arg) => {\r\n const { chain } = arg;\r\n\r\n let retrievedData;\r\n try {\r\n retrievedData = await fetch(\r\n chain === \"bitshares\"\r\n ? `https://api.bitshares.ws/openexplorer/top_markets?top_n=100`\r\n : `https://api.testnet.bitshares.ws/openexplorer/top_markets?top_n=50`\r\n );\r\n } catch (error) {\r\n console.log({error})\r\n }\r\n \r\n if (!retrievedData || !retrievedData.ok) {\r\n console.log(\"Failed to fetch top markets\");\r\n return;\r\n }\r\n \r\n const topMarkets = await retrievedData.json();\r\n return topMarkets ?? null;\r\n });\r\n\r\n ipcMain.handle(\"fetchAccountHistory\", async (event, arg) => {\r\n const { chain, accountID } = arg;\r\n\r\n const from = arg.from ?? 0;\r\n const size = arg.size ?? 100;\r\n const from_date = arg.from_date ?? \"2015-10-10\";\r\n const to_date = arg.to_date ?? \"now\";\r\n const sort_by = arg.sort_by ?? \"-operation_id_num\";\r\n const type = arg.type ?? \"data\";\r\n const agg_field = arg.agg_field ?? \"operation_type\";\r\n\r\n const url = `https://${\r\n chain === \"bitshares\" ? \"api\" : \"api.testnet\"\r\n }.bitshares.ws/openexplorer/es/account_history` +\r\n `?account_id=${accountID}` +\r\n `&from_=${from}` +\r\n `&size=${size}` +\r\n `&from_date=${from_date}` +\r\n `&to_date=${to_date}` +\r\n `&sort_by=${sort_by}` +\r\n `&type=${type}` +\r\n `&agg_field=${agg_field}`;\r\n\r\n let history;\r\n try {\r\n history = await fetch(url, { method: \"GET\" });\r\n } catch (error) {\r\n console.log({ error });\r\n return null;\r\n }\r\n\r\n if (!history || !history.ok) {\r\n console.log(\"Couldn't fetch account history.\");\r\n return null;\r\n }\r\n\r\n const accountHistory = await history.json(); \r\n return accountHistory ?? null;\r\n });\r\n\r\n ipcMain.handle(\"generateDeepLink\", async (event, arg) => {\r\n const { usrChain, operationName, trxJSON } = arg;\r\n\r\n let deeplink;\r\n try {\r\n deeplink = await generateDeepLink(usrChain, operationName, trxJSON);\r\n } catch (error) {\r\n console.log({ error });\r\n }\r\n\r\n return deeplink ?? null;\r\n });\r\n\r\n const safeDomains = [\r\n \"https://blocksights.info/\",\r\n \"https://bts.exchange/\",\r\n \"https://ex.xbts.io/\",\r\n \"https://kibana.bts.mobi/\",\r\n \"https://www.bitsharescan.info/\",\r\n \"https://github.com/bitshares/beet\",\r\n ];\r\n ipcMain.on(\"openURL\", (event, arg) => {\r\n try {\r\n const parsedUrl = new url.URL(arg);\r\n const domain = parsedUrl.hostname;\r\n\r\n const isSafeDomain = safeDomains.some(safeDomain => {\r\n const safeDomainHostname = new url.URL(safeDomain).hostname;\r\n return safeDomainHostname === domain;\r\n });\r\n\r\n if (isSafeDomain) {\r\n shell.openExternal(arg);\r\n } else {\r\n console.error(\r\n `Rejected opening URL with unsafe domain: ${domain}`\r\n );\r\n }\r\n } catch (err) {\r\n console.error(`Failed to open URL: ${err.message}`);\r\n }\r\n }); \r\n\r\n tray.on(\"click\", () => {\r\n mainWindow?.setAlwaysOnTop(true);\r\n mainWindow?.show();\r\n mainWindow?.focus();\r\n mainWindow?.setAlwaysOnTop(false);\r\n });\r\n\r\n tray.on(\"balloon-click\", () => {\r\n mainWindow?.setAlwaysOnTop(true);\r\n mainWindow?.show();\r\n mainWindow?.focus();\r\n mainWindow?.setAlwaysOnTop(false);\r\n });\r\n};\r\n\r\napp.disableHardwareAcceleration();\r\n\r\nconst currentOS = os.platform();\r\nif (currentOS === \"win32\" || currentOS === \"linux\") {\r\n // windows + linux setup phase\r\n const gotTheLock = app.requestSingleInstanceLock();\r\n\r\n if (!gotTheLock) {\r\n app.quit();\r\n }\r\n\r\n app.whenReady().then(() => {\r\n createWindow();\r\n });\r\n} else {\r\n app.whenReady().then(() => {\r\n createWindow();\r\n });\r\n\r\n app.on(\"window-all-closed\", () => {\r\n if (process.platform !== \"darwin\") {\r\n app.quit();\r\n }\r\n });\r\n\r\n app.on(\"activate\", () => {\r\n if (mainWindow === null) {\r\n createWindow();\r\n }\r\n });\r\n}\r\n"],"names":[],"sourceRoot":""} \ No newline at end of file diff --git a/src/background.js b/src/background.js index a0db8a8..090774f 100644 --- a/src/background.js +++ b/src/background.js @@ -59,6 +59,10 @@ const createWindow = async () => { mainWindow.loadURL('http://localhost:8080/index.html'); + mainWindow.webContents.setWindowOpenHandler(() => { + return { action: "deny" }; + }); + tray = new Tray(path.join(__dirname, "img", "tray.png")); const contextMenu = Menu.buildFromTemplate([ { diff --git a/src/components/CreditDeals.jsx b/src/components/CreditDeals.jsx index 663adb6..8c64b76 100644 --- a/src/components/CreditDeals.jsx +++ b/src/components/CreditDeals.jsx @@ -123,7 +123,7 @@ export default function CreditDeals(properties) { let unsubscribeBorrowerDeals; if (usr && usr.id) { - const borrowerDealsStore = createBorrowerDealsStore([usr.chain, usr.id]); + const borrowerDealsStore = createBorrowerDealsStore([usr.chain, usr.id, currentNode ? currentNode.url : null]); unsubscribeBorrowerDeals = borrowerDealsStore.subscribe(({ data, error, loading }) => { if (data && !error && !loading) { diff --git a/src/components/CreditOffers.jsx b/src/components/CreditOffers.jsx new file mode 100644 index 0000000..a14bd17 --- /dev/null +++ b/src/components/CreditOffers.jsx @@ -0,0 +1,205 @@ +import React, { useSyncExternalStore, useMemo } from "react"; +import { FixedSizeList as List } from "react-window"; +import { useTranslation } from "react-i18next"; + +import { i18n as i18nInstance, locale } from "@/lib/i18n.js"; + +import { Button } from "@/components/ui/button"; + +import { + Card, + CardContent, + CardDescription, + CardFooter, + CardHeader, + CardTitle, +} from "@/components/ui/card"; + +import { useInitCache } from "@/nanoeffects/Init.ts"; + +import { $currentUser } from "@/stores/users.ts"; +import { + $assetCacheBTS, + $assetCacheTEST, + $offersCacheBTS, + $offersCacheTEST, +} from "@/stores/cache.ts"; + +import { humanReadableFloat } from "@/lib/common.js"; + +function hoursTillExpiration(expirationTime) { + var expirationDate = new Date(expirationTime); + var currentDate = new Date(); + var difference = expirationDate - currentDate; + var hours = Math.round(difference / 1000 / 60 / 60); + return hours; +} + +export default function CreditBorrow(properties) { + const { t, i18n } = useTranslation(locale.get(), { i18n: i18nInstance }); + const usr = useSyncExternalStore($currentUser.subscribe, $currentUser.get, () => true); + + const _assetsBTS = useSyncExternalStore($assetCacheBTS.subscribe, $assetCacheBTS.get, () => true); + const _assetsTEST = useSyncExternalStore( + $assetCacheTEST.subscribe, + $assetCacheTEST.get, + () => true + ); + + const _offersBTS = useSyncExternalStore( + $offersCacheBTS.subscribe, + $offersCacheBTS.get, + () => true + ); + const _offersTEST = useSyncExternalStore( + $offersCacheTEST.subscribe, + $offersCacheTEST.get, + () => true + ); + + const _chain = useMemo(() => { + if (usr && usr.chain) { + return usr.chain; + } + return "bitshares"; + }, [usr]); + + useInitCache(_chain ?? "bitshares", ["assets", "offers"]); + + const assets = useMemo(() => { + if (_chain && (_assetsBTS || _assetsTEST)) { + return _chain === "bitshares" ? _assetsBTS : _assetsTEST; + } + return []; + }, [_assetsBTS, _assetsTEST, _chain]); + + const offers = useMemo(() => { + if (_chain && (_offersBTS || _offersTEST)) { + return _chain === "bitshares" + ? _offersBTS.filter((x) => hoursTillExpiration(x.auto_disable_time) >= 0 && x.owner_account === usr.id) + : _offersTEST.filter((x) => hoursTillExpiration(x.auto_disable_time) >= 0 && x.owner_account === usr.id); + } + return []; + }, [_offersBTS, _offersTEST, _chain, usr]); + + function CommonRow({ index, style, res, foundAsset }) { + return ( +
+ {}}> + + + {t("CreditBorrow:common.title", { + orderID: res.id.replace("1.21.", ""), + owner_name: res.owner_name, + owner_account: res.owner_account, + })} + + + {t("CreditBorrow:common.offering")} + + {` ${humanReadableFloat(res.current_balance, foundAsset.precision)} ${ + foundAsset.symbol + } (${res.asset_type})`} + +
+ {t("CreditBorrow:common.accepting")} + + {assets && assets.length + ? ` ${res.acceptable_collateral + .map((asset) => asset[0]) + .map((x) => { + return assets.find((y) => y.id === x)?.symbol; + }) + .map((x) => x) + .join(", ")}` + : t("CreditBorrow:common.loading")} + +
+
+ +
+
+ {t("CreditBorrow:common.fee", { fee: res.fee_rate / 10000 })} +
+ {t("CreditBorrow:common.repayPeriod", { + repayPeriod: (res.max_duration_seconds / 60 / 60).toFixed( + res.max_duration_seconds / 60 / 60 < 1 ? 2 : 0 + ), + })} +
+
+ {t("CreditBorrow:common.validity", { + validity: hoursTillExpiration(res.auto_disable_time), + })} +
+ {t("CreditBorrow:common.min", { + amount: humanReadableFloat(res.min_deal_amount, foundAsset.precision), + asset: foundAsset.symbol, + })} +
+
+
+ + + + + +
+
+ ); + } + + const Row = ({ index, style }) => { + let res = offers[index]; + + const foundAsset = assets.find((x) => x.id === res.asset_type); + + if (!res || !foundAsset) { + return null; + } + + return ; + }; + + return ( + <> +
+
+ + + {t("CreditOffers:card.title")} + {t("CreditOffers:card.description")} + + + <> + { + offers && offers.length + ? ( + + {Row} + + ) + : null + } + { + offers && !offers.length + ? t("CreditOffers:card.noResults") + : null + } + + + +
+
+ + ); +} diff --git a/src/components/Home.jsx b/src/components/Home.jsx index 4783b55..d859442 100644 --- a/src/components/Home.jsx +++ b/src/components/Home.jsx @@ -259,6 +259,44 @@ export default function Home(properties) { + + + + + + + {t("Home:offers.title")} + {t("Home:offers.subtitle")} + + + + + +
    +
  • {t("Home:offers.hover1")}
  • +
  • {t("Home:offers.hover2")}
  • +
+
+
+ + + + + + + {t("Home:vesting.title")} + {t("Home:vesting.subtitle")} + + + + + +
    +
  • {t("Home:vesting.hover1")}
  • +
  • {t("Home:vesting.hover2")}
  • +
+
+

diff --git a/src/components/PortfolioTabs.jsx b/src/components/PortfolioTabs.jsx index 133bd87..e65a08b 100644 --- a/src/components/PortfolioTabs.jsx +++ b/src/components/PortfolioTabs.jsx @@ -121,7 +121,6 @@ export default function PortfolioTabs(properties) { unsubscribeUserBalancesStore = userBalancesStore.subscribe(({ data, error, loading }) => { if (data && !error && !loading) { - console.log({data}) const updatedData = data.map((balance) => { return { ...balance, diff --git a/src/components/SimpleSwap.jsx b/src/components/SimpleSwap.jsx index fc00f73..b85b131 100644 --- a/src/components/SimpleSwap.jsx +++ b/src/components/SimpleSwap.jsx @@ -467,29 +467,6 @@ export default function SimpleSwap() { )) / Number(poolamountap); } - - /* - console.log({ - calculated: { - poolamounta, - poolamountap, - poolamountb, - poolamountbp, - maker_market_fee_percenta, - maker_market_fee_percentb, - max_market_feea, - max_market_feeb, - taker_fee_percenta, - taker_market_fee_percent_a - }, - inputs: { - foundPool, - assetA, - assetB, - }, - result - }) - */ return result; } diff --git a/src/components/Vesting.jsx b/src/components/Vesting.jsx new file mode 100644 index 0000000..8335a4d --- /dev/null +++ b/src/components/Vesting.jsx @@ -0,0 +1,240 @@ +import React, { useSyncExternalStore, useMemo, useEffect, useState } from "react"; +import { FixedSizeList as List } from "react-window"; +import { useStore } from '@nanostores/react'; + +import { useTranslation } from "react-i18next"; +import { i18n as i18nInstance, locale } from "@/lib/i18n.js"; + +import { Button } from "@/components/ui/button"; + +import { + Card, + CardContent, + CardDescription, + CardFooter, + CardHeader, + CardTitle, +} from "@/components/ui/card"; + +import { useInitCache } from "@/nanoeffects/Init.ts"; + +import { $currentUser } from "@/stores/users.ts"; +import { $currentNode } from "@/stores/node.ts"; +import { + $assetCacheBTS, + $assetCacheTEST, +} from "@/stores/cache.ts"; + +import { + createVestingBalanceStore +} from "@/nanoeffects/VestingBalances.ts"; + +import { humanReadableFloat } from "@/lib/common.js"; +import DeepLinkDialog from "./common/DeepLinkDialog.jsx"; + +function hoursTillExpiration(expirationTime) { + var expirationDate = new Date(expirationTime); + var currentDate = new Date(); + var difference = expirationDate - currentDate; + var hours = Math.round(difference / 1000 / 60 / 60); + return hours; +} + +export default function Vesting(properties) { + const { t, i18n } = useTranslation(locale.get(), { i18n: i18nInstance }); + const usr = useSyncExternalStore($currentUser.subscribe, $currentUser.get, () => true); + const currentNode = useStore($currentNode); + + const [showDialog, setShowDialog] = useState(false); + const [chosenVestingBalance, setChosenVestingBalance] = useState(null); + + const [vestingType, setVestingType] = useState("cashback"); + + const _assetsBTS = useSyncExternalStore($assetCacheBTS.subscribe, $assetCacheBTS.get, () => true); + const _assetsTEST = useSyncExternalStore( + $assetCacheTEST.subscribe, + $assetCacheTEST.get, + () => true + ); + + const _chain = useMemo(() => { + if (usr && usr.chain) { + return usr.chain; + } + return "bitshares"; + }, [usr]); + + useInitCache(_chain ?? "bitshares", ["assets"]); + + const assets = useMemo(() => { + if (_chain && (_assetsBTS || _assetsTEST)) { + return _chain === "bitshares" ? _assetsBTS : _assetsTEST; + } + return []; + }, [_assetsBTS, _assetsTEST, _chain]); + + const vestingStore = useMemo(() => { + if (!usr || !usr.chain || !usr.id || !currentNode) { + return; + } + return createVestingBalanceStore([usr.chain, usr.id, currentNode.url]); + }, [usr, currentNode]); + + const { + data: vestingData, + loading: vestingLoading, + error: vestingError, + } = useStore(vestingStore); + + const chosenVestingData = useMemo(() => { + if (!vestingData || !vestingData.length) { + return []; + } + return vestingData.filter((x) => x.balance_type === vestingType); + }, [vestingData, vestingType]); + + const VestingRow = ({ index, style }) => { + let res = chosenVestingData[index]; + const foundAsset = assets.find((x) => x.id === res.balance.asset_id); + + if (!res || !foundAsset) { + return null; + } + + const readableBalance = ` ${humanReadableFloat(res.balance.amount, foundAsset.precision)} ${ foundAsset.symbol }`; + + const policy = res.balance_type === "cashback" + ? res.policy[1] + : null; + + return
+ + + +
+
+ {readableBalance} +
+
+ ({res.id}) +
+
+
+
+ + { + policy + ? ( +
+
+ {t("Vesting:vesting_seconds")} {policy.vesting_seconds}
+ {t("Vesting:start_claim")}: {new Date(policy.start_claim).toLocaleString()}
+
+
+ {t("Vesting:coin_seconds_earned")}: {policy.coin_seconds_earned}
+ {t("Vesting:coin_seconds_earned_last_update")}: {new Date(policy.coin_seconds_earned_last_update).toLocaleString()}
+
+
+ ) + : null + } +
+ + + +
+
; + }; + + return ( +
+
+ + + {t("Vesting:card.title")} + {t("Vesting:card.description")} + + + +
+ + +
+ + <> + { + chosenVestingData && chosenVestingData.length + ? ( + + {VestingRow} + + ) + : null + } + { + chosenVestingData && !chosenVestingData.length + ? t("Vesting:card.empty") + : null + } + + +
+
+ { + showDialog + ? + : null + } +
+
+ ); +} diff --git a/src/data/locales/da/CreditOffers.json b/src/data/locales/da/CreditOffers.json new file mode 100644 index 0000000..39521e9 --- /dev/null +++ b/src/data/locales/da/CreditOffers.json @@ -0,0 +1,7 @@ +{ + "card": { + "title": "📜 Tjek dine kredittilbud", + "description": "Herfra kan du overvåge dine aktive kredittilbud og administrere deres indstillinger.", + "noResults": "Ingen aktive kreditaftaler fundet." + } + } \ No newline at end of file diff --git a/src/data/locales/da/Home.json b/src/data/locales/da/Home.json index 45da9af..4152f42 100644 --- a/src/data/locales/da/Home.json +++ b/src/data/locales/da/Home.json @@ -88,5 +88,17 @@ "subtitle": "Tjek dine kreditaftaler", "hover1": "Overvåg dine aktive kreditaftaler.", "hover2": "Administrer status for dine kreditaftaler." + }, + "offers": { + "title": "📜 Kredittilbud", + "subtitle": "Tjek dine kredittilbud", + "hover1": "Overvåg dine aktive kredittilbud.", + "hover2": "Administrer status for dine kredittilbud." + }, + "vesting": { + "title": "⌚ Optjening af saldi", + "subtitle": "Se optjeningssaldi", + "hover1": "Tjek dine optjente saldi.", + "hover2": "Gør krav på dine optjente saldi." } } diff --git a/src/data/locales/da/PageHeader.json b/src/data/locales/da/PageHeader.json index a9eab20..55fd459 100644 --- a/src/data/locales/da/PageHeader.json +++ b/src/data/locales/da/PageHeader.json @@ -45,7 +45,9 @@ "smartcoins": "Brug grænsefladen nedenfor til at finde et aktiv, som du kan låne", "stake": "Brug denne formular til at satse dine aktiver i likviditetspuljer", "transfer": "Brug formularen nedenfor til at overføre aktiver til andre blockchain-brugere", - "nodes": "Opret forbindelse til blockchain via en node efter eget valg" + "nodes": "Opret forbindelse til blockchain via en node efter eget valg", + "offers": "Overvåg og administrer dine kredittilbud med nedenstående formular.", + "vesting": "Overvåg og træk dine optjente saldi med nedenstående formular." }, "back": "Gå tilbage", "usage": "Designet til brug med ", diff --git a/src/data/locales/da/Vesting.json b/src/data/locales/da/Vesting.json new file mode 100644 index 0000000..b323d49 --- /dev/null +++ b/src/data/locales/da/Vesting.json @@ -0,0 +1,18 @@ +{ + "dialogContent": { + "header": "Tilbagetrækning {{readable}}" + }, + "vesting_seconds": "Optjening sekunder", + "start_claim": "Start krav", + "coin_seconds_earned": "Møntsekunder optjent", + "coin_seconds_earned_last_update": "Mønt sekunder optjent sidste opdatering", + "claim_a": "Hæv cashback", + "claim_b": "Træk andel af markedsgebyrer tilbage", + "card": { + "title": "Optjening af saldi", + "description": "Overvåg og træk dine optjente saldi.", + "empty": "Ingen optjeningssaldi fundet." + }, + "cashback": "Cashback", + "market_fees": "Markedsgebyrer" +} \ No newline at end of file diff --git a/src/data/locales/de/CreditOffers.json b/src/data/locales/de/CreditOffers.json new file mode 100644 index 0000000..9b6f63a --- /dev/null +++ b/src/data/locales/de/CreditOffers.json @@ -0,0 +1,7 @@ +{ + "card": { + "title": "📜 Prüfen Sie Ihre Kreditangebote", + "description": "Von hier aus können Sie Ihre aktiven Kreditangebote überwachen und deren Einstellungen verwalten.", + "noResults": "Keine aktiven Kreditverträge gefunden." + } + } \ No newline at end of file diff --git a/src/data/locales/de/Home.json b/src/data/locales/de/Home.json index 5fdd3b9..7edc17a 100644 --- a/src/data/locales/de/Home.json +++ b/src/data/locales/de/Home.json @@ -88,5 +88,17 @@ "subtitle": "Überprüfen Sie Ihre Kreditverträge", "hover1": "Überwachen Sie Ihre aktiven Kreditgeschäfte.", "hover2": "Verwalten Sie den Status Ihrer Kreditverträge." + }, + "offers": { + "title": "📜 Kreditangebote", + "subtitle": "Prüfen Sie Ihre Kreditangebote", + "hover1": "Überwachen Sie Ihre aktiven Kreditangebote.", + "hover2": "Verwalten Sie den Status Ihrer Kreditangebote." + }, + "vesting": { + "title": "⌚ Freizügigkeitsguthaben", + "subtitle": "Freizügigkeitsguthaben anzeigen", + "hover1": "Überprüfen Sie Ihre Sperrguthaben.", + "hover2": "Fordern Sie Ihr Freizügigkeitsguthaben an." } } diff --git a/src/data/locales/de/PageHeader.json b/src/data/locales/de/PageHeader.json index 6521c03..c72e6fe 100644 --- a/src/data/locales/de/PageHeader.json +++ b/src/data/locales/de/PageHeader.json @@ -45,7 +45,9 @@ "smartcoins": "Verwenden Sie die folgende Schnittstelle, um einen Vermögenswert zu finden, den Sie leihen können", "stake": "Verwenden Sie dieses Formular, um Ihr Vermögen in Liquiditätspools zu verpfänden", "transfer": "Verwenden Sie das untenstehende Formular, um Vermögenswerte an andere Blockchain-Benutzer zu übertragen", - "nodes": "Verbinden Sie sich über einen Knoten Ihrer Wahl mit der Blockchain" + "nodes": "Verbinden Sie sich über einen Knoten Ihrer Wahl mit der Blockchain", + "offers": "Überwachen und verwalten Sie Ihre Kreditangebote mit dem untenstehenden Formular.", + "vesting": "Überwachen und heben Sie Ihr Sperrguthaben mit dem untenstehenden Formular ab." }, "back": "Geh zurück", "usage": "Konzipiert für den Einsatz mit ", diff --git a/src/data/locales/de/Vesting.json b/src/data/locales/de/Vesting.json new file mode 100644 index 0000000..e22af32 --- /dev/null +++ b/src/data/locales/de/Vesting.json @@ -0,0 +1,18 @@ +{ + "dialogContent": { + "header": "Rückzug {{readable}}" + }, + "vesting_seconds": "Vesting-Sekunden", + "start_claim": "Anspruch starten", + "coin_seconds_earned": "Münzsekunden verdient", + "coin_seconds_earned_last_update": "Letztes Update verdiente Münzsekunden", + "claim_a": "Cashback abheben", + "claim_b": "Anteil der Marktgebühren abheben", + "card": { + "title": "Freizügigkeitsguthaben", + "description": "Überwachen Sie Ihr Sperrguthaben und ziehen Sie es ab.", + "empty": "Es wurden keine Restguthaben gefunden." + }, + "cashback": "Cashback", + "market_fees": "Marktgebühren" +} \ No newline at end of file diff --git a/src/data/locales/en/CreditOffers.json b/src/data/locales/en/CreditOffers.json new file mode 100644 index 0000000..8d2f474 --- /dev/null +++ b/src/data/locales/en/CreditOffers.json @@ -0,0 +1,7 @@ +{ + "card": { + "title": "📜 Check your credit offers", + "description": "From here you can monitor your active credit offers and manage their settings.", + "noResults": "No active credit deals found." + } +} \ No newline at end of file diff --git a/src/data/locales/en/Home.json b/src/data/locales/en/Home.json index d8e2dab..4f3104e 100644 --- a/src/data/locales/en/Home.json +++ b/src/data/locales/en/Home.json @@ -88,5 +88,17 @@ "subtitle": "Check your credit deals", "hover1": "Monitor your active credit deals.", "hover2": "Manage the state of your credit deals." + }, + "offers": { + "title": "📜 Credit offers", + "subtitle": "Check your credit offers", + "hover1": "Monitor your active credit offers.", + "hover2": "Manage the state of your credit offers." + }, + "vesting": { + "title": "⌚ Vesting balances", + "subtitle": "View vesting balances", + "hover1": "Check your vesting balances.", + "hover2": "Claim your vested balances." } } diff --git a/src/data/locales/en/PageHeader.json b/src/data/locales/en/PageHeader.json index fa91e77..9873a41 100644 --- a/src/data/locales/en/PageHeader.json +++ b/src/data/locales/en/PageHeader.json @@ -45,7 +45,9 @@ "smartcoins": "Use the interface below to locate an asset to borrow into existence", "stake": "Use this form to stake your assets in liquidity pools", "transfer": "Use the form below to transfer assets to other blockchain users", - "nodes": "Connect to the blockchain via a node of your choice" + "nodes": "Connect to the blockchain via a node of your choice", + "offers": "Monitor and manage your credit offers with the below form.", + "vesting": "Monitor and withdraw your vesting balances with the below form." }, "back": "Go back", "usage": "Designed for use with ", diff --git a/src/data/locales/en/Vesting.json b/src/data/locales/en/Vesting.json new file mode 100644 index 0000000..fdc118c --- /dev/null +++ b/src/data/locales/en/Vesting.json @@ -0,0 +1,18 @@ +{ + "dialogContent": { + "header": "Withdrawing {{readable}}" + }, + "vesting_seconds": "Vesting seconds", + "start_claim": "Start claim", + "coin_seconds_earned": "Coin seconds earned", + "coin_seconds_earned_last_update": "Coin seconds earned last update", + "claim_a": "Withdraw cashback", + "claim_b": "Withdraw share of market fees", + "card": { + "title": "Vesting balances", + "description": "Monitor and withdraw your vesting balances.", + "empty": "No vesting balances found." + }, + "cashback": "Cashback", + "market_fees": "Market fees" +} \ No newline at end of file diff --git a/src/data/locales/es/CreditOffers.json b/src/data/locales/es/CreditOffers.json new file mode 100644 index 0000000..296e349 --- /dev/null +++ b/src/data/locales/es/CreditOffers.json @@ -0,0 +1,7 @@ +{ + "card": { + "title": "📜 Consulta tus ofertas de crédito", + "description": "Desde aquí puede monitorear sus ofertas de crédito activas y administrar su configuración.", + "noResults": "No se encontraron ofertas de crédito activas." + } + } \ No newline at end of file diff --git a/src/data/locales/es/Home.json b/src/data/locales/es/Home.json index c258dc1..4f77e5a 100644 --- a/src/data/locales/es/Home.json +++ b/src/data/locales/es/Home.json @@ -88,5 +88,17 @@ "subtitle": "Consulta tus ofertas de crédito", "hover1": "Supervise sus ofertas de crédito activas.", "hover2": "Gestiona el estado de tus operaciones crediticias." + }, + "offers": { + "title": "📜 Ofertas de crédito", + "subtitle": "Consulta tus ofertas de crédito", + "hover1": "Monitoree sus ofertas de crédito activas.", + "hover2": "Gestiona el estado de tus ofertas de crédito." + }, + "vesting": { + "title": "⌚ Saldos adquiridos", + "subtitle": "Ver saldos de adquisición de derechos", + "hover1": "Verifique sus saldos de derechos adquiridos.", + "hover2": "Reclame sus saldos adquiridos." } } diff --git a/src/data/locales/es/PageHeader.json b/src/data/locales/es/PageHeader.json index 7957705..3055781 100644 --- a/src/data/locales/es/PageHeader.json +++ b/src/data/locales/es/PageHeader.json @@ -45,7 +45,9 @@ "smartcoins": "Utilice la siguiente interfaz para localizar un activo para pedir prestado y crearlo.", "stake": "Utilice este formulario para apostar sus activos en fondos de liquidez", "transfer": "Utilice el siguiente formulario para transferir activos a otros usuarios de blockchain", - "nodes": "Conéctese a la cadena de bloques a través de un nodo de su elección" + "nodes": "Conéctese a la cadena de bloques a través de un nodo de su elección", + "offers": "Monitoree y administre sus ofertas de crédito con el siguiente formulario.", + "vesting": "Supervise y retire sus saldos adquiridos con el siguiente formulario." }, "back": "Regresa", "usage": "Diseñado para usar con ", diff --git a/src/data/locales/es/Vesting.json b/src/data/locales/es/Vesting.json new file mode 100644 index 0000000..d60e623 --- /dev/null +++ b/src/data/locales/es/Vesting.json @@ -0,0 +1,18 @@ +{ + "dialogContent": { + "header": "Retirándose {{readable}}" + }, + "vesting_seconds": "Segundos de adquisición de derechos", + "start_claim": "Iniciar reclamo", + "coin_seconds_earned": "Segundos de monedas ganados", + "coin_seconds_earned_last_update": "Segundos de monedas obtenidos en la última actualización", + "claim_a": "Retirar reembolso", + "claim_b": "Retirar parte de las tarifas del mercado", + "card": { + "title": "Saldos adquiridos", + "description": "Supervise y retire sus saldos de derechos adquiridos.", + "empty": "No se encontraron saldos de adquisición de derechos." + }, + "cashback": "Reembolso", + "market_fees": "Tarifas de mercado" +} \ No newline at end of file diff --git a/src/data/locales/et/CreditOffers.json b/src/data/locales/et/CreditOffers.json new file mode 100644 index 0000000..e3b21e1 --- /dev/null +++ b/src/data/locales/et/CreditOffers.json @@ -0,0 +1,7 @@ +{ + "card": { + "title": "📜 Kontrollige oma krediidipakkumisi", + "description": "Siit saate jälgida oma aktiivseid krediidipakkumisi ja hallata nende seadeid.", + "noResults": "Ühtegi aktiivset krediiditehingut ei leitud." + } + } \ No newline at end of file diff --git a/src/data/locales/et/Home.json b/src/data/locales/et/Home.json index 195e005..8ce80d8 100644 --- a/src/data/locales/et/Home.json +++ b/src/data/locales/et/Home.json @@ -88,5 +88,17 @@ "subtitle": "Kontrollige oma krediidipakkumisi", "hover1": "Jälgige oma aktiivseid krediiditehinguid.", "hover2": "Hallake oma krediiditehingute seisu." + }, + "offers": { + "title": "📜 Krediidipakkumised", + "subtitle": "Kontrollige oma krediidipakkumisi", + "hover1": "Jälgige oma aktiivseid krediidipakkumisi.", + "hover2": "Hallake oma krediidipakkumiste olekut." + }, + "vesting": { + "title": "⌚ Üleandmise saldod", + "subtitle": "Vaadake üleandmise saldosid", + "hover1": "Kontrollige oma üleandmisjääke.", + "hover2": "Nõudke oma kontojääke." } } diff --git a/src/data/locales/et/PageHeader.json b/src/data/locales/et/PageHeader.json index b748e52..9904c5f 100644 --- a/src/data/locales/et/PageHeader.json +++ b/src/data/locales/et/PageHeader.json @@ -45,7 +45,9 @@ "smartcoins": "Kasutage laenatava vara leidmiseks allolevat liidest", "stake": "Kasutage seda vormi oma varade paigutamiseks likviidsusfondidesse", "transfer": "Kasutage allolevat vormi varade ülekandmiseks teistele plokiahela kasutajatele", - "nodes": "Ühendage plokiahelaga teie valitud sõlme kaudu" + "nodes": "Ühendage plokiahelaga teie valitud sõlme kaudu", + "offers": "Jälgige ja hallake oma krediidipakkumisi alloleva vormi abil.", + "vesting": "Jälgige ja eemaldage oma üleandmise saldosid alloleva vormi abil." }, "back": "Mine tagasi", "usage": "Mõeldud kasutamiseks koos ", diff --git a/src/data/locales/et/Vesting.json b/src/data/locales/et/Vesting.json new file mode 100644 index 0000000..9e05942 --- /dev/null +++ b/src/data/locales/et/Vesting.json @@ -0,0 +1,18 @@ +{ + "dialogContent": { + "header": "Väljatõmbumine {{readable}}" + }, + "vesting_seconds": "Sekundite omandamine", + "start_claim": "Alustage nõuet", + "coin_seconds_earned": "Teenitud mündisekundid", + "coin_seconds_earned_last_update": "Viimase värskenduse teenitud mündisekundid", + "claim_a": "Võtke raha tagasi", + "claim_b": "Võtta osa turutasudest välja", + "card": { + "title": "Üleandmise saldod", + "description": "Jälgige ja eemaldage oma üleandmise saldosid.", + "empty": "Üleandmisjääke ei leitud." + }, + "cashback": "Raha tagasi", + "market_fees": "Turu tasud" +} \ No newline at end of file diff --git a/src/data/locales/fr/CreditOffers.json b/src/data/locales/fr/CreditOffers.json new file mode 100644 index 0000000..c5d7755 --- /dev/null +++ b/src/data/locales/fr/CreditOffers.json @@ -0,0 +1,7 @@ +{ + "card": { + "title": "📜 Vérifiez vos offres de crédit", + "description": "De là, vous pouvez surveiller vos offres de crédit actives et gérer leurs paramètres.", + "noResults": "Aucune offre de crédit active trouvée." + } + } \ No newline at end of file diff --git a/src/data/locales/fr/Home.json b/src/data/locales/fr/Home.json index 5cfb49c..3a35b2c 100644 --- a/src/data/locales/fr/Home.json +++ b/src/data/locales/fr/Home.json @@ -88,5 +88,17 @@ "subtitle": "Vérifiez vos offres de crédit", "hover1": "Surveillez vos transactions de crédit actives.", "hover2": "Gérez l’état de vos transactions de crédit." + }, + "offers": { + "title": "📜 Offres de crédit", + "subtitle": "Vérifiez vos offres de crédit", + "hover1": "Surveillez vos offres de crédit actives.", + "hover2": "Gérez l’état de vos offres de crédit." + }, + "vesting": { + "title": "⌚ Soldes d’acquisition", + "subtitle": "Afficher les soldes d'acquisition", + "hover1": "Vérifiez vos soldes d’acquisition.", + "hover2": "Réclamez vos soldes acquis." } } diff --git a/src/data/locales/fr/PageHeader.json b/src/data/locales/fr/PageHeader.json index 3d670c0..28b91da 100644 --- a/src/data/locales/fr/PageHeader.json +++ b/src/data/locales/fr/PageHeader.json @@ -45,7 +45,9 @@ "smartcoins": "Utilisez l'interface ci-dessous pour localiser un actif à emprunter pour exister", "stake": "Utilisez ce formulaire pour miser vos actifs dans des pools de liquidité", "transfer": "Utilisez le formulaire ci-dessous pour transférer des actifs à d'autres utilisateurs de la blockchain", - "nodes": "Connectez-vous à la blockchain via un nœud de votre choix" + "nodes": "Connectez-vous à la blockchain via un nœud de votre choix", + "offers": "Suivez et gérez vos offres de crédit avec le formulaire ci-dessous.", + "vesting": "Surveillez et retirez vos soldes d’acquisition avec le formulaire ci-dessous." }, "back": "Retourner", "usage": "Conçu pour être utilisé avec ", diff --git a/src/data/locales/fr/Vesting.json b/src/data/locales/fr/Vesting.json new file mode 100644 index 0000000..5e4d380 --- /dev/null +++ b/src/data/locales/fr/Vesting.json @@ -0,0 +1,18 @@ +{ + "dialogContent": { + "header": "Retrait {{readable}}" + }, + "vesting_seconds": "Secondes d’acquisition", + "start_claim": "Commencer la réclamation", + "coin_seconds_earned": "Secondes de pièces gagnées", + "coin_seconds_earned_last_update": "Secondes de pièces gagnées lors de la dernière mise à jour", + "claim_a": "Retirer du cashback", + "claim_b": "Retirer une part des frais de marché", + "card": { + "title": "Soldes d’acquisition", + "description": "Surveillez et retirez vos soldes d’acquisition.", + "empty": "Aucun solde d'acquisition trouvé." + }, + "cashback": "Remise en argent", + "market_fees": "Frais de marché" +} \ No newline at end of file diff --git a/src/data/locales/it/CreditOffers.json b/src/data/locales/it/CreditOffers.json new file mode 100644 index 0000000..a2fe633 --- /dev/null +++ b/src/data/locales/it/CreditOffers.json @@ -0,0 +1,7 @@ +{ + "card": { + "title": "📜 Controlla le tue offerte di credito", + "description": "Da qui puoi monitorare le tue offerte di credito attive e gestirne le impostazioni.", + "noResults": "Nessun accordo di credito attivo trovato." + } + } \ No newline at end of file diff --git a/src/data/locales/it/Home.json b/src/data/locales/it/Home.json index a0a2d7f..72dbf0c 100644 --- a/src/data/locales/it/Home.json +++ b/src/data/locales/it/Home.json @@ -88,5 +88,17 @@ "subtitle": "Controlla le tue offerte di credito", "hover1": "Monitora le tue operazioni di credito attive.", "hover2": "Gestisci lo stato dei tuoi contratti di credito." + }, + "offers": { + "title": "📜Offerte di credito", + "subtitle": "Controlla le tue offerte di credito", + "hover1": "Monitora le tue offerte di credito attive.", + "hover2": "Gestisci lo stato delle tue offerte di credito." + }, + "vesting": { + "title": "⌚ Saldi di maturazione", + "subtitle": "Visualizza i saldi di maturazione", + "hover1": "Controlla i tuoi saldi di maturazione.", + "hover2": "Richiedi i tuoi saldi acquisiti." } } diff --git a/src/data/locales/it/PageHeader.json b/src/data/locales/it/PageHeader.json index 09ea121..18959a9 100644 --- a/src/data/locales/it/PageHeader.json +++ b/src/data/locales/it/PageHeader.json @@ -45,7 +45,9 @@ "smartcoins": "Utilizza l'interfaccia sottostante per individuare un bene da prendere in prestito", "stake": "Utilizza questo modulo per puntare i tuoi asset in pool di liquidità", "transfer": "Utilizza il modulo sottostante per trasferire risorse ad altri utenti blockchain", - "nodes": "Connettiti alla blockchain tramite un nodo a tua scelta" + "nodes": "Connettiti alla blockchain tramite un nodo a tua scelta", + "offers": "Monitora e gestisci le tue offerte di credito con il modulo sottostante.", + "vesting": "Monitora e ritira i tuoi saldi di maturazione con il modulo sottostante." }, "back": "Torna indietro", "usage": "Progettato per l'uso con ", diff --git a/src/data/locales/it/Vesting.json b/src/data/locales/it/Vesting.json new file mode 100644 index 0000000..d69defc --- /dev/null +++ b/src/data/locales/it/Vesting.json @@ -0,0 +1,18 @@ +{ + "dialogContent": { + "header": "Ritiro {{readable}}" + }, + "vesting_seconds": "Secondi di maturazione", + "start_claim": "Avvia reclamo", + "coin_seconds_earned": "Secondi di monete guadagnati", + "coin_seconds_earned_last_update": "Secondi di monete guadagnati nell'ultimo aggiornamento", + "claim_a": "Prelevare il rimborso", + "claim_b": "Ritirare la quota delle commissioni di mercato", + "card": { + "title": "Saldi di maturazione", + "description": "Monitora e ritira i tuoi saldi di maturazione.", + "empty": "Nessun saldo di maturazione trovato." + }, + "cashback": "Rimborso", + "market_fees": "Commissioni di mercato" +} \ No newline at end of file diff --git a/src/data/locales/ja/CreditOffers.json b/src/data/locales/ja/CreditOffers.json new file mode 100644 index 0000000..b37be30 --- /dev/null +++ b/src/data/locales/ja/CreditOffers.json @@ -0,0 +1,7 @@ +{ + "card": { + "title": "📜 クレジット特典を確認してください", + "description": "ここから、アクティブなクレジットオファーを監視し、その設定を管理できます。", + "noResults": "アクティブなクレジット取引が見つかりません。" + } + } \ No newline at end of file diff --git a/src/data/locales/ja/Home.json b/src/data/locales/ja/Home.json index b370267..f2cd491 100644 --- a/src/data/locales/ja/Home.json +++ b/src/data/locales/ja/Home.json @@ -88,5 +88,17 @@ "subtitle": "クレジット取引を確認する", "hover1": "アクティブなクレジット取引を監視します。", "hover2": "クレジット取引の状態を管理します。" + }, + "offers": { + "title": "📜 クレジット特典", + "subtitle": "クレジット特典を確認する", + "hover1": "アクティブなクレジットオファーを監視します。", + "hover2": "クレジットオファーの状態を管理します。" + }, + "vesting": { + "title": "⌚ 権利確定残高", + "subtitle": "権利確定残高を表示する", + "hover1": "権利確定残高を確認してください。", + "hover2": "確定残高を請求してください。" } } diff --git a/src/data/locales/ja/PageHeader.json b/src/data/locales/ja/PageHeader.json index 0b7a98f..ffdf7dc 100644 --- a/src/data/locales/ja/PageHeader.json +++ b/src/data/locales/ja/PageHeader.json @@ -45,7 +45,9 @@ "smartcoins": "以下のインターフェースを使用して、借用する資産を見つけます。", "stake": "このフォームを使用して流動性プールに資産を賭けます", "transfer": "他のブロックチェーン ユーザーに資産を転送するには、以下のフォームを使用してください", - "nodes": "選択したノードを介してブロックチェーンに接続します" + "nodes": "選択したノードを介してブロックチェーンに接続します", + "offers": "以下のフォームを使用してクレジットオファーを監視および管理します。", + "vesting": "以下のフォームを使用して、権利確定残高を監視し、出金してください。" }, "back": "戻る", "usage": "で使用するように設計されています ", diff --git a/src/data/locales/ja/Vesting.json b/src/data/locales/ja/Vesting.json new file mode 100644 index 0000000..3fc5030 --- /dev/null +++ b/src/data/locales/ja/Vesting.json @@ -0,0 +1,18 @@ +{ + "dialogContent": { + "header": "撤退する {{readable}}" + }, + "vesting_seconds": "権利確定秒数", + "start_claim": "請求を開始する", + "coin_seconds_earned": "獲得コイン秒数", + "coin_seconds_earned_last_update": "前回の更新で獲得したコイン秒数", + "claim_a": "キャッシュバックの出金", + "claim_b": "市場手数料の取り消し", + "card": { + "title": "権利確定残高", + "description": "権利確定残高を監視して引き出します。", + "empty": "権利確定残高が見つかりません。" + }, + "cashback": "キャッシュバック", + "market_fees": "市場手数料" +} \ No newline at end of file diff --git a/src/data/locales/ko/CreditOffers.json b/src/data/locales/ko/CreditOffers.json new file mode 100644 index 0000000..0379455 --- /dev/null +++ b/src/data/locales/ko/CreditOffers.json @@ -0,0 +1,7 @@ +{ + "card": { + "title": "📜 신용 제안을 확인하세요", + "description": "여기에서 귀하의 활성 크레딧 제안을 모니터링하고 해당 설정을 관리할 수 있습니다.", + "noResults": "활성 신용 거래가 없습니다." + } +} \ No newline at end of file diff --git a/src/data/locales/ko/Home.json b/src/data/locales/ko/Home.json index 8e44803..fbb660f 100644 --- a/src/data/locales/ko/Home.json +++ b/src/data/locales/ko/Home.json @@ -88,5 +88,17 @@ "subtitle": "신용 거래를 확인하세요", "hover1": "귀하의 활성 신용 거래를 모니터링하십시오.", "hover2": "신용 거래 상태를 관리하세요." + }, + "offers": { + "title": "📜 クレジット特典", + "subtitle": "クレジット特典を確認する", + "hover1": "アクティブなクレジットオファーを監視します。", + "hover2": "クレジットオファーの状態を管理します。" + }, + "vesting": { + "title": "⌚ 権利確定残高", + "subtitle": "権利確定残高を表示する", + "hover1": "権利確定残高を確認してください。", + "hover2": "確定残高を請求してください。" } } diff --git a/src/data/locales/ko/PageHeader.json b/src/data/locales/ko/PageHeader.json index 7054b65..7cc07df 100644 --- a/src/data/locales/ko/PageHeader.json +++ b/src/data/locales/ko/PageHeader.json @@ -45,7 +45,9 @@ "smartcoins": "아래 인터페이스를 사용하여 차입할 자산을 찾으세요.", "stake": "유동성 풀에 자산을 스테이킹하려면 이 양식을 사용하세요.", "transfer": "다른 블록체인 사용자에게 자산을 전송하려면 아래 양식을 사용하세요.", - "nodes": "선택한 노드를 통해 블록체인에 연결" + "nodes": "선택한 노드를 통해 블록체인에 연결", + "offers": "아래 양식을 사용하여 신용 제안을 모니터링하고 관리하세요.", + "vesting": "아래 양식을 사용하여 베스팅 잔액을 모니터링하고 인출하세요." }, "back": "돌아가기", "usage": "다음과 함께 사용하도록 설계됨 ", diff --git a/src/data/locales/ko/Vesting.json b/src/data/locales/ko/Vesting.json new file mode 100644 index 0000000..df8a8d7 --- /dev/null +++ b/src/data/locales/ko/Vesting.json @@ -0,0 +1,18 @@ +{ + "dialogContent": { + "header": "철수 {{readable}}" + }, + "vesting_seconds": "베스팅 초", + "start_claim": "청구 시작", + "coin_seconds_earned": "코인 초 획득", + "coin_seconds_earned_last_update": "코인 초 획득 마지막 업데이트", + "claim_a": "캐시백 인출", + "claim_b": "시장 수수료 지분 인출", + "card": { + "title": "베스팅 잔액", + "description": "베스팅 잔액을 모니터링하고 인출하세요.", + "empty": "베스팅 잔액이 없습니다." + }, + "cashback": "캐시백", + "market_fees": "시장 수수료" +} \ No newline at end of file diff --git a/src/data/locales/pt/CreditOffers.json b/src/data/locales/pt/CreditOffers.json new file mode 100644 index 0000000..cf97997 --- /dev/null +++ b/src/data/locales/pt/CreditOffers.json @@ -0,0 +1,7 @@ +{ + "card": { + "title": "📜 Verifique suas ofertas de crédito", + "description": "A partir daqui você pode monitorar suas ofertas de crédito ativas e gerenciar suas configurações.", + "noResults": "Nenhuma oferta de crédito ativa encontrada." + } + } \ No newline at end of file diff --git a/src/data/locales/pt/Home.json b/src/data/locales/pt/Home.json index 2893365..8a0aec2 100644 --- a/src/data/locales/pt/Home.json +++ b/src/data/locales/pt/Home.json @@ -88,5 +88,17 @@ "subtitle": "Verifique suas ofertas de crédito", "hover1": "Monitore suas ofertas de crédito ativas.", "hover2": "Gerencie o estado de suas negociações de crédito." + }, + "offers": { + "title": "📜 Ofertas de crédito", + "subtitle": "Verifique suas ofertas de crédito", + "hover1": "Monitore suas ofertas de crédito ativas.", + "hover2": "Gerencie o estado de suas ofertas de crédito." + }, + "vesting": { + "title": "⌚ Saldos adquiridos", + "subtitle": "Ver saldos de aquisição", + "hover1": "Verifique seus saldos de aquisição.", + "hover2": "Reivindique seus saldos adquiridos." } } diff --git a/src/data/locales/pt/PageHeader.json b/src/data/locales/pt/PageHeader.json index 88def21..ee28523 100644 --- a/src/data/locales/pt/PageHeader.json +++ b/src/data/locales/pt/PageHeader.json @@ -45,7 +45,9 @@ "smartcoins": "Use a interface abaixo para localizar um ativo para empréstimo", "stake": "Use este formulário para apostar seus ativos em pools de liquidez", "transfer": "Use o formulário abaixo para transferir ativos para outros usuários do blockchain", - "nodes": "Conecte-se ao blockchain através de um nó de sua escolha" + "nodes": "Conecte-se ao blockchain através de um nó de sua escolha", + "offers": "Monitore e gerencie suas ofertas de crédito com o formulário abaixo.", + "vesting": "Monitore e retire seus saldos de aquisição com o formulário abaixo." }, "back": "Volte", "usage": "Projetado para uso com ", diff --git a/src/data/locales/pt/Vesting.json b/src/data/locales/pt/Vesting.json new file mode 100644 index 0000000..6735af4 --- /dev/null +++ b/src/data/locales/pt/Vesting.json @@ -0,0 +1,18 @@ +{ + "dialogContent": { + "header": "Retirada {{readable}}" + }, + "vesting_seconds": "Segundos adquiridos", + "start_claim": "Iniciar reivindicação", + "coin_seconds_earned": "Segundos de moeda ganhos", + "coin_seconds_earned_last_update": "Segundos de moeda ganhos na última atualização", + "claim_a": "Retirar reembolso", + "claim_b": "Retirar parte das taxas de mercado", + "card": { + "title": "Saldos adquiridos", + "description": "Monitore e retire seus saldos de aquisição.", + "empty": "Nenhum saldo de aquisição encontrado." + }, + "cashback": "Reembolso", + "market_fees": "Taxas de mercado" +} \ No newline at end of file diff --git a/src/data/locales/th/CreditOffers.json b/src/data/locales/th/CreditOffers.json new file mode 100644 index 0000000..d5adbf5 --- /dev/null +++ b/src/data/locales/th/CreditOffers.json @@ -0,0 +1,7 @@ +{ + "card": { + "title": "📜 ตรวจสอบข้อเสนอเครดิตของคุณ", + "description": "จากที่นี่ คุณสามารถตรวจสอบข้อเสนอเครดิตที่ใช้งานอยู่และจัดการการตั้งค่าได้", + "noResults": "ไม่พบข้อตกลงด้านเครดิตที่ใช้งานอยู่" + } + } \ No newline at end of file diff --git a/src/data/locales/th/Home.json b/src/data/locales/th/Home.json index 6286bea..e017aab 100644 --- a/src/data/locales/th/Home.json +++ b/src/data/locales/th/Home.json @@ -88,5 +88,17 @@ "subtitle": "ตรวจสอบข้อเสนอเครดิตของคุณ", "hover1": "ติดตามข้อเสนอสินเชื่อที่ใช้งานอยู่ของคุณ", "hover2": "จัดการสถานะของข้อเสนอสินเชื่อของคุณ" + }, + "offers": { + "title": "📜 ข้อเสนอสินเชื่อ", + "subtitle": "ตรวจสอบข้อเสนอเครดิตของคุณ", + "hover1": "ตรวจสอบข้อเสนอเครดิตที่ใช้งานอยู่ของคุณ", + "hover2": "จัดการสถานะของข้อเสนอเครดิตของคุณ" + }, + "vesting": { + "title": "⌚ การมอบยอดคงเหลือ", + "subtitle": "ดูยอดคงเหลือการได้รับสิทธิ", + "hover1": "ตรวจสอบยอดคงเหลือการได้รับสิทธิ์ของคุณ", + "hover2": "เรียกร้องยอดคงเหลือของคุณ" } } diff --git a/src/data/locales/th/PageHeader.json b/src/data/locales/th/PageHeader.json index 1bfbf7b..5ca0ada 100644 --- a/src/data/locales/th/PageHeader.json +++ b/src/data/locales/th/PageHeader.json @@ -45,7 +45,9 @@ "smartcoins": "ใช้อินเทอร์เฟซด้านล่างเพื่อค้นหาสินทรัพย์ที่จะยืมที่มีอยู่", "stake": "ใช้แบบฟอร์มนี้เพื่อเดิมพันสินทรัพย์ของคุณในกลุ่มสภาพคล่อง", "transfer": "ใช้แบบฟอร์มด้านล่างเพื่อโอนสินทรัพย์ไปยังผู้ใช้บล็อคเชนรายอื่น", - "nodes": "เชื่อมต่อกับบล็อคเชนผ่านโหนดที่คุณเลือก" + "nodes": "เชื่อมต่อกับบล็อคเชนผ่านโหนดที่คุณเลือก", + "offers": "ติดตามและจัดการข้อเสนอสินเชื่อของคุณด้วยแบบฟอร์มด้านล่าง", + "vesting": "ตรวจสอบและถอนยอดคงเหลือการได้รับสิทธิ์ของคุณด้วยแบบฟอร์มด้านล่าง" }, "back": "กลับไป", "usage": "ออกแบบมาเพื่อใช้กับ ", diff --git a/src/data/locales/th/Vesting.json b/src/data/locales/th/Vesting.json new file mode 100644 index 0000000..dd87b60 --- /dev/null +++ b/src/data/locales/th/Vesting.json @@ -0,0 +1,18 @@ +{ + "dialogContent": { + "header": "การถอนตัว {{readable}}" + }, + "vesting_seconds": "การให้สิทธิ์วินาที", + "start_claim": "เริ่มการเรียกร้อง", + "coin_seconds_earned": "ได้รับเหรียญวินาที", + "coin_seconds_earned_last_update": "เหรียญวินาทีที่ได้รับการอัปเดตครั้งล่าสุด", + "claim_a": "ถอนเงินคืน", + "claim_b": "ถอนส่วนแบ่งค่าธรรมเนียมการตลาด", + "card": { + "title": "การมอบยอดคงเหลือ", + "description": "ตรวจสอบและถอนยอดคงเหลือการได้รับสิทธิของคุณ", + "empty": "ไม่พบยอดคงเหลือการให้สิทธิ" + }, + "cashback": "คืนเงิน", + "market_fees": "ค่าธรรมเนียมการตลาด" +} \ No newline at end of file diff --git a/src/lib/i18n.js b/src/lib/i18n.js index ef21208..5f5d1c8 100644 --- a/src/lib/i18n.js +++ b/src/lib/i18n.js @@ -9,6 +9,7 @@ const pages = [ "AssetDropDownCard", "CreditOfferEditor", "CreditBorrow", + "CreditOffers", "CreditDeals", "CreditOffer", "CurrentUser", @@ -40,7 +41,8 @@ const pages = [ "Smartcoins", "Transfer", "Nodes", - "SimpleSwap" + "SimpleSwap", + "Vesting" ]; const locale = persistentAtom("locale", "en"); diff --git a/src/nanoeffects/VestingBalances.ts b/src/nanoeffects/VestingBalances.ts index ac831e1..3d5bac1 100644 --- a/src/nanoeffects/VestingBalances.ts +++ b/src/nanoeffects/VestingBalances.ts @@ -26,34 +26,15 @@ function getVestingBalances (chain: string, accountID: string, specificNode?: st console.log({ error }); } + currentAPI.close(); + if (!vestingBalanceObjects) { console.log(`Failed to fetch vesting balances`); - currentAPI.close(); reject(); return; } - - console.log({vestingBalanceObjects}); - - let vestingBalances; - try { - vestingBalances = await currentAPI.db_api().exec( - "get_vested_balances", [vestingBalanceObjects.map((x: any) => x.id)] - ); - } catch (error) { - console.log({ error }); - } - - console.log({vestingBalances}); - - currentAPI.close(); - - if (!vestingBalances) { - reject(new Error("No vesting balances found")); - return; - } - - resolve({vestingBalances, vestingBalanceObjects}); + + resolve(vestingBalanceObjects); }); } @@ -61,7 +42,7 @@ const [createVestingBalanceStore] = nanoquery({ fetcher: async (...args: unknown[]) => { const chain = args[0] as string; const account_id = args[1] as string; - let specificNode = args[2] ? args[2] as string : null; + const specificNode = args[2] ? args[2] as string : null; let response; try { diff --git a/src/pages/offers.astro b/src/pages/offers.astro new file mode 100644 index 0000000..558a6bd --- /dev/null +++ b/src/pages/offers.astro @@ -0,0 +1,27 @@ +--- +import Layout from '../layouts/Layout.astro'; +import CreditOffers from '../components/CreditOffers.jsx'; +import PageHeader from '../components/PageHeader'; +import PageFooter from '../components/PageFooter'; +--- + + +
+ + + +
+
+ + \ No newline at end of file diff --git a/src/pages/vesting.astro b/src/pages/vesting.astro new file mode 100644 index 0000000..9f71c0b --- /dev/null +++ b/src/pages/vesting.astro @@ -0,0 +1,27 @@ +--- +import Layout from '../layouts/Layout.astro'; +import VestingOverview from '../components/Vesting.jsx'; +import PageHeader from '../components/PageHeader'; +import PageFooter from '../components/PageFooter'; +--- + + +
+ + + +
+
+ + \ No newline at end of file