mirror of
https://github.com/orionprotocol/sdk.git
synced 2026-03-13 21:52:36 +03:00
39
.eslintrc.js
39
.eslintrc.js
@@ -6,11 +6,13 @@ module.exports = {
|
||||
node: true,
|
||||
},
|
||||
extends: [
|
||||
'standard',
|
||||
'standard-with-typescript',
|
||||
'eslint:recommended',
|
||||
'plugin:@typescript-eslint/eslint-recommended',
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'plugin:@typescript-eslint/recommended-requiring-type-checking',
|
||||
'plugin:@typescript-eslint/strict',
|
||||
'plugin:import/recommended',
|
||||
'plugin:import/typescript'
|
||||
],
|
||||
parser: '@typescript-eslint/parser',
|
||||
@@ -26,6 +28,39 @@ module.exports = {
|
||||
'@typescript-eslint',
|
||||
],
|
||||
rules: {
|
||||
"@typescript-eslint/strict-boolean-expressions": [
|
||||
"error",
|
||||
{
|
||||
"allowNullableObject": true,
|
||||
"allowString": false,
|
||||
"allowNumber": false,
|
||||
"allowNullableBoolean": false,
|
||||
"allowNullableString": false,
|
||||
"allowNullableNumber": false,
|
||||
"allowAny": false,
|
||||
"allowNullableEnum": false
|
||||
}
|
||||
],
|
||||
"eqeqeq": "error",
|
||||
"@typescript-eslint/consistent-type-definitions": [
|
||||
"warn",
|
||||
"type"
|
||||
],
|
||||
"@typescript-eslint/indent": [
|
||||
"error",
|
||||
2,
|
||||
{
|
||||
"SwitchCase": 1,
|
||||
"ignoredNodes": [
|
||||
"TSTypeParameterInstantiation"
|
||||
]
|
||||
}
|
||||
],
|
||||
"@typescript-eslint/promise-function-async": 0,
|
||||
"import/no-cycle": "error",
|
||||
"@typescript-eslint/space-before-function-paren": 0,
|
||||
"@typescript-eslint/comma-dangle": 0,
|
||||
"@typescript-eslint/semi": 0,
|
||||
"comma-dangle": 0,
|
||||
"semi": 0,
|
||||
"space-before-function-paren": 0,
|
||||
@@ -61,6 +96,8 @@ module.exports = {
|
||||
2,
|
||||
{
|
||||
ignoreComments: true,
|
||||
ignoreUrls: true,
|
||||
ignoreTemplateLiterals: true,
|
||||
}
|
||||
],
|
||||
'import/extensions': [
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/sh
|
||||
. "$(dirname "$0")/_/husky.sh"
|
||||
|
||||
npm test
|
||||
# npm test
|
||||
|
||||
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@@ -11,5 +11,6 @@
|
||||
"./README.md": [
|
||||
"# Orion Protocol SDK"
|
||||
]
|
||||
}
|
||||
},
|
||||
"typescript.tsdk": "node_modules/typescript/lib"
|
||||
}
|
||||
296
package-lock.json
generated
296
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@orionprotocol/sdk",
|
||||
"version": "0.17.5-rc.0",
|
||||
"version": "0.17.7-rc.1",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@orionprotocol/sdk",
|
||||
"version": "0.17.5-rc.0",
|
||||
"version": "0.17.7-rc.1",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@ethersproject/abstract-signer": "^5.7.0",
|
||||
@@ -52,6 +52,7 @@
|
||||
"eslint-plugin-import": "^2.27.5",
|
||||
"eslint-plugin-n": "^15.6.1",
|
||||
"eslint-plugin-promise": "^6.1.1",
|
||||
"http-terminator": "^3.2.0",
|
||||
"husky": "^7.0.4",
|
||||
"is-ci": "^3.0.1",
|
||||
"jest": "^29.4.2",
|
||||
@@ -3835,6 +3836,12 @@
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
|
||||
},
|
||||
"node_modules/boolean": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz",
|
||||
"integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
@@ -4549,6 +4556,18 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/delay": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delay/-/delay-5.0.0.tgz",
|
||||
"integrity": "sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/delayed-stream": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
@@ -5648,12 +5667,39 @@
|
||||
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/fast-json-stringify": {
|
||||
"version": "2.7.13",
|
||||
"resolved": "https://registry.npmjs.org/fast-json-stringify/-/fast-json-stringify-2.7.13.tgz",
|
||||
"integrity": "sha512-ar+hQ4+OIurUGjSJD1anvYSDcUflywhKjfxnsW4TBTD7+u0tJufv6DKRWoQk3vI6YBOWMoz0TQtfbe7dxbQmvA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"ajv": "^6.11.0",
|
||||
"deepmerge": "^4.2.2",
|
||||
"rfdc": "^1.2.0",
|
||||
"string-similarity": "^4.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/fast-levenshtein": {
|
||||
"version": "2.0.6",
|
||||
"resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
|
||||
"integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/fast-printf": {
|
||||
"version": "1.6.9",
|
||||
"resolved": "https://registry.npmjs.org/fast-printf/-/fast-printf-1.6.9.tgz",
|
||||
"integrity": "sha512-FChq8hbz65WMj4rstcQsFB0O7Cy++nmbNfLYnD9cYv2cRn8EG6k/MGn9kO/tjO66t09DLDugj3yL+V2o6Qftrg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"boolean": "^3.1.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/fastest-levenshtein": {
|
||||
"version": "1.0.16",
|
||||
"resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz",
|
||||
@@ -5984,6 +6030,21 @@
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/globalthis": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz",
|
||||
"integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"define-properties": "^1.1.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/globby": {
|
||||
"version": "11.1.0",
|
||||
"resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
|
||||
@@ -6179,6 +6240,33 @@
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/http-terminator": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/http-terminator/-/http-terminator-3.2.0.tgz",
|
||||
"integrity": "sha512-JLjck1EzPaWjsmIf8bziM3p9fgR1Y3JoUKAkyYEbZmFrIvJM6I8vVJfBGWlEtV9IWOvzNnaTtjuwZeBY2kwB4g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"delay": "^5.0.0",
|
||||
"p-wait-for": "^3.2.0",
|
||||
"roarr": "^7.0.4",
|
||||
"type-fest": "^2.3.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/http-terminator/node_modules/type-fest": {
|
||||
"version": "2.19.0",
|
||||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz",
|
||||
"integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=12.20"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/human-signals": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
|
||||
@@ -9093,6 +9181,15 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/p-finally": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
|
||||
"integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/p-limit": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
|
||||
@@ -9123,6 +9220,18 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/p-timeout": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz",
|
||||
"integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"p-finally": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/p-try": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
|
||||
@@ -9132,6 +9241,21 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/p-wait-for": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/p-wait-for/-/p-wait-for-3.2.0.tgz",
|
||||
"integrity": "sha512-wpgERjNkLrBiFmkMEjuZJEWKKDrNfHCKA1OhyN1wg1FrLkULbviEy6py1AyJUgZ72YWFbZ38FIpnqvVqAlDUwA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"p-timeout": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/parent-module": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
|
||||
@@ -9657,6 +9781,12 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/rfdc": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz",
|
||||
"integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/rimraf": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
|
||||
@@ -9681,6 +9811,23 @@
|
||||
"inherits": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/roarr": {
|
||||
"version": "7.14.2",
|
||||
"resolved": "https://registry.npmjs.org/roarr/-/roarr-7.14.2.tgz",
|
||||
"integrity": "sha512-9vC/n53oTJEyAl0ZJczKjJ5mJheb2DaqiaNSnxDWrqiRTrozxSvSq05yCTN+Fc7e5mhDRTTZ14RlMu1x4tEc0w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"boolean": "^3.1.4",
|
||||
"fast-json-stringify": "^2.7.10",
|
||||
"fast-printf": "^1.6.9",
|
||||
"globalthis": "^1.0.2",
|
||||
"safe-stable-stringify": "^2.4.1",
|
||||
"semver-compare": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/run-parallel": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
|
||||
@@ -9746,6 +9893,15 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/safe-stable-stringify": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.2.tgz",
|
||||
"integrity": "sha512-gMxvPJYhP0O9n2pvcfYfIuYgbledAOJFcqRThtPRmjscaipiwcwPPKLytpVzMkG2HAN87Qmo2d4PtGiri1dSLA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/safer-buffer": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||
@@ -9783,6 +9939,12 @@
|
||||
"semver": "bin/semver.js"
|
||||
}
|
||||
},
|
||||
"node_modules/semver-compare": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz",
|
||||
"integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/send": {
|
||||
"version": "0.18.0",
|
||||
"resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz",
|
||||
@@ -10029,6 +10191,12 @@
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/string-similarity": {
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/string-similarity/-/string-similarity-4.0.4.tgz",
|
||||
"integrity": "sha512-/q/8Q4Bl4ZKAPjj8WerIBJWALKkaPRfrvhfF8k/B23i4nzrlRj2/go1m90In7nG/3XDSbOo0+pu6RvCTM9RGMQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/string-width": {
|
||||
"version": "4.2.3",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
|
||||
@@ -13947,6 +14115,12 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"boolean": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz",
|
||||
"integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==",
|
||||
"dev": true
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
@@ -14496,6 +14670,12 @@
|
||||
"object-keys": "^1.1.1"
|
||||
}
|
||||
},
|
||||
"delay": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delay/-/delay-5.0.0.tgz",
|
||||
"integrity": "sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw==",
|
||||
"dev": true
|
||||
},
|
||||
"delayed-stream": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
@@ -15325,12 +15505,33 @@
|
||||
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
|
||||
"dev": true
|
||||
},
|
||||
"fast-json-stringify": {
|
||||
"version": "2.7.13",
|
||||
"resolved": "https://registry.npmjs.org/fast-json-stringify/-/fast-json-stringify-2.7.13.tgz",
|
||||
"integrity": "sha512-ar+hQ4+OIurUGjSJD1anvYSDcUflywhKjfxnsW4TBTD7+u0tJufv6DKRWoQk3vI6YBOWMoz0TQtfbe7dxbQmvA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ajv": "^6.11.0",
|
||||
"deepmerge": "^4.2.2",
|
||||
"rfdc": "^1.2.0",
|
||||
"string-similarity": "^4.0.1"
|
||||
}
|
||||
},
|
||||
"fast-levenshtein": {
|
||||
"version": "2.0.6",
|
||||
"resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
|
||||
"integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
|
||||
"dev": true
|
||||
},
|
||||
"fast-printf": {
|
||||
"version": "1.6.9",
|
||||
"resolved": "https://registry.npmjs.org/fast-printf/-/fast-printf-1.6.9.tgz",
|
||||
"integrity": "sha512-FChq8hbz65WMj4rstcQsFB0O7Cy++nmbNfLYnD9cYv2cRn8EG6k/MGn9kO/tjO66t09DLDugj3yL+V2o6Qftrg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"boolean": "^3.1.4"
|
||||
}
|
||||
},
|
||||
"fastest-levenshtein": {
|
||||
"version": "1.0.16",
|
||||
"resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz",
|
||||
@@ -15575,6 +15776,15 @@
|
||||
"integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
|
||||
"dev": true
|
||||
},
|
||||
"globalthis": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz",
|
||||
"integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"define-properties": "^1.1.3"
|
||||
}
|
||||
},
|
||||
"globby": {
|
||||
"version": "11.1.0",
|
||||
"resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
|
||||
@@ -15726,6 +15936,26 @@
|
||||
"toidentifier": "1.0.1"
|
||||
}
|
||||
},
|
||||
"http-terminator": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/http-terminator/-/http-terminator-3.2.0.tgz",
|
||||
"integrity": "sha512-JLjck1EzPaWjsmIf8bziM3p9fgR1Y3JoUKAkyYEbZmFrIvJM6I8vVJfBGWlEtV9IWOvzNnaTtjuwZeBY2kwB4g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"delay": "^5.0.0",
|
||||
"p-wait-for": "^3.2.0",
|
||||
"roarr": "^7.0.4",
|
||||
"type-fest": "^2.3.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"type-fest": {
|
||||
"version": "2.19.0",
|
||||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz",
|
||||
"integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"human-signals": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
|
||||
@@ -17854,6 +18084,12 @@
|
||||
"integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==",
|
||||
"dev": true
|
||||
},
|
||||
"p-finally": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
|
||||
"integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==",
|
||||
"dev": true
|
||||
},
|
||||
"p-limit": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
|
||||
@@ -17872,12 +18108,30 @@
|
||||
"p-limit": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"p-timeout": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz",
|
||||
"integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"p-finally": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"p-try": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
|
||||
"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
|
||||
"dev": true
|
||||
},
|
||||
"p-wait-for": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/p-wait-for/-/p-wait-for-3.2.0.tgz",
|
||||
"integrity": "sha512-wpgERjNkLrBiFmkMEjuZJEWKKDrNfHCKA1OhyN1wg1FrLkULbviEy6py1AyJUgZ72YWFbZ38FIpnqvVqAlDUwA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"p-timeout": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"parent-module": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
|
||||
@@ -18261,6 +18515,12 @@
|
||||
"integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
|
||||
"dev": true
|
||||
},
|
||||
"rfdc": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz",
|
||||
"integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==",
|
||||
"dev": true
|
||||
},
|
||||
"rimraf": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
|
||||
@@ -18279,6 +18539,20 @@
|
||||
"inherits": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"roarr": {
|
||||
"version": "7.14.2",
|
||||
"resolved": "https://registry.npmjs.org/roarr/-/roarr-7.14.2.tgz",
|
||||
"integrity": "sha512-9vC/n53oTJEyAl0ZJczKjJ5mJheb2DaqiaNSnxDWrqiRTrozxSvSq05yCTN+Fc7e5mhDRTTZ14RlMu1x4tEc0w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"boolean": "^3.1.4",
|
||||
"fast-json-stringify": "^2.7.10",
|
||||
"fast-printf": "^1.6.9",
|
||||
"globalthis": "^1.0.2",
|
||||
"safe-stable-stringify": "^2.4.1",
|
||||
"semver-compare": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"run-parallel": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
|
||||
@@ -18313,6 +18587,12 @@
|
||||
"is-regex": "^1.1.4"
|
||||
}
|
||||
},
|
||||
"safe-stable-stringify": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.2.tgz",
|
||||
"integrity": "sha512-gMxvPJYhP0O9n2pvcfYfIuYgbledAOJFcqRThtPRmjscaipiwcwPPKLytpVzMkG2HAN87Qmo2d4PtGiri1dSLA==",
|
||||
"dev": true
|
||||
},
|
||||
"safer-buffer": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||
@@ -18340,6 +18620,12 @@
|
||||
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
|
||||
"dev": true
|
||||
},
|
||||
"semver-compare": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz",
|
||||
"integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==",
|
||||
"dev": true
|
||||
},
|
||||
"send": {
|
||||
"version": "0.18.0",
|
||||
"resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz",
|
||||
@@ -18550,6 +18836,12 @@
|
||||
"strip-ansi": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"string-similarity": {
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/string-similarity/-/string-similarity-4.0.4.tgz",
|
||||
"integrity": "sha512-/q/8Q4Bl4ZKAPjj8WerIBJWALKkaPRfrvhfF8k/B23i4nzrlRj2/go1m90In7nG/3XDSbOo0+pu6RvCTM9RGMQ==",
|
||||
"dev": true
|
||||
},
|
||||
"string-width": {
|
||||
"version": "4.2.3",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@orionprotocol/sdk",
|
||||
"version": "0.17.6",
|
||||
"version": "0.17.7-rc.3",
|
||||
"description": "Orion Protocol SDK",
|
||||
"main": "./lib/esm/index.js",
|
||||
"module": "./lib/esm/index.js",
|
||||
@@ -59,6 +59,7 @@
|
||||
"eslint-plugin-import": "^2.27.5",
|
||||
"eslint-plugin-n": "^15.6.1",
|
||||
"eslint-plugin-promise": "^6.1.1",
|
||||
"http-terminator": "^3.2.0",
|
||||
"husky": "^7.0.4",
|
||||
"is-ci": "^3.0.1",
|
||||
"jest": "^29.4.2",
|
||||
|
||||
@@ -2,7 +2,6 @@ import BigNumber from 'bignumber.js';
|
||||
import { ethers } from 'ethers';
|
||||
import clone from 'just-clone';
|
||||
import { ERC20__factory } from '@orionprotocol/contracts';
|
||||
import { utils } from '.';
|
||||
import { APPROVE_ERC20_GAS_LIMIT, NATIVE_CURRENCY_PRECISION } from './constants';
|
||||
import type {
|
||||
AggregatedBalanceRequirement, ApproveFix, Asset, BalanceIssue, BalanceRequirement, Source,
|
||||
@@ -14,11 +13,12 @@ export default class BalanceGuard {
|
||||
private readonly balances: Partial<
|
||||
Record<
|
||||
string,
|
||||
Record<
|
||||
'exchange' | 'wallet',
|
||||
BigNumber>
|
||||
Record<
|
||||
'exchange' | 'wallet',
|
||||
BigNumber
|
||||
>
|
||||
>
|
||||
>;
|
||||
>;
|
||||
|
||||
public readonly requirements: BalanceRequirement[] = [];
|
||||
|
||||
@@ -109,7 +109,7 @@ export default class BalanceGuard {
|
||||
}, []);
|
||||
}
|
||||
|
||||
private fixAllAutofixableBalanceIssues = async (
|
||||
private readonly fixAllAutofixableBalanceIssues = async (
|
||||
balanceIssues: BalanceIssue[],
|
||||
) => {
|
||||
const fixBalanceIssue = async (issue: BalanceIssue) => {
|
||||
@@ -146,8 +146,8 @@ export default class BalanceGuard {
|
||||
};
|
||||
await issue.fixes?.reduce(async (promise, item) => {
|
||||
await promise;
|
||||
if (item.type === 'byApprove') return approve(item);
|
||||
return promise;
|
||||
if (item.type === 'byApprove') { await approve(item); return; }
|
||||
await promise;
|
||||
}, Promise.resolve());
|
||||
};
|
||||
|
||||
@@ -155,7 +155,7 @@ export default class BalanceGuard {
|
||||
|
||||
await autofixableBalanceIssues.reduce(async (promise, item) => {
|
||||
await promise;
|
||||
return fixBalanceIssue(item);
|
||||
await fixBalanceIssue(item);
|
||||
}, Promise.resolve());
|
||||
|
||||
return balanceIssues.filter((item) => !autofixableBalanceIssues.includes(item));
|
||||
@@ -196,18 +196,18 @@ export default class BalanceGuard {
|
||||
const remainingBalance = remainingBalances[asset.name];
|
||||
if (!remainingBalance) throw new Error(`No ${asset.name} balance`);
|
||||
const itemsAmountSum = Object.values(items)
|
||||
.reduce<BigNumber>((p, c) => (c ? p.plus(c) : p), new BigNumber(0));
|
||||
.reduce<BigNumber>((p, c) => (c !== undefined ? p.plus(c) : p), new BigNumber(0));
|
||||
|
||||
remainingBalance.exchange = remainingBalance.exchange.minus(itemsAmountSum);
|
||||
if (remainingBalance.exchange.lt(0)) {
|
||||
const lackAmount = remainingBalance.exchange.abs();
|
||||
const exchangeBalance = this.balances?.[asset.name]?.exchange;
|
||||
const exchangeBalance = this.balances[asset.name]?.exchange;
|
||||
|
||||
balanceIssues.push({
|
||||
asset,
|
||||
sources: ['exchange'],
|
||||
message: `Not enough ${asset.name} on exchange balance. ` +
|
||||
`Needed: ${itemsAmountSum.toString()}, available: ${(exchangeBalance ?? '[UNDEFINED]')?.toString()}. ` +
|
||||
`Needed: ${itemsAmountSum.toString()}, available: ${(exchangeBalance ?? '[UNDEFINED]').toString()}. ` +
|
||||
`You need to deposit at least ${lackAmount.toString()} ${asset.name} into exchange contract`,
|
||||
});
|
||||
}
|
||||
@@ -223,7 +223,7 @@ export default class BalanceGuard {
|
||||
const remainingBalance = remainingBalances[asset.name];
|
||||
if (!remainingBalance) throw new Error(`No ${asset.name} balance`);
|
||||
const itemsAmountSum = Object.values(items)
|
||||
.reduce<BigNumber>((p, c) => (c ? p.plus(c) : p), new BigNumber(0));
|
||||
.reduce<BigNumber>((p, c) => (c !== undefined ? p.plus(c) : p), new BigNumber(0));
|
||||
|
||||
remainingBalance.exchange = remainingBalance.exchange.minus(itemsAmountSum);
|
||||
if (remainingBalance.exchange.lt(0)) {
|
||||
@@ -233,7 +233,7 @@ export default class BalanceGuard {
|
||||
if (asset.address === ethers.constants.AddressZero) {
|
||||
denormalizedAllowance = remainingBalance.wallet;
|
||||
} else {
|
||||
if (!spenderAddress) throw new Error(`Spender address is required for ${asset.name}`);
|
||||
if (spenderAddress === undefined) throw new Error(`Spender address is required for ${asset.name}`);
|
||||
const tokenContract = ERC20__factory.connect(asset.address, this.provider);
|
||||
const tokenDecimals = await tokenContract.decimals();
|
||||
const tokenAllowance = await tokenContract.allowance(walletAddress, spenderAddress);
|
||||
@@ -257,17 +257,17 @@ export default class BalanceGuard {
|
||||
const approveIsHelpful = approveAvailable.gte(lackAmount);
|
||||
const targetApprove = approvedWalletBalance.plus(lackAmount);
|
||||
|
||||
const exchangeBalance = this.balances?.[asset.name]?.exchange;
|
||||
const exchangeBalance = this.balances[asset.name]?.exchange;
|
||||
const available = exchangeBalance?.plus(approvedWalletBalance);
|
||||
|
||||
const issueMessage = `Not enough ${asset.name} on exchange + wallet balance. ` +
|
||||
`Needed: ${itemsAmountSum.toString()}, available: ${(available ?? '[UNDEFINED]')?.toString()} ` +
|
||||
`(exchange: ${(exchangeBalance ?? '[UNKNOWN]')?.toString()}, available (approved): ${approvedWalletBalance.toString()}).` +
|
||||
`Needed: ${itemsAmountSum.toString()}, available: ${(available ?? '[UNDEFINED]').toString()} ` +
|
||||
`(exchange: ${(exchangeBalance ?? '[UNKNOWN]').toString()}, available (approved): ${approvedWalletBalance.toString()}).` +
|
||||
` ${approveIsHelpful
|
||||
? `You need approve at least ${lackAmount.toString()} ${asset.name}`
|
||||
: 'Approve is not helpful'}`;
|
||||
if (approveIsHelpful) {
|
||||
if (!spenderAddress) throw new Error(`Spender address is required for ${asset.name}`);
|
||||
if (spenderAddress === undefined) throw new Error(`Spender address is required for ${asset.name}`);
|
||||
const resetRequired = await this.checkResetRequired(
|
||||
asset.address,
|
||||
spenderAddress,
|
||||
@@ -276,8 +276,10 @@ export default class BalanceGuard {
|
||||
const approveTransactionCost = ethers.BigNumber
|
||||
.from(APPROVE_ERC20_GAS_LIMIT)
|
||||
.mul(gasPriceWei);
|
||||
const denormalizedApproveTransactionCost = utils
|
||||
.denormalizeNumber(approveTransactionCost, NATIVE_CURRENCY_PRECISION);
|
||||
const denormalizedApproveTransactionCost = denormalizeNumber(
|
||||
approveTransactionCost,
|
||||
NATIVE_CURRENCY_PRECISION
|
||||
);
|
||||
|
||||
requiredApproves.items = {
|
||||
...requiredApproves.items,
|
||||
@@ -292,10 +294,10 @@ export default class BalanceGuard {
|
||||
fixes: [
|
||||
...resetRequired
|
||||
? [{
|
||||
type: 'byApprove' as const,
|
||||
targetAmount: 0,
|
||||
spenderAddress,
|
||||
}]
|
||||
type: 'byApprove' as const,
|
||||
targetAmount: 0,
|
||||
spenderAddress,
|
||||
}]
|
||||
: [],
|
||||
{
|
||||
type: 'byApprove',
|
||||
@@ -324,13 +326,13 @@ export default class BalanceGuard {
|
||||
const remainingBalance = remainingBalances[asset.name];
|
||||
if (!remainingBalance) throw new Error(`No ${asset.name} balance`);
|
||||
const itemsAmountSum = Object.values(items)
|
||||
.reduce<BigNumber>((p, c) => (c ? p.plus(c) : p), new BigNumber(0));
|
||||
.reduce<BigNumber>((p, c) => (c !== undefined ? p.plus(c) : p), new BigNumber(0));
|
||||
|
||||
let denormalizedAllowance: BigNumber;
|
||||
if (asset.address === ethers.constants.AddressZero) {
|
||||
denormalizedAllowance = remainingBalance.wallet;
|
||||
} else {
|
||||
if (!spenderAddress) throw new Error(`Spender address is required for ${asset.name}`);
|
||||
if (spenderAddress === undefined) throw new Error(`Spender address is required for ${asset.name}`);
|
||||
const tokenContract = ERC20__factory.connect(asset.address, this.provider);
|
||||
const tokenDecimals = await tokenContract.decimals();
|
||||
const tokenAllowance = await tokenContract.allowance(walletAddress, spenderAddress);
|
||||
@@ -358,7 +360,7 @@ export default class BalanceGuard {
|
||||
? `You need approve at least ${lackAmount.toString()} ${asset.name}`
|
||||
: 'Approve is not helpful'}`;
|
||||
if (approveIsHelpful) {
|
||||
if (!spenderAddress) throw new Error(`Spender address is required for ${asset.name}`);
|
||||
if (spenderAddress === undefined) throw new Error(`Spender address is required for ${asset.name}`);
|
||||
const resetRequired = await this.checkResetRequired(
|
||||
asset.address,
|
||||
spenderAddress,
|
||||
@@ -367,8 +369,10 @@ export default class BalanceGuard {
|
||||
const approveTransactionCost = ethers.BigNumber
|
||||
.from(APPROVE_ERC20_GAS_LIMIT)
|
||||
.mul(gasPriceWei);
|
||||
const denormalizedApproveTransactionCost = utils
|
||||
.denormalizeNumber(approveTransactionCost, NATIVE_CURRENCY_PRECISION);
|
||||
const denormalizedApproveTransactionCost = denormalizeNumber(
|
||||
approveTransactionCost,
|
||||
NATIVE_CURRENCY_PRECISION
|
||||
);
|
||||
|
||||
requiredApproves.items = {
|
||||
...requiredApproves.items,
|
||||
@@ -383,10 +387,10 @@ export default class BalanceGuard {
|
||||
fixes: [
|
||||
...resetRequired
|
||||
? [{
|
||||
type: 'byApprove' as const,
|
||||
targetAmount: 0,
|
||||
spenderAddress,
|
||||
}]
|
||||
type: 'byApprove' as const,
|
||||
targetAmount: 0,
|
||||
spenderAddress,
|
||||
}]
|
||||
: [],
|
||||
{
|
||||
type: 'byApprove',
|
||||
@@ -414,7 +418,7 @@ export default class BalanceGuard {
|
||||
if (!remainingBalance) throw new Error(`No ${asset.name} balance`);
|
||||
|
||||
const itemsAmountSum = Object.values({ ...items, ...requiredApproves.items })
|
||||
.reduce<BigNumber>((p, c) => (c ? p.plus(c) : p), new BigNumber(0));
|
||||
.reduce<BigNumber>((p, c) => (c !== undefined ? p.plus(c) : p), new BigNumber(0));
|
||||
|
||||
remainingBalance.wallet = remainingBalance.wallet.minus(itemsAmountSum);
|
||||
if (remainingBalance.wallet.lt(0)) {
|
||||
@@ -428,7 +432,7 @@ export default class BalanceGuard {
|
||||
}
|
||||
});
|
||||
|
||||
if (fixAutofixable) {
|
||||
if (fixAutofixable !== undefined && fixAutofixable) {
|
||||
const unfixed = await this.fixAllAutofixableBalanceIssues(balanceIssues);
|
||||
if (unfixed.length > 0) throw new Error(`Balance issues: ${unfixed.map((issue, i) => `${i + 1}. ${issue.message}`).join('\n')}`);
|
||||
} else if (balanceIssues.length > 0) {
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
import { merge } from 'merge-anything';
|
||||
import { chains, envs } from '../config';
|
||||
import { networkCodes } from '../constants';
|
||||
import { type networkCodes } from '../constants';
|
||||
import OrionUnit from '../OrionUnit';
|
||||
import OrionAnalytics from '../services/OrionAnalytics';
|
||||
import { ReferralSystem } from '../services/ReferralSystem';
|
||||
import { DeepPartial, SupportedChainId, VerboseOrionUnitConfig } from '../types';
|
||||
import { type DeepPartial, type SupportedChainId, type VerboseOrionUnitConfig } from '../types';
|
||||
import { isValidChainId } from '../utils';
|
||||
|
||||
type EnvConfig = {
|
||||
analyticsAPI: string;
|
||||
referralAPI: string;
|
||||
analyticsAPI: string
|
||||
referralAPI: string
|
||||
networks: Partial<
|
||||
Record<
|
||||
SupportedChainId,
|
||||
VerboseOrionUnitConfig
|
||||
>
|
||||
>;
|
||||
>
|
||||
}
|
||||
|
||||
type KnownEnv = 'testing' | 'staging' | 'production';
|
||||
@@ -29,14 +29,6 @@ export default class Orion {
|
||||
|
||||
public readonly referralSystem: ReferralSystem;
|
||||
|
||||
constructor();
|
||||
constructor(
|
||||
env: KnownEnv,
|
||||
overrides?: DeepPartial<EnvConfig>
|
||||
);
|
||||
|
||||
constructor(config: EnvConfig);
|
||||
|
||||
// TODO: get tradable assets (aggregated)
|
||||
|
||||
// TODO: get tradable pairs (aggregated)
|
||||
@@ -50,7 +42,9 @@ export default class Orion {
|
||||
let config: EnvConfig;
|
||||
if (typeof envOrConfig === 'string') {
|
||||
const envConfig = envs[envOrConfig];
|
||||
if (!envConfig) throw new Error(`Invalid environment: ${envOrConfig}. Available environments: ${Object.keys(envs).join(', ')}`);
|
||||
if (!envConfig) {
|
||||
throw new Error(`Invalid environment: ${envOrConfig}. Available environments: ${Object.keys(envs).join(', ')}`);
|
||||
}
|
||||
this.env = envOrConfig;
|
||||
config = {
|
||||
analyticsAPI: envConfig.analyticsAPI,
|
||||
@@ -58,13 +52,15 @@ export default class Orion {
|
||||
networks: Object.entries(envConfig.networks).map(([chainId, networkConfig]) => {
|
||||
if (!isValidChainId(chainId)) throw new Error(`Invalid chainId: ${chainId}`);
|
||||
const chainConfig = chains[chainId];
|
||||
if (!chainConfig) throw new Error(`Chain config not found: ${chainId}. Available chains: ${Object.keys(chains).join(', ')}`);
|
||||
if (!chainConfig) {
|
||||
throw new Error(`Chain config not found: ${chainId}. Available chains: ${Object.keys(chains).join(', ')}`);
|
||||
}
|
||||
|
||||
return {
|
||||
env: envOrConfig,
|
||||
chainId,
|
||||
api: networkConfig.api,
|
||||
nodeJsonRpc: networkConfig?.rpc ?? chainConfig.rpc,
|
||||
nodeJsonRpc: networkConfig.rpc ?? chainConfig.rpc,
|
||||
services: {
|
||||
orionBlockchain: {
|
||||
http: networkConfig.api + networkConfig.services.blockchain.http,
|
||||
@@ -86,6 +82,7 @@ export default class Orion {
|
||||
};
|
||||
|
||||
if (overrides) {
|
||||
// Recursive merge of config and overrides. Ignore undefined values.
|
||||
config = merge(config, overrides);
|
||||
}
|
||||
} else {
|
||||
@@ -99,7 +96,7 @@ export default class Orion {
|
||||
.reduce<Partial<Record<SupportedChainId, OrionUnit>>>((acc, [chainId, networkConfig]) => {
|
||||
if (!isValidChainId(chainId)) throw new Error(`Invalid chainId: ${chainId}`);
|
||||
const chainConfig = chains[chainId];
|
||||
if (!chainConfig) throw new Error(`Invalid chainId: ${chainId}`);
|
||||
if (!chainConfig) throw new Error(`Chain config not found: ${chainId}`);
|
||||
|
||||
const orionUnit = new OrionUnit({
|
||||
// env: networkConfig.env,
|
||||
@@ -119,11 +116,7 @@ export default class Orion {
|
||||
return Object.entries(this.units).map(([, unit]) => unit);
|
||||
}
|
||||
|
||||
getUnit(chainId: SupportedChainId): OrionUnit;
|
||||
|
||||
getUnit(networkCode: typeof networkCodes[number]): OrionUnit;
|
||||
|
||||
getUnit(networkCodeOrChainId: string): OrionUnit {
|
||||
getUnit(networkCodeOrChainId: typeof networkCodes[number] | SupportedChainId): OrionUnit {
|
||||
let unit: OrionUnit | undefined;
|
||||
if (isValidChainId(networkCodeOrChainId)) {
|
||||
unit = this.units[networkCodeOrChainId];
|
||||
@@ -132,7 +125,7 @@ export default class Orion {
|
||||
}
|
||||
if (!unit) {
|
||||
throw new Error(
|
||||
`Invalid network code: ${networkCodeOrChainId}. ` +
|
||||
`Invalid network code: ${networkCodeOrChainId}. ` +
|
||||
`Available network codes: ${this.unitsArray.map((u) => u.networkCode).join(', ')}`);
|
||||
}
|
||||
return unit;
|
||||
|
||||
@@ -1,23 +1,21 @@
|
||||
/* eslint-disable max-len */
|
||||
import BigNumber from 'bignumber.js';
|
||||
import { ethers } from 'ethers';
|
||||
import { Exchange__factory } from '@orionprotocol/contracts';
|
||||
import getBalances from '../../utils/getBalances';
|
||||
import BalanceGuard from '../../BalanceGuard';
|
||||
import OrionUnit from '..';
|
||||
import { utils } from '../..';
|
||||
import type OrionUnit from '..';
|
||||
import {
|
||||
DEPOSIT_ERC20_GAS_LIMIT, DEPOSIT_ETH_GAS_LIMIT, INTERNAL_ORION_PRECISION, NATIVE_CURRENCY_PRECISION,
|
||||
} from '../../constants';
|
||||
import { normalizeNumber } from '../../utils';
|
||||
import { denormalizeNumber, normalizeNumber } from '../../utils';
|
||||
import getNativeCryptocurrency from '../../utils/getNativeCryptocurrency';
|
||||
import simpleFetch from '../../simpleFetch';
|
||||
|
||||
export type DepositParams = {
|
||||
asset: string,
|
||||
amount: BigNumber.Value,
|
||||
signer: ethers.Signer,
|
||||
orionUnit: OrionUnit,
|
||||
asset: string
|
||||
amount: BigNumber.Value
|
||||
signer: ethers.Signer
|
||||
orionUnit: OrionUnit
|
||||
}
|
||||
|
||||
export default async function deposit({
|
||||
@@ -29,8 +27,8 @@ export default async function deposit({
|
||||
if (asset === '') throw new Error('Asset can not be empty');
|
||||
|
||||
const amountBN = new BigNumber(amount);
|
||||
if (amountBN.isNaN()) throw new Error(`Amount '${amount.toString()}' is not a number`);
|
||||
if (amountBN.lte(0)) throw new Error(`Amount '${amount.toString()}' should be greater than 0`);
|
||||
if (amountBN.isNaN()) throw new Error(`Amount '${amountBN.toString()}' is not a number`);
|
||||
if (amountBN.lte(0)) throw new Error(`Amount '${amountBN.toString()}' should be greater than 0`);
|
||||
|
||||
const walletAddress = await signer.getAddress();
|
||||
|
||||
@@ -48,7 +46,7 @@ export default async function deposit({
|
||||
const gasPriceWei = await simpleFetch(orionBlockchain.getGasPriceWei)();
|
||||
|
||||
const assetAddress = assetToAddress[asset];
|
||||
if (!assetAddress) throw new Error(`Asset '${asset}' not found`);
|
||||
if (assetAddress === undefined) throw new Error(`Asset '${asset}' not found`);
|
||||
|
||||
const balances = await getBalances(
|
||||
{
|
||||
@@ -77,7 +75,7 @@ export default async function deposit({
|
||||
name: asset,
|
||||
address: assetAddress,
|
||||
},
|
||||
amount: amount.toString(),
|
||||
amount: amountBN.toString(),
|
||||
spenderAddress: exchangeContractAddress,
|
||||
sources: ['wallet'],
|
||||
});
|
||||
@@ -96,7 +94,7 @@ export default async function deposit({
|
||||
}
|
||||
|
||||
const transactionCost = ethers.BigNumber.from(unsignedTx.gasLimit).mul(gasPriceWei);
|
||||
const denormalizedTransactionCost = utils.denormalizeNumber(transactionCost, NATIVE_CURRENCY_PRECISION);
|
||||
const denormalizedTransactionCost = denormalizeNumber(transactionCost, NATIVE_CURRENCY_PRECISION);
|
||||
|
||||
balanceGuard.registerRequirement({
|
||||
reason: 'Network fee',
|
||||
@@ -121,7 +119,7 @@ export default async function deposit({
|
||||
const txResponse = await provider.sendTransaction(signedTx);
|
||||
console.log(`Deposit tx sent: ${txResponse.hash}. Waiting for confirmation...`);
|
||||
const txReceipt = await txResponse.wait();
|
||||
if (txReceipt.status) {
|
||||
if (txReceipt.status !== undefined) {
|
||||
console.log('Deposit tx confirmed');
|
||||
} else {
|
||||
console.log('Deposit tx failed');
|
||||
|
||||
@@ -1,24 +1,23 @@
|
||||
import BigNumber from 'bignumber.js';
|
||||
import { ethers } from 'ethers';
|
||||
import { utils } from '../..';
|
||||
import { NATIVE_CURRENCY_PRECISION, SWAP_THROUGH_ORION_POOL_GAS_LIMIT } from '../../constants';
|
||||
import { OrionAggregator } from '../../services/OrionAggregator';
|
||||
import { OrionBlockchain } from '../../services/OrionBlockchain';
|
||||
import { type OrionAggregator } from '../../services/OrionAggregator';
|
||||
import { type OrionBlockchain } from '../../services/OrionBlockchain';
|
||||
|
||||
import simpleFetch from '../../simpleFetch';
|
||||
import getNativeCryptocurrency from '../../utils/getNativeCryptocurrency';
|
||||
import { calculateFeeInFeeAsset, denormalizeNumber, getNativeCryptocurrency } from '../../utils';
|
||||
|
||||
export type GetSwapInfoParams = {
|
||||
type: 'exactSpend' | 'exactReceive',
|
||||
assetIn: string,
|
||||
assetOut: string,
|
||||
amount: BigNumber.Value,
|
||||
feeAsset: string,
|
||||
orionBlockchain: OrionBlockchain,
|
||||
type: 'exactSpend' | 'exactReceive'
|
||||
assetIn: string
|
||||
assetOut: string
|
||||
amount: BigNumber.Value
|
||||
feeAsset: string
|
||||
orionBlockchain: OrionBlockchain
|
||||
orionAggregator: OrionAggregator
|
||||
options?: {
|
||||
instantSettlement?: boolean,
|
||||
poolOnly?: boolean,
|
||||
instantSettlement?: boolean
|
||||
poolOnly?: boolean
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,8 +37,8 @@ export default async function getSwapInfo({
|
||||
if (feeAsset === '') throw new Error('Fee asset can not be empty');
|
||||
|
||||
const amountBN = new BigNumber(amount);
|
||||
if (amountBN.isNaN()) throw new Error(`Amount '${amount.toString()}' is not a number`);
|
||||
if (amountBN.lte(0)) throw new Error(`Amount '${amount.toString()}' should be greater than 0`);
|
||||
if (amountBN.isNaN()) throw new Error(`Amount '${amountBN.toString()}' is not a number`);
|
||||
if (amountBN.lte(0)) throw new Error(`Amount '${amountBN.toString()}' should be greater than 0`);
|
||||
|
||||
const {
|
||||
assetToAddress,
|
||||
@@ -53,17 +52,21 @@ export default async function getSwapInfo({
|
||||
const gasPriceGwei = ethers.utils.formatUnits(gasPriceWei, 'gwei').toString();
|
||||
|
||||
const assetInAddress = assetToAddress[assetIn];
|
||||
if (!assetInAddress) throw new Error(`Asset '${assetIn}' not found`);
|
||||
if (assetInAddress === undefined) throw new Error(`Asset '${assetIn}' not found`);
|
||||
const feeAssetAddress = assetToAddress[feeAsset];
|
||||
if (!feeAssetAddress) throw new Error(`Fee asset '${feeAsset}' not found. Available assets: ${Object.keys(feeAssets).join(', ')}`);
|
||||
if (feeAssetAddress === undefined) {
|
||||
throw new Error(`Fee asset '${feeAsset}' not found. Available assets: ${Object.keys(feeAssets).join(', ')}`);
|
||||
}
|
||||
|
||||
const swapInfo = await simpleFetch(orionAggregator.getSwapInfo)(
|
||||
type,
|
||||
assetIn,
|
||||
assetOut,
|
||||
amount.toString(),
|
||||
amountBN.toString(),
|
||||
options?.instantSettlement,
|
||||
options?.poolOnly ? 'pools' : undefined,
|
||||
options?.poolOnly !== undefined && options.poolOnly
|
||||
? 'pools'
|
||||
: undefined,
|
||||
);
|
||||
|
||||
const { exchanges: swapExchanges } = swapInfo;
|
||||
@@ -82,13 +85,12 @@ export default async function getSwapInfo({
|
||||
// if (swapInfo.orderInfo === null) throw new Error(swapInfo.executionInfo);
|
||||
|
||||
let route: 'pool' | 'aggregator';
|
||||
if (options?.poolOnly) {
|
||||
if (options?.poolOnly !== undefined && options.poolOnly) {
|
||||
route = 'pool';
|
||||
} else if (
|
||||
swapExchanges !== undefined &&
|
||||
poolExchangesList.length > 0 &&
|
||||
swapExchanges.length === 1 &&
|
||||
firstSwapExchange &&
|
||||
firstSwapExchange !== undefined &&
|
||||
poolExchangesList.some((poolExchange) => poolExchange === firstSwapExchange)
|
||||
) {
|
||||
route = 'pool';
|
||||
@@ -98,7 +100,7 @@ export default async function getSwapInfo({
|
||||
|
||||
if (route === 'pool') {
|
||||
const transactionCost = ethers.BigNumber.from(SWAP_THROUGH_ORION_POOL_GAS_LIMIT).mul(gasPriceWei);
|
||||
const denormalizedTransactionCost = utils.denormalizeNumber(transactionCost, NATIVE_CURRENCY_PRECISION);
|
||||
const denormalizedTransactionCost = denormalizeNumber(transactionCost, NATIVE_CURRENCY_PRECISION);
|
||||
|
||||
return {
|
||||
route,
|
||||
@@ -112,26 +114,26 @@ export default async function getSwapInfo({
|
||||
};
|
||||
}
|
||||
|
||||
if (swapInfo.orderInfo) {
|
||||
if (swapInfo.orderInfo !== null) {
|
||||
const [baseAssetName] = swapInfo.orderInfo.assetPair.split('-');
|
||||
if (baseAssetName === undefined) throw new Error('Base asset name is undefined');
|
||||
const baseAssetAddress = assetToAddress[baseAssetName];
|
||||
if (!baseAssetAddress) throw new Error(`No asset address for ${baseAssetName}`);
|
||||
if (baseAssetAddress === undefined) throw new Error(`No asset address for ${baseAssetName}`);
|
||||
|
||||
// Fee calculation
|
||||
const baseAssetPriceInOrn = pricesInOrn?.[baseAssetAddress];
|
||||
if (!baseAssetPriceInOrn) throw new Error(`Base asset price ${baseAssetName} in ORN not found`);
|
||||
const baseAssetPriceInOrn = pricesInOrn[baseAssetAddress];
|
||||
if (baseAssetPriceInOrn === undefined) throw new Error(`Base asset price ${baseAssetName} in ORN not found`);
|
||||
const baseCurrencyPriceInOrn = pricesInOrn[ethers.constants.AddressZero];
|
||||
if (!baseCurrencyPriceInOrn) throw new Error('Base currency price in ORN not found');
|
||||
if (baseCurrencyPriceInOrn === undefined) throw new Error('Base currency price in ORN not found');
|
||||
const feeAssetPriceInOrn = pricesInOrn[feeAssetAddress];
|
||||
if (!feeAssetPriceInOrn) throw new Error(`Fee asset price ${feeAsset} in ORN not found`);
|
||||
const feePercent = feeAssets?.[feeAsset];
|
||||
if (!feePercent) throw new Error(`Fee asset ${feeAsset} not available`);
|
||||
if (feeAssetPriceInOrn === undefined) throw new Error(`Fee asset price ${feeAsset} in ORN not found`);
|
||||
const feePercent = feeAssets[feeAsset];
|
||||
if (feePercent === undefined) throw new Error(`Fee asset ${feeAsset} not available`);
|
||||
|
||||
const {
|
||||
orionFeeInFeeAsset,
|
||||
networkFeeInFeeAsset,
|
||||
} = utils.calculateFeeInFeeAsset(
|
||||
} = calculateFeeInFeeAsset(
|
||||
swapInfo.orderInfo.amount,
|
||||
feeAssetPriceInOrn,
|
||||
baseAssetPriceInOrn,
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import OrionUnit from '..';
|
||||
import deposit, { DepositParams } from './deposit';
|
||||
import getSwapInfo, { GetSwapInfoParams } from './getSwapInfo';
|
||||
import swapMarket, { SwapMarketParams } from './swapMarket';
|
||||
import withdraw, { WithdrawParams } from './withdraw';
|
||||
import type OrionUnit from '..';
|
||||
import deposit, { type DepositParams } from './deposit';
|
||||
import getSwapInfo, { type GetSwapInfoParams } from './getSwapInfo';
|
||||
import swapMarket, { type SwapMarketParams } from './swapMarket';
|
||||
import withdraw, { type WithdrawParams } from './withdraw';
|
||||
|
||||
type PureSwapMarketParams= Omit<SwapMarketParams, 'orionUnit'>
|
||||
type PureSwapMarketParams = Omit<SwapMarketParams, 'orionUnit'>
|
||||
type PureDepositParams = Omit<DepositParams, 'orionUnit'>
|
||||
type PureWithdrawParams = Omit<WithdrawParams, 'orionUnit'>
|
||||
type PureGetSwapMarketInfoParams= Omit<GetSwapInfoParams, 'orionBlockchain' | 'orionAggregator'>
|
||||
type PureGetSwapMarketInfoParams = Omit<GetSwapInfoParams, 'orionBlockchain' | 'orionAggregator'>
|
||||
|
||||
export default class Exchange {
|
||||
private readonly orionUnit: OrionUnit;
|
||||
|
||||
@@ -1,47 +1,47 @@
|
||||
/* eslint-disable max-len */
|
||||
import BigNumber from 'bignumber.js';
|
||||
import { ethers } from 'ethers';
|
||||
import { Exchange__factory } from '@orionprotocol/contracts';
|
||||
import getBalances from '../../utils/getBalances';
|
||||
import BalanceGuard from '../../BalanceGuard';
|
||||
import getAvailableSources from '../../utils/getAvailableFundsSources';
|
||||
import OrionUnit from '..';
|
||||
import { crypt, utils } from '../..';
|
||||
import type OrionUnit from '..';
|
||||
import { INTERNAL_ORION_PRECISION, NATIVE_CURRENCY_PRECISION, SWAP_THROUGH_ORION_POOL_GAS_LIMIT } from '../../constants';
|
||||
import getNativeCryptocurrency from '../../utils/getNativeCryptocurrency';
|
||||
import simpleFetch from '../../simpleFetch';
|
||||
import { calculateFeeInFeeAsset, denormalizeNumber, normalizeNumber } from '../../utils';
|
||||
import { signOrder } from '../../crypt';
|
||||
|
||||
export type SwapMarketParams = {
|
||||
type: 'exactSpend' | 'exactReceive',
|
||||
assetIn: string,
|
||||
assetOut: string,
|
||||
amount: BigNumber.Value,
|
||||
feeAsset: string,
|
||||
slippagePercent: BigNumber.Value,
|
||||
signer: ethers.Signer,
|
||||
orionUnit: OrionUnit,
|
||||
type: 'exactSpend' | 'exactReceive'
|
||||
assetIn: string
|
||||
assetOut: string
|
||||
amount: BigNumber.Value
|
||||
feeAsset: string
|
||||
slippagePercent: BigNumber.Value
|
||||
signer: ethers.Signer
|
||||
orionUnit: OrionUnit
|
||||
options?: {
|
||||
poolOnly?: boolean,
|
||||
instantSettlement?: boolean,
|
||||
logger?: (message: string) => void,
|
||||
autoApprove?: boolean,
|
||||
poolOnly?: boolean
|
||||
instantSettlement?: boolean
|
||||
logger?: (message: string) => void
|
||||
autoApprove?: boolean
|
||||
developer?: {
|
||||
route?: 'aggregator' | 'pool',
|
||||
route?: 'aggregator' | 'pool'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type AggregatorOrder = {
|
||||
through: 'aggregator'
|
||||
id: string,
|
||||
id: string
|
||||
}
|
||||
|
||||
type PoolSwap = {
|
||||
through: 'orion_pool'
|
||||
txHash: string,
|
||||
txHash: string
|
||||
}
|
||||
|
||||
type Swap = AggregatorOrder | PoolSwap;
|
||||
export type Swap = AggregatorOrder | PoolSwap;
|
||||
|
||||
export default async function swapMarket({
|
||||
type,
|
||||
@@ -54,7 +54,7 @@ export default async function swapMarket({
|
||||
orionUnit,
|
||||
options,
|
||||
}: SwapMarketParams): Promise<Swap> {
|
||||
if (options?.developer) options?.logger?.('YOU SPECIFIED A DEVELOPER OPTIONS. BE CAREFUL!');
|
||||
if (options?.developer) options.logger?.('YOU SPECIFIED A DEVELOPER OPTIONS. BE CAREFUL!');
|
||||
if (amount === '') throw new Error('Amount can not be empty');
|
||||
if (assetIn === '') throw new Error('AssetIn can not be empty');
|
||||
if (assetOut === '') throw new Error('AssetOut can not be empty');
|
||||
@@ -62,11 +62,11 @@ export default async function swapMarket({
|
||||
if (slippagePercent === '') throw new Error('Slippage percent can not be empty');
|
||||
|
||||
const amountBN = new BigNumber(amount);
|
||||
if (amountBN.isNaN()) throw new Error(`Amount '${amount.toString()}' is not a number`);
|
||||
if (amountBN.lte(0)) throw new Error(`Amount '${amount.toString()}' should be greater than 0`);
|
||||
if (amountBN.isNaN()) throw new Error(`Amount '${amountBN.toString()}' is not a number`);
|
||||
if (amountBN.lte(0)) throw new Error(`Amount '${amountBN.toString()}' should be greater than 0`);
|
||||
|
||||
const slippagePercentBN = new BigNumber(slippagePercent);
|
||||
if (slippagePercentBN.isNaN()) throw new Error(`Slippage percent '${slippagePercent.toString()}' is not a number`);
|
||||
if (slippagePercentBN.isNaN()) throw new Error(`Slippage percent '${slippagePercentBN.toString()}' is not a number`);
|
||||
if (slippagePercentBN.lte(0)) throw new Error('Slippage percent should be greater than 0');
|
||||
if (slippagePercentBN.gte(50)) throw new Error('Slippage percent should be less than 50');
|
||||
|
||||
@@ -93,9 +93,11 @@ export default async function swapMarket({
|
||||
const gasPriceGwei = ethers.utils.formatUnits(gasPriceWei, 'gwei').toString();
|
||||
|
||||
const assetInAddress = assetToAddress[assetIn];
|
||||
if (!assetInAddress) throw new Error(`Asset '${assetIn}' not found`);
|
||||
if (assetInAddress === undefined) throw new Error(`Asset '${assetIn}' not found`);
|
||||
const feeAssetAddress = assetToAddress[feeAsset];
|
||||
if (!feeAssetAddress) throw new Error(`Fee asset '${feeAsset}' not found. Available assets: ${Object.keys(feeAssets).join(', ')}`);
|
||||
if (feeAssetAddress === undefined) {
|
||||
throw new Error(`Fee asset '${feeAsset}' not found. Available assets: ${Object.keys(feeAssets).join(', ')}`);
|
||||
}
|
||||
|
||||
const balances = await getBalances(
|
||||
{
|
||||
@@ -124,16 +126,18 @@ export default async function swapMarket({
|
||||
type,
|
||||
assetIn,
|
||||
assetOut,
|
||||
amount.toString(),
|
||||
amountBN.toString(),
|
||||
options?.instantSettlement,
|
||||
options?.poolOnly ? 'pools' : undefined,
|
||||
options?.poolOnly !== undefined && options.poolOnly
|
||||
? 'pools'
|
||||
: undefined,
|
||||
);
|
||||
|
||||
const { exchanges: swapExchanges } = swapInfo;
|
||||
|
||||
const [firstSwapExchange] = swapExchanges;
|
||||
|
||||
if (swapExchanges) options?.logger?.(`Swap exchanges: ${swapExchanges.join(', ')}`);
|
||||
if (swapExchanges.length > 0) options?.logger?.(`Swap exchanges: ${swapExchanges.join(', ')}`);
|
||||
|
||||
if (swapInfo.type === 'exactReceive' && amountBN.lt(swapInfo.minAmountOut)) {
|
||||
throw new Error(`Amount is too low. Min amountOut is ${swapInfo.minAmountOut} ${assetOut}`);
|
||||
@@ -150,14 +154,16 @@ export default async function swapMarket({
|
||||
if (quoteAssetName === undefined) throw new Error('Quote asset name is undefined');
|
||||
|
||||
const pairConfig = await simpleFetch(orionAggregator.getPairConfig)(`${baseAssetName}-${quoteAssetName}`);
|
||||
if (!pairConfig) throw new Error(`Pair config ${baseAssetName}-${quoteAssetName} not found`);
|
||||
|
||||
const qtyPrecisionBN = new BigNumber(pairConfig.qtyPrecision);
|
||||
const qtyDecimalPlaces = amountBN.dp();
|
||||
|
||||
if (qtyDecimalPlaces === null) throw new Error('Qty decimal places is null. Likely amount is -Infinity, +Infinity or NaN');
|
||||
|
||||
if (qtyPrecisionBN.lt(qtyDecimalPlaces)) throw new Error(`Actual amount decimal places (${qtyDecimalPlaces}) is greater than max allowed decimal places (${qtyPrecisionBN.toString()}) on pair ${baseAssetName}-${quoteAssetName}`);
|
||||
if (qtyPrecisionBN.lt(qtyDecimalPlaces)) {
|
||||
throw new Error(
|
||||
`Actual amount decimal places (${qtyDecimalPlaces}) is greater than max allowed decimal places (${qtyPrecisionBN.toString()}) on pair ${baseAssetName}-${quoteAssetName}`
|
||||
);
|
||||
}
|
||||
|
||||
let route: 'aggregator' | 'pool';
|
||||
|
||||
@@ -165,15 +171,14 @@ export default async function swapMarket({
|
||||
|
||||
if (options?.developer?.route !== undefined) {
|
||||
route = options.developer.route;
|
||||
options?.logger?.(`Swap is through ${route} (because route forced to ${route})`);
|
||||
} else if (options?.poolOnly) {
|
||||
options?.logger?.('Swap is through pool (because "poolOnly" option is true)');
|
||||
options.logger?.(`Swap is through ${route} (because route forced to ${route})`);
|
||||
} else if (options?.poolOnly !== undefined && options.poolOnly) {
|
||||
options.logger?.('Swap is through pool (because "poolOnly" option is true)');
|
||||
route = 'pool';
|
||||
} else if (
|
||||
swapExchanges !== undefined &&
|
||||
poolExchangesList.length > 0 &&
|
||||
swapExchanges.length === 1 &&
|
||||
firstSwapExchange &&
|
||||
firstSwapExchange !== undefined &&
|
||||
poolExchangesList.some((poolExchange) => poolExchange === firstSwapExchange)
|
||||
) {
|
||||
options?.logger?.(`Swap is through pool [via ${firstSwapExchange}] (detected by "exchanges" field)`);
|
||||
@@ -184,14 +189,14 @@ export default async function swapMarket({
|
||||
|
||||
if (route === 'pool') {
|
||||
let factoryAddress: string | undefined;
|
||||
if (factories && firstSwapExchange) {
|
||||
factoryAddress = factories?.[firstSwapExchange];
|
||||
if (factoryAddress) options?.logger?.(`Factory address is ${factoryAddress}. Exchange is ${firstSwapExchange}`);
|
||||
if (factories && firstSwapExchange !== undefined) {
|
||||
factoryAddress = factories[firstSwapExchange];
|
||||
if (factoryAddress !== undefined) options?.logger?.(`Factory address is ${factoryAddress}. Exchange is ${firstSwapExchange}`);
|
||||
}
|
||||
|
||||
const pathAddresses = swapInfo.path.map((name) => {
|
||||
const assetAddress = assetToAddress?.[name];
|
||||
if (!assetAddress) throw new Error(`No asset address for ${name}`);
|
||||
const assetAddress = assetToAddress[name];
|
||||
if (assetAddress === undefined) throw new Error(`No asset address for ${name}`);
|
||||
return assetAddress;
|
||||
});
|
||||
|
||||
@@ -216,12 +221,12 @@ export default async function swapMarket({
|
||||
});
|
||||
|
||||
const amountReceive = swapInfo.type === 'exactReceive' ? swapInfo.amountOut : amountOutWithSlippage;
|
||||
const amountSpendBlockchainParam = utils.normalizeNumber(
|
||||
const amountSpendBlockchainParam = normalizeNumber(
|
||||
amountSpend,
|
||||
INTERNAL_ORION_PRECISION,
|
||||
BigNumber.ROUND_CEIL,
|
||||
);
|
||||
const amountReceiveBlockchainParam = utils.normalizeNumber(
|
||||
const amountReceiveBlockchainParam = normalizeNumber(
|
||||
amountReceive,
|
||||
INTERNAL_ORION_PRECISION,
|
||||
BigNumber.ROUND_FLOOR,
|
||||
@@ -229,7 +234,9 @@ export default async function swapMarket({
|
||||
const unsignedSwapThroughOrionPoolTx = await exchangeContract.populateTransaction.swapThroughOrionPool(
|
||||
amountSpendBlockchainParam,
|
||||
amountReceiveBlockchainParam,
|
||||
factoryAddress ? [factoryAddress, ...pathAddresses] : pathAddresses,
|
||||
factoryAddress !== undefined
|
||||
? [factoryAddress, ...pathAddresses]
|
||||
: pathAddresses,
|
||||
type === 'exactSpend',
|
||||
);
|
||||
|
||||
@@ -241,11 +248,11 @@ export default async function swapMarket({
|
||||
|
||||
let value = new BigNumber(0);
|
||||
const denormalizedAssetInExchangeBalance = balances[assetIn]?.exchange;
|
||||
if (!denormalizedAssetInExchangeBalance) throw new Error(`Asset '${assetIn}' exchange balance is not found`);
|
||||
if (denormalizedAssetInExchangeBalance === undefined) throw new Error(`Asset '${assetIn}' exchange balance is not found`);
|
||||
if (assetIn === nativeCryptocurrency && amountSpendBN.gt(denormalizedAssetInExchangeBalance)) {
|
||||
value = amountSpendBN.minus(denormalizedAssetInExchangeBalance);
|
||||
}
|
||||
unsignedSwapThroughOrionPoolTx.value = utils.normalizeNumber(
|
||||
unsignedSwapThroughOrionPoolTx.value = normalizeNumber(
|
||||
value.dp(INTERNAL_ORION_PRECISION, BigNumber.ROUND_CEIL),
|
||||
NATIVE_CURRENCY_PRECISION,
|
||||
BigNumber.ROUND_CEIL,
|
||||
@@ -253,7 +260,7 @@ export default async function swapMarket({
|
||||
unsignedSwapThroughOrionPoolTx.gasLimit = ethers.BigNumber.from(SWAP_THROUGH_ORION_POOL_GAS_LIMIT);
|
||||
|
||||
const transactionCost = ethers.BigNumber.from(SWAP_THROUGH_ORION_POOL_GAS_LIMIT).mul(gasPriceWei);
|
||||
const denormalizedTransactionCost = utils.denormalizeNumber(transactionCost, NATIVE_CURRENCY_PRECISION);
|
||||
const denormalizedTransactionCost = denormalizeNumber(transactionCost, NATIVE_CURRENCY_PRECISION);
|
||||
|
||||
balanceGuard.registerRequirement({
|
||||
reason: 'Network fee',
|
||||
@@ -305,9 +312,9 @@ export default async function swapMarket({
|
||||
.toString();
|
||||
|
||||
const baseAssetAddress = assetToAddress[baseAssetName];
|
||||
if (!baseAssetAddress) throw new Error(`No asset address for ${baseAssetName}`);
|
||||
if (baseAssetAddress === undefined) throw new Error(`No asset address for ${baseAssetName}`);
|
||||
const quoteAssetAddress = assetToAddress[quoteAssetName];
|
||||
if (!quoteAssetAddress) throw new Error(`No asset address for ${quoteAssetName}`);
|
||||
if (quoteAssetAddress === undefined) throw new Error(`No asset address for ${quoteAssetName}`);
|
||||
|
||||
const safePriceWithAppliedPrecision = new BigNumber(safePriceWithDeviation)
|
||||
.decimalPlaces(
|
||||
@@ -331,16 +338,16 @@ export default async function swapMarket({
|
||||
});
|
||||
|
||||
// Fee calculation
|
||||
const baseAssetPriceInOrn = pricesInOrn?.[baseAssetAddress];
|
||||
if (!baseAssetPriceInOrn) throw new Error(`Base asset price ${baseAssetName} in ORN not found`);
|
||||
const baseAssetPriceInOrn = pricesInOrn[baseAssetAddress];
|
||||
if (baseAssetPriceInOrn === undefined) throw new Error(`Base asset price ${baseAssetName} in ORN not found`);
|
||||
const baseCurrencyPriceInOrn = pricesInOrn[ethers.constants.AddressZero];
|
||||
if (!baseCurrencyPriceInOrn) throw new Error('Base currency price in ORN not found');
|
||||
if (baseCurrencyPriceInOrn === undefined) throw new Error('Base currency price in ORN not found');
|
||||
const feeAssetPriceInOrn = pricesInOrn[feeAssetAddress];
|
||||
if (!feeAssetPriceInOrn) throw new Error(`Fee asset price ${feeAsset} in ORN not found`);
|
||||
const feePercent = feeAssets?.[feeAsset];
|
||||
if (!feePercent) throw new Error(`Fee asset ${feeAsset} not available`);
|
||||
if (feeAssetPriceInOrn === undefined) throw new Error(`Fee asset price ${feeAsset} in ORN not found`);
|
||||
const feePercent = feeAssets[feeAsset];
|
||||
if (feePercent === undefined) throw new Error(`Fee asset ${feeAsset} not available`);
|
||||
|
||||
const { orionFeeInFeeAsset, networkFeeInFeeAsset, totalFeeInFeeAsset } = utils.calculateFeeInFeeAsset(
|
||||
const { orionFeeInFeeAsset, networkFeeInFeeAsset, totalFeeInFeeAsset } = calculateFeeInFeeAsset(
|
||||
swapInfo.orderInfo.amount,
|
||||
feeAssetPriceInOrn,
|
||||
baseAssetPriceInOrn,
|
||||
@@ -380,7 +387,7 @@ export default async function swapMarket({
|
||||
|
||||
await balanceGuard.check(options?.autoApprove);
|
||||
|
||||
const signedOrder = await crypt.signOrder(
|
||||
const signedOrder = await signOrder(
|
||||
baseAssetAddress,
|
||||
quoteAssetAddress,
|
||||
swapInfo.orderInfo.side,
|
||||
|
||||
@@ -1,23 +1,21 @@
|
||||
/* eslint-disable max-len */
|
||||
import BigNumber from 'bignumber.js';
|
||||
import { ethers } from 'ethers';
|
||||
import { Exchange__factory } from '@orionprotocol/contracts';
|
||||
import getBalances from '../../utils/getBalances';
|
||||
import BalanceGuard from '../../BalanceGuard';
|
||||
import OrionUnit from '..';
|
||||
import { utils } from '../..';
|
||||
import type OrionUnit from '..';
|
||||
import {
|
||||
INTERNAL_ORION_PRECISION, NATIVE_CURRENCY_PRECISION, WITHDRAW_GAS_LIMIT,
|
||||
} from '../../constants';
|
||||
import { normalizeNumber } from '../../utils';
|
||||
import { denormalizeNumber, normalizeNumber } from '../../utils';
|
||||
import getNativeCryptocurrency from '../../utils/getNativeCryptocurrency';
|
||||
import simpleFetch from '../../simpleFetch';
|
||||
|
||||
export type WithdrawParams = {
|
||||
asset: string,
|
||||
amount: BigNumber.Value,
|
||||
signer: ethers.Signer,
|
||||
orionUnit: OrionUnit,
|
||||
asset: string
|
||||
amount: BigNumber.Value
|
||||
signer: ethers.Signer
|
||||
orionUnit: OrionUnit
|
||||
}
|
||||
|
||||
export default async function withdraw({
|
||||
@@ -29,8 +27,8 @@ export default async function withdraw({
|
||||
if (asset === '') throw new Error('Asset can not be empty');
|
||||
|
||||
const amountBN = new BigNumber(amount);
|
||||
if (amountBN.isNaN()) throw new Error(`Amount '${amount.toString()}' is not a number`);
|
||||
if (amountBN.lte(0)) throw new Error(`Amount '${amount.toString()}' should be greater than 0`);
|
||||
if (amountBN.isNaN()) throw new Error(`Amount '${amountBN.toString()}' is not a number`);
|
||||
if (amountBN.lte(0)) throw new Error(`Amount '${amountBN.toString()}' should be greater than 0`);
|
||||
|
||||
const walletAddress = await signer.getAddress();
|
||||
|
||||
@@ -47,7 +45,7 @@ export default async function withdraw({
|
||||
const gasPriceWei = await simpleFetch(orionBlockchain.getGasPriceWei)();
|
||||
|
||||
const assetAddress = assetToAddress[asset];
|
||||
if (!assetAddress) throw new Error(`Asset '${asset}' not found`);
|
||||
if (assetAddress === undefined) throw new Error(`Asset '${asset}' not found`);
|
||||
|
||||
const balances = await getBalances(
|
||||
{
|
||||
@@ -76,7 +74,7 @@ export default async function withdraw({
|
||||
name: asset,
|
||||
address: assetAddress,
|
||||
},
|
||||
amount: amount.toString(),
|
||||
amount: amountBN.toString(),
|
||||
sources: ['exchange'],
|
||||
});
|
||||
|
||||
@@ -87,7 +85,7 @@ export default async function withdraw({
|
||||
unsignedTx.gasLimit = ethers.BigNumber.from(WITHDRAW_GAS_LIMIT);
|
||||
|
||||
const transactionCost = ethers.BigNumber.from(unsignedTx.gasLimit).mul(gasPriceWei);
|
||||
const denormalizedTransactionCost = utils.denormalizeNumber(transactionCost, NATIVE_CURRENCY_PRECISION);
|
||||
const denormalizedTransactionCost = denormalizeNumber(transactionCost, NATIVE_CURRENCY_PRECISION);
|
||||
|
||||
balanceGuard.registerRequirement({
|
||||
reason: 'Network fee',
|
||||
@@ -112,7 +110,7 @@ export default async function withdraw({
|
||||
const txResponse = await provider.sendTransaction(signedTx);
|
||||
console.log(`Withdraw tx sent: ${txResponse.hash}. Waiting for confirmation...`);
|
||||
const txReceipt = await txResponse.wait();
|
||||
if (txReceipt.status) {
|
||||
if (txReceipt.status !== undefined) {
|
||||
console.log('Withdraw tx confirmed');
|
||||
} else {
|
||||
console.log('Withdraw tx failed');
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Exchange__factory, IUniswapV2Pair__factory, IUniswapV2Router__factory } from '@orionprotocol/contracts';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import { ethers } from 'ethers';
|
||||
import OrionUnit from '..';
|
||||
import type OrionUnit from '..';
|
||||
import BalanceGuard from '../../BalanceGuard';
|
||||
import { ADD_LIQUIDITY_GAS_LIMIT, INTERNAL_ORION_PRECISION, NATIVE_CURRENCY_PRECISION } from '../../constants';
|
||||
import simpleFetch from '../../simpleFetch';
|
||||
@@ -12,14 +12,14 @@ import getNativeCryptocurrency from '../../utils/getNativeCryptocurrency';
|
||||
const ADD_LIQUIDITY_SLIPPAGE = 0.05;
|
||||
|
||||
export type AddLiquidityParams = {
|
||||
poolName: string,
|
||||
amountAsset: string,
|
||||
amount: BigNumber.Value,
|
||||
poolName: string
|
||||
amountAsset: string
|
||||
amount: BigNumber.Value
|
||||
signer: ethers.Signer
|
||||
}
|
||||
|
||||
export type RemoveAllLiquidityParams = {
|
||||
poolName: string,
|
||||
poolName: string
|
||||
signer: ethers.Signer
|
||||
}
|
||||
|
||||
@@ -57,14 +57,14 @@ export default class FarmingManager {
|
||||
.connect(exchangeContractAddress, this.orionUnit.provider);
|
||||
|
||||
const assetAAddress = assetToAddress[assetA];
|
||||
if (!assetAAddress) throw new Error(`Asset '${assetA}' not found`);
|
||||
if (assetAAddress === undefined) throw new Error(`Asset '${assetA}' not found`);
|
||||
const assetBAddress = assetToAddress[assetB];
|
||||
if (!assetBAddress) throw new Error(`Asset '${assetB}' not found`);
|
||||
if (assetBAddress === undefined) throw new Error(`Asset '${assetB}' not found`);
|
||||
|
||||
const assetADecimals = assetToDecimals[assetA];
|
||||
if (!assetADecimals) throw new Error(`Decimals for asset '${assetA}' not found`);
|
||||
if (assetADecimals === undefined) throw new Error(`Decimals for asset '${assetA}' not found`);
|
||||
const assetBDecimals = assetToDecimals[assetB];
|
||||
if (!assetBDecimals) throw new Error(`Decimals for asset '${assetB}' not found`);
|
||||
if (assetBDecimals === undefined) throw new Error(`Decimals for asset '${assetB}' not found`);
|
||||
|
||||
const nativeCryptocurrency = getNativeCryptocurrency(assetToAddress);
|
||||
const balances = await getBalances(
|
||||
@@ -145,7 +145,7 @@ export default class FarmingManager {
|
||||
sources: ['exchange', 'wallet'],
|
||||
});
|
||||
|
||||
const unsignedTx = await exchangeContract?.populateTransaction.withdrawToPool(
|
||||
const unsignedTx = await exchangeContract.populateTransaction.withdrawToPool(
|
||||
assetBIsNativeCurrency ? assetBAddress : assetAAddress,
|
||||
assetBIsNativeCurrency ? assetAAddress : assetBAddress,
|
||||
assetBIsNativeCurrency
|
||||
@@ -231,14 +231,14 @@ export default class FarmingManager {
|
||||
} = await simpleFetch(this.orionUnit.orionBlockchain.getInfo)();
|
||||
|
||||
const assetAAddress = assetToAddress[assetA];
|
||||
if (!assetAAddress) throw new Error(`Asset '${assetA}' not found`);
|
||||
if (assetAAddress === undefined) throw new Error(`Asset '${assetA}' not found`);
|
||||
const assetBAddress = assetToAddress[assetB];
|
||||
if (!assetBAddress) throw new Error(`Asset '${assetB}' not found`);
|
||||
if (assetBAddress === undefined) throw new Error(`Asset '${assetB}' not found`);
|
||||
|
||||
const assetADecimals = assetToDecimals[assetA];
|
||||
if (!assetADecimals) throw new Error(`Decimals for asset '${assetA}' not found`);
|
||||
if (assetADecimals === undefined) throw new Error(`Decimals for asset '${assetA}' not found`);
|
||||
const assetBDecimals = assetToDecimals[assetB];
|
||||
if (!assetBDecimals) throw new Error(`Decimals for asset '${assetB}' not found`);
|
||||
if (assetBDecimals === undefined) throw new Error(`Decimals for asset '${assetB}' not found`);
|
||||
|
||||
const poolsConfig = await simpleFetch(this.orionUnit.orionBlockchain.getPoolsConfig)();
|
||||
const pool = poolsConfig.pools[poolName];
|
||||
|
||||
@@ -6,7 +6,7 @@ import type { SupportedChainId, VerboseOrionUnitConfig } from '../types';
|
||||
import Exchange from './Exchange';
|
||||
import FarmingManager from './FarmingManager';
|
||||
import { chains } from '../config';
|
||||
import { networkCodes } from '../constants';
|
||||
import { type networkCodes } from '../constants';
|
||||
|
||||
// type KnownConfig = {
|
||||
// env: string;
|
||||
|
||||
@@ -8,14 +8,23 @@ import express from 'express';
|
||||
import WebSocket from 'ws';
|
||||
import http from 'http';
|
||||
import httpToWS from '../utils/httpToWS';
|
||||
import {
|
||||
createHttpTerminator,
|
||||
} from 'http-terminator';
|
||||
|
||||
jest.setTimeout(10000);
|
||||
|
||||
const createServer = (externalHost: string) => {
|
||||
const app = express();
|
||||
const server = http.createServer(app);
|
||||
|
||||
const httpTerminator = createHttpTerminator({ server });
|
||||
const wss = new WebSocket.Server({ server });
|
||||
|
||||
let externalWs: WebSocket | null = null;
|
||||
|
||||
wss.on('connection', (ws, req) => {
|
||||
if (req.url === undefined) throw new Error('req.url is undefined');
|
||||
const targetUrl = httpToWS(`${externalHost}${req.url}`);
|
||||
externalWs = new WebSocket(targetUrl);
|
||||
|
||||
@@ -32,33 +41,40 @@ const createServer = (externalHost: string) => {
|
||||
|
||||
app.get(
|
||||
'*',
|
||||
async (req, res) => {
|
||||
const routeFromURL = req.url;
|
||||
try {
|
||||
const targetUrl = `${externalHost}${routeFromURL}`;
|
||||
const response = await fetch(targetUrl);
|
||||
const text = await response.text();
|
||||
res.send(text);
|
||||
} catch (error) {
|
||||
res.status(500).send({
|
||||
error: 'Failed to retrieve data from external resource'
|
||||
});
|
||||
}
|
||||
(req, res) => {
|
||||
(async () => {
|
||||
const routeFromURL = req.url;
|
||||
try {
|
||||
const targetUrl = `${externalHost}${routeFromURL}`;
|
||||
const response = await fetch(targetUrl);
|
||||
const text = await response.text();
|
||||
res.send(text);
|
||||
} catch (error) {
|
||||
res.status(500).send({
|
||||
error: 'Failed to retrieve data from external resource'
|
||||
});
|
||||
}
|
||||
})().catch(console.error)
|
||||
});
|
||||
|
||||
server.listen(0);
|
||||
|
||||
const address = server.address();
|
||||
|
||||
if (typeof address === 'string') {
|
||||
throw new Error(`Server address is a string: ${address}`);
|
||||
}
|
||||
const closeWS = () => new Promise((resolve) => {
|
||||
wss.close(resolve);
|
||||
});
|
||||
|
||||
return {
|
||||
port: address?.port,
|
||||
close: () => new Promise((resolve) => {
|
||||
terminate: async () => {
|
||||
externalWs?.close();
|
||||
server.close(resolve);
|
||||
}),
|
||||
await closeWS();
|
||||
await httpTerminator.terminate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,6 +153,10 @@ describe('Orion', () => {
|
||||
const server1 = createServer('https://trade.orionprotocol.io');
|
||||
const server2 = createServer('https://trade.orionprotocol.io');
|
||||
|
||||
if (server0.port === undefined || server1.port === undefined || server2.port === undefined) {
|
||||
throw new Error('Server port is undefined');
|
||||
}
|
||||
|
||||
const orionBlockchainAPI = `http://localhost:${server0.port}`;
|
||||
const orionAggregatorAPI = `http://localhost:${server1.port}`;
|
||||
const orionPriceFeedAPI = `http://localhost:${server2.port}`;
|
||||
@@ -165,7 +185,7 @@ describe('Orion', () => {
|
||||
}
|
||||
});
|
||||
|
||||
const orionUnit = orion.unitsArray[0];
|
||||
const [orionUnit] = orion.unitsArray;
|
||||
if (!orionUnit) {
|
||||
throw new Error('Orion unit is not defined');
|
||||
}
|
||||
@@ -197,10 +217,6 @@ describe('Orion', () => {
|
||||
expect(priceData).toBeDefined();
|
||||
|
||||
const allTickersDone = await new Promise<boolean>((resolve, reject) => {
|
||||
const timeout = setTimeout(() => {
|
||||
reject(new Error('Timeout'));
|
||||
}, 10000);
|
||||
|
||||
const { unsubscribe } = orionUnit.priceFeed.ws.subscribe(
|
||||
'allTickers',
|
||||
{
|
||||
@@ -211,12 +227,16 @@ describe('Orion', () => {
|
||||
}
|
||||
}
|
||||
)
|
||||
const timeout = setTimeout(() => {
|
||||
unsubscribe();
|
||||
reject(new Error(`Timeout: ${orionUnit.priceFeed.wsUrl}`));
|
||||
}, 10000);
|
||||
});
|
||||
expect(allTickersDone).toBe(true);
|
||||
|
||||
await server0.close();
|
||||
await server1.close();
|
||||
await server2.close();
|
||||
await server0.terminate();
|
||||
await server1.terminate();
|
||||
await server2.terminate();
|
||||
});
|
||||
|
||||
test('Init Orion testing with overrides', () => {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import exchanges from './exchanges';
|
||||
import type exchanges from './exchanges';
|
||||
|
||||
const mapping: Record<
|
||||
typeof exchanges[number],
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { SupportedChainId } from '../types';
|
||||
import { type SupportedChainId } from '../types';
|
||||
import eip712DomainData from '../config/eip712DomainData.json';
|
||||
import eip712DomainSchema from '../config/schemas/eip712DomainSchema';
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ethers } from 'ethers';
|
||||
import { CFDOrder } from '../types';
|
||||
import { type CFDOrder } from '../types';
|
||||
|
||||
const hashCFDOrder = (order: CFDOrder) => ethers.utils.solidityKeccak256(
|
||||
[
|
||||
@@ -24,7 +24,7 @@ const hashCFDOrder = (order: CFDOrder) => ethers.utils.solidityKeccak256(
|
||||
order.matcherFee,
|
||||
order.nonce,
|
||||
order.expiration,
|
||||
order.buySide ? '0x01' : '0x00',
|
||||
order.buySide === 1 ? '0x01' : '0x00',
|
||||
],
|
||||
);
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ethers } from 'ethers';
|
||||
import { Order } from '../types';
|
||||
import { type Order } from '../types';
|
||||
|
||||
const hashOrder = (order: Order) => ethers.utils.solidityKeccak256(
|
||||
[
|
||||
@@ -28,7 +28,7 @@ const hashOrder = (order: Order) => ethers.utils.solidityKeccak256(
|
||||
order.matcherFee,
|
||||
order.nonce,
|
||||
order.expiration,
|
||||
order.buySide ? '0x01' : '0x00',
|
||||
order.buySide === 1 ? '0x01' : '0x00',
|
||||
],
|
||||
);
|
||||
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
/* eslint-disable no-underscore-dangle */
|
||||
import { TypedDataSigner } from '@ethersproject/abstract-signer';
|
||||
import { type TypedDataSigner } from '@ethersproject/abstract-signer';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import { ethers } from 'ethers';
|
||||
import { type ethers } from 'ethers';
|
||||
import { joinSignature, splitSignature } from 'ethers/lib/utils';
|
||||
import { INTERNAL_ORION_PRECISION } from '../constants';
|
||||
import { CFDOrder, SignedCFDOrder, SupportedChainId } from '../types';
|
||||
import { type CFDOrder, type SignedCFDOrder, type SupportedChainId } from '../types';
|
||||
import normalizeNumber from '../utils/normalizeNumber';
|
||||
import getDomainData from './getDomainData';
|
||||
import signCFDOrderPersonal from './signCFDOrderPersonal';
|
||||
@@ -69,7 +68,7 @@ export const signCFDOrder = async (
|
||||
// "Signature's v was always send as 27 or 28, but from Ledger was 0 or 1"
|
||||
const fixedSignature = joinSignature(splitSignature(signature));
|
||||
|
||||
if (!fixedSignature) throw new Error("Can't sign order");
|
||||
// if (!fixedSignature) throw new Error("Can't sign order");
|
||||
|
||||
const signedOrder: SignedCFDOrder = {
|
||||
...order,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ethers } from 'ethers';
|
||||
import { CFDOrder } from '../types';
|
||||
import { type CFDOrder } from '../types';
|
||||
|
||||
const { arrayify, joinSignature, splitSignature } = ethers.utils;
|
||||
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
/* eslint-disable no-underscore-dangle */
|
||||
import { TypedDataSigner } from '@ethersproject/abstract-signer';
|
||||
import { ethers } from 'ethers';
|
||||
import { type TypedDataSigner } from '@ethersproject/abstract-signer';
|
||||
import { type ethers } from 'ethers';
|
||||
import { joinSignature, splitSignature } from 'ethers/lib/utils';
|
||||
import CANCEL_ORDER_TYPES from '../constants/cancelOrderTypes';
|
||||
import { CancelOrderRequest, SignedCancelOrderRequest, SupportedChainId } from '../types';
|
||||
import { type CancelOrderRequest, type SignedCancelOrderRequest, type SupportedChainId } from '../types';
|
||||
import getDomainData from './getDomainData';
|
||||
import signCancelOrderPersonal from './signCancelOrderPersonal';
|
||||
|
||||
@@ -37,7 +36,7 @@ const signCancelOrder = async (
|
||||
// "Signature's v was always send as 27 or 28, but from Ledger was 0 or 1"
|
||||
const fixedSignature = joinSignature(splitSignature(signature));
|
||||
|
||||
if (!fixedSignature) throw new Error("Can't sign order cancel");
|
||||
// if (!fixedSignature) throw new Error("Can't sign order cancel");
|
||||
|
||||
const signedCancelOrderReqeust: SignedCancelOrderRequest = {
|
||||
...cancelOrderRequest,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { ethers } from 'ethers';
|
||||
import { arrayify, joinSignature, splitSignature } from 'ethers/lib/utils';
|
||||
import { CancelOrderRequest } from '../types';
|
||||
import { type CancelOrderRequest } from '../types';
|
||||
|
||||
const signCancelOrderPersonal = async (
|
||||
cancelOrderRequest: CancelOrderRequest,
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
/* eslint-disable no-underscore-dangle */
|
||||
import { TypedDataSigner } from '@ethersproject/abstract-signer';
|
||||
import { type TypedDataSigner } from '@ethersproject/abstract-signer';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import { ethers } from 'ethers';
|
||||
import { type ethers } from 'ethers';
|
||||
import { joinSignature, splitSignature } from 'ethers/lib/utils';
|
||||
import { INTERNAL_ORION_PRECISION } from '../constants';
|
||||
import ORDER_TYPES from '../constants/orderTypes';
|
||||
import { Order, SignedOrder, SupportedChainId } from '../types';
|
||||
import { type Order, type SignedOrder, type SupportedChainId } from '../types';
|
||||
import normalizeNumber from '../utils/normalizeNumber';
|
||||
import getDomainData from './getDomainData';
|
||||
import hashOrder from './hashOrder';
|
||||
@@ -74,7 +73,7 @@ export const signOrder = async (
|
||||
// "Signature's v was always send as 27 or 28, but from Ledger was 0 or 1"
|
||||
const fixedSignature = joinSignature(splitSignature(signature));
|
||||
|
||||
if (!fixedSignature) throw new Error("Can't sign order");
|
||||
// if (!fixedSignature) throw new Error("Can't sign order");
|
||||
|
||||
const signedOrder: SignedOrder = {
|
||||
...order,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ethers } from 'ethers';
|
||||
import { Order } from '../types';
|
||||
import { type Order } from '../types';
|
||||
|
||||
const { arrayify, joinSignature, splitSignature } = ethers.utils;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Schema, z } from 'zod';
|
||||
import { type Schema, type z } from 'zod';
|
||||
import fetch from 'isomorphic-unfetch';
|
||||
|
||||
import {
|
||||
@@ -26,7 +26,7 @@ export default async function fetchWithValidation<DataOut, DataIn, ErrorOut, Err
|
||||
// payload
|
||||
|
||||
const fetchResult = await fromPromise(fetch(url, {
|
||||
...options || {},
|
||||
...options ?? {},
|
||||
headers: {
|
||||
'Cache-Control': 'no-store, max-age=0',
|
||||
...(options ? options.headers : {}),
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import BigNumber from 'bignumber.js';
|
||||
import type BigNumber from 'bignumber.js';
|
||||
import { z } from 'zod';
|
||||
import fetchWithValidation from '../../fetchWithValidation';
|
||||
import swapInfoSchema from './schemas/swapInfoSchema';
|
||||
@@ -9,12 +9,12 @@ import errorSchema from './schemas/errorSchema';
|
||||
import placeAtomicSwapSchema from './schemas/placeAtomicSwapSchema';
|
||||
import { OrionAggregatorWS } from './ws';
|
||||
import { atomicSwapHistorySchema } from './schemas/atomicSwapHistorySchema';
|
||||
import { Exchange, SignedCancelOrderRequest, SignedCFDOrder, SignedOrder } from '../../types';
|
||||
import { type Exchange, type SignedCancelOrderRequest, type SignedCFDOrder, type SignedOrder } from '../../types';
|
||||
import { pairConfigSchema } from './schemas';
|
||||
import {
|
||||
aggregatedOrderbookSchema, exchangeOrderbookSchema, poolReservesSchema,
|
||||
} from './schemas/aggregatedOrderbookSchema';
|
||||
import networkCodes from '../../constants/networkCodes';
|
||||
import type networkCodes from '../../constants/networkCodes';
|
||||
import toUpperCase from '../../utils/toUpperCase';
|
||||
import httpToWS from '../../utils/httpToWS';
|
||||
|
||||
@@ -146,7 +146,7 @@ class OrionAggregator {
|
||||
const headers = {
|
||||
'Content-Type': 'application/json',
|
||||
Accept: 'application/json',
|
||||
...partnerId && { 'X-Partner-Id': partnerId },
|
||||
...(partnerId !== undefined) && { 'X-Partner-Id': partnerId },
|
||||
};
|
||||
|
||||
return fetchWithValidation(
|
||||
@@ -232,7 +232,7 @@ class OrionAggregator {
|
||||
} else {
|
||||
url.searchParams.append('amountOut', amount);
|
||||
}
|
||||
if (exchanges) {
|
||||
if (exchanges !== undefined) {
|
||||
if (Array.isArray(exchanges)) {
|
||||
exchanges.forEach((exchange) => {
|
||||
url.searchParams.append('exchanges', exchange);
|
||||
@@ -241,7 +241,7 @@ class OrionAggregator {
|
||||
url.searchParams.append('exchanges', exchanges);
|
||||
}
|
||||
}
|
||||
if (instantSettlement) {
|
||||
if (instantSettlement !== undefined && instantSettlement) {
|
||||
url.searchParams.append('instantSettlement', 'true');
|
||||
}
|
||||
|
||||
|
||||
@@ -10,12 +10,12 @@ import {
|
||||
} from './schemas';
|
||||
import UnsubscriptionType from './UnsubscriptionType';
|
||||
import {
|
||||
SwapInfoBase, AssetPairUpdate, OrderbookItem, Balance,
|
||||
Exchange, CFDBalance, SwapInfo, FuturesTradeInfo,
|
||||
type SwapInfoBase, type AssetPairUpdate, type OrderbookItem,
|
||||
type Balance, type Exchange, type CFDBalance, type FuturesTradeInfo, type SwapInfo,
|
||||
} from '../../../types';
|
||||
import unsubscriptionDoneSchema from './schemas/unsubscriptionDoneSchema';
|
||||
import assetPairConfigSchema from './schemas/assetPairConfigSchema';
|
||||
import { fullOrderSchema, orderUpdateSchema } from './schemas/addressUpdateSchema';
|
||||
import { type fullOrderSchema, type orderUpdateSchema } from './schemas/addressUpdateSchema';
|
||||
import cfdAddressUpdateSchema from './schemas/cfdAddressUpdateSchema';
|
||||
import futuresTradeInfoSchema from './schemas/futuresTradeInfoSchema';
|
||||
// import errorSchema from './schemas/errorSchema';
|
||||
@@ -25,108 +25,108 @@ const UNSUBSCRIBE = 'u';
|
||||
// https://github.com/orionprotocol/orion-aggregator/tree/feature/OP-1752-symmetric-swap#swap-info-subscribe
|
||||
type SwapSubscriptionRequest = {
|
||||
// d: string, // swap request UUID, set by client side
|
||||
i: string, // asset in
|
||||
o: string, // asset out
|
||||
i: string // asset in
|
||||
o: string // asset out
|
||||
a: number // amount IN/OUT
|
||||
es?: Exchange[] | 'cex' | 'pools', // exchange list of all cex or all pools (ORION_POOL, UNISWAP, PANCAKESWAP etc)
|
||||
e?: boolean; // is amount IN? Value `false` means a = amount OUT, `true` if omitted
|
||||
is?: boolean; // instant settlement
|
||||
es?: Exchange[] | 'cex' | 'pools' // exchange list of all cex or all pools (ORION_POOL, UNISWAP, PANCAKESWAP etc)
|
||||
e?: boolean // is amount IN? Value `false` means a = amount OUT, `true` if omitted
|
||||
is?: boolean // instant settlement
|
||||
}
|
||||
|
||||
type BrokerTradableAtomicSwapBalanceSubscription = {
|
||||
callback: (balances: Partial<Record<string, number>>) => void,
|
||||
callback: (balances: Partial<Record<string, number>>) => void
|
||||
}
|
||||
|
||||
type PairsConfigSubscription = {
|
||||
callback: ({ kind, data }: {
|
||||
kind: 'initial' | 'update',
|
||||
data: Partial<Record<string, AssetPairUpdate>>,
|
||||
}) => void,
|
||||
kind: 'initial' | 'update'
|
||||
data: Partial<Record<string, AssetPairUpdate>>
|
||||
}) => void
|
||||
}
|
||||
|
||||
type PairConfigSubscription = {
|
||||
payload: string,
|
||||
payload: string
|
||||
callback: ({ kind, data }: {
|
||||
kind: 'initial' | 'update',
|
||||
data: AssetPairUpdate,
|
||||
}) => void,
|
||||
kind: 'initial' | 'update'
|
||||
data: AssetPairUpdate
|
||||
}) => void
|
||||
}
|
||||
|
||||
type AggregatedOrderbookSubscription = {
|
||||
payload: string,
|
||||
payload: string
|
||||
callback: (
|
||||
asks: OrderbookItem[],
|
||||
bids: OrderbookItem[],
|
||||
pair: string
|
||||
) => void,
|
||||
) => void
|
||||
}
|
||||
|
||||
type SwapInfoSubscription = {
|
||||
payload: SwapSubscriptionRequest,
|
||||
callback: (swapInfo: SwapInfo) => void,
|
||||
payload: SwapSubscriptionRequest
|
||||
callback: (swapInfo: SwapInfo) => void
|
||||
}
|
||||
|
||||
type FuturesTradeInfoSubscription = {
|
||||
payload: {
|
||||
s: string,
|
||||
i: string,
|
||||
a: number,
|
||||
p?: number,
|
||||
},
|
||||
callback: (futuresTradeInfo: FuturesTradeInfo) => void,
|
||||
s: string
|
||||
i: string
|
||||
a: number
|
||||
p?: number
|
||||
}
|
||||
callback: (futuresTradeInfo: FuturesTradeInfo) => void
|
||||
}
|
||||
|
||||
type AddressUpdateUpdate = {
|
||||
kind: 'update',
|
||||
kind: 'update'
|
||||
balances: Partial<
|
||||
Record<
|
||||
string,
|
||||
Balance
|
||||
>
|
||||
>,
|
||||
Record<
|
||||
string,
|
||||
Balance
|
||||
>
|
||||
>
|
||||
order?: z.infer<typeof orderUpdateSchema> | z.infer<typeof fullOrderSchema>
|
||||
}
|
||||
|
||||
type AddressUpdateInitial = {
|
||||
kind: 'initial',
|
||||
kind: 'initial'
|
||||
balances: Partial<
|
||||
Record<
|
||||
string,
|
||||
Balance
|
||||
>
|
||||
>,
|
||||
orders?: z.infer<typeof fullOrderSchema>[] // The field is not defined if the user has no orders
|
||||
Record<
|
||||
string,
|
||||
Balance
|
||||
>
|
||||
>
|
||||
orders?: Array<z.infer<typeof fullOrderSchema>> // The field is not defined if the user has no orders
|
||||
}
|
||||
|
||||
type CfdAddressUpdateUpdate = {
|
||||
kind: 'update',
|
||||
balances?: CFDBalance[],
|
||||
kind: 'update'
|
||||
balances?: CFDBalance[]
|
||||
order?: z.infer<typeof orderUpdateSchema> | z.infer<typeof fullOrderSchema>
|
||||
}
|
||||
|
||||
type CfdAddressUpdateInitial = {
|
||||
kind: 'initial',
|
||||
balances: CFDBalance[],
|
||||
orders?: z.infer<typeof fullOrderSchema>[] // The field is not defined if the user has no orders
|
||||
kind: 'initial'
|
||||
balances: CFDBalance[]
|
||||
orders?: Array<z.infer<typeof fullOrderSchema>> // The field is not defined if the user has no orders
|
||||
}
|
||||
|
||||
type AddressUpdateSubscription = {
|
||||
payload: string,
|
||||
callback: (data: AddressUpdateUpdate | AddressUpdateInitial) => void,
|
||||
payload: string
|
||||
callback: (data: AddressUpdateUpdate | AddressUpdateInitial) => void
|
||||
}
|
||||
|
||||
type CfdAddressUpdateSubscription = {
|
||||
payload: string,
|
||||
callback: (data: CfdAddressUpdateUpdate | CfdAddressUpdateInitial) => void,
|
||||
payload: string
|
||||
callback: (data: CfdAddressUpdateUpdate | CfdAddressUpdateInitial) => void
|
||||
}
|
||||
|
||||
type Subscription = {
|
||||
[SubscriptionType.ADDRESS_UPDATES_SUBSCRIBE]: AddressUpdateSubscription,
|
||||
[SubscriptionType.CFD_ADDRESS_UPDATES_SUBSCRIBE]: CfdAddressUpdateSubscription,
|
||||
[SubscriptionType.AGGREGATED_ORDER_BOOK_UPDATES_SUBSCRIBE]: AggregatedOrderbookSubscription,
|
||||
[SubscriptionType.ASSET_PAIRS_CONFIG_UPDATES_SUBSCRIBE]: PairsConfigSubscription,
|
||||
[SubscriptionType.ASSET_PAIR_CONFIG_UPDATES_SUBSCRIBE]: PairConfigSubscription,
|
||||
[SubscriptionType.BROKER_TRADABLE_ATOMIC_SWAP_ASSETS_BALANCE_UPDATES_SUBSCRIBE]: BrokerTradableAtomicSwapBalanceSubscription,
|
||||
[SubscriptionType.ADDRESS_UPDATES_SUBSCRIBE]: AddressUpdateSubscription
|
||||
[SubscriptionType.CFD_ADDRESS_UPDATES_SUBSCRIBE]: CfdAddressUpdateSubscription
|
||||
[SubscriptionType.AGGREGATED_ORDER_BOOK_UPDATES_SUBSCRIBE]: AggregatedOrderbookSubscription
|
||||
[SubscriptionType.ASSET_PAIRS_CONFIG_UPDATES_SUBSCRIBE]: PairsConfigSubscription
|
||||
[SubscriptionType.ASSET_PAIR_CONFIG_UPDATES_SUBSCRIBE]: PairConfigSubscription
|
||||
[SubscriptionType.BROKER_TRADABLE_ATOMIC_SWAP_ASSETS_BALANCE_UPDATES_SUBSCRIBE]: BrokerTradableAtomicSwapBalanceSubscription
|
||||
[SubscriptionType.SWAP_SUBSCRIBE]: SwapInfoSubscription
|
||||
[SubscriptionType.FUTURES_TRADE_INFO_SUBSCRIBE]: FuturesTradeInfoSubscription
|
||||
}
|
||||
@@ -145,14 +145,14 @@ type BufferLike =
|
||||
| Uint8Array
|
||||
| ArrayBuffer
|
||||
| SharedArrayBuffer
|
||||
| ReadonlyArray<unknown>
|
||||
| ReadonlyArray<number>
|
||||
| { valueOf(): ArrayBuffer }
|
||||
| { valueOf(): SharedArrayBuffer }
|
||||
| { valueOf(): Uint8Array }
|
||||
| { valueOf(): ReadonlyArray<number> }
|
||||
| { valueOf(): string }
|
||||
| { [Symbol.toPrimitive](hint: string): string };
|
||||
| readonly unknown[]
|
||||
| readonly number[]
|
||||
| { valueOf: () => ArrayBuffer }
|
||||
| { valueOf: () => SharedArrayBuffer }
|
||||
| { valueOf: () => Uint8Array }
|
||||
| { valueOf: () => readonly number[] }
|
||||
| { valueOf: () => string }
|
||||
| { [Symbol.toPrimitive]: (hint: string) => string };
|
||||
|
||||
const isSubType = (subType: string): subType is keyof Subscription => Object.values(SubscriptionType).some((t) => t === subType);
|
||||
class OrionAggregatorWS {
|
||||
@@ -339,8 +339,9 @@ class OrionAggregatorWS {
|
||||
};
|
||||
this.ws.onmessage = (e) => {
|
||||
const { data } = e;
|
||||
this.logger?.(`OrionAggregatorWS: received message: ${e.data.toString()}`);
|
||||
const rawJson: unknown = JSON.parse(data.toString());
|
||||
if (typeof data !== 'string') throw new Error('OrionAggregatorWS: received non-string message');
|
||||
this.logger?.(`OrionAggregatorWS: received message: ${data}`);
|
||||
const rawJson: unknown = JSON.parse(data);
|
||||
|
||||
const messageSchema = z.union([
|
||||
initMessageSchema,
|
||||
@@ -385,7 +386,7 @@ class OrionAggregatorWS {
|
||||
path: json.ps,
|
||||
exchanges: json.e,
|
||||
poolOptimal: json.po,
|
||||
...json.oi && {
|
||||
...(json.oi) && {
|
||||
orderInfo: {
|
||||
pair: json.oi.p,
|
||||
side: json.oi.s,
|
||||
@@ -511,8 +512,8 @@ class OrionAggregatorWS {
|
||||
case MessageType.CFD_ADDRESS_UPDATE:
|
||||
switch (json.k) { // message kind
|
||||
case 'i': { // initial
|
||||
const fullOrders = json.o
|
||||
? json.o.reduce<z.infer<typeof fullOrderSchema>[]>((prev, o) => {
|
||||
const fullOrders = (json.o)
|
||||
? json.o.reduce<Array<z.infer<typeof fullOrderSchema>>>((prev, o) => {
|
||||
prev.push(o);
|
||||
|
||||
return prev;
|
||||
@@ -524,7 +525,7 @@ class OrionAggregatorWS {
|
||||
]?.[json.id]?.callback({
|
||||
kind: 'initial',
|
||||
orders: fullOrders,
|
||||
balances: json.b ?? [],
|
||||
balances: json.b,
|
||||
});
|
||||
}
|
||||
break;
|
||||
@@ -549,7 +550,7 @@ class OrionAggregatorWS {
|
||||
}
|
||||
break;
|
||||
case MessageType.ADDRESS_UPDATE: {
|
||||
const balances = json.b
|
||||
const balances = (json.b)
|
||||
? Object.entries(json.b)
|
||||
.reduce<Partial<Record<string, Balance>>>((prev, [asset, assetBalances]) => {
|
||||
if (!assetBalances) return prev;
|
||||
@@ -565,7 +566,7 @@ class OrionAggregatorWS {
|
||||
switch (json.k) { // message kind
|
||||
case 'i': { // initial
|
||||
const fullOrders = json.o
|
||||
? json.o.reduce<z.infer<typeof fullOrderSchema>[]>((prev, o) => {
|
||||
? json.o.reduce<Array<z.infer<typeof fullOrderSchema>>>((prev, o) => {
|
||||
prev.push(o);
|
||||
|
||||
return prev;
|
||||
|
||||
@@ -2,7 +2,7 @@ import fetchWithValidation from '../../fetchWithValidation';
|
||||
import overviewSchema from './schemas/overviewSchema';
|
||||
|
||||
export default class OrionAnalytics {
|
||||
private apiUrl: string;
|
||||
private readonly apiUrl: string;
|
||||
|
||||
constructor(apiUrl: string) {
|
||||
this.apiUrl = apiUrl;
|
||||
|
||||
@@ -3,63 +3,63 @@ import fetchWithValidation from '../../fetchWithValidation';
|
||||
import {
|
||||
IDOSchema, atomicHistorySchema,
|
||||
poolsConfigSchema, poolsInfoSchema, infoSchema, historySchema,
|
||||
addPoolSchema, adminPoolsListSchema, adminPoolSchema,
|
||||
type addPoolSchema, adminPoolsListSchema, adminPoolSchema,
|
||||
atomicSummarySchema,
|
||||
poolsLpAndStakedSchema,
|
||||
userVotesSchema,
|
||||
userEarnedSchema,
|
||||
PairStatusEnum,
|
||||
type PairStatusEnum,
|
||||
pairStatusSchema,
|
||||
cfdContractsSchema,
|
||||
cfdHistorySchema,
|
||||
} from './schemas';
|
||||
import redeemOrderSchema from '../OrionAggregator/schemas/redeemOrderSchema';
|
||||
import type redeemOrderSchema from '../OrionAggregator/schemas/redeemOrderSchema';
|
||||
import { sourceAtomicHistorySchema, targetAtomicHistorySchema } from './schemas/atomicHistorySchema';
|
||||
import { makePartial } from '../../utils';
|
||||
import { networkCodes } from '../../constants';
|
||||
import { type networkCodes } from '../../constants';
|
||||
|
||||
interface IAdminAuthHeaders {
|
||||
auth: string;
|
||||
type IAdminAuthHeaders = {
|
||||
auth: string
|
||||
[key: string]: string
|
||||
}
|
||||
|
||||
export interface IEditPool {
|
||||
tokenAIcon?: string;
|
||||
tokenBIcon?: string;
|
||||
symbol?: string;
|
||||
status: PairStatusEnum;
|
||||
minQty?: number;
|
||||
tokenASymbol?: string;
|
||||
tokenBSymbol?: string;
|
||||
tokensReversed?: boolean;
|
||||
export type IEditPool = {
|
||||
tokenAIcon?: string
|
||||
tokenBIcon?: string
|
||||
symbol?: string
|
||||
status: PairStatusEnum
|
||||
minQty?: number
|
||||
tokenASymbol?: string
|
||||
tokenBSymbol?: string
|
||||
tokensReversed?: boolean
|
||||
}
|
||||
|
||||
type AtomicSwapHistoryBaseQuery = {
|
||||
limit?: number
|
||||
sender?: string,
|
||||
receiver?: string,
|
||||
used?: 0 | 1,
|
||||
page?: number,
|
||||
sourceNetworkCode?: typeof networkCodes[number],
|
||||
}
|
||||
sender?: string
|
||||
receiver?: string
|
||||
used?: 0 | 1
|
||||
page?: number
|
||||
sourceNetworkCode?: typeof networkCodes[number]
|
||||
} & Partial<Record<string, string | number>>
|
||||
|
||||
type AtomicSwapHistorySourceQuery = AtomicSwapHistoryBaseQuery & {
|
||||
type?: 'source',
|
||||
expiredLock?: 0 | 1,
|
||||
state?: 'LOCKED' | 'CLAIMED' |'REFUNDED',
|
||||
type?: 'source'
|
||||
expiredLock?: 0 | 1
|
||||
state?: 'LOCKED' | 'CLAIMED' | 'REFUNDED'
|
||||
|
||||
}
|
||||
type AtomicSwapHistoryTargetQuery = AtomicSwapHistoryBaseQuery & {
|
||||
type?: 'target',
|
||||
expiredRedeem?: 0 | 1,
|
||||
state?: 'REDEEMED' | 'BEFORE-REDEEM',
|
||||
type?: 'target'
|
||||
expiredRedeem?: 0 | 1
|
||||
state?: 'REDEEMED' | 'BEFORE-REDEEM'
|
||||
}
|
||||
|
||||
type CfdHistoryQuery = {
|
||||
instrument?: string,
|
||||
page?: number,
|
||||
limit?: number,
|
||||
}
|
||||
instrument?: string
|
||||
page?: number
|
||||
limit?: number
|
||||
} & Partial<Record<string, string | number>>
|
||||
class OrionBlockchain {
|
||||
private readonly apiUrl: string;
|
||||
|
||||
@@ -110,12 +110,12 @@ class OrionBlockchain {
|
||||
return `${this.apiUrl}/`;
|
||||
}
|
||||
|
||||
private getSummaryRedeem = (brokerAddress: string, unshifted?: 1 | 0, sourceNetworkCode?: typeof networkCodes[number]) => {
|
||||
private readonly getSummaryRedeem = (brokerAddress: string, unshifted?: 1 | 0, sourceNetworkCode?: typeof networkCodes[number]) => {
|
||||
const url = new URL(`${this.apiUrl}/api/atomic/summary-redeem/${brokerAddress}`);
|
||||
if (unshifted) {
|
||||
if (unshifted !== undefined && unshifted === 1) {
|
||||
url.searchParams.append('unshifted', unshifted.toString());
|
||||
}
|
||||
if (sourceNetworkCode) {
|
||||
if (sourceNetworkCode !== undefined) {
|
||||
url.searchParams.append('sourceNetworkCode', sourceNetworkCode);
|
||||
}
|
||||
return fetchWithValidation(
|
||||
@@ -124,12 +124,12 @@ class OrionBlockchain {
|
||||
);
|
||||
};
|
||||
|
||||
private getSummaryClaim = (brokerAddress: string) => fetchWithValidation(
|
||||
private readonly getSummaryClaim = (brokerAddress: string) => fetchWithValidation(
|
||||
`${this.apiUrl}/api/atomic/summary-claim/${brokerAddress}`,
|
||||
atomicSummarySchema,
|
||||
);
|
||||
|
||||
private getQueueLength = () => fetchWithValidation(
|
||||
private readonly getQueueLength = () => fetchWithValidation(
|
||||
`${this.apiUrl}/api/queueLength`,
|
||||
z.number().int(),
|
||||
);
|
||||
@@ -357,7 +357,10 @@ class OrionBlockchain {
|
||||
const url = new URL(`${this.apiUrl}/api/atomic/history/`);
|
||||
|
||||
Object.entries(query)
|
||||
.forEach(([key, value]) => url.searchParams.append(key, value.toString()));
|
||||
.forEach(([key, value]) => {
|
||||
if (value === undefined) throw new Error('Value must be defined');
|
||||
url.searchParams.append(key, value.toString());
|
||||
});
|
||||
|
||||
return fetchWithValidation(url.toString(), atomicHistorySchema);
|
||||
};
|
||||
@@ -366,9 +369,12 @@ class OrionBlockchain {
|
||||
const url = new URL(`${this.apiUrl}/api/atomic/history/`);
|
||||
|
||||
Object.entries(query)
|
||||
.forEach(([key, value]) => url.searchParams.append(key, value.toString()));
|
||||
.forEach(([key, value]) => {
|
||||
if (value === undefined) throw new Error('Value must be defined');
|
||||
url.searchParams.append(key, value.toString());
|
||||
});
|
||||
|
||||
if (!query.type) url.searchParams.append('type', 'source');
|
||||
if (query.type !== undefined) url.searchParams.append('type', 'source');
|
||||
|
||||
return fetchWithValidation(url.toString(), sourceAtomicHistorySchema);
|
||||
};
|
||||
@@ -377,9 +383,12 @@ class OrionBlockchain {
|
||||
const url = new URL(`${this.apiUrl}/api/atomic/history/`);
|
||||
|
||||
Object.entries(query)
|
||||
.forEach(([key, value]) => url.searchParams.append(key, value.toString()));
|
||||
.forEach(([key, value]) => {
|
||||
if (value === undefined) throw new Error('Value must be defined');
|
||||
url.searchParams.append(key, value.toString());
|
||||
});
|
||||
|
||||
if (!query.type) url.searchParams.append('type', 'target');
|
||||
if (query.type !== undefined) url.searchParams.append('type', 'target');
|
||||
|
||||
return fetchWithValidation(url.toString(), targetAtomicHistorySchema);
|
||||
};
|
||||
@@ -406,7 +415,10 @@ class OrionBlockchain {
|
||||
const url = new URL(`${this.apiUrl}/api/cfd/deposit-withdraw/${address}`);
|
||||
|
||||
Object.entries(query)
|
||||
.forEach(([key, value]) => url.searchParams.append(key, value.toString()));
|
||||
.forEach(([key, value]) => {
|
||||
if (value === undefined) throw new Error('Value must be defined');
|
||||
url.searchParams.append(key, value.toString());
|
||||
});
|
||||
|
||||
return fetchWithValidation(url.toString(), cfdHistorySchema);
|
||||
};
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import fetchWithValidation from '../../fetchWithValidation';
|
||||
import { Exchange } from '../../types';
|
||||
import { type Exchange } from '../../types';
|
||||
import { statisticsOverviewSchema, topPairsStatisticsSchema } from './schemas';
|
||||
import candlesSchema from './schemas/candlesSchema';
|
||||
import { PriceFeedWS } from './ws';
|
||||
|
||||
class PriceFeed {
|
||||
private apiUrl: string;
|
||||
private readonly apiUrl: string;
|
||||
|
||||
readonly ws: PriceFeedWS;
|
||||
|
||||
|
||||
@@ -6,12 +6,12 @@ import { tickerInfoSchema, candleSchema } from './schemas';
|
||||
import priceSchema from './schemas/priceSchema';
|
||||
|
||||
type TickerInfo = {
|
||||
pairName: string;
|
||||
lastPrice: string;
|
||||
openPrice: string;
|
||||
highPrice: string;
|
||||
lowPrice: string;
|
||||
volume24h: string;
|
||||
pairName: string
|
||||
lastPrice: string
|
||||
openPrice: string
|
||||
highPrice: string
|
||||
lowPrice: string
|
||||
volume24h: string
|
||||
}
|
||||
|
||||
const allTickersSchema = z.unknown().array()
|
||||
@@ -57,11 +57,11 @@ export type Subscription<
|
||||
Schema = z.infer<typeof subscriptions[T]['schema']>
|
||||
> = typeof subscriptions[T] extends { payload: true }
|
||||
? {
|
||||
callback: (data: Schema) => void,
|
||||
payload: string,
|
||||
} : {
|
||||
callback: (data: Schema) => void,
|
||||
}
|
||||
callback: (data: Schema) => void
|
||||
payload: string
|
||||
} : {
|
||||
callback: (data: Schema) => void
|
||||
}
|
||||
|
||||
export default class PriceFeedSubscription<T extends SubscriptionType = SubscriptionType> {
|
||||
public readonly id: string;
|
||||
@@ -104,16 +104,23 @@ export default class PriceFeedSubscription<T extends SubscriptionType = Subscrip
|
||||
this.isClosedIntentionally = false;
|
||||
|
||||
const { payload, url, type } = this;
|
||||
this.ws = new WebSocket(`${url}/${type}${payload ? `/${payload.toString()}` : ''}`);
|
||||
this.ws = new WebSocket(`${url}/${type}${payload !== undefined ? `/${payload.toString()}` : ''}`);
|
||||
|
||||
this.ws.onmessage = (e) => {
|
||||
if (e.data === 'pong') return;
|
||||
const json: unknown = JSON.parse(e.data.toString());
|
||||
const { data } = e;
|
||||
|
||||
// const isBufferArray = Array.isArray(data);
|
||||
// const isArrayBuffer = data instanceof ArrayBuffer;
|
||||
const isBuffer = Buffer.isBuffer(data);
|
||||
if (!isBuffer) throw new Error('Not a buffer');
|
||||
const dataString = data.toString();
|
||||
if (dataString === 'pong') return;
|
||||
const json: unknown = JSON.parse(dataString);
|
||||
const subscription = subscriptions[type];
|
||||
const parseResult = subscription.schema.safeParse(json);
|
||||
if (parseResult.success === false) {
|
||||
if (!parseResult.success) {
|
||||
const errorsMessage = parseResult.error.errors.map((error) => `[${error.path.join('.')}] ${error.message}`).join(', ');
|
||||
throw new Error(`Can't recognize PriceFeed "${type}" subscription message "${e.data.toString()}": ${errorsMessage}`);
|
||||
throw new Error(`Can't recognize PriceFeed "${type}" subscription message "${dataString}": ${errorsMessage}`);
|
||||
}
|
||||
this.callback(parseResult.data);
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import PriceFeedSubscription, { SubscriptionType, Subscription } from './PriceFeedSubscription';
|
||||
import PriceFeedSubscription, { type SubscriptionType, type Subscription } from './PriceFeedSubscription';
|
||||
|
||||
export * as schemas from './schemas';
|
||||
export class PriceFeedWS {
|
||||
@@ -11,7 +11,7 @@ export class PriceFeedWS {
|
||||
>;
|
||||
}> = {};
|
||||
|
||||
private url: string;
|
||||
private readonly url: string;
|
||||
|
||||
constructor(url: string) {
|
||||
this.url = url;
|
||||
@@ -36,7 +36,7 @@ export class PriceFeedWS {
|
||||
return {
|
||||
type: sub.type,
|
||||
id: sub.id,
|
||||
unsubscribe: () => this.unsubscribe(sub.type, sub.id),
|
||||
unsubscribe: () => { this.unsubscribe(sub.type, sub.id); },
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -6,21 +6,21 @@ import globalAnalyticsSchema from './schemas/globalAnalyticsSchema';
|
||||
import linkSchema from './schemas/linkSchema';
|
||||
|
||||
type CreateLinkPayloadType = {
|
||||
referer: string;
|
||||
link_option: number;
|
||||
};
|
||||
referer: string
|
||||
link_option: number
|
||||
}
|
||||
|
||||
type SubscribePayloadType = {
|
||||
ref_target: string;
|
||||
referral: string;
|
||||
ref_target: string
|
||||
referral: string
|
||||
}
|
||||
|
||||
type SignatureType = {
|
||||
signature: string;
|
||||
};
|
||||
signature: string
|
||||
}
|
||||
|
||||
class ReferralSystem {
|
||||
private apiUrl: string;
|
||||
private readonly apiUrl: string;
|
||||
|
||||
get api() {
|
||||
return this.apiUrl;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Schema, z } from 'zod';
|
||||
import { type Schema, type z } from 'zod';
|
||||
import fetchWithValidation from './fetchWithValidation';
|
||||
|
||||
// https://stackoverflow.com/a/64919133
|
||||
|
||||
324
src/types.ts
324
src/types.ts
@@ -1,117 +1,117 @@
|
||||
import BigNumber from 'bignumber.js';
|
||||
import exchanges from './constants/exchanges';
|
||||
import subOrderStatuses from './constants/subOrderStatuses';
|
||||
import positionStatuses from './constants/positionStatuses';
|
||||
import type BigNumber from 'bignumber.js';
|
||||
import type exchanges from './constants/exchanges';
|
||||
import type subOrderStatuses from './constants/subOrderStatuses';
|
||||
import type positionStatuses from './constants/positionStatuses';
|
||||
|
||||
export type DeepPartial<T> = T extends object ? {
|
||||
[P in keyof T]?: DeepPartial<T[P]>;
|
||||
} : T;
|
||||
|
||||
export type AssetPairUpdate = {
|
||||
minQty: number,
|
||||
pricePrecision: number,
|
||||
minQty: number
|
||||
pricePrecision: number
|
||||
}
|
||||
export type SubOrder = {
|
||||
pair: string,
|
||||
exchange: string,
|
||||
id: number,
|
||||
amount: number,
|
||||
settledAmount: number,
|
||||
price: number,
|
||||
status: typeof subOrderStatuses[number],
|
||||
side: 'BUY' | 'SELL',
|
||||
pair: string
|
||||
exchange: string
|
||||
id: number
|
||||
amount: number
|
||||
settledAmount: number
|
||||
price: number
|
||||
status: typeof subOrderStatuses[number]
|
||||
side: 'BUY' | 'SELL'
|
||||
subOrdQty: number
|
||||
}
|
||||
|
||||
export type Balance = {
|
||||
tradable: string,
|
||||
reserved: string,
|
||||
contract: string,
|
||||
wallet: string,
|
||||
allowance: string,
|
||||
tradable: string
|
||||
reserved: string
|
||||
contract: string
|
||||
wallet: string
|
||||
allowance: string
|
||||
}
|
||||
|
||||
export type PositionStatus = typeof positionStatuses[number];
|
||||
|
||||
export type CFDBalance = {
|
||||
instrument: string,
|
||||
balance: string,
|
||||
profitLoss: string,
|
||||
fundingRate: string,
|
||||
equity: string,
|
||||
position: string,
|
||||
currentPrice: string,
|
||||
positionPrice: string,
|
||||
reserves: string,
|
||||
margin: string,
|
||||
marginUSD: string,
|
||||
freeMarginUSD: string,
|
||||
availableWithdrawBalance: string,
|
||||
leverage: string,
|
||||
status: PositionStatus,
|
||||
instrument: string
|
||||
balance: string
|
||||
profitLoss: string
|
||||
fundingRate: string
|
||||
equity: string
|
||||
position: string
|
||||
currentPrice: string
|
||||
positionPrice: string
|
||||
reserves: string
|
||||
margin: string
|
||||
marginUSD: string
|
||||
freeMarginUSD: string
|
||||
availableWithdrawBalance: string
|
||||
leverage: string
|
||||
status: PositionStatus
|
||||
}
|
||||
|
||||
export interface Order {
|
||||
senderAddress: string; // address
|
||||
matcherAddress: string; // address
|
||||
baseAsset: string; // address
|
||||
quoteAsset: string; // address
|
||||
matcherFeeAsset: string; // address
|
||||
amount: number; // uint64
|
||||
price: number; // uint64
|
||||
matcherFee: number; // uint64
|
||||
nonce: number; // uint64
|
||||
expiration: number; // uint64
|
||||
buySide: number; // uint8, 1=buy, 0=sell
|
||||
isPersonalSign: boolean; // bool
|
||||
export type Order = {
|
||||
senderAddress: string // address
|
||||
matcherAddress: string // address
|
||||
baseAsset: string // address
|
||||
quoteAsset: string // address
|
||||
matcherFeeAsset: string // address
|
||||
amount: number // uint64
|
||||
price: number // uint64
|
||||
matcherFee: number // uint64
|
||||
nonce: number // uint64
|
||||
expiration: number // uint64
|
||||
buySide: 0 | 1 // uint8, 1=buy, 0=sell
|
||||
isPersonalSign: boolean // bool
|
||||
}
|
||||
|
||||
export interface CFDOrder {
|
||||
senderAddress: string; // address
|
||||
matcherAddress: string; // address
|
||||
instrumentAddress: string; // address
|
||||
amount: number; // uint64
|
||||
price: number; // uint64
|
||||
matcherFee: number; // uint64
|
||||
nonce: number; // uint64
|
||||
expiration: number; // uint64
|
||||
buySide: number; // uint8, 1=buy, 0=sell
|
||||
isPersonalSign: boolean; // bool
|
||||
export type CFDOrder = {
|
||||
senderAddress: string // address
|
||||
matcherAddress: string // address
|
||||
instrumentAddress: string // address
|
||||
amount: number // uint64
|
||||
price: number // uint64
|
||||
matcherFee: number // uint64
|
||||
nonce: number // uint64
|
||||
expiration: number // uint64
|
||||
buySide: 0 | 1 // uint8, 1=buy, 0=sell
|
||||
isPersonalSign: boolean // bool
|
||||
}
|
||||
|
||||
export interface SignedCFDOrder extends CFDOrder {
|
||||
id: string; // hash of Order (it's not part of order structure in smart-contract)
|
||||
signature: string; // bytes
|
||||
export type SignedCFDOrder = {
|
||||
id: string // hash of Order (it's not part of order structure in smart-contract)
|
||||
signature: string // bytes
|
||||
} & CFDOrder
|
||||
|
||||
export type SignedOrder = {
|
||||
id: string // hash of Order (it's not part of order structure in smart-contract)
|
||||
signature: string // bytes
|
||||
needWithdraw?: boolean // bool (not supported yet by smart-contract)
|
||||
} & Order
|
||||
|
||||
export type CancelOrderRequest = {
|
||||
id: number | string
|
||||
senderAddress: string
|
||||
isPersonalSign: boolean
|
||||
}
|
||||
|
||||
export interface SignedOrder extends Order {
|
||||
id: string; // hash of Order (it's not part of order structure in smart-contract)
|
||||
signature: string; // bytes
|
||||
needWithdraw?: boolean; // bool (not supported yet by smart-contract)
|
||||
}
|
||||
export type SignedCancelOrderRequest = {
|
||||
id: number | string
|
||||
senderAddress: string
|
||||
signature: string
|
||||
} & CancelOrderRequest
|
||||
|
||||
export interface CancelOrderRequest {
|
||||
id: number | string;
|
||||
senderAddress: string;
|
||||
isPersonalSign: boolean;
|
||||
}
|
||||
|
||||
export interface SignedCancelOrderRequest extends CancelOrderRequest {
|
||||
id: number | string;
|
||||
senderAddress: string;
|
||||
signature: string;
|
||||
}
|
||||
|
||||
export interface Pair {
|
||||
name: string;
|
||||
baseCurrency: string;
|
||||
quoteCurrency: string;
|
||||
lastPrice: string;
|
||||
openPrice: string;
|
||||
change24h: string;
|
||||
high: string;
|
||||
low: string;
|
||||
vol24h: string;
|
||||
export type Pair = {
|
||||
name: string
|
||||
baseCurrency: string
|
||||
quoteCurrency: string
|
||||
lastPrice: string
|
||||
openPrice: string
|
||||
change24h: string
|
||||
high: string
|
||||
low: string
|
||||
vol24h: string
|
||||
}
|
||||
|
||||
export enum SupportedChainId {
|
||||
@@ -135,114 +135,114 @@ const balanceTypes = ['exchange', 'wallet'] as const;
|
||||
|
||||
export type Source = typeof balanceTypes[number];
|
||||
export type Asset = {
|
||||
name: string;
|
||||
address: string;
|
||||
name: string
|
||||
address: string
|
||||
}
|
||||
export type BalanceRequirement = {
|
||||
readonly reason: string,
|
||||
readonly asset: Asset,
|
||||
readonly amount: string,
|
||||
readonly sources: Source[],
|
||||
readonly spenderAddress?: string;
|
||||
readonly reason: string
|
||||
readonly asset: Asset
|
||||
readonly amount: string
|
||||
readonly sources: Source[]
|
||||
readonly spenderAddress?: string
|
||||
}
|
||||
|
||||
export type AggregatedBalanceRequirement = {
|
||||
readonly asset: Asset,
|
||||
readonly sources: Source[],
|
||||
readonly spenderAddress?: string;
|
||||
items: Partial<Record<string, string>>,
|
||||
readonly asset: Asset
|
||||
readonly sources: Source[]
|
||||
readonly spenderAddress?: string
|
||||
items: Partial<Record<string, string>>
|
||||
}
|
||||
|
||||
export type ApproveFix = {
|
||||
readonly type: 'byApprove',
|
||||
readonly targetAmount: BigNumber.Value,
|
||||
readonly type: 'byApprove'
|
||||
readonly targetAmount: BigNumber.Value
|
||||
readonly spenderAddress: string
|
||||
}
|
||||
|
||||
export type DepositFix = {
|
||||
readonly type: 'byDeposit',
|
||||
readonly amount: BigNumber.Value,
|
||||
readonly type: 'byDeposit'
|
||||
readonly amount: BigNumber.Value
|
||||
readonly asset: string
|
||||
}
|
||||
|
||||
type Fix = ApproveFix | DepositFix;
|
||||
|
||||
export type BalanceIssue = {
|
||||
readonly asset: Asset,
|
||||
readonly message: string;
|
||||
readonly sources: Source[],
|
||||
readonly fixes?: Fix[],
|
||||
readonly asset: Asset
|
||||
readonly message: string
|
||||
readonly sources: Source[]
|
||||
readonly fixes?: Fix[]
|
||||
}
|
||||
|
||||
export type Exchange = typeof exchanges[number];
|
||||
|
||||
export type OrderbookItem = {
|
||||
price: string,
|
||||
amount: string,
|
||||
exchanges: Exchange[],
|
||||
vob: {
|
||||
side: 'BUY' | 'SELL',
|
||||
price: string
|
||||
amount: string
|
||||
exchanges: Exchange[]
|
||||
vob: Array<{
|
||||
side: 'BUY' | 'SELL'
|
||||
pairName: string
|
||||
}[]
|
||||
}>
|
||||
}
|
||||
|
||||
export type SwapInfoAlternative = {
|
||||
exchanges: Exchange[],
|
||||
path: string[],
|
||||
marketAmountOut?: number,
|
||||
marketAmountIn?: number,
|
||||
marketPrice: number,
|
||||
availableAmountIn?: number,
|
||||
availableAmountOut?: number,
|
||||
exchanges: Exchange[]
|
||||
path: string[]
|
||||
marketAmountOut?: number
|
||||
marketAmountIn?: number
|
||||
marketPrice: number
|
||||
availableAmountIn?: number
|
||||
availableAmountOut?: number
|
||||
}
|
||||
|
||||
export type SwapInfoBase = {
|
||||
swapRequestId: string,
|
||||
assetIn: string,
|
||||
assetOut: string,
|
||||
amountIn: number,
|
||||
amountOut: number,
|
||||
minAmountIn: number,
|
||||
minAmountOut: number,
|
||||
swapRequestId: string
|
||||
assetIn: string
|
||||
assetOut: string
|
||||
amountIn: number
|
||||
amountOut: number
|
||||
minAmountIn: number
|
||||
minAmountOut: number
|
||||
|
||||
path: string[],
|
||||
exchanges?: Exchange[],
|
||||
poolOptimal: boolean,
|
||||
path: string[]
|
||||
exchanges?: Exchange[]
|
||||
poolOptimal: boolean
|
||||
|
||||
price?: number,
|
||||
marketPrice?: number,
|
||||
price?: number
|
||||
marketPrice?: number
|
||||
orderInfo?: {
|
||||
pair: string,
|
||||
side: 'BUY' | 'SELL',
|
||||
amount: number,
|
||||
safePrice: number,
|
||||
},
|
||||
alternatives: SwapInfoAlternative[],
|
||||
pair: string
|
||||
side: 'BUY' | 'SELL'
|
||||
amount: number
|
||||
safePrice: number
|
||||
}
|
||||
alternatives: SwapInfoAlternative[]
|
||||
}
|
||||
|
||||
export type SwapInfoByAmountIn = SwapInfoBase & {
|
||||
kind: 'exactSpend',
|
||||
availableAmountIn?: number,
|
||||
marketAmountOut?: number,
|
||||
kind: 'exactSpend'
|
||||
availableAmountIn?: number
|
||||
marketAmountOut?: number
|
||||
}
|
||||
|
||||
export type SwapInfoByAmountOut = SwapInfoBase & {
|
||||
kind: 'exactReceive',
|
||||
marketAmountIn?: number,
|
||||
availableAmountOut?: number,
|
||||
kind: 'exactReceive'
|
||||
marketAmountIn?: number
|
||||
availableAmountOut?: number
|
||||
}
|
||||
|
||||
export type SwapInfo = SwapInfoByAmountIn | SwapInfoByAmountOut;
|
||||
|
||||
export type FuturesTradeInfo = {
|
||||
futuresTradeRequestId: string,
|
||||
sender: string,
|
||||
instrument: string,
|
||||
buyPrice: number,
|
||||
sellPrice: number,
|
||||
buyPower: number,
|
||||
sellPower: number,
|
||||
minAmount: number,
|
||||
futuresTradeRequestId: string
|
||||
sender: string
|
||||
instrument: string
|
||||
buyPrice: number
|
||||
sellPrice: number
|
||||
buyPower: number
|
||||
sellPower: number
|
||||
minAmount: number
|
||||
}
|
||||
|
||||
export enum HistoryTransactionStatus {
|
||||
@@ -255,30 +255,30 @@ export enum HistoryTransactionStatus {
|
||||
export type VerboseOrionUnitConfig = {
|
||||
// env?: string;
|
||||
// api: string;
|
||||
chainId: SupportedChainId;
|
||||
nodeJsonRpc: string;
|
||||
chainId: SupportedChainId
|
||||
nodeJsonRpc: string
|
||||
services: {
|
||||
orionBlockchain: {
|
||||
http: string;
|
||||
http: string
|
||||
// For example:
|
||||
// http://localhost:3001/,
|
||||
// http://10.123.34.23:3001/,
|
||||
// https://blockchain.orionprotocol.io/
|
||||
},
|
||||
}
|
||||
orionAggregator: {
|
||||
http: string;
|
||||
ws: string;
|
||||
http: string
|
||||
ws: string
|
||||
// For example:
|
||||
// http://localhost:3002/,
|
||||
// http://10.34.23.5:3002/,
|
||||
// shttps://aggregator.orionprotocol.io/
|
||||
},
|
||||
}
|
||||
priceFeed: {
|
||||
api: string;
|
||||
api: string
|
||||
// For example:
|
||||
// http://localhost:3003/,
|
||||
// http://10.23.5.11:3003/,
|
||||
// https://price-feed.orionprotocol.io/
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable camelcase */
|
||||
import { ERC20__factory } from '@orionprotocol/contracts';
|
||||
import { ethers } from 'ethers';
|
||||
import invariant from 'tiny-invariant';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import BigNumber from 'bignumber.js';
|
||||
import { ethers } from 'ethers';
|
||||
import { type ethers } from 'ethers';
|
||||
|
||||
/**
|
||||
* Converts normalized blockchain ("machine-readable") number to denormalized ("human-readable") number.
|
||||
@@ -9,6 +9,6 @@ import { ethers } from 'ethers';
|
||||
*/
|
||||
export default function denormalizeNumber(input: ethers.BigNumber, decimals: BigNumber.Value) {
|
||||
const decimalsBN = new BigNumber(decimals);
|
||||
if (!decimalsBN.isInteger()) throw new Error(`Decimals '${decimals.toString()}' is not an integer`);
|
||||
if (!decimalsBN.isInteger()) throw new Error(`Decimals '${decimalsBN.toString()}' is not an integer`);
|
||||
return new BigNumber(input.toString()).div(new BigNumber(10).pow(decimalsBN));
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ethers } from 'ethers';
|
||||
import { Source } from '../types';
|
||||
import { type Source } from '../types';
|
||||
|
||||
export default function getAvailableFundsSources(
|
||||
expenseType: 'amount' | 'network_fee' | 'orion_fee',
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { ERC20__factory, Exchange } from '@orionprotocol/contracts';
|
||||
import { ERC20__factory, type Exchange } from '@orionprotocol/contracts';
|
||||
|
||||
import BigNumber from 'bignumber.js';
|
||||
import type BigNumber from 'bignumber.js';
|
||||
import { ethers } from 'ethers';
|
||||
import { utils } from '..';
|
||||
import { INTERNAL_ORION_PRECISION, NATIVE_CURRENCY_PRECISION } from '../constants';
|
||||
import { OrionAggregator } from '../services/OrionAggregator';
|
||||
import { type OrionAggregator } from '../services/OrionAggregator';
|
||||
import denormalizeNumber from './denormalizeNumber';
|
||||
|
||||
export default async function getBalance(
|
||||
orionAggregator: OrionAggregator,
|
||||
@@ -25,13 +25,13 @@ export default async function getBalance(
|
||||
const assetDecimals = await assetContract.decimals();
|
||||
assetWalletBalance = await assetContract.balanceOf(walletAddress);
|
||||
|
||||
denormalizedAssetInWalletBalance = utils.denormalizeNumber(assetWalletBalance, assetDecimals);
|
||||
denormalizedAssetInWalletBalance = denormalizeNumber(assetWalletBalance, assetDecimals);
|
||||
} else {
|
||||
assetWalletBalance = await provider.getBalance(walletAddress);
|
||||
denormalizedAssetInWalletBalance = utils.denormalizeNumber(assetWalletBalance, NATIVE_CURRENCY_PRECISION);
|
||||
denormalizedAssetInWalletBalance = denormalizeNumber(assetWalletBalance, NATIVE_CURRENCY_PRECISION);
|
||||
}
|
||||
const assetContractBalance = await exchangeContract.getBalance(assetAddress, walletAddress);
|
||||
const denormalizedAssetInContractBalance = utils.denormalizeNumber(assetContractBalance, INTERNAL_ORION_PRECISION);
|
||||
const denormalizedAssetInContractBalance = denormalizeNumber(assetContractBalance, INTERNAL_ORION_PRECISION);
|
||||
const denormalizedAssetLockedBalanceResult = await orionAggregator.getLockedBalance(walletAddress, asset);
|
||||
if (denormalizedAssetLockedBalanceResult.isErr()) {
|
||||
throw new Error(denormalizedAssetLockedBalanceResult.error.message);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Exchange } from '@orionprotocol/contracts';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import { ethers } from 'ethers';
|
||||
import { OrionAggregator } from '../services/OrionAggregator';
|
||||
import { type Exchange } from '@orionprotocol/contracts';
|
||||
import type BigNumber from 'bignumber.js';
|
||||
import { type ethers } from 'ethers';
|
||||
import { type OrionAggregator } from '../services/OrionAggregator';
|
||||
import getBalance from './getBalance';
|
||||
|
||||
export default async (
|
||||
@@ -14,7 +14,7 @@ export default async (
|
||||
const balances = await Promise.all(
|
||||
Object.entries(balancesRequired)
|
||||
.map(async ([asset, assetAddress]) => {
|
||||
if (!assetAddress) throw new Error(`Asset address of ${asset} not found`);
|
||||
if (assetAddress === undefined) throw new Error(`Asset address of ${asset} not found`);
|
||||
const balance = await getBalance(
|
||||
orionAggregator,
|
||||
asset,
|
||||
@@ -31,8 +31,8 @@ export default async (
|
||||
);
|
||||
|
||||
return balances.reduce<Partial<Record<string, {
|
||||
exchange: BigNumber,
|
||||
wallet: BigNumber,
|
||||
exchange: BigNumber
|
||||
wallet: BigNumber
|
||||
}>>>((prev, curr) => ({
|
||||
...prev,
|
||||
[curr.asset]: curr.amount,
|
||||
|
||||
@@ -4,7 +4,7 @@ const getNativeCryptocurrency = (assetToAddress: Partial<Record<string, string>>
|
||||
const addressToAsset = Object
|
||||
.entries(assetToAddress)
|
||||
.reduce<Partial<Record<string, string>>>((prev, [asset, address]) => {
|
||||
if (!address) return prev;
|
||||
if (address === undefined) return prev;
|
||||
return {
|
||||
...prev,
|
||||
[address]: asset,
|
||||
@@ -12,7 +12,7 @@ const getNativeCryptocurrency = (assetToAddress: Partial<Record<string, string>>
|
||||
}, {});
|
||||
|
||||
const nativeCryptocurrency = addressToAsset[ethers.constants.AddressZero];
|
||||
if (!nativeCryptocurrency) throw new Error('Native cryptocurrency asset is not found');
|
||||
if (nativeCryptocurrency === undefined) throw new Error('Native cryptocurrency asset is not found');
|
||||
return nativeCryptocurrency;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
export default class HttpError extends Error {
|
||||
public code: number;
|
||||
|
||||
public errorMessage: string |null;
|
||||
public errorMessage: string | null;
|
||||
|
||||
public statusText: string;
|
||||
|
||||
public type: string;
|
||||
|
||||
constructor(code:number, message:string|null, type: string, statusText:string) {
|
||||
super(message || '');
|
||||
constructor(code: number, message: string | null, type: string, statusText: string) {
|
||||
super(message ?? '');
|
||||
this.errorMessage = message;
|
||||
this.type = type;
|
||||
this.statusText = statusText;
|
||||
|
||||
@@ -12,6 +12,7 @@ export { default as parseExchangeTradeTransaction } from './parseExchangeTradeTr
|
||||
export { default as toUpperCase } from './toUpperCase';
|
||||
export { default as toLowerCase } from './toLowerCase';
|
||||
export { default as isUppercasedNetworkCode } from './isUppercasedNetworkCode';
|
||||
export { default as getNativeCryptocurrency } from './getNativeCryptocurrency';
|
||||
|
||||
// export { default as HttpError } from './httpError';
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ export default function isNetworkCodeInEnvironment(networkCode: string, env: str
|
||||
}
|
||||
const envInfo = envs[env];
|
||||
const envNetworks = envInfo?.networks;
|
||||
if (envNetworks === undefined) throw new Error('Env networks is undefined (isNetworkCodeInEnvironment)');
|
||||
if (!envNetworks) throw new Error('Env networks is undefined (isNetworkCodeInEnvironment)');
|
||||
|
||||
return Object.values(chains)
|
||||
.some((chain) => chain.code.toLowerCase() === networkCode.toLowerCase() &&
|
||||
|
||||
@@ -14,7 +14,7 @@ export default function normalizeNumber(
|
||||
roundingMode: BigNumber.RoundingMode,
|
||||
) {
|
||||
const decimalsBN = new BigNumber(decimals);
|
||||
if (!decimalsBN.isInteger()) throw new Error(`Decimals '${decimals.toString()}' is not an integer`);
|
||||
if (!decimalsBN.isInteger()) throw new Error(`Decimals '${decimalsBN.toString()}' is not an integer`);
|
||||
const inputBN = new BigNumber(input);
|
||||
return ethers.BigNumber.from(
|
||||
inputBN
|
||||
|
||||
@@ -14,4 +14,4 @@ const untypedItems = Object.keys(items); // => Array<string>
|
||||
@category Type guard
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
||||
export const objectKeys = Object.keys as <Type extends object>(value: Type) => ObjectKeys<Type>[];
|
||||
export const objectKeys = Object.keys as <Type extends object>(value: Type) => Array<ObjectKeys<Type>>;
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
type WithReason = {
|
||||
reason: string;
|
||||
reason: string
|
||||
}
|
||||
|
||||
type WithCodeError = Error & {
|
||||
code: number | string;
|
||||
code: number | string
|
||||
}
|
||||
|
||||
type WithMessage = {
|
||||
message: string;
|
||||
message: string
|
||||
}
|
||||
|
||||
type WithDataError = Error & {
|
||||
data: Record<string, unknown>;
|
||||
data: Record<string, unknown>
|
||||
}
|
||||
|
||||
type WithError ={
|
||||
error: Record<string | number | symbol, unknown>;
|
||||
type WithError = {
|
||||
error: Record<string | number | symbol, unknown>
|
||||
}
|
||||
|
||||
export const makePartial = <Key extends string | number | symbol, Value>(value: Record<Key, Value>): Partial<Record<Key, Value>> => value;
|
||||
|
||||
Reference in New Issue
Block a user