Compare commits
29 Commits
556554fbf3
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| ed03740852 | |||
| a3c1dfad2d | |||
| 9b410ace09 | |||
| 72b061749d | |||
| a42f228984 | |||
| 47b33a152d | |||
| ecffd976ac | |||
| f0f431b34e | |||
| b2457f0617 | |||
| 148b37dca3 | |||
| 1b83dad6b3 | |||
| a1bbb17b5d | |||
| 916c23e092 | |||
| 2c5116c5de | |||
| 441a514acc | |||
| 6f7388bb10 | |||
| fd7b9713ea | |||
| 7b5421e6e7 | |||
| 21f324aa12 | |||
| eeee9d9853 | |||
| 38fb66c694 | |||
| 14b8b50812 | |||
| f35b30e337 | |||
| 22f2e648a2 | |||
| 7973a1e8b7 | |||
| c50824adb6 | |||
| 257c476cc1 | |||
| 815109dec2 | |||
| 0673b01ac8 |
395
.dependency-cruiser.cjs
Normal file
395
.dependency-cruiser.cjs
Normal file
@@ -0,0 +1,395 @@
|
|||||||
|
/** @type {import('dependency-cruiser').IConfiguration} */
|
||||||
|
module.exports = {
|
||||||
|
forbidden: [
|
||||||
|
{
|
||||||
|
name: 'no-circular',
|
||||||
|
severity: 'warn',
|
||||||
|
comment:
|
||||||
|
'This dependency is part of a circular relationship. You might want to revise ' +
|
||||||
|
'your solution (i.e. use dependency inversion, make sure the modules have a single responsibility) ',
|
||||||
|
from: {},
|
||||||
|
to: {
|
||||||
|
circular: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'no-orphans',
|
||||||
|
comment:
|
||||||
|
"This is an orphan module - it's likely not used (anymore?). Either use it or " +
|
||||||
|
"remove it. If it's logical this module is an orphan (i.e. it's a config file), " +
|
||||||
|
"add an exception for it in your dependency-cruiser configuration. By default " +
|
||||||
|
"this rule does not scrutinize dot-files (e.g. .eslintrc.js), TypeScript declaration " +
|
||||||
|
"files (.d.ts), tsconfig.json and some of the babel and webpack configs.",
|
||||||
|
severity: 'warn',
|
||||||
|
from: {
|
||||||
|
orphan: true,
|
||||||
|
pathNot: [
|
||||||
|
'(^|/)[.][^/]+[.](?:js|cjs|mjs|ts|cts|mts|json)$', // dot files
|
||||||
|
'[.]d[.]ts$', // TypeScript declaration files
|
||||||
|
'(^|/)tsconfig[.]json$', // TypeScript config
|
||||||
|
'(^|/)(?:babel|webpack)[.]config[.](?:js|cjs|mjs|ts|cts|mts|json)$' // other configs
|
||||||
|
]
|
||||||
|
},
|
||||||
|
to: {},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'no-deprecated-core',
|
||||||
|
comment:
|
||||||
|
'A module depends on a node core module that has been deprecated. Find an alternative - these are ' +
|
||||||
|
"bound to exist - node doesn't deprecate lightly.",
|
||||||
|
severity: 'warn',
|
||||||
|
from: {},
|
||||||
|
to: {
|
||||||
|
dependencyTypes: [
|
||||||
|
'core'
|
||||||
|
],
|
||||||
|
path: [
|
||||||
|
'^v8/tools/codemap$',
|
||||||
|
'^v8/tools/consarray$',
|
||||||
|
'^v8/tools/csvparser$',
|
||||||
|
'^v8/tools/logreader$',
|
||||||
|
'^v8/tools/profile_view$',
|
||||||
|
'^v8/tools/profile$',
|
||||||
|
'^v8/tools/SourceMap$',
|
||||||
|
'^v8/tools/splaytree$',
|
||||||
|
'^v8/tools/tickprocessor-driver$',
|
||||||
|
'^v8/tools/tickprocessor$',
|
||||||
|
'^node-inspect/lib/_inspect$',
|
||||||
|
'^node-inspect/lib/internal/inspect_client$',
|
||||||
|
'^node-inspect/lib/internal/inspect_repl$',
|
||||||
|
'^async_hooks$',
|
||||||
|
'^punycode$',
|
||||||
|
'^domain$',
|
||||||
|
'^constants$',
|
||||||
|
'^sys$',
|
||||||
|
'^_linklist$',
|
||||||
|
'^_stream_wrap$'
|
||||||
|
],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'not-to-deprecated',
|
||||||
|
comment:
|
||||||
|
'This module uses a (version of an) npm module that has been deprecated. Either upgrade to a later ' +
|
||||||
|
'version of that module, or find an alternative. Deprecated modules are a security risk.',
|
||||||
|
severity: 'warn',
|
||||||
|
from: {},
|
||||||
|
to: {
|
||||||
|
dependencyTypes: [
|
||||||
|
'deprecated'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'no-non-package-json',
|
||||||
|
severity: 'error',
|
||||||
|
comment:
|
||||||
|
"This module depends on an npm package that isn't in the 'dependencies' section of your package.json. " +
|
||||||
|
"That's problematic as the package either (1) won't be available on live (2 - worse) will be " +
|
||||||
|
"available on live with an non-guaranteed version. Fix it by adding the package to the dependencies " +
|
||||||
|
"in your package.json.",
|
||||||
|
from: {},
|
||||||
|
to: {
|
||||||
|
dependencyTypes: [
|
||||||
|
'npm-no-pkg',
|
||||||
|
'npm-unknown'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'not-to-unresolvable',
|
||||||
|
comment:
|
||||||
|
"This module depends on a module that cannot be found ('resolved to disk'). If it's an npm " +
|
||||||
|
'module: add it to your package.json. In all other cases you likely already know what to do.',
|
||||||
|
severity: 'error',
|
||||||
|
from: {},
|
||||||
|
to: {
|
||||||
|
couldNotResolve: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'no-duplicate-dep-types',
|
||||||
|
comment:
|
||||||
|
"Likely this module depends on an external ('npm') package that occurs more than once " +
|
||||||
|
"in your package.json i.e. bot as a devDependencies and in dependencies. This will cause " +
|
||||||
|
"maintenance problems later on.",
|
||||||
|
severity: 'warn',
|
||||||
|
from: {},
|
||||||
|
to: {
|
||||||
|
moreThanOneDependencyType: true,
|
||||||
|
// as it's pretty common to have a type import be a type only import
|
||||||
|
// _and_ (e.g.) a devDependency - don't consider type-only dependency
|
||||||
|
// types for this rule
|
||||||
|
dependencyTypesNot: ["type-only"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/* rules you might want to tweak for your specific situation: */
|
||||||
|
|
||||||
|
{
|
||||||
|
name: 'not-to-spec',
|
||||||
|
comment:
|
||||||
|
'This module depends on a spec (test) file. The sole responsibility of a spec file is to test code. ' +
|
||||||
|
"If there's something in a spec that's of use to other modules, it doesn't have that single " +
|
||||||
|
'responsibility anymore. Factor it out into (e.g.) a separate utility/ helper or a mock.',
|
||||||
|
severity: 'error',
|
||||||
|
from: {},
|
||||||
|
to: {
|
||||||
|
path: '[.](?:spec|test)[.](?:js|mjs|cjs|jsx|ts|mts|cts|tsx)$'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'not-to-dev-dep',
|
||||||
|
severity: 'error',
|
||||||
|
comment:
|
||||||
|
"This module depends on an npm package from the 'devDependencies' section of your " +
|
||||||
|
'package.json. It looks like something that ships to production, though. To prevent problems ' +
|
||||||
|
"with npm packages that aren't there on production declare it (only!) in the 'dependencies'" +
|
||||||
|
'section of your package.json. If this module is development only - add it to the ' +
|
||||||
|
'from.pathNot re of the not-to-dev-dep rule in the dependency-cruiser configuration',
|
||||||
|
from: {
|
||||||
|
path: '^(src)',
|
||||||
|
pathNot: '[.](?:spec|test)[.](?:js|mjs|cjs|jsx|ts|mts|cts|tsx)$'
|
||||||
|
},
|
||||||
|
to: {
|
||||||
|
dependencyTypes: [
|
||||||
|
'npm-dev',
|
||||||
|
],
|
||||||
|
// type only dependencies are not a problem as they don't end up in the
|
||||||
|
// production code or are ignored by the runtime.
|
||||||
|
dependencyTypesNot: [
|
||||||
|
'type-only'
|
||||||
|
],
|
||||||
|
pathNot: [
|
||||||
|
'node_modules/@types/'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'optional-deps-used',
|
||||||
|
severity: 'info',
|
||||||
|
comment:
|
||||||
|
"This module depends on an npm package that is declared as an optional dependency " +
|
||||||
|
"in your package.json. As this makes sense in limited situations only, it's flagged here. " +
|
||||||
|
"If you're using an optional dependency here by design - add an exception to your" +
|
||||||
|
"dependency-cruiser configuration.",
|
||||||
|
from: {},
|
||||||
|
to: {
|
||||||
|
dependencyTypes: [
|
||||||
|
'npm-optional'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'peer-deps-used',
|
||||||
|
comment:
|
||||||
|
"This module depends on an npm package that is declared as a peer dependency " +
|
||||||
|
"in your package.json. This makes sense if your package is e.g. a plugin, but in " +
|
||||||
|
"other cases - maybe not so much. If the use of a peer dependency is intentional " +
|
||||||
|
"add an exception to your dependency-cruiser configuration.",
|
||||||
|
severity: 'warn',
|
||||||
|
from: {},
|
||||||
|
to: {
|
||||||
|
dependencyTypes: [
|
||||||
|
'npm-peer'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
options: {
|
||||||
|
|
||||||
|
/* Which modules not to follow further when encountered */
|
||||||
|
doNotFollow: {
|
||||||
|
/* path: an array of regular expressions in strings to match against */
|
||||||
|
path: ['node_modules']
|
||||||
|
},
|
||||||
|
|
||||||
|
/* Which modules to exclude */
|
||||||
|
// exclude : {
|
||||||
|
// /* path: an array of regular expressions in strings to match against */
|
||||||
|
// path: '',
|
||||||
|
// },
|
||||||
|
|
||||||
|
/* Which modules to exclusively include (array of regular expressions in strings)
|
||||||
|
dependency-cruiser will skip everything not matching this pattern
|
||||||
|
*/
|
||||||
|
// includeOnly : [''],
|
||||||
|
|
||||||
|
/* List of module systems to cruise.
|
||||||
|
When left out dependency-cruiser will fall back to the list of _all_
|
||||||
|
module systems it knows of. It's the default because it's the safe option
|
||||||
|
It might come at a performance penalty, though.
|
||||||
|
moduleSystems: ['amd', 'cjs', 'es6', 'tsd']
|
||||||
|
|
||||||
|
As in practice only commonjs ('cjs') and ecmascript modules ('es6')
|
||||||
|
are widely used, you can limit the moduleSystems to those.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// moduleSystems: ['cjs', 'es6'],
|
||||||
|
|
||||||
|
/*
|
||||||
|
false: don't look at JSDoc imports (the default)
|
||||||
|
true: dependency-cruiser will detect dependencies in JSDoc-style
|
||||||
|
import statements. Implies "parser": "tsc", so the dependency-cruiser
|
||||||
|
will use the typescript parser for JavaScript files.
|
||||||
|
|
||||||
|
For this to work the typescript compiler will need to be installed in the
|
||||||
|
same spot as you're running dependency-cruiser from.
|
||||||
|
*/
|
||||||
|
// detectJSDocImports: true,
|
||||||
|
|
||||||
|
/* prefix for links in html and svg output (e.g. 'https://github.com/you/yourrepo/blob/main/'
|
||||||
|
to open it on your online repo or `vscode://file/${process.cwd()}/` to
|
||||||
|
open it in visual studio code),
|
||||||
|
*/
|
||||||
|
// prefix: `vscode://file/${process.cwd()}/`,
|
||||||
|
|
||||||
|
/* false (the default): ignore dependencies that only exist before typescript-to-javascript compilation
|
||||||
|
true: also detect dependencies that only exist before typescript-to-javascript compilation
|
||||||
|
"specify": for each dependency identify whether it only exists before compilation or also after
|
||||||
|
*/
|
||||||
|
// tsPreCompilationDeps: false,
|
||||||
|
|
||||||
|
/* list of extensions to scan that aren't javascript or compile-to-javascript.
|
||||||
|
Empty by default. Only put extensions in here that you want to take into
|
||||||
|
account that are _not_ parsable.
|
||||||
|
*/
|
||||||
|
// extraExtensionsToScan: [".json", ".jpg", ".png", ".svg", ".webp"],
|
||||||
|
|
||||||
|
/* if true combines the package.jsons found from the module up to the base
|
||||||
|
folder the cruise is initiated from. Useful for how (some) mono-repos
|
||||||
|
manage dependencies & dependency definitions.
|
||||||
|
*/
|
||||||
|
// combinedDependencies: false,
|
||||||
|
|
||||||
|
/* if true leave symlinks untouched, otherwise use the realpath */
|
||||||
|
// preserveSymlinks: false,
|
||||||
|
|
||||||
|
/* TypeScript project file ('tsconfig.json') to use for
|
||||||
|
(1) compilation and
|
||||||
|
(2) resolution (e.g. with the paths property)
|
||||||
|
|
||||||
|
The (optional) fileName attribute specifies which file to take (relative to
|
||||||
|
dependency-cruiser's current working directory). When not provided
|
||||||
|
defaults to './tsconfig.json'.
|
||||||
|
*/
|
||||||
|
tsConfig: {
|
||||||
|
fileName: 'jsconfig.json'
|
||||||
|
},
|
||||||
|
|
||||||
|
/* Webpack configuration to use to get resolve options from.
|
||||||
|
|
||||||
|
The (optional) fileName attribute specifies which file to take (relative
|
||||||
|
to dependency-cruiser's current working directory. When not provided defaults
|
||||||
|
to './webpack.conf.js'.
|
||||||
|
|
||||||
|
The (optional) `env` and `arguments` attributes contain the parameters
|
||||||
|
to be passed if your webpack config is a function and takes them (see
|
||||||
|
webpack documentation for details)
|
||||||
|
*/
|
||||||
|
// webpackConfig: {
|
||||||
|
// fileName: 'webpack.config.js',
|
||||||
|
// env: {},
|
||||||
|
// arguments: {}
|
||||||
|
// },
|
||||||
|
|
||||||
|
/* Babel config ('.babelrc', '.babelrc.json', '.babelrc.json5', ...) to use
|
||||||
|
for compilation
|
||||||
|
*/
|
||||||
|
// babelConfig: {
|
||||||
|
// fileName: '.babelrc',
|
||||||
|
// },
|
||||||
|
|
||||||
|
/* List of strings you have in use in addition to cjs/ es6 requires
|
||||||
|
& imports to declare module dependencies. Use this e.g. if you've
|
||||||
|
re-declared require, use a require-wrapper or use window.require as
|
||||||
|
a hack.
|
||||||
|
*/
|
||||||
|
// exoticRequireStrings: [],
|
||||||
|
|
||||||
|
/* options to pass on to enhanced-resolve, the package dependency-cruiser
|
||||||
|
uses to resolve module references to disk. The values below should be
|
||||||
|
suitable for most situations
|
||||||
|
|
||||||
|
If you use webpack: you can also set these in webpack.conf.js. The set
|
||||||
|
there will override the ones specified here.
|
||||||
|
*/
|
||||||
|
enhancedResolveOptions: {
|
||||||
|
/* What to consider as an 'exports' field in package.jsons */
|
||||||
|
exportsFields: ["exports"],
|
||||||
|
/* List of conditions to check for in the exports field.
|
||||||
|
Only works when the 'exportsFields' array is non-empty.
|
||||||
|
*/
|
||||||
|
conditionNames: ["import", "require", "node", "default", "types"],
|
||||||
|
/* The extensions, by default are the same as the ones dependency-cruiser
|
||||||
|
can access (run `npx depcruise --info` to see which ones that are in
|
||||||
|
_your_ environment). If that list is larger than you need you can pass
|
||||||
|
the extensions you actually use (e.g. [".js", ".jsx"]). This can speed
|
||||||
|
up module resolution, which is the most expensive step.
|
||||||
|
*/
|
||||||
|
// extensions: [".js", ".jsx", ".ts", ".tsx", ".d.ts"],
|
||||||
|
/* What to consider a 'main' field in package.json */
|
||||||
|
mainFields: ["module", "main", "types", "typings"],
|
||||||
|
/* A list of alias fields in package.jsons
|
||||||
|
|
||||||
|
See [this specification](https://github.com/defunctzombie/package-browser-field-spec) and
|
||||||
|
the webpack [resolve.alias](https://webpack.js.org/configuration/resolve/#resolvealiasfields)
|
||||||
|
documentation.
|
||||||
|
|
||||||
|
Defaults to an empty array (= don't use alias fields).
|
||||||
|
*/
|
||||||
|
// aliasFields: ["browser"],
|
||||||
|
},
|
||||||
|
|
||||||
|
/* skipAnalysisNotInRules will make dependency-cruiser execute
|
||||||
|
analysis strictly necessary for checking the rule set only.
|
||||||
|
|
||||||
|
See https://github.com/sverweij/dependency-cruiser/blob/main/doc/options-reference.md#skipanalysisnotinrules
|
||||||
|
for details
|
||||||
|
*/
|
||||||
|
skipAnalysisNotInRules: true,
|
||||||
|
|
||||||
|
reporterOptions: {
|
||||||
|
dot: {
|
||||||
|
/* pattern of modules that can be consolidated in the detailed
|
||||||
|
graphical dependency graph. The default pattern in this configuration
|
||||||
|
collapses everything in node_modules to one folder deep so you see
|
||||||
|
the external modules, but their innards.
|
||||||
|
*/
|
||||||
|
collapsePattern: 'node_modules/(?:@[^/]+/[^/]+|[^/]+)',
|
||||||
|
|
||||||
|
/* Options to tweak the appearance of your graph.See
|
||||||
|
https://github.com/sverweij/dependency-cruiser/blob/main/doc/options-reference.md#reporteroptions
|
||||||
|
for details and some examples. If you don't specify a theme
|
||||||
|
dependency-cruiser falls back to a built-in one.
|
||||||
|
*/
|
||||||
|
// theme: {
|
||||||
|
// graph: {
|
||||||
|
// /* splines: "ortho" gives straight lines, but is slow on big graphs
|
||||||
|
// splines: "true" gives bezier curves (fast, not as nice as ortho)
|
||||||
|
// */
|
||||||
|
// splines: "true"
|
||||||
|
// },
|
||||||
|
// }
|
||||||
|
},
|
||||||
|
archi: {
|
||||||
|
/* pattern of modules that can be consolidated in the high level
|
||||||
|
graphical dependency graph. If you use the high level graphical
|
||||||
|
dependency graph reporter (`archi`) you probably want to tweak
|
||||||
|
this collapsePattern to your situation.
|
||||||
|
*/
|
||||||
|
collapsePattern: '^(?:packages|src|lib(s?)|app(s?)|bin|test(s?)|spec(s?))/[^/]+|node_modules/(?:@[^/]+/[^/]+|[^/]+)',
|
||||||
|
|
||||||
|
/* Options to tweak the appearance of your graph. If you don't specify a
|
||||||
|
theme for 'archi' dependency-cruiser will use the one specified in the
|
||||||
|
dot section above and otherwise use the default one.
|
||||||
|
*/
|
||||||
|
// theme: { },
|
||||||
|
},
|
||||||
|
"text": {
|
||||||
|
"highlightFocused": true
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// generated: dependency-cruiser@16.10.1 on 2025-04-24T20:50:32.854Z
|
||||||
@@ -1 +1,2 @@
|
|||||||
VITE_WS_URL=wss://ws.dexorder.trade
|
VITE_WS_URL=wss://ws.dexorder.com
|
||||||
|
VITE_SHARE_URL=https://app.dexorder.com
|
||||||
|
|||||||
@@ -1,2 +1,3 @@
|
|||||||
VITE_WS_URL=ws://localhost:3001
|
VITE_WS_URL=ws://localhost:3001
|
||||||
REQUIRE_AUTH=NOAUTH
|
VITE_SHARE_URL=http://localhost:3001
|
||||||
|
VITE_REQUIRE_APPROVAL=NO
|
||||||
|
|||||||
2
bin/depcruise
Executable file
2
bin/depcruise
Executable file
@@ -0,0 +1,2 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
npx depcruise src
|
||||||
@@ -25,6 +25,7 @@
|
|||||||
"pinia-plugin-persistedstate": "^4.1.3",
|
"pinia-plugin-persistedstate": "^4.1.3",
|
||||||
"roboto-fontface": "*",
|
"roboto-fontface": "*",
|
||||||
"socket.io-client": "^4.7.2",
|
"socket.io-client": "^4.7.2",
|
||||||
|
"uuid": "^11.1.0",
|
||||||
"vue": "^3.2.0",
|
"vue": "^3.2.0",
|
||||||
"vue-router": "^4.0.0",
|
"vue-router": "^4.0.0",
|
||||||
"vue-scroll-picker": "^1.2.2",
|
"vue-scroll-picker": "^1.2.2",
|
||||||
@@ -33,6 +34,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@vitejs/plugin-vue": "^4.0.0",
|
"@vitejs/plugin-vue": "^4.0.0",
|
||||||
|
"dependency-cruiser": "^16.10.1",
|
||||||
"eslint": "^8.37.0",
|
"eslint": "^8.37.0",
|
||||||
"eslint-plugin-vue": "^9.3.0",
|
"eslint-plugin-vue": "^9.3.0",
|
||||||
"sass": "^1.60.0",
|
"sass": "^1.60.0",
|
||||||
|
|||||||
@@ -6,12 +6,9 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import SupportChat from "@/components/SupportChat.vue";
|
import SupportChat from "@/components/SupportChat.vue";
|
||||||
import {detectChain} from "@/blockchain/wallet.js";
|
|
||||||
import WelcomeDialog from "@/components/WelcomeDialog.vue";
|
import WelcomeDialog from "@/components/WelcomeDialog.vue";
|
||||||
import {usePrefStore} from "@/store/store.js";
|
import {usePrefStore} from "@/store/store.js";
|
||||||
|
|
||||||
detectChain()
|
|
||||||
|
|
||||||
const prefs = usePrefStore()
|
const prefs = usePrefStore()
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
import {provider as walletProvider} from "@/blockchain/provider.js";
|
||||||
import {ethers} from "ethers";
|
import {ethers} from "ethers";
|
||||||
import {AbiURLCache} from "../common.js";
|
import {AbiURLCache} from "../common.js";
|
||||||
import {provider as walletProvider} from "@/blockchain/wallet.js";
|
|
||||||
|
|
||||||
export const abiCache = new AbiURLCache('/contract/out/')
|
export const abiCache = new AbiURLCache('/contract/out/')
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ export function subOHLC( chainId, pool, period ) {
|
|||||||
// console.log('subOHLC', chainId, pool, period, ckey, ohlcSubCounts[ckey])
|
// console.log('subOHLC', chainId, pool, period, ckey, ohlcSubCounts[ckey])
|
||||||
if (!(ckey in ohlcSubCounts) || ohlcSubCounts[ckey] === 0) {
|
if (!(ckey in ohlcSubCounts) || ohlcSubCounts[ckey] === 0) {
|
||||||
ohlcSubCounts[ckey] = 1
|
ohlcSubCounts[ckey] = 1
|
||||||
console.log('subscribing OHLCs', chainId, key)
|
// console.log('subscribing OHLCs', chainId, key)
|
||||||
socket.emit('subOHLCs', chainId, [key])
|
socket.emit('subOHLCs', chainId, [key])
|
||||||
} else
|
} else
|
||||||
ohlcSubCounts[ckey]++
|
ohlcSubCounts[ckey]++
|
||||||
@@ -30,7 +30,7 @@ export function refreshOHLCSubs() {
|
|||||||
}
|
}
|
||||||
keys.push(`${pool}|${period}`)
|
keys.push(`${pool}|${period}`)
|
||||||
}
|
}
|
||||||
console.log('refreshing OHLC subs', keys)
|
// console.log('refreshing OHLC subs', keys)
|
||||||
socket.emit('subOHLCs', chainId, keys)
|
socket.emit('subOHLCs', chainId, keys)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,7 +45,7 @@ export function unsubOHLC( chainId, pool, period ) {
|
|||||||
} else {
|
} else {
|
||||||
ohlcSubCounts[ckey]--
|
ohlcSubCounts[ckey]--
|
||||||
if (ohlcSubCounts[ckey] === 0) {
|
if (ohlcSubCounts[ckey] === 0) {
|
||||||
console.log('unsubscribing OHLCs', chainId, key)
|
// console.log('unsubscribing OHLCs', chainId, key)
|
||||||
// noinspection JSCheckFunctionSignatures
|
// noinspection JSCheckFunctionSignatures
|
||||||
socket.emit('unsubOHLCs', chainId, [key])
|
socket.emit('unsubOHLCs', chainId, [key])
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import {uint32max, uint64max} from "@/misc.js";
|
import {uint32max, uint64max} from "@/misc.js";
|
||||||
import {encodeIEE754} from "@/common.js";
|
import {encodeIEE754} from "@/common.js";
|
||||||
import {DEFAULT_SLIPPAGE, MIN_SLIPPAGE} from "@/orderbuild.js";
|
|
||||||
|
|
||||||
export const MAX_FRACTION = 65535;
|
export const MAX_FRACTION = 65535;
|
||||||
export const NO_CONDITIONAL_ORDER = uint64max;
|
export const NO_CONDITIONAL_ORDER = uint64max;
|
||||||
@@ -8,6 +8,10 @@ export const NO_OCO = uint64max;
|
|||||||
export const DISTANT_PAST = 0
|
export const DISTANT_PAST = 0
|
||||||
export const DISTANT_FUTURE = uint32max
|
export const DISTANT_FUTURE = uint32max
|
||||||
|
|
||||||
|
export const MIN_EXECUTION_TIME = 60 // give at least one full minute for each tranche to trigger
|
||||||
|
export const DEFAULT_SLIPPAGE = 0.0030;
|
||||||
|
export const MIN_SLIPPAGE = 0.0001;
|
||||||
|
|
||||||
// struct SwapOrder {
|
// struct SwapOrder {
|
||||||
// address tokenIn;
|
// address tokenIn;
|
||||||
// address tokenOut;
|
// address tokenOut;
|
||||||
@@ -140,7 +144,7 @@ export function parseElaboratedOrderStatus(chainId, status) {
|
|||||||
|
|
||||||
|
|
||||||
export function parseOrderStatus(chainId, status) {
|
export function parseOrderStatus(chainId, status) {
|
||||||
console.log('parseOrderStatus', status)
|
// console.log('parseOrderStatus', status)
|
||||||
let [
|
let [
|
||||||
order,
|
order,
|
||||||
fillFeeHalfBps,
|
fillFeeHalfBps,
|
||||||
@@ -161,7 +165,7 @@ export function parseOrderStatus(chainId, status) {
|
|||||||
chainId, order, fillFeeHalfBps, state, startTime, startPrice, ocoGroup,
|
chainId, order, fillFeeHalfBps, state, startTime, startPrice, ocoGroup,
|
||||||
filledIn, filledOut, filled, trancheStatus,
|
filledIn, filledOut, filled, trancheStatus,
|
||||||
};
|
};
|
||||||
console.log('SwapOrderStatus', result)
|
// console.log('SwapOrderStatus', result)
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -253,4 +257,3 @@ export function parseFeeSchedule(sched) {
|
|||||||
fillFee: fillFeeHalfBps/1_000_000 // fillFee is a multiplier on the filled volume. 0.0001 = 0.1% of the output token taken as a fee
|
fillFee: fillFeeHalfBps/1_000_000 // fillFee is a multiplier on the filled volume. 0.0001 = 0.1% of the output token taken as a fee
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import {socket} from "@/socket.js";
|
|
||||||
import {useStore} from "@/store/store.js";
|
import {useStore} from "@/store/store.js";
|
||||||
import {Exchange} from "@/blockchain/orderlib.js";
|
import {Exchange} from "@/blockchain/orderlib.js";
|
||||||
import {uniswapV3PoolAddress} from "@/blockchain/uniswap.js";
|
import {uniswapV3PoolAddress} from "@/blockchain/uniswap.js";
|
||||||
import {FixedNumber} from "ethers";
|
import {FixedNumber} from "ethers";
|
||||||
import {provider} from "@/blockchain/wallet.js";
|
|
||||||
import {newContract} from "@/blockchain/contract.js";
|
import {newContract} from "@/blockchain/contract.js";
|
||||||
|
import {provider} from "@/blockchain/provider.js";
|
||||||
|
import {socket} from "@/socket.js";
|
||||||
|
|
||||||
const subscriptionCounts = {} // key is route and value is a subscription counter
|
const subscriptionCounts = {} // key is route and value is a subscription counter
|
||||||
export const WIDE_PRICE_FORMAT = {decimals:38, width:512, signed:false}; // 38 decimals is 127 bits
|
export const WIDE_PRICE_FORMAT = {decimals:38, width:512, signed:false}; // 38 decimals is 127 bits
|
||||||
|
|||||||
3
src/blockchain/provider.js
Normal file
3
src/blockchain/provider.js
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
export let provider = null
|
||||||
|
|
||||||
|
export function setProvider(p) {provider = p}
|
||||||
@@ -2,7 +2,8 @@ import {Exchange} from "@/blockchain/orderlib.js";
|
|||||||
import {useOrderStore, useStore} from "@/store/store.js";
|
import {useOrderStore, useStore} from "@/store/store.js";
|
||||||
import {queryHelperContract} from "@/blockchain/contract.js";
|
import {queryHelperContract} from "@/blockchain/contract.js";
|
||||||
import {SingletonCoroutine} from "@/misc.js";
|
import {SingletonCoroutine} from "@/misc.js";
|
||||||
import {provider} from "@/blockchain/wallet.js";
|
|
||||||
|
import {provider} from "@/blockchain/provider.js";
|
||||||
|
|
||||||
|
|
||||||
export async function findRoute(helper, chainId, tokenA, tokenB) {
|
export async function findRoute(helper, chainId, tokenA, tokenB) {
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import {socket} from "@/socket.js";
|
|
||||||
import {useStore} from "@/store/store.js";
|
import {useStore} from "@/store/store.js";
|
||||||
import {metadataMap} from "@/version.js";
|
import {metadataMap} from "@/version.js";
|
||||||
import {provider} from "@/blockchain/wallet.js";
|
|
||||||
import {newContract} from "@/blockchain/contract.js";
|
import {newContract} from "@/blockchain/contract.js";
|
||||||
|
import {provider} from "@/blockchain/provider.js";
|
||||||
|
import {socket} from "@/socket.js";
|
||||||
|
|
||||||
|
|
||||||
// synchronous version may return null but will trigger a lookup
|
// synchronous version may return null but will trigger a lookup
|
||||||
@@ -31,7 +31,16 @@ export async function getToken(chainId, addr) {
|
|||||||
return found
|
return found
|
||||||
if (!(addr in s.tokens))
|
if (!(addr in s.tokens))
|
||||||
await addExtraToken(chainId, addr)
|
await addExtraToken(chainId, addr)
|
||||||
return s.tokens[addr]
|
let result = s.tokens[addr]
|
||||||
|
if (!result) {
|
||||||
|
result = {
|
||||||
|
n: addr,
|
||||||
|
a: addr,
|
||||||
|
s: addr,
|
||||||
|
d: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,28 +1,13 @@
|
|||||||
import {nav, sleep, uuid} from "@/misc.js";
|
import {provider} from "@/blockchain/provider.js";
|
||||||
|
import {TransactionState, TransactionType} from "@/blockchain/transactionDecl.js";
|
||||||
|
import {sleep, uuid} from "@/misc.js";
|
||||||
import {vaultContract} from "@/blockchain/contract.js";
|
import {vaultContract} from "@/blockchain/contract.js";
|
||||||
import {ensureVault, provider, switchChain, useWalletStore} from "@/blockchain/wallet.js";
|
import {switchChain, useWalletStore} from "@/blockchain/wallet.js";
|
||||||
import {toRaw} from "vue";
|
import {toRaw} from "vue";
|
||||||
import {useChartOrderStore} from "@/orderbuild.js";
|
import {useChartOrderStore} from "@/orderbuild.js";
|
||||||
import {placementFee} from "@/fees.js";
|
import {placementFee} from "@/fees.js";
|
||||||
|
import {router} from "@/router/router.js";
|
||||||
|
|
||||||
export const TransactionState = {
|
|
||||||
Created: 0, // user requested a transaction
|
|
||||||
Proposed: 1, // tx is sent to the wallet
|
|
||||||
Signed: 2, // tx is awaiting blockchain mining
|
|
||||||
Rejected: 3, // user refused to sign the tx
|
|
||||||
Error: 3, // unknown error sending the tx to the wallet
|
|
||||||
Mined: 4, // transaction has been confirmed on-chain
|
|
||||||
}
|
|
||||||
|
|
||||||
export const TransactionType = {
|
|
||||||
PlaceOrder: 1,
|
|
||||||
CancelOrder: 2,
|
|
||||||
CancelAll: 3,
|
|
||||||
Wrap: 4,
|
|
||||||
Unwrap: 5,
|
|
||||||
WithdrawNative: 6,
|
|
||||||
Withdraw: 7,
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Transaction {
|
export class Transaction {
|
||||||
constructor(chainId, type) {
|
constructor(chainId, type) {
|
||||||
@@ -37,6 +22,7 @@ export class Transaction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
submit() {
|
submit() {
|
||||||
|
console.log('submitting transaction', this.type)
|
||||||
const ws = useWalletStore();
|
const ws = useWalletStore();
|
||||||
if ( ws.transaction !== null ) {
|
if ( ws.transaction !== null ) {
|
||||||
console.error('Transaction already in progress', ws.transaction)
|
console.error('Transaction already in progress', ws.transaction)
|
||||||
@@ -47,6 +33,7 @@ export class Transaction {
|
|||||||
|
|
||||||
// "propose" means attach the transaction to a specific vault
|
// "propose" means attach the transaction to a specific vault
|
||||||
propose(owner, vault) {
|
propose(owner, vault) {
|
||||||
|
console.log('transaction bind', owner, vault)
|
||||||
if (this.vault !== null && this.vault !== vault) {
|
if (this.vault !== null && this.vault !== vault) {
|
||||||
this.failed('proposed vault did not match withdrawl vault', vault, this.vault)
|
this.failed('proposed vault did not match withdrawl vault', vault, this.vault)
|
||||||
return
|
return
|
||||||
@@ -195,7 +182,8 @@ export class PlaceOrderTransaction extends Transaction {
|
|||||||
super.end(state)
|
super.end(state)
|
||||||
if (state === TransactionState.Mined) {
|
if (state === TransactionState.Mined) {
|
||||||
useChartOrderStore().resetOrders()
|
useChartOrderStore().resetOrders()
|
||||||
nav('Status')
|
// noinspection JSIgnoredPromiseFromCall
|
||||||
|
router.push({name: 'Status'})
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -280,4 +268,3 @@ export class UnwrapTransaction extends Transaction {
|
|||||||
return await vaultContract.unwrap(this.amount)
|
return await vaultContract.unwrap(this.amount)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
17
src/blockchain/transactionDecl.js
Normal file
17
src/blockchain/transactionDecl.js
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
export const TransactionState = {
|
||||||
|
Created: 0, // user requested a transaction
|
||||||
|
Proposed: 1, // tx is sent to the wallet
|
||||||
|
Signed: 2, // tx is awaiting blockchain mining
|
||||||
|
Rejected: 3, // user refused to sign the tx
|
||||||
|
Error: 3, // unknown error sending the tx to the wallet
|
||||||
|
Mined: 4, // transaction has been confirmed on-chain
|
||||||
|
}
|
||||||
|
export const TransactionType = {
|
||||||
|
PlaceOrder: 1,
|
||||||
|
CancelOrder: 2,
|
||||||
|
CancelAll: 3,
|
||||||
|
Wrap: 4,
|
||||||
|
Unwrap: 5,
|
||||||
|
WithdrawNative: 6,
|
||||||
|
Withdraw: 7,
|
||||||
|
}
|
||||||
@@ -1,15 +1,14 @@
|
|||||||
|
import {provider, setProvider} from "@/blockchain/provider.js";
|
||||||
import {BrowserProvider, ethers} from "ethers";
|
import {BrowserProvider, ethers} from "ethers";
|
||||||
import {useStore} from "@/store/store";
|
import {useStore} from "@/store/store";
|
||||||
import {socket} from "@/socket.js";
|
|
||||||
import {errorSuggestsMissingVault, SingletonCoroutine} from "@/misc.js";
|
import {errorSuggestsMissingVault, SingletonCoroutine} from "@/misc.js";
|
||||||
import {newContract, vaultAddress, vaultContract} from "@/blockchain/contract.js";
|
import {newContract, vaultAddress, vaultContract} from "@/blockchain/contract.js";
|
||||||
import {defineStore} from "pinia";
|
import {defineStore} from "pinia";
|
||||||
import {computed, ref} from "vue";
|
import {computed, ref} from "vue";
|
||||||
import {metadataMap, version} from "@/version.js";
|
import {metadataMap, version} from "@/version.js";
|
||||||
import {CancelAllTransaction, TransactionState, TransactionType} from "@/blockchain/transaction.js";
|
import {TransactionState, TransactionType} from "@/blockchain/transactionDecl.js";
|
||||||
|
import {track} from "@/track.js";
|
||||||
|
import {socket} from "@/socket.js";
|
||||||
export let provider = null
|
|
||||||
|
|
||||||
|
|
||||||
export const useWalletStore = defineStore('wallet', ()=>{
|
export const useWalletStore = defineStore('wallet', ()=>{
|
||||||
@@ -34,12 +33,14 @@ export const useWalletStore = defineStore('wallet', ()=>{
|
|||||||
set(v) {
|
set(v) {
|
||||||
_tx.value = v;
|
_tx.value = v;
|
||||||
if (v===null) {
|
if (v===null) {
|
||||||
|
console.log('clear transaction')
|
||||||
if (progressionInvoker!==null) {
|
if (progressionInvoker!==null) {
|
||||||
clearTimeout(progressionInvoker)
|
clearTimeout(progressionInvoker)
|
||||||
progressionInvoker = null
|
progressionInvoker = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
console.log('set transaction', v)
|
||||||
transactionProgressor.invoke();
|
transactionProgressor.invoke();
|
||||||
if (progressionInvoker===null)
|
if (progressionInvoker===null)
|
||||||
progressionInvoker = setInterval(()=>transactionProgressor.invoke(), 1000)
|
progressionInvoker = setInterval(()=>transactionProgressor.invoke(), 1000)
|
||||||
@@ -66,7 +67,7 @@ export function onChainChanged(chainId) {
|
|||||||
console.log('app chain changed', chainId)
|
console.log('app chain changed', chainId)
|
||||||
store.chainId = chainId
|
store.chainId = chainId
|
||||||
store.account = null
|
store.account = null
|
||||||
provider = new BrowserProvider(window.ethereum, chainId)
|
setProvider(new BrowserProvider(window.ethereum, chainId))
|
||||||
updateAccounts(chainId, provider)
|
updateAccounts(chainId, provider)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -90,6 +91,7 @@ function changeAccounts(chainId, accounts) {
|
|||||||
const addr = accounts[0]
|
const addr = accounts[0]
|
||||||
if (addr !== store.account) {
|
if (addr !== store.account) {
|
||||||
console.log('account logged in', addr)
|
console.log('account logged in', addr)
|
||||||
|
track('login', {chainId, address: addr})
|
||||||
store.account = addr
|
store.account = addr
|
||||||
store.vaults = []
|
store.vaults = []
|
||||||
// one of these two methods will call flushTransactions()
|
// one of these two methods will call flushTransactions()
|
||||||
@@ -119,17 +121,17 @@ export function detectChain() {
|
|||||||
try {
|
try {
|
||||||
window.ethereum.on('chainChanged', onChainChanged);
|
window.ethereum.on('chainChanged', onChainChanged);
|
||||||
window.ethereum.on('accountsChanged', onAccountsChanged);
|
window.ethereum.on('accountsChanged', onAccountsChanged);
|
||||||
|
new ethers.BrowserProvider(window.ethereum).getNetwork().then((network)=>{
|
||||||
|
const chainId = network.chainId
|
||||||
|
onChainChanged(chainId)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
console.log('Could not connect change hooks to wallet', e)
|
console.log('Could not connect change hooks to wallet', e)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
new ethers.BrowserProvider(window.ethereum).getNetwork().then((network)=>{
|
|
||||||
const chainId = network.chainId
|
|
||||||
onChainChanged(chainId)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
detectChain()
|
||||||
|
|
||||||
const errorHandlingProxy = {
|
const errorHandlingProxy = {
|
||||||
get(target, prop, proxy) {
|
get(target, prop, proxy) {
|
||||||
@@ -242,7 +244,7 @@ async function _discoverVaults(owner) {
|
|||||||
if( useWalletStore().transaction ) {
|
if( useWalletStore().transaction ) {
|
||||||
const num = 0 // todo multiple vaults
|
const num = 0 // todo multiple vaults
|
||||||
if (result.length)
|
if (result.length)
|
||||||
flushOrders(s.chainId, owner, num, result[0])
|
flushWalletTransactions(s.chainId, owner, num, result[0])
|
||||||
else
|
else
|
||||||
ensureVault2(s.chainId, owner, num)
|
ensureVault2(s.chainId, owner, num)
|
||||||
}
|
}
|
||||||
@@ -284,7 +286,7 @@ async function doEnsureVault(chainId, owner, num) {
|
|||||||
if (s.vaults.length <= num)
|
if (s.vaults.length <= num)
|
||||||
await _discoverVaults(owner)
|
await _discoverVaults(owner)
|
||||||
if( s.vaults[num] )
|
if( s.vaults[num] )
|
||||||
flushOrders(chainId, owner, num, s.vaults[num])
|
flushWalletTransactions(chainId, owner, num, s.vaults[num])
|
||||||
else {
|
else {
|
||||||
console.log(`requesting vault ${owner} ${num}`)
|
console.log(`requesting vault ${owner} ${num}`)
|
||||||
socket.emit('ensureVault', chainId, owner, num)
|
socket.emit('ensureVault', chainId, owner, num)
|
||||||
@@ -306,23 +308,20 @@ export async function cancelOrder(vault, orderIndex) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function cancelAll(vault) {
|
|
||||||
new CancelAllTransaction(useStore().chainId, vault).submit()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
async function progressTransactions() {
|
async function progressTransactions() {
|
||||||
const s = useStore()
|
const s = useStore()
|
||||||
const ws = useWalletStore();
|
const ws = useWalletStore();
|
||||||
|
console.log('progressTransactions', ws.transaction)
|
||||||
if( ws.transaction===null )
|
if( ws.transaction===null )
|
||||||
return
|
return
|
||||||
if( s.account === null ) {
|
if( s.account === null ) {
|
||||||
let signer = null
|
let signer = null
|
||||||
try {
|
try {
|
||||||
|
console.log('account is null. requesting sign-in.')
|
||||||
signer = await provider.getSigner()
|
signer = await provider.getSigner()
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
console.log('signer error', e.code, e.info.error.code)
|
console.log('signer error', e.code, e.info?.error?.code)
|
||||||
if (e?.info?.error?.code === 4001) {
|
if (e?.info?.error?.code === 4001) {
|
||||||
console.log('signer rejected')
|
console.log('signer rejected')
|
||||||
signer = null
|
signer = null
|
||||||
@@ -338,11 +337,27 @@ async function progressTransactions() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if( s.vault === null ) {
|
if( s.vault === null ) {
|
||||||
|
console.log('vault is null. requesting vault creation.')
|
||||||
ensureVault()
|
ensureVault()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if( ws.transaction.state < TransactionState.Proposed )
|
||||||
|
ws.transaction.propose(s.account, s.vault)
|
||||||
if( ws.transaction.type === TransactionType.PlaceOrder ) {
|
if( ws.transaction.type === TransactionType.PlaceOrder ) {
|
||||||
flushOrders(s.chainId, s.account, 0, s.vault)
|
flushWalletTransactions(s.chainId, s.account, 0, s.vault)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.log('flushing transaction', ws.transaction.type)
|
||||||
|
if (ws.transaction.state < TransactionState.Proposed) {
|
||||||
|
pendTransaction(async (signer) => {
|
||||||
|
if (signer.address !== ws.transaction.owner) {
|
||||||
|
console.error('signer address does not match transaction owner', signer.address, ws.transaction.owner)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const contract = await vaultContract(ws.transaction.vault, signer)
|
||||||
|
return await ws.transaction.createTx(contract)
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -351,12 +366,10 @@ const transactionProgressor = new SingletonCoroutine(progressTransactions, 10)
|
|||||||
let progressionInvoker = null
|
let progressionInvoker = null
|
||||||
|
|
||||||
|
|
||||||
export function flushOrders(chainId, owner, num, vault) {
|
export function flushWalletTransactions(chainId, owner, num, vault) {
|
||||||
const ws = useWalletStore();
|
const ws = useWalletStore();
|
||||||
console.log('flushOrders', chainId, owner, num, vault)
|
console.log('flushWalletTransactions', chainId, owner, num, vault)
|
||||||
if (ws.transaction!==null && ws.transaction.type === TransactionType.PlaceOrder && ws.transaction.state < TransactionState.Proposed)
|
let needsFlush = ws.transaction !== null && ws.transaction.type !== TransactionType.PlaceOrder
|
||||||
ws.transaction.propose(owner, vault)
|
|
||||||
let needsFlush = false
|
|
||||||
for( const pend of ws.pendingOrders ) {
|
for( const pend of ws.pendingOrders ) {
|
||||||
if (pend.vault === null)
|
if (pend.vault === null)
|
||||||
pend.vault = vault
|
pend.vault = vault
|
||||||
@@ -425,6 +438,7 @@ function pendOrderAsTransaction(pend) {
|
|||||||
|
|
||||||
|
|
||||||
export function pendTransaction(sender, errHandler) {
|
export function pendTransaction(sender, errHandler) {
|
||||||
|
console.log('pendTransaction')
|
||||||
const s = useStore()
|
const s = useStore()
|
||||||
s.transactionSenders.push([sender,errHandler])
|
s.transactionSenders.push([sender,errHandler])
|
||||||
flushTransactions()
|
flushTransactions()
|
||||||
@@ -443,6 +457,7 @@ async function asyncFlushTransactions() {
|
|||||||
console.log('flushTransactions', ws.transaction, s.vault)
|
console.log('flushTransactions', ws.transaction, s.vault)
|
||||||
if (ws.transaction !== null) {
|
if (ws.transaction !== null) {
|
||||||
if (s.vault === null) {
|
if (s.vault === null) {
|
||||||
|
console.log('transaction doesn\'t have a vault. creating one.')
|
||||||
await ensureVault()
|
await ensureVault()
|
||||||
if (s.vault === null) {
|
if (s.vault === null) {
|
||||||
console.error('vault could not be created')
|
console.error('vault could not be created')
|
||||||
@@ -460,8 +475,10 @@ async function asyncFlushTransactions() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
const senders = s.transactionSenders
|
const senders = s.transactionSenders
|
||||||
if (!senders.length)
|
if (!senders.length) {
|
||||||
|
console.log('no transactionSenders!')
|
||||||
return
|
return
|
||||||
|
}
|
||||||
console.log(`flushing ${senders.length} transactions`)
|
console.log(`flushing ${senders.length} transactions`)
|
||||||
let signer
|
let signer
|
||||||
try {
|
try {
|
||||||
@@ -577,7 +594,7 @@ const _chainInfos = {
|
|||||||
1337: {
|
1337: {
|
||||||
"chainId": "0x539",
|
"chainId": "0x539",
|
||||||
"chainName": "Dexorder Alpha Testnet",
|
"chainName": "Dexorder Alpha Testnet",
|
||||||
"rpcUrls": ["https://rpc.alpha.dexorder.trade"],
|
"rpcUrls": ["https://rpc.alpha.dexorder.com"],
|
||||||
"nativeCurrency": {
|
"nativeCurrency": {
|
||||||
"name": "Test Ethereum",
|
"name": "Test Ethereum",
|
||||||
"symbol": "TETH",
|
"symbol": "TETH",
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
import {useChartOrderStore} from "@/orderbuild.js";
|
import {useChartOrderStore} from "@/orderbuild.js";
|
||||||
import {invokeCallbacks, prototype} from "@/common.js";
|
import {invokeCallbacks, prototype} from "@/common.js";
|
||||||
import {DataFeed, defaultSymbol, feelessTickerKey, getAllSymbols, lookupSymbol} from "@/charts/datafeed.js";
|
import {DataFeed, defaultSymbol, feelessTickerKey, getAllSymbols, lookupSymbol} from "@/charts/datafeed.js";
|
||||||
import {intervalToSeconds, SingletonCoroutine, toHuman, toPrecision} from "@/misc.js";
|
import {intervalToSeconds, secondsToInterval, SingletonCoroutine, toHuman, toPrecision} from "@/misc.js";
|
||||||
import {usePrefStore, useStore} from "@/store/store.js";
|
import {usePrefStore, useStore} from "@/store/store.js";
|
||||||
import {tvCustomThemes} from "../../theme.js";
|
import {tvCustomThemes} from "../../theme.js";
|
||||||
|
|
||||||
export let widget = null
|
export let widget = null
|
||||||
export let chart = null
|
export let chart = null
|
||||||
export let crosshairPoint = null
|
export let crosshairPoint = null
|
||||||
|
export let defaultShapeHandler = null // if set, then TV events that dont have a registered shape handler get passed directly to this function
|
||||||
let symbolChangedCbs = [] // callbacks for TV's chart.onSymbolChanged()
|
let symbolChangedCbs = [] // callbacks for TV's chart.onSymbolChanged()
|
||||||
|
|
||||||
|
|
||||||
@@ -26,11 +27,11 @@ export function removeSymbolChangedCallback(cb) {
|
|||||||
function symbolChanged(symbol) {
|
function symbolChanged(symbol) {
|
||||||
const info = symbol===null ? (defaultSymbol===null?'default':defaultSymbol) : lookupSymbol(symbol.ticker)
|
const info = symbol===null ? (defaultSymbol===null?'default':defaultSymbol) : lookupSymbol(symbol.ticker)
|
||||||
co.selectedSymbol = info
|
co.selectedSymbol = info
|
||||||
console.log('setting prefs ticker', info.ticker)
|
// console.log('setting prefs ticker', info.ticker)
|
||||||
prefs.selectedTicker = info.ticker
|
prefs.selectedTicker = info.ticker
|
||||||
symbolChangedCbs.forEach((cb) => cb(info))
|
symbolChangedCbs.forEach((cb) => cb(info))
|
||||||
updateFeeDropdown()
|
updateFeeDropdown()
|
||||||
console.log('symbol changed', info)
|
// console.log('symbol changed', info)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -57,15 +58,23 @@ export async function setSymbolTicker(ticker) {
|
|||||||
|
|
||||||
|
|
||||||
function changeInterval(interval) {
|
function changeInterval(interval) {
|
||||||
co.intervalSecs = intervalToSeconds(interval)
|
const secs = intervalToSeconds(interval)
|
||||||
|
co.intervalSecs = secs
|
||||||
prefs.selectedTimeframe = interval
|
prefs.selectedTimeframe = interval
|
||||||
DataFeed.intervalChanged(co.intervalSecs)
|
DataFeed.intervalChanged(secs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function changeIntervalSecs(secs) {
|
||||||
|
const interval = secondsToInterval(secs);
|
||||||
|
co.intervalSecs = secs
|
||||||
|
prefs.selectedTimeframe = interval
|
||||||
|
DataFeed.intervalChanged(secs)
|
||||||
|
}
|
||||||
|
|
||||||
function dataLoaded() {
|
function dataLoaded() {
|
||||||
const range = chartMeanRange()
|
const range = chartMeanRange()
|
||||||
console.log('new mean range', range,)
|
// console.log('new mean range', range,)
|
||||||
co.meanRange = range
|
co.meanRange = range
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,6 +158,7 @@ export function initTVButtons() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function initWidget(el) {
|
export function initWidget(el) {
|
||||||
|
getAllSymbols()
|
||||||
const symbol = prefs.selectedTicker === null ? 'default' : prefs.selectedTicker
|
const symbol = prefs.selectedTicker === null ? 'default' : prefs.selectedTicker
|
||||||
const interval = prefs.selectedTimeframe === null ? '15' : prefs.selectedTimeframe
|
const interval = prefs.selectedTimeframe === null ? '15' : prefs.selectedTimeframe
|
||||||
widget = window.tvWidget = new TradingView.widget({
|
widget = window.tvWidget = new TradingView.widget({
|
||||||
@@ -163,8 +173,8 @@ export function initWidget(el) {
|
|||||||
container: el,
|
container: el,
|
||||||
datafeed: DataFeed, // use this for ohlc
|
datafeed: DataFeed, // use this for ohlc
|
||||||
locale: "en",
|
locale: "en",
|
||||||
disabled_features: ['main_series_scale_menu',],
|
disabled_features: ['main_series_scale_menu','display_market_status',],
|
||||||
enabled_features: ['saveload_separate_drawings_storage',],
|
enabled_features: ['saveload_separate_drawings_storage','snapshot_trading_drawings','show_exchange_logos','show_symbol_logos',],
|
||||||
// drawings_access: {type: 'white', tools: [],}, // show no tools
|
// drawings_access: {type: 'white', tools: [],}, // show no tools
|
||||||
custom_themes: tvCustomThemes,
|
custom_themes: tvCustomThemes,
|
||||||
theme: useStore().theme,
|
theme: useStore().theme,
|
||||||
@@ -192,8 +202,18 @@ export function initWidget(el) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function onChartReady(f) {
|
||||||
|
if (co.chartReady)
|
||||||
|
f(widget, chart)
|
||||||
|
else
|
||||||
|
chartInitCbs.push(f)
|
||||||
|
}
|
||||||
|
|
||||||
|
let chartInitCbs = []
|
||||||
|
|
||||||
|
|
||||||
function initChart() {
|
function initChart() {
|
||||||
console.log('init chart')
|
// console.log('init chart')
|
||||||
chart = widget.activeChart()
|
chart = widget.activeChart()
|
||||||
const themeName = useStore().theme;
|
const themeName = useStore().theme;
|
||||||
widget.changeTheme(themeName).catch((e)=>console.warn(`Could not change theme to ${themeName}`, e))
|
widget.changeTheme(themeName).catch((e)=>console.warn(`Could not change theme to ${themeName}`, e))
|
||||||
@@ -216,7 +236,12 @@ function initChart() {
|
|||||||
}
|
}
|
||||||
changeInterval(widget.symbolInterval().interval)
|
changeInterval(widget.symbolInterval().interval)
|
||||||
co.chartReady = true
|
co.chartReady = true
|
||||||
console.log('chart ready')
|
setTimeout(()=>{
|
||||||
|
for (const cb of chartInitCbs)
|
||||||
|
cb(widget, chart)
|
||||||
|
chartInitCbs = []
|
||||||
|
}, 1)
|
||||||
|
// console.log('chart ready')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -261,13 +286,14 @@ let drawingCallbacks = null
|
|||||||
|
|
||||||
export function drawShape(shapeType, ...callbacks) {
|
export function drawShape(shapeType, ...callbacks) {
|
||||||
// puts the chart into a line-drawing mode for a new shape
|
// puts the chart into a line-drawing mode for a new shape
|
||||||
console.log('drawShape', callbacks, shapeType.name, shapeType.code)
|
// console.log('drawShape', callbacks, shapeType.name, shapeType.code)
|
||||||
if( drawingCallbacks )
|
if( drawingCallbacks )
|
||||||
invokeCallbacks(drawingCallbacks, 'onUndraw')
|
invokeCallbacks(drawingCallbacks, 'onUndraw')
|
||||||
drawingCallbacks = callbacks
|
drawingCallbacks = callbacks
|
||||||
drawingTool = null
|
drawingTool = null
|
||||||
previousDrawingTool = widget.selectedLineTool()
|
previousDrawingTool = widget.selectedLineTool()
|
||||||
co.drawing = true
|
co.drawing = true
|
||||||
|
co.drew = false
|
||||||
widget.selectLineTool(shapeType.code)
|
widget.selectLineTool(shapeType.code)
|
||||||
invokeCallbacks(callbacks, 'onDraw')
|
invokeCallbacks(callbacks, 'onDraw')
|
||||||
}
|
}
|
||||||
@@ -326,7 +352,7 @@ const shapeCallbacks = {}
|
|||||||
|
|
||||||
function onSelectedLineToolChanged() {
|
function onSelectedLineToolChanged() {
|
||||||
const tool = widget.selectedLineTool();
|
const tool = widget.selectedLineTool();
|
||||||
console.log('line tool changed', tool)
|
// console.log('line tool changed', tool)
|
||||||
if (drawingTool===null)
|
if (drawingTool===null)
|
||||||
drawingTool = tool
|
drawingTool = tool
|
||||||
else if (tool!==drawingTool && co.drawing)
|
else if (tool!==drawingTool && co.drawing)
|
||||||
@@ -462,9 +488,11 @@ function doHandleDrawingEvent(id, event) {
|
|||||||
const props = shape.getProperties()
|
const props = shape.getProperties()
|
||||||
if (id in shapeCallbacks)
|
if (id in shapeCallbacks)
|
||||||
invokeCallbacks(shapeCallbacks[id], 'onProps', id, shape, props)
|
invokeCallbacks(shapeCallbacks[id], 'onProps', id, shape, props)
|
||||||
else
|
else {
|
||||||
// otherwise it's an event on a shape we don't "own"
|
// otherwise it's an event on a shape we don't "own" that could be being drawn
|
||||||
|
co.drew = true
|
||||||
console.log('warning: ignoring setProperties on TV shape', id, props)
|
console.log('warning: ignoring setProperties on TV shape', id, props)
|
||||||
|
}
|
||||||
} else if (event === 'move') {
|
} else if (event === 'move') {
|
||||||
if (id in shapeCallbacks) {
|
if (id in shapeCallbacks) {
|
||||||
invokeCallbacks(shapeCallbacks[id], 'onMove', id, shape)
|
invokeCallbacks(shapeCallbacks[id], 'onMove', id, shape)
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import {provider} from "@/blockchain/provider.js";
|
||||||
import {convertTvResolution, loadOHLC} from './ohlc.js';
|
import {convertTvResolution, loadOHLC} from './ohlc.js';
|
||||||
import {metadata} from "@/version.js";
|
import {metadata} from "@/version.js";
|
||||||
import FlexSearch from "flexsearch";
|
import FlexSearch from "flexsearch";
|
||||||
@@ -5,10 +6,10 @@ import {useChartOrderStore} from "@/orderbuild.js";
|
|||||||
import {useStore} from "@/store/store.js";
|
import {useStore} from "@/store/store.js";
|
||||||
import {subOHLC, unsubOHLC} from "@/blockchain/ohlcs.js";
|
import {subOHLC, unsubOHLC} from "@/blockchain/ohlcs.js";
|
||||||
import {ohlcStart} from "@/charts/chart-misc.js";
|
import {ohlcStart} from "@/charts/chart-misc.js";
|
||||||
|
import {timestamp, withTimeout} from "@/common.js";
|
||||||
import {timestamp, USD_FIAT} from "@/common.js";
|
|
||||||
import {erc20Contract} from "@/blockchain/contract.js";
|
import {erc20Contract} from "@/blockchain/contract.js";
|
||||||
import {provider} from "@/blockchain/wallet.js";
|
import {track} from "@/track.js";
|
||||||
|
|
||||||
|
|
||||||
const DEBUG_LOGGING = false
|
const DEBUG_LOGGING = false
|
||||||
const log = DEBUG_LOGGING ? console.log : ()=>{}
|
const log = DEBUG_LOGGING ? console.log : ()=>{}
|
||||||
@@ -63,7 +64,7 @@ const configurationData = {
|
|||||||
value: 'UNIv3',
|
value: 'UNIv3',
|
||||||
name: 'Uniswap v3',
|
name: 'Uniswap v3',
|
||||||
desc: 'Uniswap v3',
|
desc: 'Uniswap v3',
|
||||||
logo: 'https://upload.wikimedia.org/wikipedia/commons/e/e7/Uniswap_Logo.svg',
|
logo: '/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
|
||||||
@@ -110,8 +111,10 @@ export function feelessTickerKey(ticker) {
|
|||||||
|
|
||||||
function addSymbol(chainId, p, base, quote, inverted) {
|
function addSymbol(chainId, p, base, quote, inverted) {
|
||||||
const symbol = base.s + '/' + quote.s
|
const symbol = base.s + '/' + quote.s
|
||||||
const fee = `${(p.f/10000).toFixed(2)}%`
|
// const fee = `${(p.f/10000).toFixed(2)}%`
|
||||||
const exchange = ['Uniswap v2', 'Uniswap v3'][p.e] + ' ' + fee
|
// const exchange = ['Uniswap v2', 'Uniswap v3'][p.e] + ' ' + fee
|
||||||
|
const exchange = ['Uniswap v2', 'Uniswap v3'][p.e]
|
||||||
|
const exchange_logo = '/uniswap-logo.svg'
|
||||||
const full_name = exchange + ':' + symbol // + '%' + formatFee(fee)
|
const full_name = exchange + ':' + symbol // + '%' + formatFee(fee)
|
||||||
const ticker = tickerKey(chainId, p.e, base.a, quote.a, p.f)
|
const ticker = tickerKey(chainId, p.e, base.a, quote.a, p.f)
|
||||||
// add the search index only if this is the natural, noninverted base/quote pair
|
// add the search index only if this is the natural, noninverted base/quote pair
|
||||||
@@ -122,7 +125,7 @@ function addSymbol(chainId, p, base, quote, inverted) {
|
|||||||
const symbolInfo = {
|
const symbolInfo = {
|
||||||
key: ticker, ticker,
|
key: ticker, ticker,
|
||||||
chainId, address: p.a, exchangeId: p.e,
|
chainId, address: p.a, exchangeId: p.e,
|
||||||
full_name, symbol, description, exchange, type, inverted, base, quote, decimals, x:p.x, fee:p.f,
|
full_name, symbol, description, exchange, exchange_logo, type, inverted, base, quote, decimals, x:p.x, fee:p.f,
|
||||||
};
|
};
|
||||||
_symbols[ticker] = symbolInfo
|
_symbols[ticker] = symbolInfo
|
||||||
const feelessKey = feelessTickerKey(ticker)
|
const feelessKey = feelessTickerKey(ticker)
|
||||||
@@ -332,6 +335,14 @@ class RealtimeSubscription {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async function getLiquidities(markToken, symbolItem) {
|
||||||
|
const token = await erc20Contract(markToken.a, provider)
|
||||||
|
const liquidities = await Promise.all(symbolItem.feeGroup.map(
|
||||||
|
async ([addr, fee]) => await token.balanceOf(addr)
|
||||||
|
))
|
||||||
|
return liquidities;
|
||||||
|
}
|
||||||
|
|
||||||
export const DataFeed = {
|
export const DataFeed = {
|
||||||
onReady(callback) {
|
onReady(callback) {
|
||||||
log('[onReady]: Method call');
|
log('[onReady]: Method call');
|
||||||
@@ -356,6 +367,8 @@ export const DataFeed = {
|
|||||||
result.push(_symbols[ticker])
|
result.push(_symbols[ticker])
|
||||||
seen[ticker] = true
|
seen[ticker] = true
|
||||||
}
|
}
|
||||||
|
if (userInput.length>=3)
|
||||||
|
track('search', {search_term: userInput})
|
||||||
onResultReadyCallback(result);
|
onResultReadyCallback(result);
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -376,11 +389,14 @@ export const DataFeed = {
|
|||||||
onResolveErrorCallback,
|
onResolveErrorCallback,
|
||||||
extension
|
extension
|
||||||
) {
|
) {
|
||||||
log('[resolveSymbol]: Method call', symbolName);
|
console.log('resolveSymbol', symbolName);
|
||||||
const symbols = getAllSymbols();
|
const symbols = getAllSymbols();
|
||||||
const symbolItem = symbolName === 'default' ? defaultSymbol : symbols[symbolName]
|
const symbolItem = symbolName === 'default' ? defaultSymbol : symbols[symbolName]
|
||||||
|
if (symbolName==='default') {
|
||||||
|
console.log('using default symbol', defaultSymbol)
|
||||||
|
}
|
||||||
if (!symbolItem) {
|
if (!symbolItem) {
|
||||||
log('[resolveSymbol]: Cannot resolve symbol', symbolName);
|
console.log('[resolveSymbol]: Cannot resolve symbol', symbolName);
|
||||||
onResolveErrorCallback('cannot resolve symbol');
|
onResolveErrorCallback('cannot resolve symbol');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -394,10 +410,11 @@ export const DataFeed = {
|
|||||||
const inv = invertedDefault(symbolItem.base.a, symbolItem.quote.a)
|
const inv = invertedDefault(symbolItem.base.a, symbolItem.quote.a)
|
||||||
const markToken = inv ? symbolItem.base : symbolItem.quote
|
const markToken = inv ? symbolItem.base : symbolItem.quote
|
||||||
const mark = useStore().markPrice(markToken.a)
|
const mark = useStore().markPrice(markToken.a)
|
||||||
const token = await erc20Contract(markToken.a, provider)
|
const liquidities = await withTimeout(
|
||||||
const liquidities = await Promise.all(symbolItem.feeGroup.map(
|
getLiquidities(markToken, symbolItem),
|
||||||
async ([addr, fee]) => await token.balanceOf(addr)
|
3000,
|
||||||
))
|
'liquidity fetch timeout'
|
||||||
|
)
|
||||||
symbolItem.liquidities = liquidities.map(l => Number(l / 10n ** BigInt(markToken.d)))
|
symbolItem.liquidities = liquidities.map(l => Number(l / 10n ** BigInt(markToken.d)))
|
||||||
if (mark) {
|
if (mark) {
|
||||||
symbolItem.liquidities = symbolItem.liquidities.map(l => l * mark)
|
symbolItem.liquidities = symbolItem.liquidities.map(l => l * mark)
|
||||||
@@ -446,7 +463,7 @@ export const DataFeed = {
|
|||||||
// volume_precision: 2,
|
// volume_precision: 2,
|
||||||
data_status: 'streaming',
|
data_status: 'streaming',
|
||||||
};
|
};
|
||||||
log('[resolveSymbol]: Symbol resolved', symbolName);
|
// console.log('[resolveSymbol]: Symbol resolved', symbolName);
|
||||||
onSymbolResolvedCallback(symbolInfo)
|
onSymbolResolvedCallback(symbolInfo)
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ function addDay(timestamp) {
|
|||||||
function addMonth(timestamp) {
|
function addMonth(timestamp) {
|
||||||
const date = new Date(timestamp*1000)
|
const date = new Date(timestamp*1000)
|
||||||
const result = Date.UTC(date.getUTCFullYear(), date.getUTCMonth() + 1, date.getUTCDate()) / 1000
|
const result = Date.UTC(date.getUTCFullYear(), date.getUTCMonth() + 1, date.getUTCDate()) / 1000
|
||||||
console.log('addMonth', timestamp, result, new Date(timestamp*1000), new Date(result*1000))
|
// console.log('addMonth', timestamp, result, new Date(timestamp*1000), new Date(result*1000))
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,7 +137,7 @@ async function getUrl(url) {
|
|||||||
|
|
||||||
|
|
||||||
export async function loadOHLC (symbol, contract, from, to, tvRes) {
|
export async function loadOHLC (symbol, contract, from, to, tvRes) {
|
||||||
console.log('loadOHLC', tvRes, new Date(1000*from), new Date(1000*to), symbol, contract);
|
// console.log('loadOHLC', tvRes, new Date(1000*from), new Date(1000*to), symbol, contract);
|
||||||
let chainId
|
let chainId
|
||||||
let bars = [];
|
let bars = [];
|
||||||
let inverted = false;
|
let inverted = false;
|
||||||
@@ -179,7 +179,7 @@ export async function loadOHLC (symbol, contract, from, to, tvRes) {
|
|||||||
if (response.length) {
|
if (response.length) {
|
||||||
const [start,end,price] = response.split(',')
|
const [start,end,price] = response.split(',')
|
||||||
seriesStarts[baseUrl] = parseInt(start)
|
seriesStarts[baseUrl] = parseInt(start)
|
||||||
console.log(`Series ${baseUrl} starts at ${new Date(start*1000)}`)
|
// console.log(`Series ${baseUrl} starts at ${new Date(start*1000)}`)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
console.error(`Bad response while fetching ${baseUrl+'quote.csv'}`)
|
console.error(`Bad response while fetching ${baseUrl+'quote.csv'}`)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import {DISTANT_FUTURE, DISTANT_PAST, MAX_FRACTION} from "@/blockchain/orderlib.js";
|
import {DISTANT_FUTURE, DISTANT_PAST, MAX_FRACTION} from "@/blockchain/orderlib.js";
|
||||||
import {allocationText, DLine, HLine} from "@/charts/shape.js";
|
import {allocationText, DLine, HLine} from "@/charts/shape.js";
|
||||||
import {createShape, deleteShapeId} from "@/charts/chart.js";
|
import {createShape, deleteShapeId, widget} from "@/charts/chart.js";
|
||||||
import {sideColor} from "@/misc.js";
|
import {sideColor} from "@/misc.js";
|
||||||
import {useChartOrderStore} from "@/orderbuild.js";
|
import {useChartOrderStore} from "@/orderbuild.js";
|
||||||
import {timestamp} from "@/common.js";
|
import {timestamp} from "@/common.js";
|
||||||
@@ -88,8 +88,10 @@ class TrancheShapes {
|
|||||||
// console.log('price', price)
|
// console.log('price', price)
|
||||||
const channel = buy?'low':'high';
|
const channel = buy?'low':'high';
|
||||||
const text = allocationText(buy, weight, amount, amountSymbol, amountIsBase ? null : this.symbol.base.s, 1, '\n')
|
const text = allocationText(buy, weight, amount, amountSymbol, amountIsBase ? null : this.symbol.base.s, 1, '\n')
|
||||||
const s = createShape(buy?'arrow_up':'arrow_down', {time, price}, {channel,text,lock:true})
|
const color = sideColor(buy);
|
||||||
// console.log('created fill shape at', time, price)
|
const options = {channel,text,lock:true,overrides:{color: color, arrowColor: color}};
|
||||||
|
const s = createShape(buy?'arrow_up':'arrow_down', {time, price}, options)
|
||||||
|
console.log('created fill shape at', time, price, widget.activeChart().getShapeById(s).getProperties())
|
||||||
this.fills.push(s)
|
this.fills.push(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -173,7 +173,7 @@ export class Shape {
|
|||||||
// text label
|
// text label
|
||||||
let text = allocationText(this.model.buy, this.model.allocation, this.model.amount, this.model.baseSymbol, this.model.amountSymbol)
|
let text = allocationText(this.model.buy, this.model.allocation, this.model.amount, this.model.baseSymbol, this.model.amountSymbol)
|
||||||
if (this.model.breakout)
|
if (this.model.breakout)
|
||||||
text += ' ' + (this.model.textLocation==='above' ? '▲Breakout▲' : '▼Breakout▼')
|
text += ' ' + (this.model.textLocation==='above' ? '▲Breakout▲' : '▼Breakdown▼')
|
||||||
if (this.model.extraText)
|
if (this.model.extraText)
|
||||||
text += ' '+this.model.extraText
|
text += ' '+this.model.extraText
|
||||||
if (this.debug) text = `${this.id} ` + text
|
if (this.debug) text = `${this.id} ` + text
|
||||||
|
|||||||
@@ -154,3 +154,37 @@ export function timestamp(date = null) {
|
|||||||
export function dateString(datetime) {
|
export function dateString(datetime) {
|
||||||
return datetime.toLocaleString({dateStyle: 'medium', timeStyle: 'short'})
|
return datetime.toLocaleString({dateStyle: 'medium', timeStyle: 'short'})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function withTimeout(promise, timeoutDuration, fallbackErrorMessage) {
|
||||||
|
return Promise.race([
|
||||||
|
promise,
|
||||||
|
new Promise((_, reject) =>
|
||||||
|
setTimeout(() => reject(new Error(fallbackErrorMessage)), timeoutDuration)
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
|
<v-alert class="d-sm-none" type="info" title="Mobile Screen" text="Dexorder is designed for desktop. Mobile coming soon!" rounded="0"/>
|
||||||
<v-alert v-if='!s.connected' icon="mdi-wifi-off" type="error" title="Not Connected" class="mb-3" rounded="0" density="compact"/>
|
<v-alert v-if='!s.connected' icon="mdi-wifi-off" type="error" title="Not Connected" class="mb-3" rounded="0" density="compact"/>
|
||||||
<v-alert v-for="e in s.errors" icon="mdi-alert" type="error" :title="e.title" :text="e.text" class="mb-3" :closable="e.closeable" rounded="0"/>
|
<v-alert v-for="e in s.errors" icon="mdi-alert" type="error" :title="e.title" :text="e.text" class="mb-3" :closable="e.closeable" rounded="0"/>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -8,8 +8,8 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import {useStore} from "@/store/store";
|
import {useStore} from "@/store/store";
|
||||||
import {socket} from "@/socket.js";
|
|
||||||
import {useRoute} from "vue-router";
|
import {useRoute} from "vue-router";
|
||||||
|
import {socket} from "@/socket.js";
|
||||||
|
|
||||||
const s = useStore()
|
const s = useStore()
|
||||||
|
|
||||||
|
|||||||
65
src/components/DebugConsole.vue
Normal file
65
src/components/DebugConsole.vue
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
<template>
|
||||||
|
<div class="debug-console">
|
||||||
|
<div v-for="(entry, idx) in logs" :key="idx" :class="['log-entry', entry.type]">
|
||||||
|
[{{ entry.type }}] {{ entry.message }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, onMounted, onBeforeUnmount } from 'vue';
|
||||||
|
|
||||||
|
const logs = ref([]);
|
||||||
|
|
||||||
|
function stringify(args) {
|
||||||
|
return args.map(arg => {
|
||||||
|
if (typeof arg === 'object') {
|
||||||
|
try { return JSON.stringify(arg); } catch { return String(arg); }
|
||||||
|
}
|
||||||
|
return String(arg);
|
||||||
|
}).join(' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
let original = {};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
['log', 'warn', 'error', 'info'].forEach(type => {
|
||||||
|
// Save the original method
|
||||||
|
original[type] = console[type];
|
||||||
|
console[type] = function(...args) {
|
||||||
|
logs.value.push({
|
||||||
|
type,
|
||||||
|
message: stringify(args)
|
||||||
|
});
|
||||||
|
// Optionally limit log length:
|
||||||
|
if (logs.value.length > 200) logs.value.shift();
|
||||||
|
original[type].apply(console, args);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
// Restore the original methods
|
||||||
|
Object.keys(original).forEach(type => {
|
||||||
|
if (original[type]) console[type] = original[type];
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.debug-console {
|
||||||
|
background: #1a1a1a;
|
||||||
|
color: #0f0;
|
||||||
|
font-family: monospace;
|
||||||
|
font-size: 14px;
|
||||||
|
padding: 10px;
|
||||||
|
max-height: 260px;
|
||||||
|
overflow-y: auto;
|
||||||
|
border-radius: 5px;
|
||||||
|
margin: 8px 0;
|
||||||
|
}
|
||||||
|
.log-entry { margin-bottom: 2px; }
|
||||||
|
.log-entry.warn { color: #ff0; }
|
||||||
|
.log-entry.error { color: #f55; }
|
||||||
|
.log-entry.info { color: #0cf; }
|
||||||
|
</style>
|
||||||
@@ -36,8 +36,8 @@
|
|||||||
import {useStore} from "@/store/store";
|
import {useStore} from "@/store/store";
|
||||||
import {computed, ref} from "vue";
|
import {computed, ref} from "vue";
|
||||||
import Btn from "@/components/Btn.vue";
|
import Btn from "@/components/Btn.vue";
|
||||||
import {socket} from "@/socket.js";
|
|
||||||
import {metadata} from "@/version.js";
|
import {metadata} from "@/version.js";
|
||||||
|
import {socket} from "@/socket.js";
|
||||||
|
|
||||||
const DISABLED_DURATION = 60_000;
|
const DISABLED_DURATION = 60_000;
|
||||||
|
|
||||||
|
|||||||
142
src/components/FloatingDiv.vue
Normal file
142
src/components/FloatingDiv.vue
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
<template>
|
||||||
|
<div
|
||||||
|
ref="floatingDiv"
|
||||||
|
:style="divStyle"
|
||||||
|
@mousedown="startDrag"
|
||||||
|
>
|
||||||
|
<slot></slot>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, reactive, onMounted, onBeforeUnmount } from 'vue';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
id: {
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const floatingDiv = ref(null);
|
||||||
|
const position = reactive({ x: 0, y: 0 });
|
||||||
|
const isDragging = ref(false);
|
||||||
|
const isFloating = ref(false);
|
||||||
|
const dragStartOffset = reactive({ x: 0, y: 0 });
|
||||||
|
|
||||||
|
const divStyle = reactive({
|
||||||
|
position: "",
|
||||||
|
top: "",
|
||||||
|
left: "",
|
||||||
|
zIndex: "",
|
||||||
|
cursor: "default",
|
||||||
|
});
|
||||||
|
|
||||||
|
let activeComponent = null;
|
||||||
|
|
||||||
|
function positionKey() {
|
||||||
|
return props.id ? `floating-div-pos:${props.id}` : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function savePosition() {
|
||||||
|
if (props.id) {
|
||||||
|
localStorage.setItem(
|
||||||
|
positionKey(),
|
||||||
|
JSON.stringify({ x: position.x, y: position.y })
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadPosition() {
|
||||||
|
if (props.id) {
|
||||||
|
const data = localStorage.getItem(positionKey());
|
||||||
|
if (data) {
|
||||||
|
try {
|
||||||
|
const { x, y } = JSON.parse(data);
|
||||||
|
position.x = x;
|
||||||
|
position.y = y;
|
||||||
|
divStyle.position = "fixed";
|
||||||
|
divStyle.top = `${position.y}px`;
|
||||||
|
divStyle.left = `${position.x}px`;
|
||||||
|
divStyle.zIndex = 9999;
|
||||||
|
isFloating.value = true;
|
||||||
|
} catch {
|
||||||
|
// Ignore corrupted data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const startDrag = (event) => {
|
||||||
|
if (event.shiftKey || event.ctrlKey) {
|
||||||
|
if (!isFloating.value) {
|
||||||
|
const rect = floatingDiv.value.getBoundingClientRect();
|
||||||
|
position.x = rect.left;
|
||||||
|
position.y = rect.top;
|
||||||
|
divStyle.position = "fixed";
|
||||||
|
divStyle.top = `${position.y}px`;
|
||||||
|
divStyle.left = `${position.x}px`;
|
||||||
|
divStyle.zIndex = 9999;
|
||||||
|
isFloating.value = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
isDragging.value = true;
|
||||||
|
dragStartOffset.x = event.clientX - position.x;
|
||||||
|
dragStartOffset.y = event.clientY - position.y;
|
||||||
|
divStyle.cursor = "move";
|
||||||
|
document.body.style.userSelect = "none";
|
||||||
|
|
||||||
|
activeComponent = floatingDiv;
|
||||||
|
|
||||||
|
window.addEventListener("mousemove", handleDrag);
|
||||||
|
window.addEventListener("mouseup", stopDrag);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDrag = (event) => {
|
||||||
|
if (isDragging.value && activeComponent === floatingDiv) {
|
||||||
|
position.x = event.clientX - dragStartOffset.x;
|
||||||
|
position.y = event.clientY - dragStartOffset.y;
|
||||||
|
divStyle.top = `${position.y}px`;
|
||||||
|
divStyle.left = `${position.x}px`;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const stopDrag = () => {
|
||||||
|
if (isDragging.value && activeComponent === floatingDiv) {
|
||||||
|
isDragging.value = false;
|
||||||
|
divStyle.cursor = "default";
|
||||||
|
document.body.style.userSelect = "auto";
|
||||||
|
activeComponent = null;
|
||||||
|
|
||||||
|
savePosition();
|
||||||
|
|
||||||
|
window.removeEventListener("mousemove", handleDrag);
|
||||||
|
window.removeEventListener("mouseup", stopDrag);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleOutsideDrag = (event) => {
|
||||||
|
if (event.key === "Shift" || event.key === "Control") {
|
||||||
|
stopDrag();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
document.addEventListener("keyup", handleOutsideDrag);
|
||||||
|
loadPosition();
|
||||||
|
});
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
document.removeEventListener("keyup", handleOutsideDrag);
|
||||||
|
window.removeEventListener("mousemove", handleDrag);
|
||||||
|
window.removeEventListener("mouseup", stopDrag);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
div[ref="floatingDiv"] {
|
||||||
|
background: rgba(255, 255, 255, 0.8);
|
||||||
|
box-shadow: 0 4px 8px rgba(0,0,0,0.2);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import {useStore} from "@/store/store";
|
import {useStore} from "@/store/store";
|
||||||
import router from "@/router/index.js";
|
import {router} from "@/router/router.js";
|
||||||
const s = useStore()
|
const s = useStore()
|
||||||
|
|
||||||
function nav(path) {
|
function nav(path) {
|
||||||
|
|||||||
@@ -68,7 +68,6 @@ function reload() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function connect() {
|
async function connect() {
|
||||||
track('connect_wallet')
|
|
||||||
disabled.value = true
|
disabled.value = true
|
||||||
try {
|
try {
|
||||||
await addNetworkAndConnectWallet(s.chainId);
|
await addNetworkAndConnectWallet(s.chainId);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<v-tooltip v-model="show" :close-on-content-click="true"/>
|
<v-tooltip v-model="show" :close-on-content-click="true" :close-on-back="false" :close-delay="null"/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
@@ -8,25 +8,30 @@ import {usePrefStore} from "@/store/store.js";
|
|||||||
|
|
||||||
const prefs = usePrefStore()
|
const prefs = usePrefStore()
|
||||||
|
|
||||||
const modelValue = defineModel()
|
|
||||||
const hasBeenShown = ref(false)
|
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
key: {type: String, required: true},
|
name: {type: String, required: true},
|
||||||
after: {type: String, default: null},
|
when: {type: Boolean, default: true}, // optional conditional for when to show
|
||||||
|
after: {type: String, default: null}, // set to the name of another hint that must happen before this hint, to chain hints into a tutorial.
|
||||||
|
onComplete: {type: Function, default: null},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const forceClose = ref(false)
|
||||||
|
const shown = ref(false)
|
||||||
|
|
||||||
const show = computed({
|
const show = computed({
|
||||||
get() {
|
get() {
|
||||||
const result = !prefs.hints[props.key] && modelValue.value && (props.after === null || prefs.hints[props.after])
|
const shownBefore = prefs.hints[props.name];
|
||||||
&& !props.finished
|
const whenOk = props.when;
|
||||||
if (result)
|
const afterOk = props.after === null || prefs.hints[props.after];
|
||||||
hasBeenShown.value = true
|
const result = !forceClose.value && !shownBefore && whenOk && afterOk
|
||||||
else if (hasBeenShown.value)
|
// console.log(`show ${props.name}? ${result} <=`, !forceClose.value, whenOk, afterOk, prefs.hints)
|
||||||
prefs.hints[props.key] = true
|
if (result) {
|
||||||
|
shown.value = true
|
||||||
|
prefs.hints[props.name] = true
|
||||||
|
}
|
||||||
return result
|
return result
|
||||||
},
|
},
|
||||||
set(v) { if(!v) prefs.hints[props.key] = true}
|
set(v) { if(!v) { forceClose.value=true; if (shown.value && props.onComplete) props.onComplete(); } }
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</v-card-item>
|
</v-card-item>
|
||||||
<v-card-actions class="d-flex justify-space-evenly mb-4">
|
<v-card-actions class="d-flex justify-space-evenly mb-4">
|
||||||
<v-btn variant="outlined" color="red" @click="nav('Assets')">Cancel</v-btn>
|
<v-btn variant="outlined" color="red" @click="// noinspection JSIgnoredPromiseFromCall
|
||||||
|
router.push({name: 'Assets'})">Cancel</v-btn>
|
||||||
<v-btn variant="flat" color="green" :disabled="!valid()" @click="placeOrder">Place Dexorder</v-btn>
|
<v-btn variant="flat" color="green" :disabled="!valid()" @click="placeOrder">Place Dexorder</v-btn>
|
||||||
</v-card-actions>
|
</v-card-actions>
|
||||||
</phone-card>
|
</phone-card>
|
||||||
@@ -23,12 +24,13 @@ import {useOrderStore, useStore} from "@/store/store";
|
|||||||
import PhoneCard from "@/components/PhoneCard.vue";
|
import PhoneCard from "@/components/PhoneCard.vue";
|
||||||
import Amount from "@/components/Amount.vue"
|
import Amount from "@/components/Amount.vue"
|
||||||
// noinspection ES6UnusedImports
|
// noinspection ES6UnusedImports
|
||||||
import {nav, SingletonCoroutine, vAutoSelect} from "@/misc.js";
|
import {SingletonCoroutine, vAutoSelect} from "@/misc.js";
|
||||||
import {newOrder} from "@/blockchain/orderlib.js";
|
import {newOrder} from "@/blockchain/orderlib.js";
|
||||||
import {FixedNumber} from "ethers";
|
import {FixedNumber} from "ethers";
|
||||||
import PairChoice from "@/components/PairChoice.vue";
|
import PairChoice from "@/components/PairChoice.vue";
|
||||||
import NeedsSigner from "@/components/NeedsSigner.vue";
|
import NeedsSigner from "@/components/NeedsSigner.vue";
|
||||||
import {useChartOrderStore} from "@/orderbuild.js";
|
import {useChartOrderStore} from "@/orderbuild.js";
|
||||||
|
import {router} from "@/router/router.js";
|
||||||
|
|
||||||
const s = useStore()
|
const s = useStore()
|
||||||
const os = useOrderStore()
|
const os = useOrderStore()
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<v-data-table :headers="datatableHeaders" :items="orders" item-value="id"
|
<v-data-table :headers="datatableHeaders" :items="orders" item-value="id"
|
||||||
:show-select="true" :show-expand="true" v-model="selected" select-strategy="single">
|
:show-select="false" :show-expand="true" v-model="selected" select-strategy="single"
|
||||||
|
:row-props="rowPropsHandler" :hover="true"
|
||||||
|
>
|
||||||
<template v-slot:item.startTime="{ value }">{{ timestampString(value) }}</template>
|
<template v-slot:item.startTime="{ value }">{{ timestampString(value) }}</template>
|
||||||
<template v-slot:item.input="{ item }">
|
<template v-slot:item.input="{ item }">
|
||||||
<span v-if="item.order.amountIsInput">
|
<span v-if="item.order.amountIsInput">
|
||||||
@@ -163,7 +165,7 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import LinePrice from "@/components/LinePrice.vue";
|
import LinePrice from "@/components/LinePrice.vue";
|
||||||
import {useStore} from "@/store/store";
|
import {useStore} from "@/store/store";
|
||||||
import {computed, defineAsyncComponent, onUnmounted, ref, watch} from "vue";
|
import {computed, defineAsyncComponent, onMounted, onUnmounted, ref, watch} from "vue";
|
||||||
import Btn from "@/components/Btn.vue"
|
import Btn from "@/components/Btn.vue"
|
||||||
import {cancelOrder, useWalletStore} from "@/blockchain/wallet.js";
|
import {cancelOrder, useWalletStore} from "@/blockchain/wallet.js";
|
||||||
import {DISTANT_FUTURE, isOpen, MAX_FRACTION, OrderState} from "@/blockchain/orderlib.js";
|
import {DISTANT_FUTURE, isOpen, MAX_FRACTION, OrderState} from "@/blockchain/orderlib.js";
|
||||||
@@ -171,7 +173,7 @@ import Pulse from "@/components/Pulse.vue";
|
|||||||
import {OrderShapes} from "@/charts/ordershapes.js";
|
import {OrderShapes} from "@/charts/ordershapes.js";
|
||||||
import {useChartOrderStore} from "@/orderbuild.js";
|
import {useChartOrderStore} from "@/orderbuild.js";
|
||||||
import {lookupSymbol, tickerForOrder} from "@/charts/datafeed.js";
|
import {lookupSymbol, tickerForOrder} from "@/charts/datafeed.js";
|
||||||
import {setSymbol} from "@/charts/chart.js";
|
import {addSymbolChangedCallback, removeSymbolChangedCallback, setSymbol} from "@/charts/chart.js";
|
||||||
import {uniswapV3AveragePrice} from "@/blockchain/uniswap.js";
|
import {uniswapV3AveragePrice} from "@/blockchain/uniswap.js";
|
||||||
import {timestampString} from "@/misc.js";
|
import {timestampString} from "@/misc.js";
|
||||||
import {metadataMap} from "@/version.js";
|
import {metadataMap} from "@/version.js";
|
||||||
@@ -238,6 +240,16 @@ const datatableHeaders = [
|
|||||||
// {title: '', align: 'end', key: 'action'},
|
// {title: '', align: 'end', key: 'action'},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const rowPropsHandler = ({ item }) => ({
|
||||||
|
class: selected.value.indexOf(item.id) !== -1 ? 'selected-row' : '',
|
||||||
|
onClick: () => {
|
||||||
|
if (selected.value.indexOf(item.id) === -1)
|
||||||
|
selected.value = [item.id]
|
||||||
|
else
|
||||||
|
selected.value = []
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
const orders = computed(()=>{
|
const orders = computed(()=>{
|
||||||
// example twap
|
// example twap
|
||||||
// status = [
|
// status = [
|
||||||
@@ -389,12 +401,16 @@ function describeTrancheTime(st, trancheIndex, isStart) {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function symbolChanged() {
|
||||||
|
selected.value = []
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(()=>addSymbolChangedCallback(symbolChanged))
|
||||||
|
onUnmounted(()=>removeSymbolChangedCallback(symbolChanged))
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
@use "src/styles/vars" as *;
|
|
||||||
|
|
||||||
// columns
|
// columns
|
||||||
.num {
|
.num {
|
||||||
min-width: 1em;
|
min-width: 1em;
|
||||||
@@ -417,5 +433,12 @@ function describeTrancheTime(st, trancheIndex, isStart) {
|
|||||||
}
|
}
|
||||||
.cancel {
|
.cancel {
|
||||||
}
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
@use "src/styles/settings" as *;
|
||||||
|
|
||||||
|
tr.selected-row {
|
||||||
|
background-color: #616161;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -3,6 +3,6 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
if(window.location.hostname !== 'localhost') {
|
if(window.location.hostname !== 'localhost') {
|
||||||
window.$crisp = [];window.CRISP_WEBSITE_ID = "b153f30a-4b0b-49cc-8a38-989409a73acb";(function () {const d = document;const s = d.createElement("script");s.src = "https://client.crisp.chat/l.js";s.async = 1;d.getElementsByTagName("head")[0].appendChild(s);})();
|
window.$crisp=[];window.CRISP_WEBSITE_ID="a88f707f-adee-4960-b6de-c328c9d86945";(function(){const d=document;const s=d.createElement("script");s.src="https://client.crisp.chat/l.js";s.async=1;d.getElementsByTagName("head")[0].appendChild(s);})();
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@@ -22,8 +22,8 @@
|
|||||||
import {usePrefStore} from "@/store/store.js";
|
import {usePrefStore} from "@/store/store.js";
|
||||||
import {computed, ref, watch} from "vue";
|
import {computed, ref, watch} from "vue";
|
||||||
|
|
||||||
import {socket} from "@/socket.js";
|
|
||||||
import TosCard from "@/components/TosCard.vue";
|
import TosCard from "@/components/TosCard.vue";
|
||||||
|
import {socket} from "@/socket.js";
|
||||||
|
|
||||||
// UPDATE THIS WHEN CHANGING THE TOS
|
// UPDATE THIS WHEN CHANGING THE TOS
|
||||||
const CURRENT_VERSION='2024-11-18' // this must be a parseable date
|
const CURRENT_VERSION='2024-11-18' // this must be a parseable date
|
||||||
|
|||||||
@@ -5,10 +5,10 @@
|
|||||||
<v-card-text class="text-center">Last Updated November 18, 2024</v-card-text>
|
<v-card-text class="text-center">Last Updated November 18, 2024</v-card-text>
|
||||||
|
|
||||||
<v-card-text>
|
<v-card-text>
|
||||||
Please read these Terms of Service (the “<b>Terms</b>”) and our <a href="https://dexorder.trade/privacy-policy" target="dexorder">Privacy Policy</a> carefully because they govern your
|
Please read these Terms of Service (the “<b>Terms</b>”) and our <a href="https://dexorder.com/privacy-policy" target="dexorder">Privacy Policy</a> carefully because they govern your
|
||||||
use of the
|
use of the
|
||||||
website (and all subdomains and subpages thereon) located at dexorder.trade, including without limitation the
|
website (and all subdomains and subpages thereon) located at dexorder.com, including without limitation the
|
||||||
subdomains app.dexorder.trade and www.dexorder.trade (collectively, the “<b>Site</b>”), and the Dexorder web
|
subdomains app.dexorder.com and www.dexorder.com (collectively, the “<b>Site</b>”), and the Dexorder web
|
||||||
application graphical user interface and any other services accessible via the Site (together with the Site, web
|
application graphical user interface and any other services accessible via the Site (together with the Site, web
|
||||||
application, and other services, collectively, the “<b>Dexorder Service</b>”) offered by Dexorder Trading Services
|
application, and other services, collectively, the “<b>Dexorder Service</b>”) offered by Dexorder Trading Services
|
||||||
Ltd.
|
Ltd.
|
||||||
@@ -205,7 +205,7 @@
|
|||||||
(i) Subject to your compliance with these Terms, Dexorder will use its commercially
|
(i) Subject to your compliance with these Terms, Dexorder will use its commercially
|
||||||
reasonable efforts to provide you with access to the Dexorder Service and to cause your Interactions to be
|
reasonable efforts to provide you with access to the Dexorder Service and to cause your Interactions to be
|
||||||
executed on the applicable DEX in accordance with Dexorder’s Execution Policy located at
|
executed on the applicable DEX in accordance with Dexorder’s Execution Policy located at
|
||||||
<a href="https://dexorder.trade/execution-policy">https://dexorder.trade/execution-policy</a>
|
<a href="https://dexorder.com/execution-policy">https://dexorder.com/execution-policy</a>
|
||||||
(“<b>Execution Policy</b>”), however from time to time the Site and the Dexorder Service may be inaccessible or
|
(“<b>Execution Policy</b>”), however from time to time the Site and the Dexorder Service may be inaccessible or
|
||||||
inoperable for any
|
inoperable for any
|
||||||
reason, including, without limitation: (a) if an Interaction repeatedly fails to be executed (such as due to an
|
reason, including, without limitation: (a) if an Interaction repeatedly fails to be executed (such as due to an
|
||||||
@@ -690,7 +690,7 @@
|
|||||||
<v-card-title>18. Contact Information</v-card-title>
|
<v-card-title>18. Contact Information</v-card-title>
|
||||||
<v-card-text>
|
<v-card-text>
|
||||||
If you have any questions about these Terms or the Dexorder Service, please contact Dexorder
|
If you have any questions about these Terms or the Dexorder Service, please contact Dexorder
|
||||||
at <a href="mailto:legal@dexorder.trade">legal@dexorder.trade</a> or <a href="mailto:support@dexorder.trade">support@dexorder.trade</a>.
|
at <a href="mailto:legal@dexorder.com">legal@dexorder.com</a> or <a href="mailto:support@dexorder.com">support@dexorder.com</a>.
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -34,10 +34,10 @@
|
|||||||
<v-card-item v-if="!empty">
|
<v-card-item v-if="!empty">
|
||||||
<v-table>
|
<v-table>
|
||||||
<tbody>
|
<tbody>
|
||||||
<native-row v-if="nativeBalance" :chain-id="s.chainId" :addr="s.vault" :amount="nativeBalance"
|
<native-row v-if="nativeBalance && BigInt(nativeBalance)>0n" :chain-id="s.chainId" :addr="s.vault" :amount="nativeBalance"
|
||||||
:on-withdraw="onWithdrawNative" :on-wrap="()=>wrapShow=true"/>
|
:on-withdraw="onWithdrawNative" :on-wrap="()=>wrapShow=true"/>
|
||||||
<suspense v-for="(amount,addr) of balances">
|
<suspense v-for="(amount,addr) of balances">
|
||||||
<token-row v-if="BigInt(amount)!==0n" :chain-id="s.chainId" :addr="addr" :amount="amount" :onWithdraw="onWithdraw"/>
|
<token-row v-if="amount && BigInt(amount)>0n" :chain-id="s.chainId" :addr="addr" :amount="amount" :onWithdraw="onWithdraw"/>
|
||||||
</suspense>
|
</suspense>
|
||||||
</tbody>
|
</tbody>
|
||||||
</v-table>
|
</v-table>
|
||||||
@@ -60,12 +60,13 @@
|
|||||||
import {useStore} from "@/store/store.js";
|
import {useStore} from "@/store/store.js";
|
||||||
import {computed, defineAsyncComponent, onUnmounted, ref, watchEffect} from "vue";
|
import {computed, defineAsyncComponent, onUnmounted, ref, watchEffect} from "vue";
|
||||||
import {vaultAddress} from "@/blockchain/contract.js";
|
import {vaultAddress} from "@/blockchain/contract.js";
|
||||||
import {ensureVault, provider} from "@/blockchain/wallet.js";
|
import {ensureVault} from "@/blockchain/wallet.js";
|
||||||
import CopyButton from "@/components/CopyButton.vue";
|
import CopyButton from "@/components/CopyButton.vue";
|
||||||
import Withdraw from "@/components/Withdraw.vue";
|
import Withdraw from "@/components/Withdraw.vue";
|
||||||
import NativeRow from "@/components/NativeRow.vue";
|
import NativeRow from "@/components/NativeRow.vue";
|
||||||
import NativeWrap from "@/components/NativeWrap.vue";
|
import NativeWrap from "@/components/NativeWrap.vue";
|
||||||
import WithdrawNative from "@/components/WithdrawNative.vue";
|
import WithdrawNative from "@/components/WithdrawNative.vue";
|
||||||
|
import {provider} from "@/blockchain/provider.js";
|
||||||
|
|
||||||
const TokenRow = defineAsyncComponent(()=>import('./TokenRow.vue'))
|
const TokenRow = defineAsyncComponent(()=>import('./TokenRow.vue'))
|
||||||
const s = useStore()
|
const s = useStore()
|
||||||
@@ -89,7 +90,7 @@ const hasVault = computed(()=>s.vault!==null)
|
|||||||
const withdrawToken = ref(null)
|
const withdrawToken = ref(null)
|
||||||
const withdrawShow = ref(false)
|
const withdrawShow = ref(false)
|
||||||
async function onWithdraw(token) {
|
async function onWithdraw(token) {
|
||||||
console.log('withdraw', addr, token)
|
console.log('withdraw', addr.value, token)
|
||||||
withdrawToken.value = token
|
withdrawToken.value = token
|
||||||
withdrawShow.value = true
|
withdrawShow.value = true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
<v-list-item prepend-icon="mdi-chart-line"><b>Breakout Orders</b> <small>buy <i>above</i> a price level</small></v-list-item>
|
<v-list-item prepend-icon="mdi-chart-line"><b>Breakout Orders</b> <small>buy <i>above</i> a price level</small></v-list-item>
|
||||||
<v-list-item prepend-icon="mdi-plus-minus"><b>Stop-loss</b> <small>coming soon</small></v-list-item>
|
<v-list-item prepend-icon="mdi-plus-minus"><b>Stop-loss</b> <small>coming soon</small></v-list-item>
|
||||||
<!-- <v-list-item prepend-icon="mdi-cancel">One-click Cancel All</v-list-item>-->
|
<!-- <v-list-item prepend-icon="mdi-cancel">One-click Cancel All</v-list-item>-->
|
||||||
|
<!--
|
||||||
<v-list-item>
|
<v-list-item>
|
||||||
<template #prepend>
|
<template #prepend>
|
||||||
<v-avatar image="/arbitrum-logo.svg" size="1.5em" class="mr-4"/>
|
<v-avatar image="/arbitrum-logo.svg" size="1.5em" class="mr-4"/>
|
||||||
@@ -26,6 +27,7 @@
|
|||||||
<b>Arbitrum One</b> support <small>fast and cheap</small>
|
<b>Arbitrum One</b> support <small>fast and cheap</small>
|
||||||
</template>
|
</template>
|
||||||
</v-list-item>
|
</v-list-item>
|
||||||
|
-->
|
||||||
<v-list-item>
|
<v-list-item>
|
||||||
<template #prepend>
|
<template #prepend>
|
||||||
<v-avatar image="/uniswap-logo.svg" size="1.5em" class="mr-4" style="background-color: white"/>
|
<v-avatar image="/uniswap-logo.svg" size="1.5em" class="mr-4" style="background-color: white"/>
|
||||||
@@ -51,13 +53,13 @@ import Logo from "@/components/Logo.vue";
|
|||||||
const modelValue = defineModel()
|
const modelValue = defineModel()
|
||||||
|
|
||||||
function tryIt() {
|
function tryIt() {
|
||||||
track('try-it')
|
track('tutorial_begin')
|
||||||
modelValue.value = false
|
modelValue.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
function learnMore() {
|
function learnMore() {
|
||||||
track('learn-more')
|
track('learn-more')
|
||||||
window.open('https://dexorder.trade/introduction.html', 'dexordertrade')
|
window.open('https://dexorder.com/introduction.html', 'dexorderwww')
|
||||||
modelValue.value = false
|
modelValue.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
<v-btn variant="text" text="max" @click="floatAmount=balanceFloat"/>
|
<v-btn variant="text" text="max" @click="floatAmount=balanceFloat"/>
|
||||||
</template>
|
</template>
|
||||||
<template v-slot:append-inner>
|
<template v-slot:append-inner>
|
||||||
<span>{{ token.s }}</span>
|
<span style="max-width: 6em">{{ token.s }}</span>
|
||||||
</template>
|
</template>
|
||||||
</v-text-field>
|
</v-text-field>
|
||||||
<v-card-actions>
|
<v-card-actions>
|
||||||
@@ -36,11 +36,17 @@ const s = useStore()
|
|||||||
const props = defineProps(['modelValue', 'vault', 'token'])
|
const props = defineProps(['modelValue', 'vault', 'token'])
|
||||||
const emit = defineEmits(['update:modelValue'])
|
const emit = defineEmits(['update:modelValue'])
|
||||||
const balance = computed(() => {
|
const balance = computed(() => {
|
||||||
console.log('balance', props.vault, props.token, s.vaultBalances)
|
const b = s.getBalance(props.token?.a)
|
||||||
const b = s.vaultBalances[props.vault][props.token.address];
|
console.log('balance', b)
|
||||||
|
// const b = s.vaultBalances[props.vault][props.token.address];
|
||||||
return b === undefined ? 0n : BigInt(b)
|
return b === undefined ? 0n : BigInt(b)
|
||||||
})
|
})
|
||||||
const balanceFloat = computed(() => tokenFloat(props.token, balance.value))
|
const balanceFloat = computed(() => {
|
||||||
|
let balance = tokenFloat(props.token, s.getBalance(props.token?.a))
|
||||||
|
balance /= 10**props.token.d
|
||||||
|
console.log('balanceFloat', balance, s.getBalance(props.token?.a), props.token)
|
||||||
|
return balance
|
||||||
|
})
|
||||||
const floatAmount = ref(0)
|
const floatAmount = ref(0)
|
||||||
|
|
||||||
function withdraw() {
|
function withdraw() {
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div ref="element" class="chart"/>
|
<div id="tv-widget" ref="element" class="chart"/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
// import "/public/datafeeds/udf/dist/bundle.js"
|
|
||||||
import {onMounted, ref} from "vue";
|
import {onMounted, ref} from "vue";
|
||||||
import {initWidget} from "@/charts/chart.js";
|
import {initWidget} from "@/charts/chart.js";
|
||||||
|
|
||||||
@@ -12,18 +11,8 @@ const element = ref()
|
|||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
const el = element.value;
|
const el = element.value;
|
||||||
initWidget(el)
|
initWidget(el)
|
||||||
initShapes()
|
|
||||||
})
|
})
|
||||||
|
|
||||||
function initShapes() {
|
|
||||||
// const c = widget.chart()
|
|
||||||
// for( const s of ss.shapes ) {
|
|
||||||
// const type = s.type.toLowerCase().replace(' ','_')
|
|
||||||
// console.log('create type', type)
|
|
||||||
// c.createMultipointShape(s.points, {shape:type})
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
|||||||
@@ -11,28 +11,28 @@
|
|||||||
<v-tooltip text="Up to 1000 equal parts spread across time" location="top">
|
<v-tooltip text="Up to 1000 equal parts spread across time" location="top">
|
||||||
<template v-slot:activator="{ props }">
|
<template v-slot:activator="{ props }">
|
||||||
<span v-bind="props">
|
<span v-bind="props">
|
||||||
<v-btn :class="order.buy?'green':'red'" variant="text" prepend-icon="mdi-clock-outline" @click="build(order,'DCABuilder')">DCA</v-btn>
|
<v-btn id="DCA-button" :class="order.buy?'green':'red'" variant="text" prepend-icon="mdi-clock-outline" @click="build(order,'DCABuilder')">DCA</v-btn>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</v-tooltip>
|
</v-tooltip>
|
||||||
<v-tooltip text="Trade a price level" location="top">
|
<v-tooltip text="Trade a price level" location="top">
|
||||||
<template v-slot:activator="{ props }">
|
<template v-slot:activator="{ props }">
|
||||||
<span v-bind="props">
|
<span v-bind="props">
|
||||||
<v-btn :class="order.buy?'green':'red'" variant="text" prepend-icon="mdi-ray-vertex" @click="build(order,'LimitBuilder')">Limit</v-btn>
|
<v-btn id="LimitBuilder-button" :class="order.buy?'green':'red'" variant="text" prepend-icon="mdi-ray-vertex" @click="build(order,'LimitBuilder')">Limit</v-btn>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</v-tooltip>
|
</v-tooltip>
|
||||||
<v-tooltip text="Trade trends and channels" location="top">
|
<v-tooltip text="Trade trends and channels" location="top">
|
||||||
<template v-slot:activator="{ props }">
|
<template v-slot:activator="{ props }">
|
||||||
<span v-bind="props">
|
<span v-bind="props">
|
||||||
<v-btn :class="order.buy?'green':'red'" variant="text" prepend-icon="mdi-vector-line" @click="build(order,'DiagonalBuilder')">Diagonal</v-btn>
|
<v-btn id="Diagonal-button" :class="order.buy?'green':'red'" variant="text" prepend-icon="mdi-vector-line" @click="build(order,'DiagonalBuilder')">Diagonal</v-btn>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</v-tooltip>
|
</v-tooltip>
|
||||||
<v-tooltip text="Up to 10 weighted parts spaced out in time" location="top">
|
<v-tooltip text="Up to 10 weighted parts spaced out in time" location="top">
|
||||||
<template v-slot:activator="{ props }">
|
<template v-slot:activator="{ props }">
|
||||||
<span v-bind="props">
|
<span v-bind="props">
|
||||||
<v-btn :class="order.buy?'green':'red'" variant="text" prepend-icon="mdi-reorder-vertical" @click="build(order,'DateBuilder')">Dates</v-btn>
|
<v-btn id="Dates-button" :class="order.buy?'green':'red'" variant="text" prepend-icon="mdi-reorder-vertical" @click="build(order,'DateBuilder')">Dates</v-btn>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</v-tooltip>
|
</v-tooltip>
|
||||||
@@ -44,6 +44,12 @@
|
|||||||
</template>
|
</template>
|
||||||
</v-tooltip>
|
</v-tooltip>
|
||||||
<!-- mdi-ray-start-end mdi-vector-polyline -->
|
<!-- mdi-ray-start-end mdi-vector-polyline -->
|
||||||
|
|
||||||
|
<!-- after="newbie"-->
|
||||||
|
<one-time-hint name="choose-builder" :activator="hintData.activator"
|
||||||
|
:text="hintData.text" location="top"
|
||||||
|
:when="!builtAny"/>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -55,7 +61,7 @@
|
|||||||
import BuilderFactory from "@/components/chart/BuilderFactory.vue";
|
import BuilderFactory from "@/components/chart/BuilderFactory.vue";
|
||||||
import {builderFuncs, newBuilder, orderFuncs, useChartOrderStore} from "@/orderbuild.js";
|
import {builderFuncs, newBuilder, orderFuncs, useChartOrderStore} from "@/orderbuild.js";
|
||||||
import {useStore} from "@/store/store.js";
|
import {useStore} from "@/store/store.js";
|
||||||
import {computed, onUnmounted, onUpdated, watchEffect} from "vue";
|
import {computed, onUnmounted, onUpdated, ref, watchEffect} from "vue";
|
||||||
import {toPrecision} from "@/misc.js";
|
import {toPrecision} from "@/misc.js";
|
||||||
import {useTheme} from "vuetify";
|
import {useTheme} from "vuetify";
|
||||||
import RowBar from "@/components/chart/RowBar.vue";
|
import RowBar from "@/components/chart/RowBar.vue";
|
||||||
@@ -63,6 +69,7 @@ import Color from "color";
|
|||||||
import {newOrder} from "@/blockchain/orderlib.js";
|
import {newOrder} from "@/blockchain/orderlib.js";
|
||||||
import OrderAmount from "@/components/chart/OrderAmount.vue";
|
import OrderAmount from "@/components/chart/OrderAmount.vue";
|
||||||
import {track} from "@/track.js";
|
import {track} from "@/track.js";
|
||||||
|
import OneTimeHint from "@/components/OneTimeHint.vue";
|
||||||
|
|
||||||
const props = defineProps(['order'])
|
const props = defineProps(['order'])
|
||||||
const s = useStore()
|
const s = useStore()
|
||||||
@@ -70,14 +77,17 @@ const co = useChartOrderStore()
|
|||||||
|
|
||||||
const marketBuilder = newBuilder('MarketBuilder')
|
const marketBuilder = newBuilder('MarketBuilder')
|
||||||
|
|
||||||
|
console.log('chart order', props.order)
|
||||||
const builders = computed(()=>props.order.builders.length > 0 ? props.order.builders : [marketBuilder])
|
const builders = computed(()=>props.order.builders.length > 0 ? props.order.builders : [marketBuilder])
|
||||||
const tokenIn = computed(()=>props.order.buy ? co.quoteToken : co.baseToken)
|
const tokenIn = computed(()=>props.order.buy ? co.quoteToken : co.baseToken)
|
||||||
const tokenOut = computed(()=>props.order.buy ? co.baseToken : co.quoteToken)
|
const tokenOut = computed(()=>props.order.buy ? co.baseToken : co.quoteToken)
|
||||||
|
|
||||||
|
|
||||||
console.log('order', props.order)
|
const builtAny = ref(false)
|
||||||
|
|
||||||
function build(order, component, options={}) {
|
function build(order, component, options={}) {
|
||||||
track('build', {builder:component})
|
track('build', {builder:component})
|
||||||
|
builtAny.value = true
|
||||||
order.builders.push(newBuilder(component, options))
|
order.builders.push(newBuilder(component, options))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,6 +197,19 @@ const color = computed(()=>theme.value.colors["on-background"])
|
|||||||
// const lightColorStyle = computed(() => { return {'background-color': lightColor.value} })
|
// const lightColorStyle = computed(() => { return {'background-color': lightColor.value} })
|
||||||
// const faintColorStyle = computed(() => { return {'background-color': faintColor.value} })
|
// const faintColorStyle = computed(() => { return {'background-color': faintColor.value} })
|
||||||
|
|
||||||
|
// Tutorial Hint
|
||||||
|
|
||||||
|
let tutorial = 'limit'
|
||||||
|
|
||||||
|
const _hintData = {
|
||||||
|
'limit': {
|
||||||
|
activator: '#LimitBuilder-button',
|
||||||
|
text: '↓ Try a Limit Ladder ↓'
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const hintData = computed(()=>_hintData[tutorial] || _hintData['limit'])
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
|||||||
@@ -8,6 +8,12 @@
|
|||||||
</v-btn>
|
</v-btn>
|
||||||
<v-btn variant="text" prepend-icon="mdi-delete" v-if="co.orders.length>0"
|
<v-btn variant="text" prepend-icon="mdi-delete" v-if="co.orders.length>0"
|
||||||
:disabled="!orderChanged" @click="resetOrder">Reset</v-btn>
|
:disabled="!orderChanged" @click="resetOrder">Reset</v-btn>
|
||||||
|
<v-btn id="share-btn" variant="text" prepend-icon="mdi-share" v-if="co.orders.length>0"
|
||||||
|
:disabled="sharing"
|
||||||
|
@click="shareOrder">{{sharing?'Preparing...':'Share Order'}}</v-btn>
|
||||||
|
<v-tooltip activator="#share-btn" :text="shareError?'Error copying share link :(':'Copied share link!'" v-model="showSharedTooltip"
|
||||||
|
:open-on-hover="false" :open-on-click="false"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
<div class="overflow-y-auto">
|
<div class="overflow-y-auto">
|
||||||
<needs-chart>
|
<needs-chart>
|
||||||
@@ -66,6 +72,7 @@ import NeedsChart from "@/components/NeedsChart.vue";
|
|||||||
import {PlaceOrderTransaction} from "@/blockchain/transaction.js";
|
import {PlaceOrderTransaction} from "@/blockchain/transaction.js";
|
||||||
import {errorSuggestsMissingVault} from "@/misc.js";
|
import {errorSuggestsMissingVault} from "@/misc.js";
|
||||||
import {track} from "@/track.js";
|
import {track} from "@/track.js";
|
||||||
|
import {getShareUrl} from "@/share.js";
|
||||||
|
|
||||||
const s = useStore()
|
const s = useStore()
|
||||||
const co = useChartOrderStore()
|
const co = useChartOrderStore()
|
||||||
@@ -73,7 +80,7 @@ const os = useOrderStore()
|
|||||||
const ws = useWalletStore()
|
const ws = useWalletStore()
|
||||||
|
|
||||||
function changeSymbol(symbol) {
|
function changeSymbol(symbol) {
|
||||||
console.log('changeSymbol', symbol)
|
// console.log('changeSymbol', symbol)
|
||||||
os.tokenA = symbol.base
|
os.tokenA = symbol.base
|
||||||
os.tokenB = symbol.quote
|
os.tokenB = symbol.quote
|
||||||
// routeFinder.invoke()
|
// routeFinder.invoke()
|
||||||
@@ -149,7 +156,7 @@ watchEffect(()=>{
|
|||||||
let built = []
|
let built = []
|
||||||
|
|
||||||
async function placeOrder() {
|
async function placeOrder() {
|
||||||
track('place_order')
|
track('place-order')
|
||||||
const chartOrders = co.orders;
|
const chartOrders = co.orders;
|
||||||
const allWarns = []
|
const allWarns = []
|
||||||
built = []
|
built = []
|
||||||
@@ -196,6 +203,42 @@ async function doPlaceOrder() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const sharing = ref(false)
|
||||||
|
const showSharedTooltip = ref(false)
|
||||||
|
const shareError = ref(false)
|
||||||
|
const showShareDialog = ref(false)
|
||||||
|
const shareUrl = ref(null)
|
||||||
|
|
||||||
|
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) => {
|
||||||
|
const permitted = permission.state === "granted" || permission.state === "prompt"
|
||||||
|
if (!permitted) {
|
||||||
|
showShareDialog.value = true
|
||||||
|
} else {
|
||||||
|
navigator.clipboard.writeText(url)
|
||||||
|
.then(() => {
|
||||||
|
showSharedTooltip.value = true
|
||||||
|
setTimeout(() => showSharedTooltip.value = false, 3000)
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
showShareDialog.value = true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}).catch(() => null)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss"> // NOT scoped
|
<style lang="scss"> // NOT scoped
|
||||||
|
|||||||
@@ -2,7 +2,9 @@
|
|||||||
<toolbar-pane title="Status" icon="mdi-format-list-bulleted-square">
|
<toolbar-pane title="Status" icon="mdi-format-list-bulleted-square">
|
||||||
<template #toolbar>
|
<template #toolbar>
|
||||||
<v-btn variant="text" v-if="s.vault" prepend-icon="mdi-delete-alert" color="red"
|
<v-btn variant="text" v-if="s.vault" prepend-icon="mdi-delete-alert" color="red"
|
||||||
@click="cancelAll(s.vault)" :disabled="!anyOrdersOpen"
|
@click="(async function (vault){
|
||||||
|
new CancelAllTransaction(useStore().chainId, vault).submit()
|
||||||
|
})(s.vault)" :disabled="!anyOrdersOpen"
|
||||||
text="Cancel All"/>
|
text="Cancel All"/>
|
||||||
</template>
|
</template>
|
||||||
<needs-signer>
|
<needs-signer>
|
||||||
@@ -16,10 +18,10 @@
|
|||||||
import ToolbarPane from "@/components/chart/ToolbarPane.vue";
|
import ToolbarPane from "@/components/chart/ToolbarPane.vue";
|
||||||
import Orders from "@/components/Status.vue";
|
import Orders from "@/components/Status.vue";
|
||||||
import NeedsSigner from "@/components/NeedsSigner.vue";
|
import NeedsSigner from "@/components/NeedsSigner.vue";
|
||||||
import {cancelAll} from "@/blockchain/wallet.js";
|
|
||||||
import {useStore} from "@/store/store.js";
|
import {useStore} from "@/store/store.js";
|
||||||
import {computed} from "vue";
|
import {computed} from "vue";
|
||||||
import {isOpen} from "@/blockchain/orderlib.js";
|
import {isOpen} from "@/blockchain/orderlib.js";
|
||||||
|
import {CancelAllTransaction} from "@/blockchain/transaction.js";
|
||||||
|
|
||||||
const s = useStore()
|
const s = useStore()
|
||||||
|
|
||||||
|
|||||||
@@ -46,7 +46,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import {builderDefaults, DEFAULT_SLIPPAGE, useChartOrderStore} from "@/orderbuild.js";
|
import {builderDefaults, useChartOrderStore} from "@/orderbuild.js";
|
||||||
import {allocationText, ShapeType} from "@/charts/shape.js";
|
import {allocationText, ShapeType} from "@/charts/shape.js";
|
||||||
import {sideColor, SingletonCoroutine, toPrecision, vAutoSelect} from "@/misc.js";
|
import {sideColor, SingletonCoroutine, toPrecision, vAutoSelect} from "@/misc.js";
|
||||||
import {useStore} from "@/store/store.js";
|
import {useStore} from "@/store/store.js";
|
||||||
@@ -57,7 +57,7 @@ import BuilderPanel from "@/components/chart/BuilderPanel.vue";
|
|||||||
import {ohlcStart} from "@/charts/chart-misc.js";
|
import {ohlcStart} from "@/charts/chart-misc.js";
|
||||||
import Color from "color";
|
import Color from "color";
|
||||||
import OrderAmount from "@/components/chart/OrderAmount.vue";
|
import OrderAmount from "@/components/chart/OrderAmount.vue";
|
||||||
import {MAX_FRACTION, newTranche} from "@/blockchain/orderlib.js";
|
import {DEFAULT_SLIPPAGE, MAX_FRACTION, newTranche} from "@/blockchain/orderlib.js";
|
||||||
import {getFeeSchedule} from "@/fees.js";
|
import {getFeeSchedule} from "@/fees.js";
|
||||||
import {NATIVE_TOKEN} from "@/common.js";
|
import {NATIVE_TOKEN} from "@/common.js";
|
||||||
|
|
||||||
|
|||||||
@@ -39,11 +39,11 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import {builderDefaults, DEFAULT_SLIPPAGE, MIN_EXECUTION_TIME, useChartOrderStore} from "@/orderbuild.js";
|
import {builderDefaults, useChartOrderStore} from "@/orderbuild.js";
|
||||||
import {allocationText, VLine} from "@/charts/shape.js";
|
import {allocationText, VLine} from "@/charts/shape.js";
|
||||||
import {sideColor} from "@/misc.js";
|
import {sideColor} from "@/misc.js";
|
||||||
import {useOrderStore, usePrefStore, useStore} from "@/store/store.js";
|
import {useOrderStore, usePrefStore, useStore} from "@/store/store.js";
|
||||||
import {DISTANT_FUTURE, MAX_FRACTION, newTranche} from "@/blockchain/orderlib.js";
|
import {DEFAULT_SLIPPAGE, DISTANT_FUTURE, MAX_FRACTION, MIN_EXECUTION_TIME, newTranche} from "@/blockchain/orderlib.js";
|
||||||
import RungBuilder from "@/components/chart/RungBuilder.vue";
|
import RungBuilder from "@/components/chart/RungBuilder.vue";
|
||||||
import {computed, ref, watchEffect} from "vue";
|
import {computed, ref, watchEffect} from "vue";
|
||||||
import {chart, dragging} from "@/charts/chart.js";
|
import {chart, dragging} from "@/charts/chart.js";
|
||||||
@@ -177,10 +177,8 @@ function update(a, b, updateA, updateB) {
|
|||||||
a = maxA
|
a = maxA
|
||||||
}
|
}
|
||||||
_timeEndpoints.value = [a, b]
|
_timeEndpoints.value = [a, b]
|
||||||
const newBuilder = {...props.builder}
|
props.builder.timeA = a
|
||||||
newBuilder.timeA = a
|
props.builder.timeB = b
|
||||||
newBuilder.timeB = b
|
|
||||||
emit('update:builder', newBuilder)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const flipped = computed(()=>{
|
const flipped = computed(()=>{
|
||||||
|
|||||||
@@ -89,12 +89,16 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
<one-time-hint name="click-chart" activator="#tv-widget" location="center"
|
||||||
|
:when="builder.lineA===null && !co.drew" text="Click the chart!"
|
||||||
|
:on-complete="()=>track('click-chart')"
|
||||||
|
/>
|
||||||
</rung-builder>
|
</rung-builder>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import {applyLinePoints, builderDefaults, useChartOrderStore} from "@/orderbuild.js";
|
import {applyLinePoints, builderDefaults, useChartOrderStore} from "@/orderbuild.js";
|
||||||
import {sideColor} from "@/misc.js";
|
import {sideColor, toPrecisionOrNull} from "@/misc.js";
|
||||||
import {MAX_FRACTION, newTranche} from "@/blockchain/orderlib.js";
|
import {MAX_FRACTION, newTranche} from "@/blockchain/orderlib.js";
|
||||||
import RungBuilder from "@/components/chart/RungBuilder.vue";
|
import RungBuilder from "@/components/chart/RungBuilder.vue";
|
||||||
import {computed, ref} from "vue";
|
import {computed, ref} from "vue";
|
||||||
@@ -102,6 +106,8 @@ import {allocationText, DLine} from "@/charts/shape.js";
|
|||||||
import {vectorEquals, vectorInterpolate} from "@/vector.js";
|
import {vectorEquals, vectorInterpolate} from "@/vector.js";
|
||||||
import AbsoluteTimeEntry from "@/components/AbsoluteTimeEntry.vue";
|
import AbsoluteTimeEntry from "@/components/AbsoluteTimeEntry.vue";
|
||||||
import {useStore} from "@/store/store.js";
|
import {useStore} from "@/store/store.js";
|
||||||
|
import OneTimeHint from "@/components/OneTimeHint.vue";
|
||||||
|
import {track} from "@/track.js";
|
||||||
|
|
||||||
const s = useStore()
|
const s = useStore()
|
||||||
const co = useChartOrderStore()
|
const co = useChartOrderStore()
|
||||||
@@ -204,7 +210,7 @@ const time1A = computed({
|
|||||||
})
|
})
|
||||||
|
|
||||||
const price1A = computed({
|
const price1A = computed({
|
||||||
get() { return _endpoints.value[0] === null ? null : _endpoints.value[0][1] },
|
get() { return toPrecisionOrNull(_endpoints.value[0] === null ? null : _endpoints.value[0][1], 6) },
|
||||||
set(v) {
|
set(v) {
|
||||||
const flatline0 = _endpoints.value[0];
|
const flatline0 = _endpoints.value[0];
|
||||||
update(
|
update(
|
||||||
@@ -226,7 +232,7 @@ const time1B = computed({
|
|||||||
})
|
})
|
||||||
|
|
||||||
const price1B = computed({
|
const price1B = computed({
|
||||||
get() { return _endpoints.value[0] === null ? null : _endpoints.value[0][3] },
|
get() { return toPrecisionOrNull(_endpoints.value[0] === null ? null : _endpoints.value[0][3], 6) },
|
||||||
set(v) {
|
set(v) {
|
||||||
const flatline0 = _endpoints.value[0];
|
const flatline0 = _endpoints.value[0];
|
||||||
update(
|
update(
|
||||||
@@ -248,7 +254,7 @@ const time2A = computed({
|
|||||||
})
|
})
|
||||||
|
|
||||||
const price2A = computed({
|
const price2A = computed({
|
||||||
get() { return _endpoints.value[1] === null ? null : _endpoints.value[1][1] },
|
get() { return toPrecisionOrNull(_endpoints.value[1] === null ? null : _endpoints.value[1][1], 6) },
|
||||||
set(v) {
|
set(v) {
|
||||||
const flatline = _endpoints.value[1];
|
const flatline = _endpoints.value[1];
|
||||||
update(
|
update(
|
||||||
@@ -270,7 +276,7 @@ const time2B = computed({
|
|||||||
})
|
})
|
||||||
|
|
||||||
const price2B = computed({
|
const price2B = computed({
|
||||||
get() { return _endpoints.value[1] === null ? null : _endpoints.value[1][3] },
|
get() { return toPrecisionOrNull(_endpoints.value[1] === null ? null : _endpoints.value[1][3], 6) },
|
||||||
set(v) {
|
set(v) {
|
||||||
const flatline = _endpoints.value[1];
|
const flatline = _endpoints.value[1];
|
||||||
update(
|
update(
|
||||||
@@ -283,10 +289,8 @@ const price2B = computed({
|
|||||||
function update(a, b) { // a and b are lines of two points
|
function update(a, b) { // a and b are lines of two points
|
||||||
if (!vectorEquals(props.builder.lineA, a) || !vectorEquals(props.builder.lineB, b)) {
|
if (!vectorEquals(props.builder.lineA, a) || !vectorEquals(props.builder.lineB, b)) {
|
||||||
_endpoints.value = [flattenLine(a), flattenLine(b)]
|
_endpoints.value = [flattenLine(a), flattenLine(b)]
|
||||||
const newBuilder = {...props.builder}
|
props.builder.lineA = a
|
||||||
newBuilder.lineA = a
|
props.builder.lineB = b
|
||||||
newBuilder.lineB = b
|
|
||||||
emit('update:builder', newBuilder)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -405,12 +409,12 @@ function dirtyLine(a, b) {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
const name = computed(()=>props.builder.breakout?'Breakout':'Limit')
|
const name = computed(()=>props.builder.breakout?(props.order.buy?'Breakout':'Breakdown'):'Limit')
|
||||||
|
|
||||||
const description = computed(()=>{
|
const description = computed(()=>{
|
||||||
const buy = props.order.buy
|
const buy = props.order.buy
|
||||||
const above = buy === props.builder.breakout
|
const above = buy === props.builder.breakout
|
||||||
const plural = props.builder
|
const plural = props.builder.rungs > 1 ? 's' : ''
|
||||||
return (buy?'Buy ':'Sell ')+(above?'above':'below')+' the line'+(plural?'s':'')
|
return (buy?'Buy ':'Sell ')+(above?'above':'below')+' the line'+(plural?'s':'')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<rung-builder :name="(builder.breakout?'Breakout':'Limit')+(builder.rungs>1?' Ladder':'')"
|
<rung-builder :name="(builder.breakout?(order.buy?'Breakout':'Breakdown'):'Limit')+(builder.rungs>1?' Ladder':'')"
|
||||||
:description="description"
|
:description="description"
|
||||||
:order="order" :builder="builder"
|
:order="order" :builder="builder"
|
||||||
v-model="priceEndpoints" :mode="0" :flip="flipped"
|
v-model="priceEndpoints" :mode="0" :flip="flipped"
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
<td class="weight" style="vertical-align: bottom">{{ allocationTexts[higherIndex] }}</td>
|
<td class="weight" style="vertical-align: bottom">{{ allocationTexts[higherIndex] }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr v-for="i in innerIndexes" class="ml-5">
|
<tr v-for="i in innerIndexes" class="ml-5">
|
||||||
<td class="pl-5">{{ prices[i] }}</td>
|
<td class="pl-5">{{ toPrecision(prices[i],6) }}</td>
|
||||||
<td class="weight">{{ allocationTexts[i] }}</td>
|
<td class="weight">{{ allocationTexts[i] }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</template>
|
</template>
|
||||||
@@ -33,10 +33,14 @@
|
|||||||
style="flex: 6em"
|
style="flex: 6em"
|
||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
<td class="weight">{{ weights.length ? allocationTexts[lowerIndex] : '' }}</td>
|
<td class="weight">{{ weights.length > 1 ? allocationTexts[lowerIndex] : '' }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
<one-time-hint name="click-chart" activator="#tv-widget" location="center"
|
||||||
|
:when="priceA===null" text="Click the chart!"
|
||||||
|
:on-complete="()=>track('click-chart')"
|
||||||
|
/>
|
||||||
</rung-builder>
|
</rung-builder>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -48,6 +52,9 @@ import {MAX_FRACTION, newTranche} from "@/blockchain/orderlib.js";
|
|||||||
import RungBuilder from "@/components/chart/RungBuilder.vue";
|
import RungBuilder from "@/components/chart/RungBuilder.vue";
|
||||||
import {computed, ref} from "vue";
|
import {computed, ref} from "vue";
|
||||||
import {allocationText, HLine} from "@/charts/shape.js";
|
import {allocationText, HLine} from "@/charts/shape.js";
|
||||||
|
import OneTimeHint from "@/components/OneTimeHint.vue";
|
||||||
|
import {track} from "@/track.js";
|
||||||
|
import {toPrecision, toPrecisionOrNull} from "@/misc.js";
|
||||||
|
|
||||||
const s = useStore()
|
const s = useStore()
|
||||||
const os = useOrderStore()
|
const os = useOrderStore()
|
||||||
@@ -132,10 +139,8 @@ const priceEndpoints = computed({
|
|||||||
|
|
||||||
function update(a, b) {
|
function update(a, b) {
|
||||||
_priceEndpoints.value = [a, b]
|
_priceEndpoints.value = [a, b]
|
||||||
const newBuilder = {...props.builder}
|
props.builder.priceA = a
|
||||||
newBuilder.priceA = a
|
props.builder.priceB = b
|
||||||
newBuilder.priceB = b
|
|
||||||
emit('update:builder', newBuilder)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const flipped = computed(()=>{
|
const flipped = computed(()=>{
|
||||||
@@ -145,7 +150,7 @@ const flipped = computed(()=>{
|
|||||||
})
|
})
|
||||||
|
|
||||||
const higherPrice = computed({
|
const higherPrice = computed({
|
||||||
get() { return flipped.value ? priceA.value : priceB.value },
|
get() { return toPrecisionOrNull(flipped.value ? priceA.value : priceB.value, 6) },
|
||||||
set(v) {
|
set(v) {
|
||||||
if (flipped.value)
|
if (flipped.value)
|
||||||
priceA.value = v
|
priceA.value = v
|
||||||
@@ -166,9 +171,7 @@ const innerIndexes = computed(()=>{
|
|||||||
})
|
})
|
||||||
|
|
||||||
const lowerPrice = computed({
|
const lowerPrice = computed({
|
||||||
get() {
|
get() {return toPrecisionOrNull(!flipped.value ? priceA.value : priceB.value, 6)},
|
||||||
return !flipped.value ? priceA.value : priceB.value
|
|
||||||
},
|
|
||||||
set(v) {
|
set(v) {
|
||||||
if (!flipped.value)
|
if (!flipped.value)
|
||||||
priceA.value = v
|
priceA.value = v
|
||||||
@@ -200,7 +203,8 @@ const stdWidth = computed(()=>co.meanRange)
|
|||||||
const description = computed(()=>{
|
const description = computed(()=>{
|
||||||
const buy = props.order.buy
|
const buy = props.order.buy
|
||||||
const above = buy === props.builder.breakout
|
const above = buy === props.builder.breakout
|
||||||
return (buy?'Buy ':'Sell ')+(above?'above':'below')+' the line'
|
const plural = props.builder.rungs > 1 ? 's' : ''
|
||||||
|
return (buy?'Buy ':'Sell ')+(above?'above':'below')+' the line'+plural
|
||||||
})
|
})
|
||||||
|
|
||||||
function getModelValue(model) {
|
function getModelValue(model) {
|
||||||
|
|||||||
@@ -18,9 +18,9 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import {builderDefaults, builderFuncs, DEFAULT_SLIPPAGE, useChartOrderStore} from "@/orderbuild.js";
|
import {builderDefaults, builderFuncs, useChartOrderStore} from "@/orderbuild.js";
|
||||||
import {computed, onMounted, onUnmounted} from "vue";
|
import {computed, onMounted, onUnmounted} from "vue";
|
||||||
import {newTranche} from "@/blockchain/orderlib.js";
|
import {DEFAULT_SLIPPAGE, newTranche} from "@/blockchain/orderlib.js";
|
||||||
|
|
||||||
const co = useChartOrderStore()
|
const co = useChartOrderStore()
|
||||||
const props = defineProps(['order', 'builder'])
|
const props = defineProps(['order', 'builder'])
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ const s = useStore()
|
|||||||
const co = useChartOrderStore()
|
const co = useChartOrderStore()
|
||||||
|
|
||||||
const theme = useTheme().current
|
const theme = useTheme().current
|
||||||
console.log('theme', theme.value)
|
// console.log('theme', theme.value)
|
||||||
const sideColor = computed(()=>new Color(props.order.buy?theme.value.colors.success:theme.value.colors.error).darken(0.2).string())
|
const sideColor = computed(()=>new Color(props.order.buy?theme.value.colors.success:theme.value.colors.error).darken(0.2).string())
|
||||||
const switchModel = computed({
|
const switchModel = computed({
|
||||||
get() {return !props.order.buy},
|
get() {return !props.order.buy},
|
||||||
|
|||||||
@@ -9,6 +9,9 @@
|
|||||||
@click="()=>{if (props.builder.breakout!==undefined) props.builder.breakout=!props.builder.breakout}">{{ name }}</v-btn>
|
@click="()=>{if (props.builder.breakout!==undefined) props.builder.breakout=!props.builder.breakout}">{{ name }}</v-btn>
|
||||||
<div class="description w-100 text-center">{{description}}</div>
|
<div class="description w-100 text-center">{{description}}</div>
|
||||||
</div>
|
</div>
|
||||||
|
-->
|
||||||
|
<!--
|
||||||
|
<floating-div id="rungs" v-if="endpoints[0]">
|
||||||
-->
|
-->
|
||||||
<v-text-field type="number" v-model="rungs"
|
<v-text-field type="number" v-model="rungs"
|
||||||
density="compact" hide-details class="mx-1 my-2" variant="outlined"
|
density="compact" hide-details class="mx-1 my-2" variant="outlined"
|
||||||
@@ -16,13 +19,32 @@
|
|||||||
:color="color"
|
:color="color"
|
||||||
min="1" :max="MAX_RUNGS"
|
min="1" :max="MAX_RUNGS"
|
||||||
:disabled="rungsDisabled"
|
:disabled="rungsDisabled"
|
||||||
style="width: 6.6em; max-height: 2.5em; height: 2.5em"
|
id="rungs"
|
||||||
/>
|
/>
|
||||||
<v-switch v-model="builder.breakout" label="Breakout" persistent-hint :color="color" hide-details/>
|
<!--
|
||||||
<div class="mx-auto"><span style="font-size: .7em; vertical-align: top"
|
</floating-div>
|
||||||
:style="builder.breakout?{color:color}:null">
|
-->
|
||||||
{{description}}
|
<one-time-hint name="rungs" activator="#rungs" after="choose-builder"
|
||||||
</span></div>
|
text="↓ Try increasing rungs!" location="top"
|
||||||
|
:when="rungs===1&&endpoints[0]!==null"
|
||||||
|
:on-complete="()=>track('rungs')"
|
||||||
|
/>
|
||||||
|
<v-tooltip v-if="builder.breakout!==undefined"
|
||||||
|
:text="order.buy?'Breakout orders buy above the breakout line':'Breakdown orders sell below the breakdown line'">
|
||||||
|
<template #activator="{ props }">
|
||||||
|
<div v-bind="props">
|
||||||
|
<v-switch v-model="breakout" :label="order.buy?'Breakout':'Breakdown'"
|
||||||
|
persistent-hint :color="switchColor" :base-color="switchColor" hide-details direction="vertical"
|
||||||
|
density="compact"/>
|
||||||
|
<div class="mx-auto">
|
||||||
|
<span style="font-size: .7em; vertical-align: top"
|
||||||
|
:style="builder.breakout?{color:new Color(color).lighten(0.5).string()}:null">
|
||||||
|
{{ description }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</v-tooltip>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<slot/>
|
<slot/>
|
||||||
@@ -33,8 +55,21 @@
|
|||||||
</div>
|
</div>
|
||||||
<div v-if="rungs>1" class="mx-2 d-flex justify-start">
|
<div v-if="rungs>1" class="mx-2 d-flex justify-start">
|
||||||
<div class="d-flex align-center mt-2">
|
<div class="d-flex align-center mt-2">
|
||||||
<v-slider v-if="rungs>1" :direction="orientation?'vertical':'horizontal'" min="-100" max="100" v-model="balance100"
|
<!--
|
||||||
class="no-slider-bg ml-2 mr-4" hide-details/>
|
<floating-div id="slider" v-if="endpoints[0]">
|
||||||
|
-->
|
||||||
|
<div id="balance-slider">
|
||||||
|
<v-slider v-if="rungs>1" :direction="orientation?'vertical':'horizontal'" min="-100" max="100" v-model="balance100"
|
||||||
|
class="no-slider-bg ml-2 mr-4" hide-details/>
|
||||||
|
</div>
|
||||||
|
<!--
|
||||||
|
</floating-div>
|
||||||
|
-->
|
||||||
|
<one-time-hint name="balance-slider" activator="#balance-slider" after="rungs"
|
||||||
|
text="↓ Slide the amount balance ↓" location="top"
|
||||||
|
:when="balance100===0"
|
||||||
|
:on-complete="()=>track('balance-slider')"
|
||||||
|
/>
|
||||||
<v-text-field type="number" v-model="balance100" min="-100" max="100"
|
<v-text-field type="number" v-model="balance100" min="-100" max="100"
|
||||||
density="compact" hide-details variant="outlined" label="Balance" step="5"
|
density="compact" hide-details variant="outlined" label="Balance" step="5"
|
||||||
class="balance">
|
class="balance">
|
||||||
@@ -66,6 +101,10 @@ import {
|
|||||||
vectorNeg,
|
vectorNeg,
|
||||||
vectorSub
|
vectorSub
|
||||||
} from "@/vector.js";
|
} from "@/vector.js";
|
||||||
|
import {logicalXOR} from "@/common.js";
|
||||||
|
import OneTimeHint from "@/components/OneTimeHint.vue";
|
||||||
|
import {track} from "@/track.js";
|
||||||
|
import FloatingDiv from "@/components/FloatingDiv.vue";
|
||||||
|
|
||||||
const co = useChartOrderStore()
|
const co = useChartOrderStore()
|
||||||
const endpoints = defineModel('modelValue') // 2-item list of points/values
|
const endpoints = defineModel('modelValue') // 2-item list of points/values
|
||||||
@@ -92,14 +131,16 @@ const flippedSign = computed(()=>props.flip?-1:1)
|
|||||||
|
|
||||||
const balance100 = computed( {
|
const balance100 = computed( {
|
||||||
get() {return flippedSign.value*props.builder.balance*100},
|
get() {return flippedSign.value*props.builder.balance*100},
|
||||||
set(v) {props.builder.balance = flippedSign.value*v/100; }
|
set(v) {
|
||||||
|
// if (v<-60) v = -60;
|
||||||
|
props.builder.balance = flippedSign.value*v/100; }
|
||||||
} )
|
} )
|
||||||
|
|
||||||
// validity checks
|
// validity checks
|
||||||
watchEffect(()=>{
|
watchEffect(()=>{
|
||||||
const rungs = props.builder.rungs
|
const rungs = props.builder.rungs
|
||||||
// const prev = props.builder.valid
|
// const prev = props.builder.valid
|
||||||
props.builder.valid = rungs >= 1 && endpoints.value[0] && (rungs < 2 || endpoints.value[1])
|
props.builder.valid = rungs >= 1 && endpoints.value[0] > 0 && (rungs < 2 || endpoints.value[1])
|
||||||
// console.log('valid?', prev, props.builder.valid, rungs, valueA.value, valueB.value)
|
// console.log('valid?', prev, props.builder.valid, rungs, valueA.value, valueB.value)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -111,6 +152,11 @@ watchEffect(()=>{
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const breakout = computed({
|
||||||
|
get() {return !logicalXOR(props.builder.breakout, props.order.buy)},
|
||||||
|
set(v) {props.builder.breakout = !logicalXOR(v, props.order.buy)},
|
||||||
|
})
|
||||||
|
|
||||||
function setEndpoints(a, b) {
|
function setEndpoints(a, b) {
|
||||||
endpoints.value = [devectorize(a), devectorize(b)]
|
endpoints.value = [devectorize(a), devectorize(b)]
|
||||||
}
|
}
|
||||||
@@ -204,11 +250,7 @@ const values = computed(()=>{
|
|||||||
const weights = computed(() => {
|
const weights = computed(() => {
|
||||||
// const balance = props.flip ? -props.builder.balance : props.builder.balance
|
// const balance = props.flip ? -props.builder.balance : props.builder.balance
|
||||||
const most = 0.998
|
const most = 0.998
|
||||||
let balance = -props.builder.balance
|
let balance = Math.min(most, Math.max(-most, -props.builder.balance))
|
||||||
if (balance <= -1)
|
|
||||||
balance = -most
|
|
||||||
else if (balance >= 1)
|
|
||||||
balance = most
|
|
||||||
const ws = linearWeights(props.builder.rungs, balance)
|
const ws = linearWeights(props.builder.rungs, balance)
|
||||||
if (props.setWeights)
|
if (props.setWeights)
|
||||||
props.setWeights(ws)
|
props.setWeights(ws)
|
||||||
@@ -235,6 +277,7 @@ const color = computed({
|
|||||||
props.builder.color = c.saturation <= maxLightness ? v : c.lightness(maxLightness).rgb().string()
|
props.builder.color = c.saturation <= maxLightness ? v : c.lightness(maxLightness).rgb().string()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
const switchColor = computed(()=>props.builder.breakout ? color.value : null)
|
||||||
const colorStyle = computed(() => {
|
const colorStyle = computed(() => {
|
||||||
// return {'color': color.value}
|
// return {'color': color.value}
|
||||||
return {}
|
return {}
|
||||||
@@ -424,6 +467,8 @@ function deleteShapes() {
|
|||||||
|
|
||||||
if (!endpoints.value[0])
|
if (!endpoints.value[0])
|
||||||
shapeA.createOrDraw(); // initiate drawing mode
|
shapeA.createOrDraw(); // initiate drawing mode
|
||||||
|
else
|
||||||
|
adjustShapes()
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
28
src/components/chart/Shared.vue
Normal file
28
src/components/chart/Shared.vue
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
<template>
|
||||||
|
<h2>Shared Order</h2>
|
||||||
|
<p>Loading the shared order into the app...</p>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import {loadShareUrl} from "@/share.js";
|
||||||
|
import {router} from "@/router/router.js";
|
||||||
|
import {useRoute} from "vue-router";
|
||||||
|
|
||||||
|
const route = useRoute()
|
||||||
|
const code = route.params.code
|
||||||
|
loadShareUrl(code).then((ok)=> {
|
||||||
|
if (ok) {
|
||||||
|
console.log('loaded share data',code)
|
||||||
|
router.replace('/order');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.log('failed to load share data',code)
|
||||||
|
}
|
||||||
|
}).catch((e)=> {
|
||||||
|
console.error(e)
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
|
||||||
|
</style>
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="d-flex mb-1 align-center w-100">
|
<div class="d-flex mb-1 align-center w-100">
|
||||||
<logo class="d-flex align-end clickable logo-large ml-1" @click="nav('Order')" :show-tag="true" max-height="32"/>
|
<logo class="d-flex align-end clickable logo-large ml-1" @click="// noinspection JSIgnoredPromiseFromCall
|
||||||
|
router.push({name: 'Order'})" :show-tag="true" max-height="32"/>
|
||||||
<slot/>
|
<slot/>
|
||||||
<div class="ml-auto d-flex align-center">
|
<div class="ml-auto d-flex align-center">
|
||||||
<span class="title mr-4">{{title}}</span>
|
<span class="title mr-4">{{title}}</span>
|
||||||
@@ -9,7 +10,7 @@
|
|||||||
<toolbar-button tooltip="Assets" icon="mdi-currency-btc" route="Assets"/>
|
<toolbar-button tooltip="Assets" icon="mdi-currency-btc" route="Assets"/>
|
||||||
<!-- mdi-format-list-checks mdi-format-list-bulleted-square -->
|
<!-- mdi-format-list-checks mdi-format-list-bulleted-square -->
|
||||||
<toolbar-button tooltip="Status" icon="mdi-format-list-checks" route="Status"/>
|
<toolbar-button tooltip="Status" icon="mdi-format-list-checks" route="Status"/>
|
||||||
<toolbar-button tooltip="About" icon="mdi-information-outline" href="https://dexorder.trade/" target="dexorder"/>
|
<toolbar-button tooltip="About" icon="mdi-information-outline" href="https://dexorder.com/" target="dexorderwww"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -17,7 +18,7 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import ToolbarButton from "@/components/chart/ToolbarButton.vue";
|
import ToolbarButton from "@/components/chart/ToolbarButton.vue";
|
||||||
import Logo from "@/components/Logo.vue";
|
import Logo from "@/components/Logo.vue";
|
||||||
import {nav} from "@/misc.js";
|
import {router} from "@/router/router.js";
|
||||||
|
|
||||||
const props = defineProps(['title', 'icon'])
|
const props = defineProps(['title', 'icon'])
|
||||||
|
|
||||||
|
|||||||
@@ -9,11 +9,9 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import {computed} from "vue";
|
import {computed} from "vue";
|
||||||
import {useRoute} from "vue-router";
|
import {router} from "@/router/router.js";
|
||||||
import {nav} from "/src/misc.js"
|
|
||||||
|
|
||||||
const props = defineProps(['icon', 'route', 'tooltip', 'href', 'target'])
|
const props = defineProps(['icon', 'route', 'tooltip', 'href', 'target'])
|
||||||
const router = useRoute();
|
|
||||||
const isCurrent = computed(() => router.name === props.route)
|
const isCurrent = computed(() => router.name === props.route)
|
||||||
|
|
||||||
function click() {
|
function click() {
|
||||||
@@ -29,7 +27,8 @@ function click() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
nav(props.route)
|
// noinspection JSIgnoredPromiseFromCall
|
||||||
|
router.push({name: props.route})
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
function openApp() {
|
function openApp() {
|
||||||
window.open('https://app.dexorder.trade/', 'dexorderapp')
|
window.open('https://app.dexorder.com/', 'dexorderapp')
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,8 @@
|
|||||||
</v-card-text>
|
</v-card-text>
|
||||||
<div class="w-100 d-flex justify-center my-6 actions">
|
<div class="w-100 d-flex justify-center my-6 actions">
|
||||||
<app-btn/>
|
<app-btn/>
|
||||||
<v-btn prepend-icon="mdi-information-outline" variant="flat" text="How It Works" @click="nav('HowItWorks')"/>
|
<v-btn prepend-icon="mdi-information-outline" variant="flat" text="How It Works" @click="// noinspection JSIgnoredPromiseFromCall
|
||||||
|
router.push({name: 'HowItWorks'})"/>
|
||||||
</div>
|
</div>
|
||||||
</v-card>
|
</v-card>
|
||||||
</template>
|
</template>
|
||||||
@@ -36,10 +37,8 @@ import beta from "@/components/Beta.vue";
|
|||||||
import Soon from "@/components/Soon.vue";
|
import Soon from "@/components/Soon.vue";
|
||||||
import UniswapLogo from "@/corp/UniswapLogo.vue";
|
import UniswapLogo from "@/corp/UniswapLogo.vue";
|
||||||
import Logo from "@/components/Logo.vue";
|
import Logo from "@/components/Logo.vue";
|
||||||
import {nav} from "@/misc.js";
|
|
||||||
import AppBtn from "@/corp/AppBtn.vue";
|
import AppBtn from "@/corp/AppBtn.vue";
|
||||||
import Social from "@/components/Social.vue";
|
import {router} from "@/router/router.js";
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
|||||||
@@ -49,7 +49,8 @@
|
|||||||
</v-card-text>
|
</v-card-text>
|
||||||
<v-card-actions class="justify-center my-6 actions">
|
<v-card-actions class="justify-center my-6 actions">
|
||||||
<app-btn/>
|
<app-btn/>
|
||||||
<v-btn prepend-icon="mdi-home-outline" variant="flat" text="Home" @click="nav('Home')"/>
|
<v-btn prepend-icon="mdi-home-outline" variant="flat" text="Home" @click="// noinspection JSIgnoredPromiseFromCall
|
||||||
|
router.push({name: 'Home'})"/>
|
||||||
</v-card-actions>
|
</v-card-actions>
|
||||||
</v-card>
|
</v-card>
|
||||||
</template>
|
</template>
|
||||||
@@ -57,8 +58,8 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
|
|
||||||
import UniswapLogo from "@/corp/UniswapLogo.vue";
|
import UniswapLogo from "@/corp/UniswapLogo.vue";
|
||||||
import {nav} from "@/misc.js";
|
|
||||||
import AppBtn from "@/corp/AppBtn.vue";
|
import AppBtn from "@/corp/AppBtn.vue";
|
||||||
|
import {router} from "@/router/router.js";
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
|||||||
@@ -3,11 +3,13 @@
|
|||||||
<!-- <v-app-bar-nav-icon @click="s.nav=!s.nav" icon="mdi-plus"/>-->
|
<!-- <v-app-bar-nav-icon @click="s.nav=!s.nav" icon="mdi-plus"/>-->
|
||||||
|
|
||||||
<v-app-bar-title>
|
<v-app-bar-title>
|
||||||
<logo @click="nav('Home')" class="clickable"/>
|
<logo @click="// noinspection JSIgnoredPromiseFromCall
|
||||||
|
router.push({name: 'Home'})" class="clickable"/>
|
||||||
<social class="d-inline" size="small"/>
|
<social class="d-inline" size="small"/>
|
||||||
</v-app-bar-title>
|
</v-app-bar-title>
|
||||||
|
|
||||||
<v-btn @click="nav('HowItWorks')" prepend-icon="mdi-information-outline" text="How It Works"/>
|
<v-btn @click="// noinspection JSIgnoredPromiseFromCall
|
||||||
|
router.push({name: 'HowItWorks'})" prepend-icon="mdi-information-outline" text="How It Works"/>
|
||||||
<v-btn prepend-icon="mdi-arrow-up-bold" variant="tonal" color="primary" @click="openApp" text="Launch App"/>
|
<v-btn prepend-icon="mdi-arrow-up-bold" variant="tonal" color="primary" @click="openApp" text="Launch App"/>
|
||||||
|
|
||||||
</v-app-bar>
|
</v-app-bar>
|
||||||
@@ -16,13 +18,13 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import {useTheme} from "vuetify";
|
import {useTheme} from "vuetify";
|
||||||
import Logo from "@/components/Logo.vue";
|
import Logo from "@/components/Logo.vue";
|
||||||
import {nav} from "@/misc.js";
|
|
||||||
import Social from "@/components/Social.vue";
|
import Social from "@/components/Social.vue";
|
||||||
|
import {router} from "@/router/router.js";
|
||||||
|
|
||||||
const theme = useTheme().current
|
const theme = useTheme().current
|
||||||
|
|
||||||
function openApp() {
|
function openApp() {
|
||||||
window.open('https://app.dexorder.trade/', 'dexorderapp')
|
window.open('https://app.dexorder.com/', 'dexorderapp')
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
47
src/debug_console.js
Normal file
47
src/debug_console.js
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
(function() {
|
||||||
|
let debugDiv = document.createElement('div');
|
||||||
|
debugDiv.id = 'debug-log';
|
||||||
|
debugDiv.setAttribute(
|
||||||
|
'style',
|
||||||
|
`
|
||||||
|
background:#222 !important;
|
||||||
|
color:#0f0 !important;
|
||||||
|
padding:8px !important;
|
||||||
|
font-family:monospace !important;
|
||||||
|
font-size:14px !important;
|
||||||
|
position:fixed !important;
|
||||||
|
left:0 !important; right:0 !important;
|
||||||
|
bottom:0 !important;
|
||||||
|
max-height:35vh !important;
|
||||||
|
width:100vw !important;
|
||||||
|
overflow-y:auto !important;
|
||||||
|
z-index:9999 !important;
|
||||||
|
pointer-events:auto !important;
|
||||||
|
box-shadow:0 0 8px #000 !important;
|
||||||
|
touch-action: auto !important;
|
||||||
|
-webkit-overflow-scrolling: touch !important;
|
||||||
|
white-space: pre-wrap !important;
|
||||||
|
word-break: break-word !important;
|
||||||
|
`
|
||||||
|
);
|
||||||
|
document.body.appendChild(debugDiv);
|
||||||
|
|
||||||
|
function printLog(type, args) {
|
||||||
|
let msg = Array.from(args).map(a => {
|
||||||
|
try { return typeof a === 'object' ? JSON.stringify(a, null, 2) : String(a); }
|
||||||
|
catch { return String(a); }
|
||||||
|
}).join(' ');
|
||||||
|
let line = document.createElement('div');
|
||||||
|
line.textContent = `[${type}] ${msg}`;
|
||||||
|
debugDiv.appendChild(line);
|
||||||
|
debugDiv.scrollTop = debugDiv.scrollHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
['trace', 'log', 'info', 'warn', 'error'].forEach(type => {
|
||||||
|
let orig = console[type];
|
||||||
|
console[type] = function(...args) {
|
||||||
|
printLog(type, args);
|
||||||
|
orig.apply(console, args);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})();
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import {newContract, vaultContract} from "@/blockchain/contract.js";
|
import {newContract, vaultContract} from "@/blockchain/contract.js";
|
||||||
import {provider} from "@/blockchain/wallet.js";
|
|
||||||
import {timestamp} from "@/common.js";
|
import {timestamp} from "@/common.js";
|
||||||
import TTLCache from "@isaacs/ttlcache";
|
import TTLCache from "@isaacs/ttlcache";
|
||||||
|
import {provider} from "@/blockchain/provider.js";
|
||||||
|
|
||||||
|
|
||||||
async function getFeeManagerContract(vaultContract) {
|
async function getFeeManagerContract(vaultContract) {
|
||||||
|
|||||||
@@ -19,9 +19,9 @@ import MainView from './MainView.vue'
|
|||||||
import {useStore} from "@/store/store.js";
|
import {useStore} from "@/store/store.js";
|
||||||
import {computed} from "vue";
|
import {computed} from "vue";
|
||||||
import {useWalletStore} from "@/blockchain/wallet.js";
|
import {useWalletStore} from "@/blockchain/wallet.js";
|
||||||
import {TransactionState, TransactionType} from "@/blockchain/transaction.js";
|
|
||||||
import {FixedNumber} from "ethers";
|
import {FixedNumber} from "ethers";
|
||||||
import PoolSelectionDialog from "@/components/PoolSelectionDialog.vue";
|
import PoolSelectionDialog from "@/components/PoolSelectionDialog.vue";
|
||||||
|
import {TransactionState, TransactionType} from "@/blockchain/transactionDecl.js";
|
||||||
|
|
||||||
const s = useStore()
|
const s = useStore()
|
||||||
const ws = useWalletStore()
|
const ws = useWalletStore()
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import { createApp } from 'vue'
|
|||||||
// Plugins
|
// Plugins
|
||||||
import { registerPlugins } from '@/plugins'
|
import { registerPlugins } from '@/plugins'
|
||||||
import '@/styles/style.scss'
|
import '@/styles/style.scss'
|
||||||
import "./socket.js"
|
import "./socketInit.js"
|
||||||
import "./version.js"
|
import "./version.js"
|
||||||
|
|
||||||
BigInt.prototype.toJSON = function() { return this.toString() }
|
BigInt.prototype.toJSON = function() { return this.toString() }
|
||||||
|
|||||||
37
src/misc.js
37
src/misc.js
@@ -3,13 +3,8 @@ import {usePrefStore, useStore} from "@/store/store.js";
|
|||||||
import {token} from "@/blockchain/token.js";
|
import {token} from "@/blockchain/token.js";
|
||||||
import Color from "color";
|
import Color from "color";
|
||||||
import {DateTime} from "luxon";
|
import {DateTime} from "luxon";
|
||||||
import router from "@/router/index.js";
|
|
||||||
import {dateString} from "@/common.js";
|
import {dateString} from "@/common.js";
|
||||||
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
export function nav(name) {
|
|
||||||
// noinspection JSIgnoredPromiseFromCall
|
|
||||||
router.push({name})
|
|
||||||
}
|
|
||||||
|
|
||||||
const QUOTE_SYMBOLS = [
|
const QUOTE_SYMBOLS = [
|
||||||
// in order of preference
|
// in order of preference
|
||||||
@@ -71,7 +66,9 @@ export const uint32max = 4294967295
|
|||||||
export const uint64max = 18446744073709551615n
|
export const uint64max = 18446744073709551615n
|
||||||
|
|
||||||
export function tokenNumber(token, balance) {
|
export function tokenNumber(token, balance) {
|
||||||
return FixedNumber.fromValue(balance, token.decimals, {decimals: token.decimals, width: 256})
|
const dec = token ? token.decimals : 0
|
||||||
|
console.log('token dec', dec, balance)
|
||||||
|
return FixedNumber.fromValue(balance, dec, {decimals: dec, width: 256})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function tokenFloat(token, balance) {
|
export function tokenFloat(token, balance) {
|
||||||
@@ -153,10 +150,7 @@ export function inversionPreference(chainId, base, quote) {
|
|||||||
|
|
||||||
export const sleep = ms => new Promise(r => setTimeout(r, ms))
|
export const sleep = ms => new Promise(r => setTimeout(r, ms))
|
||||||
|
|
||||||
export function uuid() {
|
export function uuid() {return uuidv4()}
|
||||||
// noinspection JSUnresolvedReference
|
|
||||||
return crypto.randomUUID();
|
|
||||||
}
|
|
||||||
|
|
||||||
export function lightenColor(color, lightness = 85, alpha = null) {
|
export function lightenColor(color, lightness = 85, alpha = null) {
|
||||||
let c = new Color(color).hsl()
|
let c = new Color(color).hsl()
|
||||||
@@ -230,6 +224,21 @@ export function intervalToSeconds(interval) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function secondsToInterval(seconds) {
|
||||||
|
const units = [
|
||||||
|
[30 * 24 * 60 * 60, 'M'],
|
||||||
|
[7 * 24 * 60 * 60, 'W'],
|
||||||
|
[24 * 60 * 60, 'D'],
|
||||||
|
[60, ''],
|
||||||
|
[1, 'S'],
|
||||||
|
]
|
||||||
|
for( const [unit, suffix] of units)
|
||||||
|
if (seconds % unit === 0)
|
||||||
|
return `${seconds / unit}${suffix}`
|
||||||
|
throw Error(`invalid secondsToInterval ${seconds}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export function interpolate(a, b, zeroToOne) {
|
export function interpolate(a, b, zeroToOne) {
|
||||||
const d = (b-a)
|
const d = (b-a)
|
||||||
return a + d * zeroToOne
|
return a + d * zeroToOne
|
||||||
@@ -260,6 +269,12 @@ export function toPrecision(value, significantDigits = 3) {
|
|||||||
return value.toFixed(decimalsNeeded); // Use toFixed to completely avoid scientific notation
|
return value.toFixed(decimalsNeeded); // Use toFixed to completely avoid scientific notation
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function toPrecisionOrNull(value, significantDigits = 3) {
|
||||||
|
if (value===null) return null
|
||||||
|
if (value===undefined) return undefined
|
||||||
|
return toPrecision(value, significantDigits)
|
||||||
|
}
|
||||||
|
|
||||||
export function toHuman(value, significantDigits = 2) {
|
export function toHuman(value, significantDigits = 2) {
|
||||||
if (!isFinite(value)) return value.toString(); // Handle Infinity and NaN
|
if (!isFinite(value)) return value.toString(); // Handle Infinity and NaN
|
||||||
let suffix = ''
|
let suffix = ''
|
||||||
|
|||||||
@@ -1,20 +1,20 @@
|
|||||||
import {getToken} from "@/blockchain/token.js";
|
import {getToken} from "@/blockchain/token.js";
|
||||||
|
|
||||||
let native = false // whether native browser notifications are allowed
|
let notificationsAllowed = false // whether native browser notifications are allowed
|
||||||
|
|
||||||
Notification.requestPermission()
|
if ('Notification' in window) {
|
||||||
.then(permission => {
|
Notification.requestPermission()
|
||||||
console.log(`notification permission: ${permission}`);
|
.then(permission => {
|
||||||
native = permission === 'granted'
|
notificationsAllowed = permission === 'granted'
|
||||||
})
|
if (!notificationsAllowed)
|
||||||
.catch(error => {
|
console.log(`notification permission denied: ${permission}`);
|
||||||
console.error(`notification permission error: ${error}`);
|
})
|
||||||
native = false;
|
.catch(error => {console.error(`notification permission error: ${error}`);});
|
||||||
});
|
}
|
||||||
|
|
||||||
|
|
||||||
export function notify(title, message=null) {
|
export function notify(title, message=null) {
|
||||||
if (native) {
|
if (notificationsAllowed) {
|
||||||
const options = {
|
const options = {
|
||||||
renotify: true,
|
renotify: true,
|
||||||
tag: title,
|
tag: title,
|
||||||
|
|||||||
@@ -7,11 +7,6 @@ import {computed, ref} from "vue";
|
|||||||
import Color from "color";
|
import Color from "color";
|
||||||
|
|
||||||
|
|
||||||
export const MIN_EXECUTION_TIME = 60 // give at least one full minute for each tranche to trigger
|
|
||||||
export const DEFAULT_SLIPPAGE = 0.0030;
|
|
||||||
export const MIN_SLIPPAGE = 0.0001;
|
|
||||||
|
|
||||||
|
|
||||||
// Builders are data objects which store a configuration state
|
// Builders are data objects which store a configuration state
|
||||||
// the component name must match a corresponding Vue component in the BuilderFactory.vue component, which is responsible
|
// the component name must match a corresponding Vue component in the BuilderFactory.vue component, which is responsible
|
||||||
// for instantiating the UI component for a given builder dictionary, based on its builder.component field.
|
// for instantiating the UI component for a given builder dictionary, based on its builder.component field.
|
||||||
@@ -68,6 +63,7 @@ export const useChartOrderStore = defineStore('chart_orders', () => {
|
|||||||
const meanRange = ref(1)
|
const meanRange = ref(1)
|
||||||
|
|
||||||
const drawing = ref(false)
|
const drawing = ref(false)
|
||||||
|
const drew = ref(true) // true if at least one of the points has been drawn already
|
||||||
|
|
||||||
function newOrder() {
|
function newOrder() {
|
||||||
const order = newDefaultOrder()
|
const order = newDefaultOrder()
|
||||||
@@ -97,7 +93,7 @@ export const useChartOrderStore = defineStore('chart_orders', () => {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
chartReady, selectedSymbol, intervalSecs, baseToken, quoteToken, price,
|
chartReady, selectedSymbol, intervalSecs, baseToken, quoteToken, price,
|
||||||
orders, drawing, newOrder, removeOrder, resetOrders, meanRange,
|
orders, drawing, drew, newOrder, removeOrder, resetOrders, meanRange,
|
||||||
showPoolSelection,
|
showPoolSelection,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -198,8 +194,9 @@ export function timesliceTranches() {
|
|||||||
|
|
||||||
export function builderDefaults(builder, defaults) {
|
export function builderDefaults(builder, defaults) {
|
||||||
for (const k in defaults)
|
for (const k in defaults)
|
||||||
if (builder[k] === undefined)
|
if (!Object.prototype.hasOwnProperty.call(builder, k)) {
|
||||||
builder[k] = defaults[k] instanceof Function ? defaults[k]() : defaults[k]
|
builder[k] = defaults[k] instanceof Function ? defaults[k]() : defaults[k]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function linearWeights(num, skew) {
|
export function linearWeights(num, skew) {
|
||||||
|
|||||||
@@ -8,11 +8,15 @@
|
|||||||
import { loadFonts } from './webfontloader'
|
import { loadFonts } from './webfontloader'
|
||||||
import vuetify from './vuetify'
|
import vuetify from './vuetify'
|
||||||
import {pinia} from '../store/pinia.js'
|
import {pinia} from '../store/pinia.js'
|
||||||
import router from '../router'
|
import {setRouter} from '../router/router.js'
|
||||||
|
import {newRouter} from '../router/newRouter.js'
|
||||||
import vsp from "vue-scroll-picker";
|
import vsp from "vue-scroll-picker";
|
||||||
|
|
||||||
import "vue-scroll-picker/lib/style.css";
|
import "vue-scroll-picker/lib/style.css";
|
||||||
|
|
||||||
|
const router = newRouter();
|
||||||
|
setRouter(router)
|
||||||
|
|
||||||
export function registerPlugins (app) {
|
export function registerPlugins (app) {
|
||||||
loadFonts().catch((e)=>console.error('Could not load fonts!',e))
|
loadFonts().catch((e)=>console.error('Could not load fonts!',e))
|
||||||
app
|
app
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ function makeColors(isLight) {
|
|||||||
"on-warning": ink,
|
"on-warning": ink,
|
||||||
"on-error": ink,
|
"on-error": ink,
|
||||||
}
|
}
|
||||||
console.log('colors', isLight?'light':'dark', colors)
|
// console.log('colors', isLight?'light':'dark', colors)
|
||||||
return colors;
|
return colors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,50 +0,0 @@
|
|||||||
// Composables
|
|
||||||
import { createRouter, createWebHistory } from 'vue-router'
|
|
||||||
|
|
||||||
const routes = [
|
|
||||||
{
|
|
||||||
path: '/',
|
|
||||||
component: () => import('@/layouts/chart/ChartLayout.vue'),
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
name: 'App',
|
|
||||||
path: '/',
|
|
||||||
// route level code-splitting
|
|
||||||
// this generates a separate chunk (about.[hash].js) for this route
|
|
||||||
// which is lazy-loaded when the route is visited.
|
|
||||||
component: () => import('@/components/chart/ChartPlaceOrder.vue'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Order',
|
|
||||||
path: '/order',
|
|
||||||
// route level code-splitting
|
|
||||||
// this generates a separate chunk (about.[hash].js) for this route
|
|
||||||
// which is lazy-loaded when the route is visited.
|
|
||||||
component: () => import('@/components/chart/ChartPlaceOrder.vue'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Assets',
|
|
||||||
path: '/assets',
|
|
||||||
// route level code-splitting
|
|
||||||
// this generates a separate chunk (about.[hash].js) for this route
|
|
||||||
// which is lazy-loaded when the route is visited.
|
|
||||||
component: () => import('@/components/chart/ChartVault.vue'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Status',
|
|
||||||
path: '/status',
|
|
||||||
// route level code-splitting
|
|
||||||
// this generates a separate chunk (about.[hash].js) for this route
|
|
||||||
// which is lazy-loaded when the route is visited.
|
|
||||||
component: () => import('@/components/chart/ChartStatus.vue'),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
const router = createRouter({
|
|
||||||
history: createWebHistory(process.env.BASE_URL),
|
|
||||||
routes,
|
|
||||||
})
|
|
||||||
|
|
||||||
export default router
|
|
||||||
10
src/router/newRouter.js
Normal file
10
src/router/newRouter.js
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
// Composables
|
||||||
|
import {createRouter, createWebHistory} from 'vue-router'
|
||||||
|
import {routes} from "@/router/routes.js";
|
||||||
|
|
||||||
|
export function newRouter() {
|
||||||
|
return createRouter({
|
||||||
|
history: createWebHistory(process.env.BASE_URL),
|
||||||
|
routes,
|
||||||
|
})
|
||||||
|
}
|
||||||
3
src/router/router.js
Normal file
3
src/router/router.js
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
export let router = null
|
||||||
|
|
||||||
|
export function setRouter (r) { router = r }
|
||||||
45
src/router/routes.js
Normal file
45
src/router/routes.js
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
export const routes = [
|
||||||
|
{
|
||||||
|
path: '/',
|
||||||
|
component: () => import('@/layouts/chart/ChartLayout.vue'),
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
name: 'App',
|
||||||
|
path: '/',
|
||||||
|
// route level code-splitting
|
||||||
|
// this generates a separate chunk (about.[hash].js) for this route
|
||||||
|
// which is lazy-loaded when the route is visited.
|
||||||
|
component: () => import('@/components/chart/ChartPlaceOrder.vue'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Shared',
|
||||||
|
path: '/shared/:code',
|
||||||
|
component: () => import('@/components/chart/Shared.vue')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Order',
|
||||||
|
path: '/order',
|
||||||
|
// route level code-splitting
|
||||||
|
// this generates a separate chunk (about.[hash].js) for this route
|
||||||
|
// which is lazy-loaded when the route is visited.
|
||||||
|
component: () => import('@/components/chart/ChartPlaceOrder.vue'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Assets',
|
||||||
|
path: '/assets',
|
||||||
|
// route level code-splitting
|
||||||
|
// this generates a separate chunk (about.[hash].js) for this route
|
||||||
|
// which is lazy-loaded when the route is visited.
|
||||||
|
component: () => import('@/components/chart/ChartVault.vue'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Status',
|
||||||
|
path: '/status',
|
||||||
|
// route level code-splitting
|
||||||
|
// this generates a separate chunk (about.[hash].js) for this route
|
||||||
|
// which is lazy-loaded when the route is visited.
|
||||||
|
component: () => import('@/components/chart/ChartStatus.vue'),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]
|
||||||
88
src/share.js
Normal file
88
src/share.js
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
import {useChartOrderStore} from "@/orderbuild.js";
|
||||||
|
import {changeIntervalSecs, onChartReady, setSymbol, widget} from "@/charts/chart.js";
|
||||||
|
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();
|
||||||
|
const s = useStore()
|
||||||
|
const sym = co.selectedSymbol
|
||||||
|
console.log('symbol', sym)
|
||||||
|
const data = {
|
||||||
|
version: 1,
|
||||||
|
chainId: s.chainId,
|
||||||
|
orders: co.orders,
|
||||||
|
symbol: {
|
||||||
|
base: {a: sym.base.a, s: sym.base.s},
|
||||||
|
quote: {a: sym.quote.a, s: sym.quote.s},
|
||||||
|
route: {
|
||||||
|
fee: sym.fee,
|
||||||
|
exchange: sym.exchangeId,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
period: co.intervalSecs,
|
||||||
|
}
|
||||||
|
const json = JSON.stringify(data)
|
||||||
|
console.log('sharing data', json, data)
|
||||||
|
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 async function loadShareUrl(code) {
|
||||||
|
// console.log('loading share url', code)
|
||||||
|
const data = await new Promise((resolve, reject) => {
|
||||||
|
// Set a timeout (e.g., 8 seconds)
|
||||||
|
const timeout = setTimeout(() => {
|
||||||
|
reject(new Error('Timed out waiting for response from server'));
|
||||||
|
}, 8000);
|
||||||
|
|
||||||
|
socket.emit('shared', code, (response) => {
|
||||||
|
clearTimeout(timeout);
|
||||||
|
resolve(response);
|
||||||
|
});
|
||||||
|
}).catch(err => {
|
||||||
|
// Optional: show error to user or log it
|
||||||
|
console.error('Failed to load shared URL:', err.message);
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
if (data===null) return false
|
||||||
|
console.log('loaded shared orders data', data)
|
||||||
|
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}`;
|
||||||
|
const symbol = lookupSymbol(ticker)
|
||||||
|
if (symbol===null) {
|
||||||
|
console.error('could not find symbol for ticker', ticker)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
s.chainId = data.chainId
|
||||||
|
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
|
||||||
|
changeIntervalSecs(data.period)
|
||||||
|
onChartReady(()=>{
|
||||||
|
setSymbol(symbol)
|
||||||
|
.catch((e)=>console.error('could not set symbol', e))
|
||||||
|
})
|
||||||
|
track('shared')
|
||||||
|
console.log('loaded orders', s.chainId, co.orders)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function takeSnapshot() {
|
||||||
|
const screenshotCanvas = await widget.takeClientScreenshot();
|
||||||
|
return await new Promise((resolve) => screenshotCanvas.toBlob(resolve));
|
||||||
|
}
|
||||||
157
src/socket.js
157
src/socket.js
@@ -1,155 +1,8 @@
|
|||||||
import {io} from "socket.io-client";
|
import {io} from "socket.io-client";
|
||||||
import {useStore} from "@/store/store.js";
|
|
||||||
import {ensureVault, flushOrders} from "@/blockchain/wallet.js";
|
|
||||||
import {parseElaboratedOrderStatus} from "@/blockchain/orderlib.js";
|
|
||||||
import { DataFeed } from "./charts/datafeed";
|
|
||||||
import {notifyFillEvent} from "@/notify.js";
|
|
||||||
import {refreshOHLCSubs} from "@/blockchain/ohlcs.js";
|
|
||||||
|
|
||||||
export const socket = io(import.meta.env.VITE_WS_URL || undefined, {transports: ["websocket"]})
|
const socketOptions = {
|
||||||
|
transport: ['polling', 'websocket'],
|
||||||
socket.on('connect', () => {
|
pingInterval: 25000, // PING every 25 seconds
|
||||||
console.log(new Date(), 'ws connected')
|
pingTimeout: 60000 // Timeout if no PONG in 60 seconds
|
||||||
const s = useStore();
|
|
||||||
s.connected = true
|
|
||||||
if (s.chainId && s.account)
|
|
||||||
socket.emit('address', s.chainId, s.account)
|
|
||||||
refreshOHLCSubs()
|
|
||||||
})
|
|
||||||
|
|
||||||
socket.on('disconnect', () => {
|
|
||||||
console.log(new Date(), 'ws disconnected')
|
|
||||||
useStore().connected = false
|
|
||||||
})
|
|
||||||
|
|
||||||
socket.on('approvedRegion', (approved) => {
|
|
||||||
console.log('approved region', approved)
|
|
||||||
useStore().regionApproved = approved
|
|
||||||
})
|
|
||||||
|
|
||||||
socket.on('approvedWallet', (approved) => {
|
|
||||||
console.log('approved wallet', approved)
|
|
||||||
useStore().walletApproved = approved
|
|
||||||
})
|
|
||||||
|
|
||||||
socket.on('p', async (chainId, pool, price) => {
|
|
||||||
console.log('pool price from message', chainId, pool, price)
|
|
||||||
const s = useStore()
|
|
||||||
if( s.chainId !== chainId )
|
|
||||||
return
|
|
||||||
s.poolPrices[[chainId,pool]] = price
|
|
||||||
})
|
|
||||||
|
|
||||||
socket.on('ohlc', async (chainId, poolPeriod, ohlcs) => {
|
|
||||||
// console.log('pool bars', poolPeriod, ohlcs)
|
|
||||||
if (ohlcs && ohlcs.length) {
|
|
||||||
const split = poolPeriod.indexOf('|')
|
|
||||||
const pool = poolPeriod.slice(0,split)
|
|
||||||
useStore().poolPrices[[chainId, pool]] = parseFloat(ohlcs[ohlcs.length - 1][4]) // closing price
|
|
||||||
}
|
|
||||||
DataFeed.poolCallback(chainId, poolPeriod, ohlcs)
|
|
||||||
})
|
|
||||||
|
|
||||||
socket.on('vb', async (chainId, vault, balances) => {
|
|
||||||
const s = useStore()
|
|
||||||
if( s.chainId !== chainId )
|
|
||||||
return
|
|
||||||
console.log('vb', vault, balances)
|
|
||||||
s.vaultBalances[vault] = JSON.parse(balances)
|
|
||||||
console.log('vault balances', vault, s.vaultBalances[vault])
|
|
||||||
})
|
|
||||||
|
|
||||||
socket.on('vaults', (chainId, owner, vaults)=>{
|
|
||||||
const s = useStore()
|
|
||||||
console.log('vaults', chainId, owner, vaults)
|
|
||||||
if( s.chainId !== chainId || s.account !== owner )
|
|
||||||
return
|
|
||||||
if( vaults.length > s.vaults.length ) {
|
|
||||||
s.vaults = vaults
|
|
||||||
if( vaults.length ) {
|
|
||||||
const vault = vaults[0]
|
|
||||||
flushOrders(chainId, owner, 0, vault)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
socket.on('mark.usd', (chainId, token, value)=>{
|
|
||||||
const s = useStore()
|
|
||||||
s.markPrices[`${chainId}|${token}`] = Number(value)
|
|
||||||
// console.log('mark.usd', token, value)
|
|
||||||
})
|
|
||||||
|
|
||||||
function handleOrderStatus(chainId, vault, orderIndex, status) {
|
|
||||||
const s = useStore()
|
|
||||||
if( s.chainId !== chainId )
|
|
||||||
return
|
|
||||||
// message 'o' is a single order status
|
|
||||||
const parsed = parseElaboratedOrderStatus(chainId, status);
|
|
||||||
console.log('o', chainId, vault, orderIndex, status, parsed)
|
|
||||||
if( !(vault in s.orders) )
|
|
||||||
s.orders[vault] = {}
|
|
||||||
s.orders[vault][orderIndex] = parsed
|
|
||||||
}
|
}
|
||||||
|
export const socket = io(import.meta.env.VITE_WS_URL || undefined, socketOptions)
|
||||||
socket.on('os', (chainId, vault, orders) => {
|
|
||||||
// message 'os' has multiple order statuses
|
|
||||||
console.log('os', orders)
|
|
||||||
for( const [orderIndex, status] of orders )
|
|
||||||
handleOrderStatus(chainId, vault, orderIndex, status)
|
|
||||||
})
|
|
||||||
|
|
||||||
socket.on( 'o', handleOrderStatus)
|
|
||||||
|
|
||||||
socket.on( 'of', (chainId, vault, orderIndex, filled)=>{
|
|
||||||
const s = useStore()
|
|
||||||
if( s.chainId !== chainId )
|
|
||||||
return
|
|
||||||
console.log('of', chainId, vault, orderIndex, filled)
|
|
||||||
if( !(vault in s.orders) ) {
|
|
||||||
console.log('warning: got fill on an order in an unknown vault')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if( !(orderIndex in s.orders[vault]) ) {
|
|
||||||
console.log(`warning: orderIndex ${orderIndex} missing from vault ${vault}`)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const status = s.orders[vault][orderIndex]
|
|
||||||
console.log('apply fills', status, filled)
|
|
||||||
|
|
||||||
let orderIn = 0n
|
|
||||||
let orderOut = 0n
|
|
||||||
for (const i in filled) {
|
|
||||||
const ts = status.trancheStatus[i]
|
|
||||||
let filledIn = 0n
|
|
||||||
let filledOut = 0n
|
|
||||||
const [activationTime, fills] = filled[i];
|
|
||||||
const numOld = ts.fills.length;
|
|
||||||
for (let i=0; i<fills.length; i++) {
|
|
||||||
const fill = fills[i]
|
|
||||||
let [tx, time, fi, fo, fee] = fill
|
|
||||||
fi = BigInt(fi)
|
|
||||||
fo = BigInt(fo)
|
|
||||||
fee = BigInt(fee)
|
|
||||||
filledIn += fi
|
|
||||||
filledOut += fo
|
|
||||||
if (i>=numOld) {
|
|
||||||
// new fill detected
|
|
||||||
const f = {tx, time, filledIn: fi, filledOut: fo, fee, filled: status.order.amountIsInput ? fi : fo};
|
|
||||||
console.log('new fill', f)
|
|
||||||
notifyFillEvent(chainId, status, i, f).catch((e)=>console.log('fill notification error', e))
|
|
||||||
ts.fills.push(f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ts.filledIn = filledIn
|
|
||||||
ts.filledOut = filledOut
|
|
||||||
ts.activationTime = activationTime
|
|
||||||
orderIn += filledIn
|
|
||||||
orderOut += filledOut
|
|
||||||
}
|
|
||||||
status.filledIn = orderIn
|
|
||||||
status.filledOut = orderOut
|
|
||||||
status.filled = status.order.amountIsInput ? orderIn : orderOut
|
|
||||||
|
|
||||||
console.log('apply fills completed', status)
|
|
||||||
})
|
|
||||||
|
|||||||
165
src/socketInit.js
Normal file
165
src/socketInit.js
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
import {socket} from "@/socket.js";
|
||||||
|
import {useStore} from "@/store/store.js";
|
||||||
|
import {flushWalletTransactions} from "@/blockchain/wallet.js";
|
||||||
|
import {parseElaboratedOrderStatus} from "@/blockchain/orderlib.js";
|
||||||
|
import {DataFeed} from "./charts/datafeed";
|
||||||
|
import {notifyFillEvent} from "@/notify.js";
|
||||||
|
import {refreshOHLCSubs} from "@/blockchain/ohlcs.js";
|
||||||
|
|
||||||
|
socket.on('connect', () => {
|
||||||
|
console.log('ws connected')
|
||||||
|
const s = useStore();
|
||||||
|
s.connected = true
|
||||||
|
if (s.chainId && s.account)
|
||||||
|
socket.emit('address', s.chainId, s.account)
|
||||||
|
refreshOHLCSubs()
|
||||||
|
})
|
||||||
|
|
||||||
|
socket.on('disconnect', () => {
|
||||||
|
console.log('ws disconnected')
|
||||||
|
useStore().connected = false
|
||||||
|
})
|
||||||
|
|
||||||
|
socket.on('connect_error', (err) => {
|
||||||
|
console.log('ws connect error', err)
|
||||||
|
useStore().connected = false
|
||||||
|
})
|
||||||
|
|
||||||
|
socket.on('error', (err) => {
|
||||||
|
console.log('ws error', err)
|
||||||
|
useStore().connected = false
|
||||||
|
})
|
||||||
|
|
||||||
|
socket.on('approvedRegion', (approved) => {
|
||||||
|
console.log('approved region', approved)
|
||||||
|
useStore().regionApproved = approved
|
||||||
|
})
|
||||||
|
|
||||||
|
socket.on('approvedWallet', (approved) => {
|
||||||
|
console.log('approved wallet', approved)
|
||||||
|
useStore().walletApproved = approved
|
||||||
|
})
|
||||||
|
|
||||||
|
socket.on('p', async (chainId, pool, price) => {
|
||||||
|
console.log('pool price from message', chainId, pool, price)
|
||||||
|
const s = useStore()
|
||||||
|
if( s.chainId !== chainId )
|
||||||
|
return
|
||||||
|
s.poolPrices[[chainId,pool]] = price
|
||||||
|
})
|
||||||
|
|
||||||
|
socket.on('ohlc', async (chainId, poolPeriod, ohlcs) => {
|
||||||
|
// console.log('pool bars', poolPeriod, ohlcs)
|
||||||
|
if (ohlcs && ohlcs.length) {
|
||||||
|
const split = poolPeriod.indexOf('|')
|
||||||
|
const pool = poolPeriod.slice(0,split)
|
||||||
|
useStore().poolPrices[[chainId, pool]] = parseFloat(ohlcs[ohlcs.length - 1][4]) // closing price
|
||||||
|
}
|
||||||
|
DataFeed.poolCallback(chainId, poolPeriod, ohlcs)
|
||||||
|
})
|
||||||
|
|
||||||
|
socket.on('vb', async (chainId, vault, balances) => {
|
||||||
|
const s = useStore()
|
||||||
|
if( s.chainId !== chainId )
|
||||||
|
return
|
||||||
|
console.log('vb', vault, balances)
|
||||||
|
s.vaultBalances[vault] = JSON.parse(balances)
|
||||||
|
console.log('vault balances', vault, s.vaultBalances[vault])
|
||||||
|
})
|
||||||
|
|
||||||
|
socket.on('vaults', (chainId, owner, vaults)=>{
|
||||||
|
const s = useStore()
|
||||||
|
console.log('vaults', chainId, owner, vaults)
|
||||||
|
if( s.chainId !== chainId || s.account !== owner )
|
||||||
|
return
|
||||||
|
if( vaults.length > s.vaults.length ) {
|
||||||
|
s.vaults = vaults
|
||||||
|
if( vaults.length ) {
|
||||||
|
const vault = vaults[0]
|
||||||
|
flushWalletTransactions(chainId, owner, 0, vault)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
socket.on('mark.usd', (chainId, token, value)=>{
|
||||||
|
const s = useStore()
|
||||||
|
s.markPrices[`${chainId}|${token}`] = Number(value)
|
||||||
|
// console.log('mark.usd', token, value)
|
||||||
|
})
|
||||||
|
|
||||||
|
function handleOrderStatus(chainId, vault, orderIndex, status) {
|
||||||
|
const s = useStore()
|
||||||
|
if( s.chainId !== chainId )
|
||||||
|
return
|
||||||
|
// message 'o' is a single order status
|
||||||
|
const parsed = parseElaboratedOrderStatus(chainId, status);
|
||||||
|
// console.log('o', chainId, vault, orderIndex, status, parsed)
|
||||||
|
if( !(vault in s.orders) )
|
||||||
|
s.orders[vault] = {}
|
||||||
|
s.orders[vault][orderIndex] = parsed
|
||||||
|
}
|
||||||
|
|
||||||
|
socket.on('os', (chainId, vault, orders) => {
|
||||||
|
// message 'os' has multiple order statuses
|
||||||
|
console.log('os', orders)
|
||||||
|
for( const [orderIndex, status] of orders )
|
||||||
|
handleOrderStatus(chainId, vault, orderIndex, status)
|
||||||
|
})
|
||||||
|
|
||||||
|
socket.on( 'o', handleOrderStatus)
|
||||||
|
|
||||||
|
socket.on( 'of', (chainId, vault, orderIndex, filled)=>{
|
||||||
|
const s = useStore()
|
||||||
|
if( s.chainId !== chainId )
|
||||||
|
return
|
||||||
|
console.log('of', chainId, vault, orderIndex, filled)
|
||||||
|
if( !(vault in s.orders) ) {
|
||||||
|
console.log('warning: got fill on an order in an unknown vault')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if( !(orderIndex in s.orders[vault]) ) {
|
||||||
|
console.log(`warning: orderIndex ${orderIndex} missing from vault ${vault}`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const status = s.orders[vault][orderIndex]
|
||||||
|
console.log('apply fills', status, filled)
|
||||||
|
|
||||||
|
let orderIn = 0n
|
||||||
|
let orderOut = 0n
|
||||||
|
for (const i in filled) {
|
||||||
|
const ts = status.trancheStatus[i]
|
||||||
|
let filledIn = 0n
|
||||||
|
let filledOut = 0n
|
||||||
|
const [activationTime, fills] = filled[i];
|
||||||
|
const numOld = ts.fills.length;
|
||||||
|
for (let i=0; i<fills.length; i++) {
|
||||||
|
const fill = fills[i]
|
||||||
|
let [tx, time, fi, fo, fee] = fill
|
||||||
|
fi = BigInt(fi)
|
||||||
|
fo = BigInt(fo)
|
||||||
|
fee = BigInt(fee)
|
||||||
|
filledIn += fi
|
||||||
|
filledOut += fo
|
||||||
|
if (i>=numOld) {
|
||||||
|
// new fill detected
|
||||||
|
const f = {tx, time, filledIn: fi, filledOut: fo, fee, filled: status.order.amountIsInput ? fi : fo};
|
||||||
|
console.log('new fill', f)
|
||||||
|
notifyFillEvent(chainId, status, i, f).catch((e)=>console.log('fill notification error', e))
|
||||||
|
ts.fills.push(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ts.filledIn = filledIn
|
||||||
|
ts.filledOut = filledOut
|
||||||
|
ts.activationTime = activationTime
|
||||||
|
orderIn += filledIn
|
||||||
|
orderOut += filledOut
|
||||||
|
}
|
||||||
|
status.filledIn = orderIn
|
||||||
|
status.filledOut = orderOut
|
||||||
|
status.filled = status.order.amountIsInput ? orderIn : orderOut
|
||||||
|
|
||||||
|
console.log('apply fills completed', status)
|
||||||
|
})
|
||||||
|
|
||||||
|
console.log('initialized socketio')
|
||||||
@@ -224,4 +224,3 @@ export const usePrefStore = defineStore({
|
|||||||
return {inverted, acceptedTos, selectedTicker, selectedTimeframe, timezone, newbie, hints, }
|
return {inverted, acceptedTos, selectedTicker, selectedTimeframe, timezone, newbie, hints, }
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
19
src/track.js
19
src/track.js
@@ -1,12 +1,17 @@
|
|||||||
export let tracking_enabled = true
|
export let tracking_enabled = window.gtag !== undefined
|
||||||
|
|
||||||
export function track(event, info) {
|
if(tracking_enabled) {
|
||||||
|
// console.log('gtag', tracking_enabled)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.log('tracking disabled')
|
||||||
|
}
|
||||||
|
|
||||||
|
export function track(...args) {
|
||||||
if (tracking_enabled) {
|
if (tracking_enabled) {
|
||||||
if (window.gtag !== undefined)
|
try {
|
||||||
window.gtag('event', event, info)
|
window.gtag('event', ...args)
|
||||||
else {
|
} catch (e) {
|
||||||
console.log('gtag not available')
|
|
||||||
tracking_enabled = false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,9 +16,9 @@ const versionPromise = fetch('/contract/version.json').then(_json('version.json'
|
|||||||
const metadataPromise = fetch('/metadata.json').then(_json('metadata.json'))
|
const metadataPromise = fetch('/metadata.json').then(_json('metadata.json'))
|
||||||
|
|
||||||
export const version = await versionPromise
|
export const version = await versionPromise
|
||||||
console.log('version', version)
|
// console.log('version', version)
|
||||||
export const metadata = await metadataPromise
|
export const metadata = await metadataPromise
|
||||||
console.log('metadata', metadata)
|
// console.log('metadata', metadata)
|
||||||
|
|
||||||
export function dexorderAddress(chainId) { return version['chainInfo'][chainId]['dexorder'] }
|
export function dexorderAddress(chainId) { return version['chainInfo'][chainId]['dexorder'] }
|
||||||
export function factoryAddress(chainId) { return version['chainInfo'][chainId]['factory'] }
|
export function factoryAddress(chainId) { return version['chainInfo'][chainId]['factory'] }
|
||||||
|
|||||||
@@ -24,6 +24,17 @@ export default defineConfig({
|
|||||||
configFile: 'src/styles/settings.scss',
|
configFile: 'src/styles/settings.scss',
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
/*
|
||||||
|
{
|
||||||
|
name: 'log-http-requests',
|
||||||
|
configureServer(server) {
|
||||||
|
server.middlewares.use((req, res, next) => {
|
||||||
|
console.log(`${req.method} ${req.url}`)
|
||||||
|
next()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
*/
|
||||||
],
|
],
|
||||||
define: { 'process.env': {} },
|
define: { 'process.env': {} },
|
||||||
resolve: {
|
resolve: {
|
||||||
|
|||||||
270
yarn.lock
270
yarn.lock
@@ -650,11 +650,35 @@
|
|||||||
find-cache-dir "^3.3.2"
|
find-cache-dir "^3.3.2"
|
||||||
upath "^2.0.1"
|
upath "^2.0.1"
|
||||||
|
|
||||||
|
acorn-jsx-walk@^2.0.0:
|
||||||
|
version "2.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/acorn-jsx-walk/-/acorn-jsx-walk-2.0.0.tgz#a5ed648264e68282d7c2aead80216bfdf232573a"
|
||||||
|
integrity sha512-uuo6iJj4D4ygkdzd6jPtcxs8vZgDX9YFIkqczGImoypX2fQ4dVImmu3UzA4ynixCIMTrEOWW+95M2HuBaCEOVA==
|
||||||
|
|
||||||
acorn-jsx@^5.3.2:
|
acorn-jsx@^5.3.2:
|
||||||
version "5.3.2"
|
version "5.3.2"
|
||||||
resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937"
|
resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937"
|
||||||
integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==
|
integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==
|
||||||
|
|
||||||
|
acorn-loose@^8.4.0:
|
||||||
|
version "8.5.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/acorn-loose/-/acorn-loose-8.5.0.tgz#11fbd555827d551dd16ca812c078e382400b1bc7"
|
||||||
|
integrity sha512-ppga7pybjwX2HSJv5ayHe6QG4wmNS1RQ2wjBMFTVnOj0h8Rxsmtc6fnVzINqHSSRz23sTe9IL3UAt/PU9gc4FA==
|
||||||
|
dependencies:
|
||||||
|
acorn "^8.14.0"
|
||||||
|
|
||||||
|
acorn-walk@^8.3.4:
|
||||||
|
version "8.3.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.4.tgz#794dd169c3977edf4ba4ea47583587c5866236b7"
|
||||||
|
integrity sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==
|
||||||
|
dependencies:
|
||||||
|
acorn "^8.11.0"
|
||||||
|
|
||||||
|
acorn@^8.11.0, acorn@^8.14.1:
|
||||||
|
version "8.14.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.1.tgz#721d5dc10f7d5b5609a891773d47731796935dfb"
|
||||||
|
integrity sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==
|
||||||
|
|
||||||
acorn@^8.14.0, acorn@^8.9.0:
|
acorn@^8.14.0, acorn@^8.9.0:
|
||||||
version "8.14.0"
|
version "8.14.0"
|
||||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.0.tgz#063e2c70cac5fb4f6467f0b11152e04c682795b0"
|
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.0.tgz#063e2c70cac5fb4f6467f0b11152e04c682795b0"
|
||||||
@@ -675,6 +699,16 @@ ajv@^6.12.4:
|
|||||||
json-schema-traverse "^0.4.1"
|
json-schema-traverse "^0.4.1"
|
||||||
uri-js "^4.2.2"
|
uri-js "^4.2.2"
|
||||||
|
|
||||||
|
ajv@^8.17.1:
|
||||||
|
version "8.17.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.17.1.tgz#37d9a5c776af6bc92d7f4f9510eba4c0a60d11a6"
|
||||||
|
integrity sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==
|
||||||
|
dependencies:
|
||||||
|
fast-deep-equal "^3.1.3"
|
||||||
|
fast-uri "^3.0.1"
|
||||||
|
json-schema-traverse "^1.0.0"
|
||||||
|
require-from-string "^2.0.2"
|
||||||
|
|
||||||
ansi-regex@^5.0.1:
|
ansi-regex@^5.0.1:
|
||||||
version "5.0.1"
|
version "5.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304"
|
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304"
|
||||||
@@ -755,7 +789,7 @@ caniuse-lite@^1.0.30001688:
|
|||||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001695.tgz#39dfedd8f94851132795fdf9b79d29659ad9c4d4"
|
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001695.tgz#39dfedd8f94851132795fdf9b79d29659ad9c4d4"
|
||||||
integrity sha512-vHyLade6wTgI2u1ec3WQBxv+2BrTERV28UXQu9LO6lZ9pYeMk34vjXFLOxo1A4UBA8XTL4njRQZdno/yYaSmWw==
|
integrity sha512-vHyLade6wTgI2u1ec3WQBxv+2BrTERV28UXQu9LO6lZ9pYeMk34vjXFLOxo1A4UBA8XTL4njRQZdno/yYaSmWw==
|
||||||
|
|
||||||
chalk@^4.0.0:
|
chalk@^4.0.0, chalk@^4.1.0:
|
||||||
version "4.1.2"
|
version "4.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
|
resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
|
||||||
integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
|
integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
|
||||||
@@ -810,6 +844,11 @@ color@^4.2.3:
|
|||||||
color-convert "^2.0.1"
|
color-convert "^2.0.1"
|
||||||
color-string "^1.9.0"
|
color-string "^1.9.0"
|
||||||
|
|
||||||
|
commander@^13.1.0:
|
||||||
|
version "13.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/commander/-/commander-13.1.0.tgz#776167db68c78f38dcce1f9b8d7b8b9a488abf46"
|
||||||
|
integrity sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==
|
||||||
|
|
||||||
commondir@^1.0.1:
|
commondir@^1.0.1:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
|
resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
|
||||||
@@ -888,6 +927,34 @@ defu@^6.1.4:
|
|||||||
resolved "https://registry.yarnpkg.com/defu/-/defu-6.1.4.tgz#4e0c9cf9ff68fe5f3d7f2765cc1a012dfdcb0479"
|
resolved "https://registry.yarnpkg.com/defu/-/defu-6.1.4.tgz#4e0c9cf9ff68fe5f3d7f2765cc1a012dfdcb0479"
|
||||||
integrity sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==
|
integrity sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==
|
||||||
|
|
||||||
|
dependency-cruiser@^16.10.1:
|
||||||
|
version "16.10.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/dependency-cruiser/-/dependency-cruiser-16.10.1.tgz#6d9dac4e6a3825a48b7755da8d19f684ec986954"
|
||||||
|
integrity sha512-Uw8/emAfzD+Zcua6Hfg1wCnskJd2QSRGKw5tUWrCtA8PBSz+n/zfUYCTjFi9MwdiTA5oecN93FBvh9jJhTLs4A==
|
||||||
|
dependencies:
|
||||||
|
acorn "^8.14.1"
|
||||||
|
acorn-jsx "^5.3.2"
|
||||||
|
acorn-jsx-walk "^2.0.0"
|
||||||
|
acorn-loose "^8.4.0"
|
||||||
|
acorn-walk "^8.3.4"
|
||||||
|
ajv "^8.17.1"
|
||||||
|
commander "^13.1.0"
|
||||||
|
enhanced-resolve "^5.18.1"
|
||||||
|
ignore "^7.0.3"
|
||||||
|
interpret "^3.1.1"
|
||||||
|
is-installed-globally "^1.0.0"
|
||||||
|
json5 "^2.2.3"
|
||||||
|
memoize "^10.1.0"
|
||||||
|
picocolors "^1.1.1"
|
||||||
|
picomatch "^4.0.2"
|
||||||
|
prompts "^2.4.2"
|
||||||
|
rechoir "^0.8.0"
|
||||||
|
safe-regex "^2.1.1"
|
||||||
|
semver "^7.7.1"
|
||||||
|
teamcity-service-messages "^0.1.14"
|
||||||
|
tsconfig-paths-webpack-plugin "^4.2.0"
|
||||||
|
watskeburt "^4.2.3"
|
||||||
|
|
||||||
destr@^2.0.3:
|
destr@^2.0.3:
|
||||||
version "2.0.3"
|
version "2.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/destr/-/destr-2.0.3.tgz#7f9e97cb3d16dbdca7be52aca1644ce402cfe449"
|
resolved "https://registry.yarnpkg.com/destr/-/destr-2.0.3.tgz#7f9e97cb3d16dbdca7be52aca1644ce402cfe449"
|
||||||
@@ -931,6 +998,14 @@ engine.io-parser@~5.2.1:
|
|||||||
resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-5.2.3.tgz#00dc5b97b1f233a23c9398d0209504cf5f94d92f"
|
resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-5.2.3.tgz#00dc5b97b1f233a23c9398d0209504cf5f94d92f"
|
||||||
integrity sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==
|
integrity sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==
|
||||||
|
|
||||||
|
enhanced-resolve@^5.18.1, enhanced-resolve@^5.7.0:
|
||||||
|
version "5.18.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.18.1.tgz#728ab082f8b7b6836de51f1637aab5d3b9568faf"
|
||||||
|
integrity sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==
|
||||||
|
dependencies:
|
||||||
|
graceful-fs "^4.2.4"
|
||||||
|
tapable "^2.2.0"
|
||||||
|
|
||||||
entities@^4.5.0:
|
entities@^4.5.0:
|
||||||
version "4.5.0"
|
version "4.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48"
|
resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48"
|
||||||
@@ -1134,6 +1209,11 @@ fast-levenshtein@^2.0.6:
|
|||||||
resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
|
resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
|
||||||
integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==
|
integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==
|
||||||
|
|
||||||
|
fast-uri@^3.0.1:
|
||||||
|
version "3.0.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.0.6.tgz#88f130b77cfaea2378d56bf970dea21257a68748"
|
||||||
|
integrity sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==
|
||||||
|
|
||||||
fastq@^1.6.0:
|
fastq@^1.6.0:
|
||||||
version "1.18.0"
|
version "1.18.0"
|
||||||
resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.18.0.tgz#d631d7e25faffea81887fe5ea8c9010e1b36fee0"
|
resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.18.0.tgz#d631d7e25faffea81887fe5ea8c9010e1b36fee0"
|
||||||
@@ -1216,6 +1296,11 @@ fsevents@~2.3.2:
|
|||||||
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6"
|
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6"
|
||||||
integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==
|
integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==
|
||||||
|
|
||||||
|
function-bind@^1.1.2:
|
||||||
|
version "1.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c"
|
||||||
|
integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==
|
||||||
|
|
||||||
gensync@^1.0.0-beta.2:
|
gensync@^1.0.0-beta.2:
|
||||||
version "1.0.0-beta.2"
|
version "1.0.0-beta.2"
|
||||||
resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0"
|
resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0"
|
||||||
@@ -1261,6 +1346,13 @@ glob@^7.1.3:
|
|||||||
once "^1.3.0"
|
once "^1.3.0"
|
||||||
path-is-absolute "^1.0.0"
|
path-is-absolute "^1.0.0"
|
||||||
|
|
||||||
|
global-directory@^4.0.1:
|
||||||
|
version "4.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/global-directory/-/global-directory-4.0.1.tgz#4d7ac7cfd2cb73f304c53b8810891748df5e361e"
|
||||||
|
integrity sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==
|
||||||
|
dependencies:
|
||||||
|
ini "4.1.1"
|
||||||
|
|
||||||
globals@^11.1.0:
|
globals@^11.1.0:
|
||||||
version "11.12.0"
|
version "11.12.0"
|
||||||
resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e"
|
resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e"
|
||||||
@@ -1285,6 +1377,11 @@ globby@^14.0.2:
|
|||||||
slash "^5.1.0"
|
slash "^5.1.0"
|
||||||
unicorn-magic "^0.1.0"
|
unicorn-magic "^0.1.0"
|
||||||
|
|
||||||
|
graceful-fs@^4.2.4:
|
||||||
|
version "4.2.11"
|
||||||
|
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3"
|
||||||
|
integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==
|
||||||
|
|
||||||
graphemer@^1.4.0:
|
graphemer@^1.4.0:
|
||||||
version "1.4.0"
|
version "1.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6"
|
resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6"
|
||||||
@@ -1295,6 +1392,13 @@ has-flag@^4.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
|
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
|
||||||
integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
|
integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
|
||||||
|
|
||||||
|
hasown@^2.0.2:
|
||||||
|
version "2.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003"
|
||||||
|
integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==
|
||||||
|
dependencies:
|
||||||
|
function-bind "^1.1.2"
|
||||||
|
|
||||||
ignore@^5.2.0, ignore@^5.2.4:
|
ignore@^5.2.0, ignore@^5.2.4:
|
||||||
version "5.3.2"
|
version "5.3.2"
|
||||||
resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5"
|
resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5"
|
||||||
@@ -1336,11 +1440,28 @@ inherits@2:
|
|||||||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
|
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
|
||||||
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
||||||
|
|
||||||
|
ini@4.1.1:
|
||||||
|
version "4.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/ini/-/ini-4.1.1.tgz#d95b3d843b1e906e56d6747d5447904ff50ce7a1"
|
||||||
|
integrity sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==
|
||||||
|
|
||||||
|
interpret@^3.1.1:
|
||||||
|
version "3.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/interpret/-/interpret-3.1.1.tgz#5be0ceed67ca79c6c4bc5cf0d7ee843dcea110c4"
|
||||||
|
integrity sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==
|
||||||
|
|
||||||
is-arrayish@^0.3.1:
|
is-arrayish@^0.3.1:
|
||||||
version "0.3.2"
|
version "0.3.2"
|
||||||
resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03"
|
resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03"
|
||||||
integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==
|
integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==
|
||||||
|
|
||||||
|
is-core-module@^2.16.0:
|
||||||
|
version "2.16.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.16.1.tgz#2a98801a849f43e2add644fbb6bc6229b19a4ef4"
|
||||||
|
integrity sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==
|
||||||
|
dependencies:
|
||||||
|
hasown "^2.0.2"
|
||||||
|
|
||||||
is-extglob@^2.1.1:
|
is-extglob@^2.1.1:
|
||||||
version "2.1.1"
|
version "2.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
|
resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
|
||||||
@@ -1353,6 +1474,14 @@ is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3:
|
|||||||
dependencies:
|
dependencies:
|
||||||
is-extglob "^2.1.1"
|
is-extglob "^2.1.1"
|
||||||
|
|
||||||
|
is-installed-globally@^1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-1.0.0.tgz#08952c43758c33d815692392f7f8437b9e436d5a"
|
||||||
|
integrity sha512-K55T22lfpQ63N4KEN57jZUAaAYqYHEe8veb/TycJRk9DdSCLLcovXz/mL6mOnhQaZsQGwPhuFopdQIlqGSEjiQ==
|
||||||
|
dependencies:
|
||||||
|
global-directory "^4.0.1"
|
||||||
|
is-path-inside "^4.0.0"
|
||||||
|
|
||||||
is-number@^7.0.0:
|
is-number@^7.0.0:
|
||||||
version "7.0.0"
|
version "7.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
|
resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
|
||||||
@@ -1363,6 +1492,11 @@ is-path-inside@^3.0.3:
|
|||||||
resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283"
|
resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283"
|
||||||
integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==
|
integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==
|
||||||
|
|
||||||
|
is-path-inside@^4.0.0:
|
||||||
|
version "4.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-4.0.0.tgz#805aeb62c47c1b12fc3fd13bfb3ed1e7430071db"
|
||||||
|
integrity sha512-lJJV/5dYS+RcL8uQdBDW9c9uWFLLBNRyFhnAKXw5tVqLlKZ4RMGZKv+YQ/IA3OhD+RpbJa1LLFM1FQPGyIXvOA==
|
||||||
|
|
||||||
isexe@^2.0.0:
|
isexe@^2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
|
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
|
||||||
@@ -1405,12 +1539,17 @@ json-schema-traverse@^0.4.1:
|
|||||||
resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
|
resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
|
||||||
integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==
|
integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==
|
||||||
|
|
||||||
|
json-schema-traverse@^1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2"
|
||||||
|
integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==
|
||||||
|
|
||||||
json-stable-stringify-without-jsonify@^1.0.1:
|
json-stable-stringify-without-jsonify@^1.0.1:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651"
|
resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651"
|
||||||
integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==
|
integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==
|
||||||
|
|
||||||
json5@^2.2.3:
|
json5@^2.2.2, json5@^2.2.3:
|
||||||
version "2.2.3"
|
version "2.2.3"
|
||||||
resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283"
|
resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283"
|
||||||
integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==
|
integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==
|
||||||
@@ -1422,6 +1561,11 @@ keyv@^4.5.3:
|
|||||||
dependencies:
|
dependencies:
|
||||||
json-buffer "3.0.1"
|
json-buffer "3.0.1"
|
||||||
|
|
||||||
|
kleur@^3.0.3:
|
||||||
|
version "3.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e"
|
||||||
|
integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==
|
||||||
|
|
||||||
klona@^2.0.6:
|
klona@^2.0.6:
|
||||||
version "2.0.6"
|
version "2.0.6"
|
||||||
resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.6.tgz#85bffbf819c03b2f53270412420a4555ef882e22"
|
resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.6.tgz#85bffbf819c03b2f53270412420a4555ef882e22"
|
||||||
@@ -1503,6 +1647,13 @@ make-dir@^3.0.2:
|
|||||||
dependencies:
|
dependencies:
|
||||||
semver "^6.0.0"
|
semver "^6.0.0"
|
||||||
|
|
||||||
|
memoize@^10.1.0:
|
||||||
|
version "10.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/memoize/-/memoize-10.1.0.tgz#32a9d09da985a1ab518dfe9fd52d14d1d130446f"
|
||||||
|
integrity sha512-MMbFhJzh4Jlg/poq1si90XRlTZRDHVqdlz2mPyGJ6kqMpyHUyVpDd5gpFAvVehW64+RA1eKE9Yt8aSLY7w2Kgg==
|
||||||
|
dependencies:
|
||||||
|
mimic-function "^5.0.1"
|
||||||
|
|
||||||
merge2@^1.3.0:
|
merge2@^1.3.0:
|
||||||
version "1.4.1"
|
version "1.4.1"
|
||||||
resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
|
resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
|
||||||
@@ -1516,6 +1667,11 @@ micromatch@^4.0.5, micromatch@^4.0.8:
|
|||||||
braces "^3.0.3"
|
braces "^3.0.3"
|
||||||
picomatch "^2.3.1"
|
picomatch "^2.3.1"
|
||||||
|
|
||||||
|
mimic-function@^5.0.1:
|
||||||
|
version "5.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/mimic-function/-/mimic-function-5.0.1.tgz#acbe2b3349f99b9deaca7fb70e48b83e94e67076"
|
||||||
|
integrity sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==
|
||||||
|
|
||||||
minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2:
|
minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2:
|
||||||
version "3.1.2"
|
version "3.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
|
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
|
||||||
@@ -1523,6 +1679,11 @@ minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2:
|
|||||||
dependencies:
|
dependencies:
|
||||||
brace-expansion "^1.1.7"
|
brace-expansion "^1.1.7"
|
||||||
|
|
||||||
|
minimist@^1.2.6:
|
||||||
|
version "1.2.8"
|
||||||
|
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c"
|
||||||
|
integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==
|
||||||
|
|
||||||
minipass@^3.0.0:
|
minipass@^3.0.0:
|
||||||
version "3.3.6"
|
version "3.3.6"
|
||||||
resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.3.6.tgz#7bba384db3a1520d18c9c0e5251c3444e95dd94a"
|
resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.3.6.tgz#7bba384db3a1520d18c9c0e5251c3444e95dd94a"
|
||||||
@@ -1686,6 +1847,11 @@ path-key@^3.1.0:
|
|||||||
resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375"
|
resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375"
|
||||||
integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==
|
integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==
|
||||||
|
|
||||||
|
path-parse@^1.0.7:
|
||||||
|
version "1.0.7"
|
||||||
|
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
|
||||||
|
integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
|
||||||
|
|
||||||
path-type@^5.0.0:
|
path-type@^5.0.0:
|
||||||
version "5.0.0"
|
version "5.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/path-type/-/path-type-5.0.0.tgz#14b01ed7aea7ddf9c7c3f46181d4d04f9c785bb8"
|
resolved "https://registry.yarnpkg.com/path-type/-/path-type-5.0.0.tgz#14b01ed7aea7ddf9c7c3f46181d4d04f9c785bb8"
|
||||||
@@ -1777,6 +1943,14 @@ prelude-ls@^1.2.1:
|
|||||||
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"
|
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"
|
||||||
integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==
|
integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==
|
||||||
|
|
||||||
|
prompts@^2.4.2:
|
||||||
|
version "2.4.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069"
|
||||||
|
integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==
|
||||||
|
dependencies:
|
||||||
|
kleur "^3.0.3"
|
||||||
|
sisteransi "^1.0.5"
|
||||||
|
|
||||||
punycode@^2.1.0:
|
punycode@^2.1.0:
|
||||||
version "2.3.1"
|
version "2.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5"
|
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5"
|
||||||
@@ -1800,11 +1974,37 @@ readdirp@^4.0.1:
|
|||||||
resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-4.1.1.tgz#bd115327129672dc47f87408f05df9bd9ca3ef55"
|
resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-4.1.1.tgz#bd115327129672dc47f87408f05df9bd9ca3ef55"
|
||||||
integrity sha512-h80JrZu/MHUZCyHu5ciuoI0+WxsCxzxJTILn6Fs8rxSnFPh+UVHYfeIxK1nVGugMqkfC4vJcBOYbkfkwYK0+gw==
|
integrity sha512-h80JrZu/MHUZCyHu5ciuoI0+WxsCxzxJTILn6Fs8rxSnFPh+UVHYfeIxK1nVGugMqkfC4vJcBOYbkfkwYK0+gw==
|
||||||
|
|
||||||
|
rechoir@^0.8.0:
|
||||||
|
version "0.8.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.8.0.tgz#49f866e0d32146142da3ad8f0eff352b3215ff22"
|
||||||
|
integrity sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==
|
||||||
|
dependencies:
|
||||||
|
resolve "^1.20.0"
|
||||||
|
|
||||||
|
regexp-tree@~0.1.1:
|
||||||
|
version "0.1.27"
|
||||||
|
resolved "https://registry.yarnpkg.com/regexp-tree/-/regexp-tree-0.1.27.tgz#2198f0ef54518ffa743fe74d983b56ffd631b6cd"
|
||||||
|
integrity sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==
|
||||||
|
|
||||||
|
require-from-string@^2.0.2:
|
||||||
|
version "2.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909"
|
||||||
|
integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==
|
||||||
|
|
||||||
resolve-from@^4.0.0:
|
resolve-from@^4.0.0:
|
||||||
version "4.0.0"
|
version "4.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6"
|
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6"
|
||||||
integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==
|
integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==
|
||||||
|
|
||||||
|
resolve@^1.20.0:
|
||||||
|
version "1.22.10"
|
||||||
|
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.10.tgz#b663e83ffb09bbf2386944736baae803029b8b39"
|
||||||
|
integrity sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==
|
||||||
|
dependencies:
|
||||||
|
is-core-module "^2.16.0"
|
||||||
|
path-parse "^1.0.7"
|
||||||
|
supports-preserve-symlinks-flag "^1.0.0"
|
||||||
|
|
||||||
reusify@^1.0.4:
|
reusify@^1.0.4:
|
||||||
version "1.0.4"
|
version "1.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
|
resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
|
||||||
@@ -1836,6 +2036,13 @@ run-parallel@^1.1.9:
|
|||||||
dependencies:
|
dependencies:
|
||||||
queue-microtask "^1.2.2"
|
queue-microtask "^1.2.2"
|
||||||
|
|
||||||
|
safe-regex@^2.1.1:
|
||||||
|
version "2.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-2.1.1.tgz#f7128f00d056e2fe5c11e81a1324dd974aadced2"
|
||||||
|
integrity sha512-rx+x8AMzKb5Q5lQ95Zoi6ZbJqwCLkqi3XuJXp5P3rT8OEc6sZCJG5AE5dU3lsgRr/F4Bs31jSlVN+j5KrsGu9A==
|
||||||
|
dependencies:
|
||||||
|
regexp-tree "~0.1.1"
|
||||||
|
|
||||||
sass@^1.60.0:
|
sass@^1.60.0:
|
||||||
version "1.83.4"
|
version "1.83.4"
|
||||||
resolved "https://registry.yarnpkg.com/sass/-/sass-1.83.4.tgz#5ccf60f43eb61eeec300b780b8dcb85f16eec6d1"
|
resolved "https://registry.yarnpkg.com/sass/-/sass-1.83.4.tgz#5ccf60f43eb61eeec300b780b8dcb85f16eec6d1"
|
||||||
@@ -1862,6 +2069,11 @@ semver@^7.3.6, semver@^7.6.3:
|
|||||||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143"
|
resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143"
|
||||||
integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==
|
integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==
|
||||||
|
|
||||||
|
semver@^7.7.1:
|
||||||
|
version "7.7.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.1.tgz#abd5098d82b18c6c81f6074ff2647fd3e7220c9f"
|
||||||
|
integrity sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==
|
||||||
|
|
||||||
shebang-command@^2.0.0:
|
shebang-command@^2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea"
|
resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea"
|
||||||
@@ -1881,6 +2093,11 @@ simple-swizzle@^0.2.2:
|
|||||||
dependencies:
|
dependencies:
|
||||||
is-arrayish "^0.3.1"
|
is-arrayish "^0.3.1"
|
||||||
|
|
||||||
|
sisteransi@^1.0.5:
|
||||||
|
version "1.0.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed"
|
||||||
|
integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==
|
||||||
|
|
||||||
slash@^5.1.0:
|
slash@^5.1.0:
|
||||||
version "5.1.0"
|
version "5.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/slash/-/slash-5.1.0.tgz#be3adddcdf09ac38eebe8dcdc7b1a57a75b095ce"
|
resolved "https://registry.yarnpkg.com/slash/-/slash-5.1.0.tgz#be3adddcdf09ac38eebe8dcdc7b1a57a75b095ce"
|
||||||
@@ -1921,6 +2138,11 @@ strip-ansi@^6.0.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
ansi-regex "^5.0.1"
|
ansi-regex "^5.0.1"
|
||||||
|
|
||||||
|
strip-bom@^3.0.0:
|
||||||
|
version "3.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3"
|
||||||
|
integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==
|
||||||
|
|
||||||
strip-json-comments@^3.1.1:
|
strip-json-comments@^3.1.1:
|
||||||
version "3.1.1"
|
version "3.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"
|
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"
|
||||||
@@ -1940,6 +2162,16 @@ supports-color@^7.1.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
has-flag "^4.0.0"
|
has-flag "^4.0.0"
|
||||||
|
|
||||||
|
supports-preserve-symlinks-flag@^1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"
|
||||||
|
integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
|
||||||
|
|
||||||
|
tapable@^2.2.0, tapable@^2.2.1:
|
||||||
|
version "2.2.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0"
|
||||||
|
integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==
|
||||||
|
|
||||||
tar@^6.2.1:
|
tar@^6.2.1:
|
||||||
version "6.2.1"
|
version "6.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/tar/-/tar-6.2.1.tgz#717549c541bc3c2af15751bea94b1dd068d4b03a"
|
resolved "https://registry.yarnpkg.com/tar/-/tar-6.2.1.tgz#717549c541bc3c2af15751bea94b1dd068d4b03a"
|
||||||
@@ -1952,6 +2184,11 @@ tar@^6.2.1:
|
|||||||
mkdirp "^1.0.3"
|
mkdirp "^1.0.3"
|
||||||
yallist "^4.0.0"
|
yallist "^4.0.0"
|
||||||
|
|
||||||
|
teamcity-service-messages@^0.1.14:
|
||||||
|
version "0.1.14"
|
||||||
|
resolved "https://registry.yarnpkg.com/teamcity-service-messages/-/teamcity-service-messages-0.1.14.tgz#193d420a5e4aef8e5e50b8c39e7865e08fbb5d8a"
|
||||||
|
integrity sha512-29aQwaHqm8RMX74u2o/h1KbMLP89FjNiMxD9wbF2BbWOnbM+q+d1sCEC+MqCc4QW3NJykn77OMpTFw/xTHIc0w==
|
||||||
|
|
||||||
text-table@^0.2.0:
|
text-table@^0.2.0:
|
||||||
version "0.2.0"
|
version "0.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
|
resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
|
||||||
@@ -1969,6 +2206,25 @@ to-regex-range@^5.0.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
is-number "^7.0.0"
|
is-number "^7.0.0"
|
||||||
|
|
||||||
|
tsconfig-paths-webpack-plugin@^4.2.0:
|
||||||
|
version "4.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/tsconfig-paths-webpack-plugin/-/tsconfig-paths-webpack-plugin-4.2.0.tgz#f7459a8ed1dd4cf66ad787aefc3d37fff3cf07fc"
|
||||||
|
integrity sha512-zbem3rfRS8BgeNK50Zz5SIQgXzLafiHjOwUAvk/38/o1jHn/V5QAgVUcz884or7WYcPaH3N2CIfUc2u0ul7UcA==
|
||||||
|
dependencies:
|
||||||
|
chalk "^4.1.0"
|
||||||
|
enhanced-resolve "^5.7.0"
|
||||||
|
tapable "^2.2.1"
|
||||||
|
tsconfig-paths "^4.1.2"
|
||||||
|
|
||||||
|
tsconfig-paths@^4.1.2:
|
||||||
|
version "4.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz#ef78e19039133446d244beac0fd6a1632e2d107c"
|
||||||
|
integrity sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==
|
||||||
|
dependencies:
|
||||||
|
json5 "^2.2.2"
|
||||||
|
minimist "^1.2.6"
|
||||||
|
strip-bom "^3.0.0"
|
||||||
|
|
||||||
tslib@2.7.0:
|
tslib@2.7.0:
|
||||||
version "2.7.0"
|
version "2.7.0"
|
||||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.7.0.tgz#d9b40c5c40ab59e8738f297df3087bf1a2690c01"
|
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.7.0.tgz#d9b40c5c40ab59e8738f297df3087bf1a2690c01"
|
||||||
@@ -2078,6 +2334,11 @@ util-deprecate@^1.0.2:
|
|||||||
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
||||||
integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==
|
integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==
|
||||||
|
|
||||||
|
uuid@^11.1.0:
|
||||||
|
version "11.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/uuid/-/uuid-11.1.0.tgz#9549028be1753bb934fc96e2bca09bb4105ae912"
|
||||||
|
integrity sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==
|
||||||
|
|
||||||
vite-plugin-vuetify@^1.0.0:
|
vite-plugin-vuetify@^1.0.0:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/vite-plugin-vuetify/-/vite-plugin-vuetify-1.0.2.tgz#d1777c63aa1b3a308756461b3d0299fd101ee8f4"
|
resolved "https://registry.yarnpkg.com/vite-plugin-vuetify/-/vite-plugin-vuetify-1.0.2.tgz#d1777c63aa1b3a308756461b3d0299fd101ee8f4"
|
||||||
@@ -2144,6 +2405,11 @@ vuetify@^3.4.6:
|
|||||||
resolved "https://registry.yarnpkg.com/vuetify/-/vuetify-3.7.7.tgz#f40e06abf81c426a29aee53e166fb7fcb05e98cd"
|
resolved "https://registry.yarnpkg.com/vuetify/-/vuetify-3.7.7.tgz#f40e06abf81c426a29aee53e166fb7fcb05e98cd"
|
||||||
integrity sha512-YqKnRo2+BZWQRzfxHVA/5reQo1eLvbS9Z6N+Lvaot/5lpdi7JWooMr/hWoCr7/QPBGRcXArHppqIB+hMfPlsXw==
|
integrity sha512-YqKnRo2+BZWQRzfxHVA/5reQo1eLvbS9Z6N+Lvaot/5lpdi7JWooMr/hWoCr7/QPBGRcXArHppqIB+hMfPlsXw==
|
||||||
|
|
||||||
|
watskeburt@^4.2.3:
|
||||||
|
version "4.2.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/watskeburt/-/watskeburt-4.2.3.tgz#fc830280f466e201b55c517024aaf3aad2f5121e"
|
||||||
|
integrity sha512-uG9qtQYoHqAsnT711nG5iZc/8M5inSmkGCOp7pFaytKG2aTfIca7p//CjiVzAE4P7hzaYuCozMjNNaLgmhbK5g==
|
||||||
|
|
||||||
webfontloader@^1.0.0:
|
webfontloader@^1.0.0:
|
||||||
version "1.6.28"
|
version "1.6.28"
|
||||||
resolved "https://registry.yarnpkg.com/webfontloader/-/webfontloader-1.6.28.tgz#db786129253cb6e8eae54c2fb05f870af6675bae"
|
resolved "https://registry.yarnpkg.com/webfontloader/-/webfontloader-1.6.28.tgz#db786129253cb6e8eae54c2fb05f870af6675bae"
|
||||||
|
|||||||
Reference in New Issue
Block a user