symbol search in tv
This commit is contained in:
@@ -14,6 +14,7 @@
|
|||||||
"color": "^4.2.3",
|
"color": "^4.2.3",
|
||||||
"core-js": "^3.29.0",
|
"core-js": "^3.29.0",
|
||||||
"ethers": "^6.7.1",
|
"ethers": "^6.7.1",
|
||||||
|
"flexsearch": "^0.7.43",
|
||||||
"pinia": "2.1.6",
|
"pinia": "2.1.6",
|
||||||
"roboto-fontface": "*",
|
"roboto-fontface": "*",
|
||||||
"socket.io-client": "^4.7.2",
|
"socket.io-client": "^4.7.2",
|
||||||
|
|||||||
5042
public/metadata.json
Normal file
5042
public/metadata.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,6 @@
|
|||||||
import {useChartOrderStore} from "@/orderbuild.js";
|
import {useChartOrderStore} from "@/orderbuild.js";
|
||||||
import {invokeCallbacks, prototype} from "@/common.js";
|
import {invokeCallbacks, prototype} from "@/common.js";
|
||||||
|
import datafeed from "@/charts/datafeed.js";
|
||||||
|
|
||||||
export let widget = null
|
export let widget = null
|
||||||
export let chart = null
|
export let chart = null
|
||||||
@@ -21,12 +22,12 @@ export function initWidget(el) {
|
|||||||
library_path: "/charting_library/",
|
library_path: "/charting_library/",
|
||||||
// debug: true,
|
// debug: true,
|
||||||
autosize: true,
|
autosize: true,
|
||||||
symbol: 'AAPL',
|
// symbol: 'AAPL',
|
||||||
// symbol: 'Uniswap:WETH/USD', // use this for ohlc
|
symbol: 'UNIv3:WETH/USDC', // use this for ohlc
|
||||||
interval: '1D',
|
interval: '1D',
|
||||||
container: el,
|
container: el,
|
||||||
datafeed: new Datafeeds.UDFCompatibleDatafeed("https://demo-feed-data.tradingview.com"),
|
// datafeed: new Datafeeds.UDFCompatibleDatafeed("https://demo-feed-data.tradingview.com"),
|
||||||
// datafeed: datafeed, // use this for ohlc
|
datafeed: datafeed, // use this for ohlc
|
||||||
locale: "en",
|
locale: "en",
|
||||||
disabled_features: [],
|
disabled_features: [],
|
||||||
enabled_features: ['saveload_separate_drawings_storage'],
|
enabled_features: ['saveload_separate_drawings_storage'],
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
import {jBars} from './jBars.js';
|
import {jBars} from './jBars.js';
|
||||||
|
import {metadata} from "@/version.js";
|
||||||
|
import FlexSearch from "flexsearch";
|
||||||
|
|
||||||
const lastBarsCache = new Map();
|
const lastBarsCache = new Map();
|
||||||
|
|
||||||
@@ -9,29 +11,81 @@ const configurationData = {
|
|||||||
['1', '3', '5', '10', '15', '30', '60', '120', '240', '480', '720', '1D', '2D', '3D', '1W'],
|
['1', '3', '5', '10', '15', '30', '60', '120', '240', '480', '720', '1D', '2D', '3D', '1W'],
|
||||||
|
|
||||||
// The `exchanges` arguments are used for the `searchSymbols` method if a user selects the exchange
|
// The `exchanges` arguments are used for the `searchSymbols` method if a user selects the exchange
|
||||||
exchanges: [{
|
exchanges: [
|
||||||
value: 'Uniswap',
|
// {
|
||||||
name: 'Uniswap',
|
// value: 'UNIv2',
|
||||||
desc: 'Uniswap',
|
// name: 'Uniswap v2',
|
||||||
},
|
// desc: 'Uniswap v2',
|
||||||
|
// },
|
||||||
|
{
|
||||||
|
value: 'UNIv3',
|
||||||
|
name: 'Uniswap v3',
|
||||||
|
desc: 'Uniswap v3',
|
||||||
|
logo: 'https://upload.wikimedia.org/wikipedia/commons/e/e7/Uniswap_Logo.svg',
|
||||||
|
},
|
||||||
],
|
],
|
||||||
// The `symbols_types` arguments are used for the `searchSymbols` method if a user selects this symbol type
|
// The `symbols_types` arguments are used for the `searchSymbols` method if a user selects this symbol type
|
||||||
symbols_types: [{
|
symbols_types: [
|
||||||
name: 'crypto',
|
{name: 'swap', value: 'swap',},
|
||||||
value: 'crypto',
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
// Obtains all symbols for all exchanges supported by CryptoCompare API
|
|
||||||
|
const tokenMap = {}
|
||||||
|
const poolMap = {}
|
||||||
|
let symbols = null
|
||||||
|
const indexer = new FlexSearch.Document({
|
||||||
|
document: {id: 'id', index: ['id', 'a', 'b', 'q', 'bs', 'qs', 'e', 'd']},
|
||||||
|
charset: {split: /\W+/},
|
||||||
|
tokenize: 'forward',
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
async function getAllSymbols() {
|
async function getAllSymbols() {
|
||||||
return [{
|
const built = {} // keyed by (base,quote) so we only list one pool per pair even if there are many fee tiers
|
||||||
symbol: 'WETH/USD',
|
if (symbols===null) {
|
||||||
full_name: 'Uniswap:WETH/USD',
|
symbols = {}
|
||||||
description: 'WETH/USD 42161/0xC31E54c7a869B9Fc',
|
for (const t of metadata['t'])
|
||||||
exchange: 'Uniswap',
|
tokenMap[t['a']] = t
|
||||||
type: 'crypto'}
|
metadata['p'].forEach((p)=>{
|
||||||
];
|
poolMap[p['a']] = p
|
||||||
|
// todo inversion
|
||||||
|
const base = tokenMap[p['b']];
|
||||||
|
const quote = tokenMap[p['q']];
|
||||||
|
if (!base) {
|
||||||
|
console.log(`No token ${p['b']} found`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!quote) {
|
||||||
|
console.log(`No token ${p['q']} found`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const symbol = base['s'] + '/' + quote['s']
|
||||||
|
const exchange = ['UNIv2','UNIv3'][p['e']]
|
||||||
|
const full_name = exchange+':'+symbol
|
||||||
|
if (full_name in built)
|
||||||
|
return
|
||||||
|
built[full_name] = true
|
||||||
|
const longExchange = ['Uniswap v2', 'Uniswap v3',][p['e']]
|
||||||
|
const description = `${base['n']} / ${quote['n']}`
|
||||||
|
const type = 'swap'
|
||||||
|
symbols[full_name] = {symbol, full_name, description, exchange, type,}
|
||||||
|
indexer.add({
|
||||||
|
// key
|
||||||
|
id: full_name,
|
||||||
|
// addresses
|
||||||
|
a: p['a'],
|
||||||
|
b: p['b'],
|
||||||
|
q: p['q'],
|
||||||
|
// symbols
|
||||||
|
bs: base['s'],
|
||||||
|
qs: quote['s'],
|
||||||
|
e: exchange,
|
||||||
|
d: description,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return Object.values(symbols)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@@ -40,6 +94,24 @@ export default {
|
|||||||
setTimeout(() => callback(configurationData));
|
setTimeout(() => callback(configurationData));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// searchSymbols: async (
|
||||||
|
// userInput,
|
||||||
|
// exchange,
|
||||||
|
// symbolType,
|
||||||
|
// onResultReadyCallback,
|
||||||
|
// ) => {
|
||||||
|
// console.log('[searchSymbols]: Method call');
|
||||||
|
// const symbols = await getAllSymbols();
|
||||||
|
// const newSymbols = symbols.filter(symbol => {
|
||||||
|
// const isExchangeValid = exchange === '' || symbol.exchange === exchange;
|
||||||
|
// const isFullSymbolContainsInput = symbol.full_name
|
||||||
|
// .toLowerCase()
|
||||||
|
// .indexOf(userInput.toLowerCase()) !== -1;
|
||||||
|
// return isExchangeValid && isFullSymbolContainsInput;
|
||||||
|
// });
|
||||||
|
// onResultReadyCallback(newSymbols);
|
||||||
|
// },
|
||||||
|
|
||||||
searchSymbols: async (
|
searchSymbols: async (
|
||||||
userInput,
|
userInput,
|
||||||
exchange,
|
exchange,
|
||||||
@@ -47,15 +119,14 @@ export default {
|
|||||||
onResultReadyCallback,
|
onResultReadyCallback,
|
||||||
) => {
|
) => {
|
||||||
console.log('[searchSymbols]: Method call');
|
console.log('[searchSymbols]: Method call');
|
||||||
const symbols = await getAllSymbols();
|
// todo limit results by exchange. use a separate indexer per exchange?
|
||||||
const newSymbols = symbols.filter(symbol => {
|
const found = indexer.search(userInput, 10)
|
||||||
const isExchangeValid = exchange === '' || symbol.exchange === exchange;
|
console.log('found', found)
|
||||||
const isFullSymbolContainsInput = symbol.full_name
|
const result = []
|
||||||
.toLowerCase()
|
for (const f of found)
|
||||||
.indexOf(userInput.toLowerCase()) !== -1;
|
for (const key of f.result)
|
||||||
return isExchangeValid && isFullSymbolContainsInput;
|
result.push(symbols[key])
|
||||||
});
|
onResultReadyCallback(result);
|
||||||
onResultReadyCallback(newSymbols);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
resolveSymbol: async (
|
resolveSymbol: async (
|
||||||
@@ -66,9 +137,7 @@ export default {
|
|||||||
) => {
|
) => {
|
||||||
console.log('[resolveSymbol]: Method call', symbolName);
|
console.log('[resolveSymbol]: Method call', symbolName);
|
||||||
const symbols = await getAllSymbols();
|
const symbols = await getAllSymbols();
|
||||||
const symbolItem = symbols.find(({
|
const symbolItem = symbols[symbolName]
|
||||||
full_name,
|
|
||||||
}) => full_name === symbolName);
|
|
||||||
if (!symbolItem) {
|
if (!symbolItem) {
|
||||||
console.log('[resolveSymbol]: Cannot resolve symbol', symbolName);
|
console.log('[resolveSymbol]: Cannot resolve symbol', symbolName);
|
||||||
onResolveErrorCallback('cannot resolve symbol');
|
onResolveErrorCallback('cannot resolve symbol');
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import { registerPlugins } from '@/plugins'
|
|||||||
import '@/styles/style.scss'
|
import '@/styles/style.scss'
|
||||||
import {detectChain} from "@/blockchain/wallet.js";
|
import {detectChain} from "@/blockchain/wallet.js";
|
||||||
import "./socket.js"
|
import "./socket.js"
|
||||||
|
import "./version.js"
|
||||||
|
|
||||||
BigInt.prototype.toJSON = function() { return this.toString() }
|
BigInt.prototype.toJSON = function() { return this.toString() }
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
import {defineStore} from 'pinia'
|
import {defineStore} from 'pinia'
|
||||||
import {knownTokens} from "@/knownTokens.js";
|
import {knownTokens} from "@/knownTokens.js";
|
||||||
import {computed, ref} from "vue";
|
import {computed, ref} from "vue";
|
||||||
|
import {version} from "@/version.js";
|
||||||
|
|
||||||
// USING THE STORE:
|
// USING THE STORE:
|
||||||
//
|
//
|
||||||
@@ -30,10 +31,6 @@ function timestamp() {
|
|||||||
return Math.round(new Date().getTime() / 1000)
|
return Math.round(new Date().getTime() / 1000)
|
||||||
}
|
}
|
||||||
|
|
||||||
const response = await fetch('/version.json')
|
|
||||||
const version = await response.json()
|
|
||||||
console.log('version', version)
|
|
||||||
|
|
||||||
export const useStore = defineStore('app', ()=> {
|
export const useStore = defineStore('app', ()=> {
|
||||||
const clock = ref(timestamp())
|
const clock = ref(timestamp())
|
||||||
const nav = ref(false) // controls opening navigation drawer
|
const nav = ref(false) // controls opening navigation drawer
|
||||||
|
|||||||
6
src/version.js
Normal file
6
src/version.js
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
const versionPromise = fetch('/version.json').then(async (response)=>await response.json())
|
||||||
|
const metadataPromise = fetch('/metadata.json').then(async (response)=>await response.json())
|
||||||
|
|
||||||
|
export const version = await versionPromise
|
||||||
|
export const metadata = await metadataPromise
|
||||||
|
console.log('version', version)
|
||||||
@@ -772,6 +772,11 @@ flatted@^3.2.9:
|
|||||||
resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.9.tgz#7eb4c67ca1ba34232ca9d2d93e9886e611ad7daf"
|
resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.9.tgz#7eb4c67ca1ba34232ca9d2d93e9886e611ad7daf"
|
||||||
integrity sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==
|
integrity sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==
|
||||||
|
|
||||||
|
flexsearch@^0.7.43:
|
||||||
|
version "0.7.43"
|
||||||
|
resolved "https://registry.yarnpkg.com/flexsearch/-/flexsearch-0.7.43.tgz#34f89b36278a466ce379c5bf6fb341965ed3f16c"
|
||||||
|
integrity sha512-c5o/+Um8aqCSOXGcZoqZOm+NqtVwNsvVpWv6lfmSclU954O3wvQKxxK8zj74fPaSJbXpSLTs4PRhh+wnoCXnKg==
|
||||||
|
|
||||||
fs.realpath@^1.0.0:
|
fs.realpath@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
|
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
|
||||||
|
|||||||
Reference in New Issue
Block a user