From 441a514accb2a8766ef12e4224534b7dd2171fde Mon Sep 17 00:00:00 2001 From: tim Date: Wed, 23 Apr 2025 12:55:49 -0400 Subject: [PATCH] short share urls --- .env-arb1 | 2 +- .env-mock | 4 ++-- public/snapshot.js | 28 ----------------------- src/common.js | 20 ++++++++++++++++ src/components/chart/ChartPlaceOrder.vue | 9 +++++++- src/components/chart/Shared.vue | 11 ++++++--- src/router/index.js | 2 +- src/share.js | 29 +++++++++++------------- 8 files changed, 53 insertions(+), 52 deletions(-) delete mode 100644 public/snapshot.js diff --git a/.env-arb1 b/.env-arb1 index 3692391..e896cf8 100644 --- a/.env-arb1 +++ b/.env-arb1 @@ -1,2 +1,2 @@ VITE_WS_URL=wss://ws.dexorder.trade -VITE_SERVER_URL=https://share.dexorder.trade +VITE_SHARE_URL=https://dexorder.trade diff --git a/.env-mock b/.env-mock index f402083..a01e403 100644 --- a/.env-mock +++ b/.env-mock @@ -1,3 +1,3 @@ VITE_WS_URL=ws://localhost:3001 -VITE_SNAPSHOT_URL=http://localhost:3001/snapshot -REQUIRE_AUTH=NOAUTH +VITE_SHARE_URL=http://localhost:3001 +VITE_REQUIRE_APPROVAL=NO diff --git a/public/snapshot.js b/public/snapshot.js deleted file mode 100644 index cbd28d6..0000000 --- a/public/snapshot.js +++ /dev/null @@ -1,28 +0,0 @@ -console.log('snapshot.js') - -async function getSnapCode() { - const formData = new FormData; - formData.append('language', 'en'); - formData.append('timezone', 'Etc/UTC'); - formData.append('symbol', 'BTC/USD'); - formData.append('preparedImage', window.snapshotImage, 'blob'); - - try { - const response = await fetch('https://tradingview.com/snapshot/', { - method: 'POST', - body: formData, - credentials: "same-origin", - }); - - if (!response.ok) { - console.error('Failed to upload snapshot:', response.status, response); - return null; - } - return await response.text(); - } catch (error) { - console.error('Error uploading snapshot:', error); - return null - } -} - -getSnapCode().then((code)=>console.log('snapshot code', code)).catch((e)=>console.error('snapshot error', e)) diff --git a/src/common.js b/src/common.js index 50febbf..8522ca5 100644 --- a/src/common.js +++ b/src/common.js @@ -158,3 +158,23 @@ export function dateString(datetime) { export function logicalXOR(a, b) { return (a || b) && !(a && b) } + +// Base62 + +// base62.js +const base62charset = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + +export function encodeBase62(num) { + if (num === 0) return base62charset[0]; + let encoded = ""; + while (num > 0) { + encoded = base62charset[num % 62] + encoded; + num = Math.floor(num / 62); + } + return encoded; +} + +export function decodeBase62(str) { + return str.split('').reverse().reduce((acc, char, i) => + acc + base62charset.indexOf(char) * Math.pow(62, i), 0); +} diff --git a/src/components/chart/ChartPlaceOrder.vue b/src/components/chart/ChartPlaceOrder.vue index 9dbcd64..796fd86 100644 --- a/src/components/chart/ChartPlaceOrder.vue +++ b/src/components/chart/ChartPlaceOrder.vue @@ -11,7 +11,7 @@ {{sharing?'Preparing...':'Share'}} - @@ -205,6 +205,7 @@ async function doPlaceOrder() { const sharing = ref(false) const showSharedTooltip = ref(false) +const shareError = ref(false) const showShareDialog = ref(false) const shareUrl = ref(null) @@ -212,6 +213,12 @@ function shareOrder() { sharing.value = true track('share') getShareUrl().then(url => { + shareError.value = url === null + if (url === null) { + sharing.value = false + return + } + console.log('share url', url) shareUrl.value = url sharing.value = false navigator.permissions.query({name: "clipboard-write"}).then((permission) => { diff --git a/src/components/chart/Shared.vue b/src/components/chart/Shared.vue index ee2f117..a0ec1a6 100644 --- a/src/components/chart/Shared.vue +++ b/src/components/chart/Shared.vue @@ -1,14 +1,19 @@ \ No newline at end of file + diff --git a/src/router/index.js b/src/router/index.js index 48424ef..d3ace51 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -16,7 +16,7 @@ const routes = [ }, { name: 'Shared', - path: '/shared', + path: '/shared/:code', component: ()=> import('@/components/chart/Shared.vue') }, { diff --git a/src/share.js b/src/share.js index aa29b11..ba09404 100644 --- a/src/share.js +++ b/src/share.js @@ -4,6 +4,7 @@ import {changeIntervalSecs, onChartReady, setSymbol, widget} from "@/charts/char import {usePrefStore, useStore} from "@/store/store.js"; import {lookupSymbol} from "@/charts/datafeed.js"; import {track} from "@/track.js"; +import {socket} from "@/socket.js"; export async function getShareUrl() { const co = useChartOrderStore(); @@ -26,18 +27,18 @@ export async function getShareUrl() { } const json = JSON.stringify(data) console.log('sharing data', json, data) - const compressed = compressToEncodedURIComponent(json); - const imageFile = await takeSnapshot() - return import.meta.env.VITE_SERVER_URL+ `/share?i=${imageFile}&d=${compressed}`; + const snapshot = await takeSnapshot() + + const code = await new Promise((resolve)=>socket.emit('share', data, snapshot, resolve)) + if (code===null) return null + + return import.meta.env.VITE_SHARE_URL+ '/share/'+code; } -export function loadShareUrl() { - const urlParams = new URLSearchParams(window.location.search); - const dataStr = urlParams.get('d'); - if (!dataStr) return - const json = decompressFromEncodedURIComponent(dataStr); - const data = JSON.parse(json); +export async function loadShareUrl(code) { + const data = await new Promise((resolve)=>socket.emit('shared', code, resolve)) console.log('loaded shared orders data', data) + if (data===null) return const co = useChartOrderStore(); const s = useStore() const ticker = `${data.chainId}|${data.symbol.route.exchange}|${data.symbol.base.a}|${data.symbol.quote.a}|${data.symbol.route.fee}`; @@ -50,7 +51,9 @@ export function loadShareUrl() { const prefs = usePrefStore() prefs.selectedSymbol = ticker for (const order of data.orders) { + // force amount to be zero so that the user MUST enter a size before confirming the placement order.amount = 0 + order.amountIsTokenA = true order.valid = false } co.orders = data.orders @@ -65,11 +68,5 @@ export function loadShareUrl() { export async function takeSnapshot() { const screenshotCanvas = await widget.takeClientScreenshot(); - const image = await new Promise((resolve) => screenshotCanvas.toBlob(resolve)); - const response = await fetch(import.meta.env.VITE_SERVER_URL + '/snapshot', { - method: 'PUT', - body: image, - credentials: 'same-origin', - }); - return response.text() + return await new Promise((resolve) => screenshotCanvas.toBlob(resolve)); }