mirror of
https://github.com/oceanprotocol/market.git
synced 2024-12-02 05:57:29 +01:00
Merge branch 'v4' into feature/v4-c2d
This commit is contained in:
commit
b4a60b833c
@ -41,7 +41,7 @@
|
||||
"add": {
|
||||
"title": "Add Liquidity",
|
||||
"output": {
|
||||
"help": "Providing liquidity will earn you SWAPFEE% on every transaction in this pool, proportionally to your share of the pool. Your token input will be converted based on the weight of the pool.",
|
||||
"help": "Providing liquidity will earn you SWAPFEE% on every transaction in this pool, proportionally to your share of the pool.",
|
||||
"titleIn": "You will receive",
|
||||
"titleOut": "Pool conversion"
|
||||
},
|
||||
@ -50,8 +50,7 @@
|
||||
},
|
||||
"remove": {
|
||||
"title": "Remove Liquidity",
|
||||
"simple": "Set the amount of your pool shares to spend. You will get the equivalent value in OCEAN, limited to maximum amount for pool protection. If you have Datatokens left in your wallet, you can add them to the pool to increase the maximum amount.",
|
||||
"advanced": "Set the amount of your pool shares to spend. You will get OCEAN and Datatokens equivalent to your pool share, without any limit. You can use these Datatokens in other DeFi tools.",
|
||||
"simple": "Set the amount of your pool shares to spend. You will get the equivalent value in OCEAN, limited to maximum amount for pool protection.",
|
||||
"output": {
|
||||
"titleIn": "You will spend",
|
||||
"titleOut": "You will receive"
|
||||
|
122
package-lock.json
generated
122
package-lock.json
generated
@ -13,7 +13,7 @@
|
||||
"@coingecko/cryptoformat": "^0.4.4",
|
||||
"@loadable/component": "^5.15.2",
|
||||
"@oceanprotocol/art": "^3.2.0",
|
||||
"@oceanprotocol/lib": "^1.0.0-next.10",
|
||||
"@oceanprotocol/lib": "^1.0.0-next.11",
|
||||
"@oceanprotocol/typographies": "^0.1.0",
|
||||
"@portis/web3": "^4.0.6",
|
||||
"@tippyjs/react": "^4.2.6",
|
||||
@ -193,7 +193,6 @@
|
||||
"version": "7.16.12",
|
||||
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.16.12.tgz",
|
||||
"integrity": "sha512-dK5PtG1uiN2ikk++5OzSYsitZKny4wOCD0nrO4TqnW4BVBTQ2NGS3NgilvT/TEyxTST7LNyWV/T4tXDoD3fOgg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/code-frame": "^7.16.7",
|
||||
"@babel/generator": "^7.16.8",
|
||||
@ -223,7 +222,6 @@
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
||||
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
}
|
||||
@ -438,7 +436,6 @@
|
||||
"version": "7.16.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.16.7.tgz",
|
||||
"integrity": "sha512-gaqtLDxJEFCeQbYp9aLAefjhkKdjKcdh6DB7jniIGU3Pz52WAmP268zK0VgPz9hUNkMSYeH976K2/Y6yPadpng==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/helper-environment-visitor": "^7.16.7",
|
||||
"@babel/helper-module-imports": "^7.16.7",
|
||||
@ -507,7 +504,6 @@
|
||||
"version": "7.16.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.16.7.tgz",
|
||||
"integrity": "sha512-ZIzHVyoeLMvXMN/vok/a4LWRy8G2v205mNP0XOuf9XRLyX5/u9CnVulUtDgUTama3lT+bf/UqucuZjqiGuTS1g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/types": "^7.16.7"
|
||||
},
|
||||
@ -573,7 +569,6 @@
|
||||
"version": "7.16.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.16.7.tgz",
|
||||
"integrity": "sha512-9ZDoqtfY7AuEOt3cxchfii6C7GDyyMBffktR5B2jvWv8u2+efwvpnVKXMWzNehqy68tKgAfSwfdw/lWpthS2bw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/template": "^7.16.7",
|
||||
"@babel/traverse": "^7.16.7",
|
||||
@ -3179,9 +3174,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@oceanprotocol/lib": {
|
||||
"version": "1.0.0-next.10",
|
||||
"resolved": "https://registry.npmjs.org/@oceanprotocol/lib/-/lib-1.0.0-next.10.tgz",
|
||||
"integrity": "sha512-a2o2tC+IvFyaWFlCI2l8qxtTG8keerkVSiAzx+f7goFJZM50YoKpajJSGc+UpslEPgfcuueNTuuGLXKeCQvwKA==",
|
||||
"version": "1.0.0-next.11",
|
||||
"resolved": "https://registry.npmjs.org/@oceanprotocol/lib/-/lib-1.0.0-next.11.tgz",
|
||||
"integrity": "sha512-75+9AHVhYXQQYAC65ksyQ5Oy6mFEaK8WOSna2Kr9cz5NHS7eAtG6f71wT0e6cDcZ9u70IMOoSnIqfIT8OmXkwg==",
|
||||
"dependencies": {
|
||||
"@oceanprotocol/contracts": "^1.0.0-alpha.17",
|
||||
"bignumber.js": "^9.0.2",
|
||||
@ -10192,7 +10187,6 @@
|
||||
"version": "1.8.0",
|
||||
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz",
|
||||
"integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"safe-buffer": "~5.1.1"
|
||||
}
|
||||
@ -10200,8 +10194,7 @@
|
||||
"node_modules/convert-source-map/node_modules/safe-buffer": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
|
||||
"dev": true
|
||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
|
||||
},
|
||||
"node_modules/cookie": {
|
||||
"version": "0.4.1",
|
||||
@ -15245,7 +15238,6 @@
|
||||
"version": "1.0.0-beta.2",
|
||||
"resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
|
||||
"integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
@ -15568,7 +15560,6 @@
|
||||
"version": "15.8.0",
|
||||
"resolved": "https://registry.npmjs.org/graphql/-/graphql-15.8.0.tgz",
|
||||
"integrity": "sha512-5gghUc24tP9HRznNpV2+FIoq3xKkj5dTQqf4v0CpdPbFVwFkWoxOM+o+2OC9ZSvjEMTjfmG9QT+gcvggTwW1zw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 10.x"
|
||||
}
|
||||
@ -17196,7 +17187,6 @@
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz",
|
||||
"integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"minimist": "^1.2.5"
|
||||
},
|
||||
@ -26877,7 +26867,8 @@
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@apollographql/graphql-language-service-types/-/graphql-language-service-types-2.0.2.tgz",
|
||||
"integrity": "sha512-vE+Dz8pG+Xa1Z2nMl82LoO66lQ6JqBUjaXqLDvS3eMjvA3N4hf+YUDOWfPdNZ0zjhHhHXzUIIZCkax6bXfFbzQ==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"@apollographql/graphql-language-service-utils": {
|
||||
"version": "2.0.2",
|
||||
@ -26905,7 +26896,6 @@
|
||||
"version": "7.16.12",
|
||||
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.16.12.tgz",
|
||||
"integrity": "sha512-dK5PtG1uiN2ikk++5OzSYsitZKny4wOCD0nrO4TqnW4BVBTQ2NGS3NgilvT/TEyxTST7LNyWV/T4tXDoD3fOgg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/code-frame": "^7.16.7",
|
||||
"@babel/generator": "^7.16.8",
|
||||
@ -26927,8 +26917,7 @@
|
||||
"semver": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
||||
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
|
||||
"dev": true
|
||||
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -27089,7 +27078,6 @@
|
||||
"version": "7.16.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.16.7.tgz",
|
||||
"integrity": "sha512-gaqtLDxJEFCeQbYp9aLAefjhkKdjKcdh6DB7jniIGU3Pz52WAmP268zK0VgPz9hUNkMSYeH976K2/Y6yPadpng==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/helper-environment-visitor": "^7.16.7",
|
||||
"@babel/helper-module-imports": "^7.16.7",
|
||||
@ -27143,7 +27131,6 @@
|
||||
"version": "7.16.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.16.7.tgz",
|
||||
"integrity": "sha512-ZIzHVyoeLMvXMN/vok/a4LWRy8G2v205mNP0XOuf9XRLyX5/u9CnVulUtDgUTama3lT+bf/UqucuZjqiGuTS1g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/types": "^7.16.7"
|
||||
}
|
||||
@ -27191,7 +27178,6 @@
|
||||
"version": "7.16.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.16.7.tgz",
|
||||
"integrity": "sha512-9ZDoqtfY7AuEOt3cxchfii6C7GDyyMBffktR5B2jvWv8u2+efwvpnVKXMWzNehqy68tKgAfSwfdw/lWpthS2bw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/template": "^7.16.7",
|
||||
"@babel/traverse": "^7.16.7",
|
||||
@ -28572,7 +28558,8 @@
|
||||
"ws": {
|
||||
"version": "7.4.6",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz",
|
||||
"integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A=="
|
||||
"integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==",
|
||||
"requires": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -28715,7 +28702,8 @@
|
||||
"@graphql-typed-document-node/core": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.1.1.tgz",
|
||||
"integrity": "sha512-NQ17ii0rK1b34VZonlmT2QMJFI70m0TRwbknO/ihlbatXyaktDhN/98vBiUU6kNBPljqGqyIrl2T4nY2RpFANg=="
|
||||
"integrity": "sha512-NQ17ii0rK1b34VZonlmT2QMJFI70m0TRwbknO/ihlbatXyaktDhN/98vBiUU6kNBPljqGqyIrl2T4nY2RpFANg==",
|
||||
"requires": {}
|
||||
},
|
||||
"@humanwhocodes/config-array": {
|
||||
"version": "0.5.0",
|
||||
@ -28873,9 +28861,9 @@
|
||||
}
|
||||
},
|
||||
"@oceanprotocol/lib": {
|
||||
"version": "1.0.0-next.10",
|
||||
"resolved": "https://registry.npmjs.org/@oceanprotocol/lib/-/lib-1.0.0-next.10.tgz",
|
||||
"integrity": "sha512-a2o2tC+IvFyaWFlCI2l8qxtTG8keerkVSiAzx+f7goFJZM50YoKpajJSGc+UpslEPgfcuueNTuuGLXKeCQvwKA==",
|
||||
"version": "1.0.0-next.11",
|
||||
"resolved": "https://registry.npmjs.org/@oceanprotocol/lib/-/lib-1.0.0-next.11.tgz",
|
||||
"integrity": "sha512-75+9AHVhYXQQYAC65ksyQ5Oy6mFEaK8WOSna2Kr9cz5NHS7eAtG6f71wT0e6cDcZ9u70IMOoSnIqfIT8OmXkwg==",
|
||||
"requires": {
|
||||
"@oceanprotocol/contracts": "^1.0.0-alpha.17",
|
||||
"bignumber.js": "^9.0.2",
|
||||
@ -29807,49 +29795,57 @@
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-6.0.0.tgz",
|
||||
"integrity": "sha512-MdPdhdWLtQsjd29Wa4pABdhWbaRMACdM1h31BY+c6FghTZqNGT7pEYdBoaGeKtdTOBC/XNFQaKVj+r/Ei2ryWA==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"@svgr/babel-plugin-remove-jsx-attribute": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-6.0.0.tgz",
|
||||
"integrity": "sha512-aVdtfx9jlaaxc3unA6l+M9YRnKIZjOhQPthLKqmTXC8UVkBLDRGwPKo+r8n3VZN8B34+yVajzPTZ+ptTSuZZCw==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"@svgr/babel-plugin-remove-jsx-empty-expression": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-6.0.0.tgz",
|
||||
"integrity": "sha512-Ccj42ApsePD451AZJJf1QzTD1B/BOU392URJTeXFxSK709i0KUsGtbwyiqsKu7vsYxpTM0IA5clAKDyf9RCZyA==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"@svgr/babel-plugin-replace-jsx-attribute-value": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-6.0.0.tgz",
|
||||
"integrity": "sha512-88V26WGyt1Sfd1emBYmBJRWMmgarrExpKNVmI9vVozha4kqs6FzQJ/Kp5+EYli1apgX44518/0+t9+NU36lThQ==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"@svgr/babel-plugin-svg-dynamic-title": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-6.0.0.tgz",
|
||||
"integrity": "sha512-F7YXNLfGze+xv0KMQxrl2vkNbI9kzT9oDK55/kUuymh1ACyXkMV+VZWX1zEhSTfEKh7VkHVZGmVtHg8eTZ6PRg==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"@svgr/babel-plugin-svg-em-dimensions": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-6.0.0.tgz",
|
||||
"integrity": "sha512-+rghFXxdIqJNLQK08kwPBD3Z22/0b2tEZ9lKiL/yTfuyj1wW8HUXu4bo/XkogATIYuXSghVQOOCwURXzHGKyZA==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"@svgr/babel-plugin-transform-react-native-svg": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-6.0.0.tgz",
|
||||
"integrity": "sha512-VaphyHZ+xIKv5v0K0HCzyfAaLhPGJXSk2HkpYfXIOKb7DjLBv0soHDxNv6X0vr2titsxE7klb++u7iOf7TSrFQ==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"@svgr/babel-plugin-transform-svg-component": {
|
||||
"version": "6.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-6.2.0.tgz",
|
||||
"integrity": "sha512-bhYIpsORb++wpsp91fymbFkf09Z/YEKR0DnFjxvN+8JHeCUD2unnh18jIMKnDJTWtvpTaGYPXELVe4OOzFI0xg==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"@svgr/babel-preset": {
|
||||
"version": "6.2.0",
|
||||
@ -31407,7 +31403,8 @@
|
||||
"@use-it/event-listener": {
|
||||
"version": "0.1.7",
|
||||
"resolved": "https://registry.npmjs.org/@use-it/event-listener/-/event-listener-0.1.7.tgz",
|
||||
"integrity": "sha512-hgfExDzUU9uTRTPDCpw2s9jWTxcxmpJya3fK5ADpf5VDpSy8WYwY/kh28XE0tUcbsljeP8wfan48QvAQTSSa3Q=="
|
||||
"integrity": "sha512-hgfExDzUU9uTRTPDCpw2s9jWTxcxmpJya3fK5ADpf5VDpSy8WYwY/kh28XE0tUcbsljeP8wfan48QvAQTSSa3Q==",
|
||||
"requires": {}
|
||||
},
|
||||
"@walletconnect/browser-utils": {
|
||||
"version": "1.7.1",
|
||||
@ -31676,7 +31673,8 @@
|
||||
"version": "5.3.2",
|
||||
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
|
||||
"integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"aes-js": {
|
||||
"version": "3.1.2",
|
||||
@ -31697,7 +31695,8 @@
|
||||
"ajv-keywords": {
|
||||
"version": "3.5.2",
|
||||
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
|
||||
"integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ=="
|
||||
"integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
|
||||
"requires": {}
|
||||
},
|
||||
"align-text": {
|
||||
"version": "0.1.4",
|
||||
@ -32823,7 +32822,8 @@
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/apollo-server-errors/-/apollo-server-errors-2.5.0.tgz",
|
||||
"integrity": "sha512-lO5oTjgiC3vlVg2RKr3RiXIIQ5pGXBFxYGGUkKDhTud3jMIhs+gel8L8zsEjKaKxkjHhCQAA/bcEfYiKkGQIvA==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"apollo-utilities": {
|
||||
"version": "1.3.4",
|
||||
@ -33878,7 +33878,8 @@
|
||||
"chai-bn": {
|
||||
"version": "0.2.2",
|
||||
"resolved": "https://registry.npmjs.org/chai-bn/-/chai-bn-0.2.2.tgz",
|
||||
"integrity": "sha512-MzjelH0p8vWn65QKmEq/DLBG1Hle4WeyqT79ANhXZhn/UxRWO0OogkAxi5oGGtfzwU9bZR8mvbvYdoqNVWQwFg=="
|
||||
"integrity": "sha512-MzjelH0p8vWn65QKmEq/DLBG1Hle4WeyqT79ANhXZhn/UxRWO0OogkAxi5oGGtfzwU9bZR8mvbvYdoqNVWQwFg==",
|
||||
"requires": {}
|
||||
},
|
||||
"chalk": {
|
||||
"version": "2.4.2",
|
||||
@ -34620,7 +34621,6 @@
|
||||
"version": "1.8.0",
|
||||
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz",
|
||||
"integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"safe-buffer": "~5.1.1"
|
||||
},
|
||||
@ -34628,8 +34628,7 @@
|
||||
"safe-buffer": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
|
||||
"dev": true
|
||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -36200,19 +36199,22 @@
|
||||
"version": "8.3.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.3.0.tgz",
|
||||
"integrity": "sha512-BgZuLUSeKzvlL/VUjx/Yb787VQ26RU3gGjA3iiFvdsp/2bMfVIWUVP7tjxtjS0e+HP409cPlPvNkQloz8C91ew==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"eslint-config-standard": {
|
||||
"version": "14.1.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-14.1.1.tgz",
|
||||
"integrity": "sha512-Z9B+VR+JIXRxz21udPTL9HpFMyoMUEeX1G251EQ6e05WD9aPVtVBn09XUmZ259wCMlCDmYDSZG62Hhm+ZTJcUg==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"eslint-config-standard-jsx": {
|
||||
"version": "8.1.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-config-standard-jsx/-/eslint-config-standard-jsx-8.1.0.tgz",
|
||||
"integrity": "sha512-ULVC8qH8qCqbU792ZOO6DaiaZyHNS/5CZt3hKqHkEhVlhPEPN3nfBqqxJCyp59XrjIBZPu1chMYe9T2DXZ7TMw==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"eslint-config-standard-react": {
|
||||
"version": "9.2.0",
|
||||
@ -36499,7 +36501,8 @@
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.3.0.tgz",
|
||||
"integrity": "sha512-XslZy0LnMn+84NEG9jSGR6eGqaZB3133L8xewQo3fQagbQuGt7a63gf+P1NGKZavEYEC3UXaWEAA/AqDkuN6xA==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"eslint-plugin-security": {
|
||||
"version": "1.4.0",
|
||||
@ -36514,7 +36517,8 @@
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-4.1.0.tgz",
|
||||
"integrity": "sha512-ZL7+QRixjTR6/528YNGyDotyffm5OQst/sGxKDwGb9Uqs4In5Egi4+jbobhqJoyoCM6/7v/1A5fhQ7ScMtDjaQ==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"eslint-scope": {
|
||||
"version": "5.1.1",
|
||||
@ -38508,8 +38512,7 @@
|
||||
"gensync": {
|
||||
"version": "1.0.0-beta.2",
|
||||
"resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
|
||||
"integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
|
||||
"dev": true
|
||||
"integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg=="
|
||||
},
|
||||
"get-caller-file": {
|
||||
"version": "2.0.5",
|
||||
@ -38764,8 +38767,7 @@
|
||||
"graphql": {
|
||||
"version": "15.8.0",
|
||||
"resolved": "https://registry.npmjs.org/graphql/-/graphql-15.8.0.tgz",
|
||||
"integrity": "sha512-5gghUc24tP9HRznNpV2+FIoq3xKkj5dTQqf4v0CpdPbFVwFkWoxOM+o+2OC9ZSvjEMTjfmG9QT+gcvggTwW1zw==",
|
||||
"dev": true
|
||||
"integrity": "sha512-5gghUc24tP9HRznNpV2+FIoq3xKkj5dTQqf4v0CpdPbFVwFkWoxOM+o+2OC9ZSvjEMTjfmG9QT+gcvggTwW1zw=="
|
||||
},
|
||||
"graphql-tag": {
|
||||
"version": "2.12.4",
|
||||
@ -39942,7 +39944,6 @@
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz",
|
||||
"integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"minimist": "^1.2.5"
|
||||
}
|
||||
@ -42625,7 +42626,8 @@
|
||||
"react-chartjs-2": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/react-chartjs-2/-/react-chartjs-2-4.0.1.tgz",
|
||||
"integrity": "sha512-q8bgWzKoFvBvD7YcjT/hXG8jt55TaMAuJ1dmI3tKFJ7CijUWYz4pIfOhkTI6PBTwqu/pmeWsClBRd/7HiWzN1g=="
|
||||
"integrity": "sha512-q8bgWzKoFvBvD7YcjT/hXG8jt55TaMAuJ1dmI3tKFJ7CijUWYz4pIfOhkTI6PBTwqu/pmeWsClBRd/7HiWzN1g==",
|
||||
"requires": {}
|
||||
},
|
||||
"react-clipboard.js": {
|
||||
"version": "2.0.16",
|
||||
@ -44401,7 +44403,8 @@
|
||||
"styled-jsx": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.0.0.tgz",
|
||||
"integrity": "sha512-qUqsWoBquEdERe10EW8vLp3jT25s/ssG1/qX5gZ4wu15OZpmSMFI2v+fWlRhLfykA5rFtlJ1ME8A8pm/peV4WA=="
|
||||
"integrity": "sha512-qUqsWoBquEdERe10EW8vLp3jT25s/ssG1/qX5gZ4wu15OZpmSMFI2v+fWlRhLfykA5rFtlJ1ME8A8pm/peV4WA==",
|
||||
"requires": {}
|
||||
},
|
||||
"super-split": {
|
||||
"version": "1.1.0",
|
||||
@ -44565,7 +44568,8 @@
|
||||
"swr": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/swr/-/swr-1.2.0.tgz",
|
||||
"integrity": "sha512-C3IXeKOREn0jQ1ewXRENE7ED7jjGbFTakwB64eLACkCqkF/A0N2ckvpCTftcaSYi5yV36PzoehgVCOVRmtECcA=="
|
||||
"integrity": "sha512-C3IXeKOREn0jQ1ewXRENE7ED7jjGbFTakwB64eLACkCqkF/A0N2ckvpCTftcaSYi5yV36PzoehgVCOVRmtECcA==",
|
||||
"requires": {}
|
||||
},
|
||||
"symbol-observable": {
|
||||
"version": "1.2.0",
|
||||
@ -45449,7 +45453,8 @@
|
||||
"use-sync-external-store": {
|
||||
"version": "1.0.0-rc.0",
|
||||
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.0.0-rc.0.tgz",
|
||||
"integrity": "sha512-0U9Xlc2QDFzSGMB0DvcJQL0+DIdxDPJC7mnZlYFbl7wrSrPMcs89X5TVkNB6Dzg618m8lZop+U+J6ow3vq9RAQ=="
|
||||
"integrity": "sha512-0U9Xlc2QDFzSGMB0DvcJQL0+DIdxDPJC7mnZlYFbl7wrSrPMcs89X5TVkNB6Dzg618m8lZop+U+J6ow3vq9RAQ==",
|
||||
"requires": {}
|
||||
},
|
||||
"utf-8-validate": {
|
||||
"version": "5.0.8",
|
||||
@ -47392,7 +47397,8 @@
|
||||
"ws": {
|
||||
"version": "7.5.3",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.3.tgz",
|
||||
"integrity": "sha512-kQ/dHIzuLrS6Je9+uv81ueZomEwH0qVYstcAQ4/Z93K8zeko9gtAbttJWzoC5ukqXY1PpoouV3+VSOqEAFt5wg=="
|
||||
"integrity": "sha512-kQ/dHIzuLrS6Je9+uv81ueZomEwH0qVYstcAQ4/Z93K8zeko9gtAbttJWzoC5ukqXY1PpoouV3+VSOqEAFt5wg==",
|
||||
"requires": {}
|
||||
},
|
||||
"xhr": {
|
||||
"version": "2.6.0",
|
||||
|
@ -21,7 +21,7 @@
|
||||
"@coingecko/cryptoformat": "^0.4.4",
|
||||
"@loadable/component": "^5.15.2",
|
||||
"@oceanprotocol/art": "^3.2.0",
|
||||
"@oceanprotocol/lib": "^1.0.0-next.10",
|
||||
"@oceanprotocol/lib": "^1.0.0-next.11",
|
||||
"@oceanprotocol/typographies": "^0.1.0",
|
||||
"@portis/web3": "^4.0.6",
|
||||
"@tippyjs/react": "^4.2.6",
|
||||
|
@ -25,7 +25,6 @@ interface AssetProviderValue {
|
||||
title: string
|
||||
owner: string
|
||||
error?: string
|
||||
refreshInterval: number
|
||||
isAssetNetwork: boolean
|
||||
oceanConfig: Config
|
||||
loading: boolean
|
||||
@ -34,8 +33,6 @@ interface AssetProviderValue {
|
||||
|
||||
const AssetContext = createContext({} as AssetProviderValue)
|
||||
|
||||
const refreshInterval = 10000 // 10 sec.
|
||||
|
||||
function AssetProvider({
|
||||
did,
|
||||
children
|
||||
@ -168,7 +165,6 @@ function AssetProvider({
|
||||
error,
|
||||
isInPurgatory,
|
||||
purgatoryData,
|
||||
refreshInterval,
|
||||
loading,
|
||||
fetchAsset,
|
||||
isAssetNetwork,
|
||||
|
46
src/@context/Pool/_queries.ts
Normal file
46
src/@context/Pool/_queries.ts
Normal file
@ -0,0 +1,46 @@
|
||||
import { gql } from 'urql'
|
||||
|
||||
export const poolDataQuery = gql`
|
||||
query PoolData(
|
||||
$pool: ID!
|
||||
$poolAsString: String!
|
||||
$owner: String!
|
||||
$user: String
|
||||
) {
|
||||
poolData: pool(id: $pool) {
|
||||
id
|
||||
totalShares
|
||||
poolFee
|
||||
opfFee
|
||||
marketFee
|
||||
spotPrice
|
||||
baseToken {
|
||||
address
|
||||
symbol
|
||||
}
|
||||
baseTokenWeight
|
||||
baseTokenLiquidity
|
||||
datatoken {
|
||||
address
|
||||
symbol
|
||||
}
|
||||
datatokenWeight
|
||||
datatokenLiquidity
|
||||
shares(where: { user: $owner }) {
|
||||
shares
|
||||
}
|
||||
}
|
||||
poolDataUser: pool(id: $pool) {
|
||||
shares(where: { user: $user }) {
|
||||
shares
|
||||
}
|
||||
}
|
||||
poolSnapshots(first: 1000, where: { pool: $poolAsString }, orderBy: date) {
|
||||
date
|
||||
spotPrice
|
||||
baseTokenLiquidity
|
||||
datatokenLiquidity
|
||||
swapVolume
|
||||
}
|
||||
}
|
||||
`
|
36
src/@context/Pool/_types.ts
Normal file
36
src/@context/Pool/_types.ts
Normal file
@ -0,0 +1,36 @@
|
||||
import Decimal from 'decimal.js'
|
||||
import {
|
||||
PoolData_poolSnapshots as PoolDataPoolSnapshots,
|
||||
PoolData_poolData as PoolDataPoolData
|
||||
} from 'src/@types/subgraph/PoolData'
|
||||
|
||||
export interface PoolInfo {
|
||||
poolFee: string
|
||||
marketFee: string
|
||||
opfFee: string
|
||||
weightBaseToken: string
|
||||
weightDt: string
|
||||
datatokenSymbol: string
|
||||
baseTokenSymbol: string
|
||||
baseTokenAddress: string
|
||||
totalPoolTokens: string
|
||||
totalLiquidityInOcean: Decimal
|
||||
}
|
||||
|
||||
export interface PoolInfoUser {
|
||||
liquidity: Decimal // liquidity in base token
|
||||
poolShares: string // pool share tokens
|
||||
poolShare: string // in %
|
||||
}
|
||||
|
||||
export interface PoolProviderValue {
|
||||
poolData: PoolDataPoolData
|
||||
poolInfo: PoolInfo
|
||||
poolInfoOwner: PoolInfoUser
|
||||
poolInfoUser: PoolInfoUser
|
||||
poolSnapshots: PoolDataPoolSnapshots[]
|
||||
hasUserAddedLiquidity: boolean
|
||||
isRemoveDisabled: boolean
|
||||
refreshInterval: number
|
||||
fetchAllData: () => void
|
||||
}
|
38
src/@context/Pool/_utils.ts
Normal file
38
src/@context/Pool/_utils.ts
Normal file
@ -0,0 +1,38 @@
|
||||
import { isValidNumber } from '@utils/numbers'
|
||||
import { getQueryContext, fetchData } from '@utils/subgraph'
|
||||
import Decimal from 'decimal.js'
|
||||
import { PoolData } from 'src/@types/subgraph/PoolData'
|
||||
import { OperationResult } from 'urql'
|
||||
import { poolDataQuery } from './_queries'
|
||||
|
||||
export async function getPoolData(
|
||||
chainId: number,
|
||||
pool: string,
|
||||
owner: string,
|
||||
user: string
|
||||
) {
|
||||
const queryVariables = {
|
||||
// Using `pool` & `poolAsString` is a workaround to make the mega query work.
|
||||
// See https://github.com/oceanprotocol/ocean-subgraph/issues/301
|
||||
pool: pool.toLowerCase(),
|
||||
poolAsString: pool.toLowerCase(),
|
||||
owner: owner.toLowerCase(),
|
||||
user: user.toLowerCase()
|
||||
}
|
||||
|
||||
const response: OperationResult<PoolData> = await fetchData(
|
||||
poolDataQuery,
|
||||
queryVariables,
|
||||
getQueryContext(chainId)
|
||||
)
|
||||
return response?.data
|
||||
}
|
||||
|
||||
export function getWeight(weight: string) {
|
||||
return isValidNumber(weight) ? new Decimal(weight).mul(10).toString() : '0'
|
||||
}
|
||||
|
||||
export function getFee(fee: string) {
|
||||
// fees are tricky: to get 0.1% you need to convert from 0.001
|
||||
return isValidNumber(fee) ? new Decimal(fee).mul(100).toString() : '0'
|
||||
}
|
280
src/@context/Pool/index.tsx
Normal file
280
src/@context/Pool/index.tsx
Normal file
@ -0,0 +1,280 @@
|
||||
import { LoggerInstance } from '@oceanprotocol/lib'
|
||||
import { isValidNumber } from '@utils/numbers'
|
||||
import Decimal from 'decimal.js'
|
||||
import React, {
|
||||
useContext,
|
||||
useState,
|
||||
useEffect,
|
||||
createContext,
|
||||
ReactElement,
|
||||
useCallback,
|
||||
ReactNode
|
||||
} from 'react'
|
||||
import {
|
||||
PoolData_poolSnapshots as PoolDataPoolSnapshots,
|
||||
PoolData_poolData as PoolDataPoolData
|
||||
} from 'src/@types/subgraph/PoolData'
|
||||
import { useAsset } from '../Asset'
|
||||
import { useWeb3 } from '../Web3'
|
||||
import { PoolProviderValue, PoolInfo, PoolInfoUser } from './_types'
|
||||
import { getFee, getPoolData, getWeight } from './_utils'
|
||||
|
||||
Decimal.set({ toExpNeg: -18, precision: 18, rounding: 1 })
|
||||
|
||||
const PoolContext = createContext({} as PoolProviderValue)
|
||||
|
||||
const refreshInterval = 10000 // 10 sec.
|
||||
|
||||
const initialPoolInfo: Partial<PoolInfo> = {
|
||||
totalLiquidityInOcean: new Decimal(0)
|
||||
}
|
||||
|
||||
const initialPoolInfoUser: Partial<PoolInfoUser> = {
|
||||
liquidity: new Decimal(0)
|
||||
}
|
||||
|
||||
const initialPoolInfoCreator: Partial<PoolInfoUser> = initialPoolInfoUser
|
||||
|
||||
function PoolProvider({ children }: { children: ReactNode }): ReactElement {
|
||||
const { accountId } = useWeb3()
|
||||
const { isInPurgatory, asset, owner } = useAsset()
|
||||
|
||||
const [poolData, setPoolData] = useState<PoolDataPoolData>()
|
||||
const [poolInfo, setPoolInfo] = useState<PoolInfo>(
|
||||
initialPoolInfo as PoolInfo
|
||||
)
|
||||
const [poolInfoOwner, setPoolInfoOwner] = useState<PoolInfoUser>(
|
||||
initialPoolInfoCreator as PoolInfoUser
|
||||
)
|
||||
const [poolInfoUser, setPoolInfoUser] = useState<PoolInfoUser>(
|
||||
initialPoolInfoUser as PoolInfoUser
|
||||
)
|
||||
const [poolSnapshots, setPoolSnapshots] = useState<PoolDataPoolSnapshots[]>()
|
||||
const [hasUserAddedLiquidity, setUserHasAddedLiquidity] = useState(false)
|
||||
const [isRemoveDisabled, setIsRemoveDisabled] = useState(false)
|
||||
const [fetchInterval, setFetchInterval] = useState<NodeJS.Timeout>()
|
||||
|
||||
const fetchAllData = useCallback(async () => {
|
||||
if (!asset?.chainId || !asset?.accessDetails?.addressOrId || !owner) return
|
||||
|
||||
const response = await getPoolData(
|
||||
asset.chainId,
|
||||
asset.accessDetails.addressOrId,
|
||||
owner,
|
||||
accountId || ''
|
||||
)
|
||||
if (!response) return
|
||||
|
||||
setPoolData(response.poolData)
|
||||
setPoolInfoUser((prevState) => ({
|
||||
...prevState,
|
||||
poolShares: response.poolDataUser?.shares[0]?.shares
|
||||
}))
|
||||
setPoolSnapshots(response.poolSnapshots)
|
||||
LoggerInstance.log('[pool] Fetched pool data:', response.poolData)
|
||||
LoggerInstance.log('[pool] Fetched user data:', response.poolDataUser)
|
||||
LoggerInstance.log('[pool] Fetched pool snapshots:', response.poolSnapshots)
|
||||
}, [asset?.chainId, asset?.accessDetails?.addressOrId, owner, accountId])
|
||||
|
||||
// Helper: start interval fetching
|
||||
// Having `accountId` as dependency is important for interval to
|
||||
// change after user account switch.
|
||||
const initFetchInterval = useCallback(() => {
|
||||
if (fetchInterval) return
|
||||
|
||||
const newInterval = setInterval(() => {
|
||||
fetchAllData()
|
||||
LoggerInstance.log(
|
||||
`[pool] Refetch interval fired after ${refreshInterval / 1000}s`
|
||||
)
|
||||
}, refreshInterval)
|
||||
setFetchInterval(newInterval)
|
||||
}, [fetchInterval, fetchAllData, accountId])
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
clearInterval(fetchInterval)
|
||||
}
|
||||
}, [fetchInterval])
|
||||
|
||||
//
|
||||
// 0 Fetch all the data on mount if we are on a pool.
|
||||
// All further effects depend on the fetched data
|
||||
// and only do further data checking and manipulation.
|
||||
//
|
||||
useEffect(() => {
|
||||
if (asset?.accessDetails?.type !== 'dynamic') return
|
||||
|
||||
fetchAllData()
|
||||
initFetchInterval()
|
||||
}, [fetchAllData, initFetchInterval, asset?.accessDetails?.type])
|
||||
|
||||
//
|
||||
// 1 General Pool Info
|
||||
//
|
||||
useEffect(() => {
|
||||
if (!poolData) return
|
||||
|
||||
// Fees
|
||||
const poolFee = getFee(poolData.poolFee)
|
||||
const marketFee = getFee(poolData.marketFee)
|
||||
const opfFee = getFee(poolData.opfFee)
|
||||
|
||||
// Total Liquidity
|
||||
const totalLiquidityInOcean = isValidNumber(poolData.spotPrice)
|
||||
? new Decimal(poolData.baseTokenLiquidity).add(
|
||||
new Decimal(poolData.datatokenLiquidity).mul(poolData.spotPrice)
|
||||
)
|
||||
: new Decimal(0)
|
||||
|
||||
const newPoolInfo = {
|
||||
poolFee,
|
||||
marketFee,
|
||||
opfFee,
|
||||
weightBaseToken: getWeight(poolData.baseTokenWeight),
|
||||
weightDt: getWeight(poolData.datatokenWeight),
|
||||
datatokenSymbol: poolData.datatoken.symbol,
|
||||
baseTokenSymbol: poolData.baseToken.symbol,
|
||||
baseTokenAddress: poolData.baseToken.address,
|
||||
totalPoolTokens: poolData.totalShares,
|
||||
totalLiquidityInOcean
|
||||
}
|
||||
setPoolInfo(newPoolInfo)
|
||||
LoggerInstance.log('[pool] Created new pool info:', newPoolInfo)
|
||||
}, [poolData])
|
||||
|
||||
//
|
||||
// 2 Pool Creator Info
|
||||
//
|
||||
useEffect(() => {
|
||||
if (!poolData || !poolInfo?.totalPoolTokens) return
|
||||
|
||||
// Staking bot receives half the pool shares so for display purposes
|
||||
// we can multiply by 2 as we have a hardcoded 50/50 pool weight.
|
||||
const ownerPoolShares = new Decimal(poolData.shares[0]?.shares)
|
||||
.mul(2)
|
||||
.toString()
|
||||
|
||||
// Liquidity in base token, calculated from pool share tokens.
|
||||
const liquidity =
|
||||
isValidNumber(ownerPoolShares) &&
|
||||
isValidNumber(poolInfo.totalPoolTokens) &&
|
||||
isValidNumber(poolData.baseTokenLiquidity)
|
||||
? new Decimal(ownerPoolShares)
|
||||
.dividedBy(new Decimal(poolInfo.totalPoolTokens))
|
||||
.mul(poolData.baseTokenLiquidity)
|
||||
: new Decimal(0)
|
||||
|
||||
// Pool share tokens.
|
||||
const poolShare =
|
||||
isValidNumber(ownerPoolShares) && isValidNumber(poolInfo.totalPoolTokens)
|
||||
? new Decimal(ownerPoolShares)
|
||||
.dividedBy(new Decimal(poolInfo.totalPoolTokens))
|
||||
.mul(100)
|
||||
.toFixed(2)
|
||||
: '0'
|
||||
|
||||
const newPoolOwnerInfo = {
|
||||
liquidity,
|
||||
poolShares: ownerPoolShares,
|
||||
poolShare
|
||||
}
|
||||
setPoolInfoOwner(newPoolOwnerInfo)
|
||||
LoggerInstance.log('[pool] Created new owner pool info:', newPoolOwnerInfo)
|
||||
}, [poolData, poolInfo?.totalPoolTokens])
|
||||
|
||||
//
|
||||
// 3 User Pool Info
|
||||
//
|
||||
useEffect(() => {
|
||||
if (
|
||||
!poolData ||
|
||||
!poolInfo?.totalPoolTokens ||
|
||||
!asset?.chainId ||
|
||||
!accountId
|
||||
)
|
||||
return
|
||||
|
||||
// Staking bot receives half the pool shares so for display purposes
|
||||
// we can multiply by 2 as we have a hardcoded 50/50 pool weight.
|
||||
const userPoolShares = new Decimal(poolInfoUser.poolShares)
|
||||
.mul(2)
|
||||
.toString()
|
||||
|
||||
// Pool share in %.
|
||||
const poolShare =
|
||||
isValidNumber(userPoolShares) &&
|
||||
isValidNumber(poolInfo.totalPoolTokens) &&
|
||||
new Decimal(userPoolShares)
|
||||
.dividedBy(new Decimal(poolInfo.totalPoolTokens))
|
||||
.mul(100)
|
||||
.toFixed(2)
|
||||
|
||||
setUserHasAddedLiquidity(Number(poolShare) > 0)
|
||||
|
||||
// Liquidity in base token, calculated from pool share tokens.
|
||||
const liquidity =
|
||||
isValidNumber(userPoolShares) &&
|
||||
isValidNumber(poolInfo.totalPoolTokens) &&
|
||||
isValidNumber(poolData.baseTokenLiquidity)
|
||||
? new Decimal(userPoolShares)
|
||||
.dividedBy(new Decimal(poolInfo.totalPoolTokens))
|
||||
.mul(poolData.baseTokenLiquidity)
|
||||
: new Decimal(0)
|
||||
|
||||
const newPoolInfoUser = {
|
||||
liquidity,
|
||||
poolShare
|
||||
}
|
||||
setPoolInfoUser((prevState: PoolInfoUser) => ({
|
||||
...prevState,
|
||||
...newPoolInfoUser
|
||||
}))
|
||||
|
||||
LoggerInstance.log('[pool] Created new user pool info:', {
|
||||
poolShares: userPoolShares,
|
||||
...newPoolInfoUser
|
||||
})
|
||||
}, [
|
||||
poolData,
|
||||
poolInfoUser?.poolShares,
|
||||
accountId,
|
||||
asset?.chainId,
|
||||
owner,
|
||||
poolInfo?.totalPoolTokens
|
||||
])
|
||||
|
||||
//
|
||||
// Check if removing liquidity should be disabled.
|
||||
//
|
||||
useEffect(() => {
|
||||
if (!owner || !accountId) return
|
||||
setIsRemoveDisabled(isInPurgatory && owner === accountId)
|
||||
}, [isInPurgatory, owner, accountId])
|
||||
|
||||
return (
|
||||
<PoolContext.Provider
|
||||
value={
|
||||
{
|
||||
poolData,
|
||||
poolInfo,
|
||||
poolInfoOwner,
|
||||
poolInfoUser,
|
||||
poolSnapshots,
|
||||
hasUserAddedLiquidity,
|
||||
isRemoveDisabled,
|
||||
refreshInterval,
|
||||
fetchAllData
|
||||
} as PoolProviderValue
|
||||
}
|
||||
>
|
||||
{children}
|
||||
</PoolContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
// Helper hook to access the provider values
|
||||
const usePool = (): PoolProviderValue => useContext(PoolContext)
|
||||
|
||||
export { PoolProvider, usePool, PoolContext }
|
||||
export default PoolProvider
|
@ -10,11 +10,15 @@ import useSWR from 'swr'
|
||||
import { useSiteMetadata } from '@hooks/useSiteMetadata'
|
||||
import { LoggerInstance } from '@oceanprotocol/lib'
|
||||
|
||||
interface PricesValue {
|
||||
interface Prices {
|
||||
[key: string]: number
|
||||
}
|
||||
|
||||
const initialData: PricesValue = {
|
||||
interface PricesValue {
|
||||
prices: Prices
|
||||
}
|
||||
|
||||
const initialData: Prices = {
|
||||
eur: 0.0,
|
||||
usd: 0.0,
|
||||
eth: 0.0,
|
||||
@ -37,7 +41,7 @@ export default function PricesProvider({
|
||||
|
||||
const [prices, setPrices] = useState(initialData)
|
||||
|
||||
const onSuccess = async (data: { [tokenId]: { [key: string]: number } }) => {
|
||||
const onSuccess = async (data: { [tokenId]: Prices }) => {
|
||||
if (!data) return
|
||||
LoggerInstance.log('[prices] Got new OCEAN spot prices.', data[tokenId])
|
||||
setPrices(data[tokenId])
|
||||
|
@ -18,7 +18,24 @@ export async function getEncryptedFiles(
|
||||
}
|
||||
}
|
||||
|
||||
export async function getFileInfo(
|
||||
export async function getFileDidInfo(
|
||||
did: string,
|
||||
serviceId: string,
|
||||
providerUrl: string
|
||||
): Promise<FileMetadata[]> {
|
||||
try {
|
||||
const response = await ProviderInstance.checkDidFiles(
|
||||
did,
|
||||
serviceId as any, // TODO: why does ocean.js want a number here?
|
||||
providerUrl
|
||||
)
|
||||
return response
|
||||
} catch (error) {
|
||||
LoggerInstance.error(error.message)
|
||||
}
|
||||
}
|
||||
|
||||
export async function getFileUrlInfo(
|
||||
url: string,
|
||||
providerUrl: string
|
||||
): Promise<FileMetadata[]> {
|
||||
|
@ -2,18 +2,7 @@ import { gql, OperationResult, TypedDocumentNode, OperationContext } from 'urql'
|
||||
import { Asset, LoggerInstance } from '@oceanprotocol/lib'
|
||||
import { getUrqlClientInstance } from '@context/UrqlProvider'
|
||||
import { getOceanConfig } from './ocean'
|
||||
import {
|
||||
AssetsPoolPrice,
|
||||
AssetsPoolPrice_pools as AssetsPoolPricePool
|
||||
} from '../@types/subgraph/AssetsPoolPrice'
|
||||
import {
|
||||
AssetsFrePrice,
|
||||
AssetsFrePrice_fixedRateExchanges as AssetsFrePriceFixedRateExchange
|
||||
} from '../@types/subgraph/AssetsFrePrice'
|
||||
import {
|
||||
AssetsFreePrice,
|
||||
AssetsFreePrice_dispensers as AssetFreePriceDispenser
|
||||
} from '../@types/subgraph/AssetsFreePrice'
|
||||
import { AssetPoolPrice } from '../@types/subgraph/AssetPoolPrice'
|
||||
import { AssetPreviousOrder } from '../@types/subgraph/AssetPreviousOrder'
|
||||
import {
|
||||
HighestLiquidityAssets_pools as HighestLiquidityAssetsPool,
|
||||
@ -25,7 +14,6 @@ import {
|
||||
} from '../@types/subgraph/PoolShares'
|
||||
import { OrdersData_orders as OrdersData } from '../@types/subgraph/OrdersData'
|
||||
import { UserSalesQuery as UsersSalesList } from '../@types/subgraph/UserSalesQuery'
|
||||
import { PoolData } from 'src/@types/subgraph/PoolData'
|
||||
|
||||
export interface UserLiquidity {
|
||||
price: string
|
||||
@ -36,91 +24,6 @@ export interface PriceList {
|
||||
[key: string]: string
|
||||
}
|
||||
|
||||
interface DidAndDatatokenMap {
|
||||
[name: string]: string
|
||||
}
|
||||
|
||||
const FreeQuery = gql`
|
||||
query AssetsFreePrice($datatoken_in: [String!]) {
|
||||
dispensers(orderBy: id, where: { token_in: $datatoken_in }) {
|
||||
token {
|
||||
id
|
||||
address
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
const AssetFreeQuery = gql`
|
||||
query AssetFreePrice($datatoken: String) {
|
||||
dispensers(orderBy: id, where: { token: $datatoken }) {
|
||||
active
|
||||
owner
|
||||
isMinter
|
||||
maxTokens
|
||||
maxBalance
|
||||
balance
|
||||
token {
|
||||
id
|
||||
isDatatoken
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
const FreQuery = gql`
|
||||
query AssetsFrePrice($datatoken_in: [String!]) {
|
||||
fixedRateExchanges(orderBy: id, where: { datatoken_in: $datatoken_in }) {
|
||||
id
|
||||
price
|
||||
baseToken {
|
||||
symbol
|
||||
}
|
||||
datatoken {
|
||||
id
|
||||
address
|
||||
symbol
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
const AssetFreQuery = gql`
|
||||
query AssetFrePrice($datatoken: String) {
|
||||
fixedRateExchanges(orderBy: id, where: { datatoken: $datatoken }) {
|
||||
id
|
||||
price
|
||||
baseToken {
|
||||
symbol
|
||||
}
|
||||
datatoken {
|
||||
id
|
||||
address
|
||||
symbol
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
const PoolQuery = gql`
|
||||
query AssetsPoolPrice($datatokenAddress_in: [String!]) {
|
||||
pools(where: { datatoken_in: $datatokenAddress_in }) {
|
||||
id
|
||||
spotPrice
|
||||
datatoken {
|
||||
address
|
||||
symbol
|
||||
}
|
||||
baseToken {
|
||||
address
|
||||
symbol
|
||||
}
|
||||
datatokenLiquidity
|
||||
baseTokenLiquidity
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
const AssetPoolPriceQuery = gql`
|
||||
query AssetPoolPrice($datatokenAddress: String) {
|
||||
pools(where: { datatoken: $datatokenAddress }) {
|
||||
@ -280,51 +183,6 @@ const TopSalesQuery = gql`
|
||||
}
|
||||
`
|
||||
|
||||
const poolDataQuery = gql`
|
||||
query PoolData(
|
||||
$pool: ID!
|
||||
$poolAsString: String!
|
||||
$owner: String!
|
||||
$user: String
|
||||
) {
|
||||
poolData: pool(id: $pool) {
|
||||
id
|
||||
totalShares
|
||||
poolFee
|
||||
opfFee
|
||||
marketFee
|
||||
spotPrice
|
||||
baseToken {
|
||||
address
|
||||
symbol
|
||||
}
|
||||
baseTokenWeight
|
||||
baseTokenLiquidity
|
||||
datatoken {
|
||||
address
|
||||
symbol
|
||||
}
|
||||
datatokenWeight
|
||||
datatokenLiquidity
|
||||
shares(where: { user: $owner }) {
|
||||
shares
|
||||
}
|
||||
}
|
||||
poolDataUser: pool(id: $pool) {
|
||||
shares(where: { user: $user }) {
|
||||
shares
|
||||
}
|
||||
}
|
||||
poolSnapshots(first: 1000, where: { pool: $poolAsString }, orderBy: date) {
|
||||
date
|
||||
spotPrice
|
||||
baseTokenLiquidity
|
||||
datatokenLiquidity
|
||||
swapVolume
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
export function getSubgraphUri(chainId: number): string {
|
||||
const config = getOceanConfig(chainId)
|
||||
return config.subgraphUri
|
||||
@ -411,7 +269,7 @@ export async function getSpotPrice(asset: Asset): Promise<number> {
|
||||
}
|
||||
const queryContext = getQueryContext(Number(asset.chainId))
|
||||
|
||||
const poolPriceResponse: OperationResult<AssetsPoolPrice> = await fetchData(
|
||||
const poolPriceResponse: OperationResult<AssetPoolPrice> = await fetchData(
|
||||
AssetPoolPriceQuery,
|
||||
poolVariables,
|
||||
queryContext
|
||||
@ -430,14 +288,14 @@ export async function getHighestLiquidityDatatokens(
|
||||
const fetchedPools: OperationResult<HighestLiquidityGraphAssets, any> =
|
||||
await fetchData(HighestLiquidityAssets, null, queryContext)
|
||||
highestLiquidityAssets = highestLiquidityAssets.concat(
|
||||
fetchedPools.data.pools
|
||||
fetchedPools?.data?.pools
|
||||
)
|
||||
}
|
||||
highestLiquidityAssets.sort(
|
||||
(a, b) => b.baseTokenLiquidity - a.baseTokenLiquidity
|
||||
)
|
||||
for (let i = 0; i < highestLiquidityAssets.length; i++) {
|
||||
if (!highestLiquidityAssets[i].datatoken.address) continue
|
||||
if (!highestLiquidityAssets[i]?.datatoken?.address) continue
|
||||
dtList.push(highestLiquidityAssets[i].datatoken.address)
|
||||
}
|
||||
return dtList
|
||||
@ -588,26 +446,3 @@ export async function getTopAssetsPublishers(
|
||||
|
||||
return publisherSales.slice(0, nrItems)
|
||||
}
|
||||
|
||||
export async function getPoolData(
|
||||
chainId: number,
|
||||
pool: string,
|
||||
owner: string,
|
||||
user: string
|
||||
) {
|
||||
const queryVariables = {
|
||||
// Using `pool` & `poolAsString` is a workaround to make the mega query work.
|
||||
// See https://github.com/oceanprotocol/ocean-subgraph/issues/301
|
||||
pool: pool.toLowerCase(),
|
||||
poolAsString: pool.toLowerCase(),
|
||||
owner: owner.toLowerCase(),
|
||||
user: user.toLowerCase()
|
||||
}
|
||||
|
||||
const response: OperationResult<PoolData> = await fetchData(
|
||||
poolDataQuery,
|
||||
queryVariables,
|
||||
getQueryContext(chainId)
|
||||
)
|
||||
return response?.data
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ import FileInfo from './Info'
|
||||
import UrlInput from '../URLInput'
|
||||
import { InputProps } from '@shared/FormInput'
|
||||
import { initialValues } from 'src/components/Publish/_constants'
|
||||
import { getFileInfo } from '@utils/provider'
|
||||
import { getFileUrlInfo } from '@utils/provider'
|
||||
import { FormPublishData } from 'src/components/Publish/_types'
|
||||
|
||||
export default function FilesInput(props: InputProps): ReactElement {
|
||||
@ -19,7 +19,7 @@ export default function FilesInput(props: InputProps): ReactElement {
|
||||
async function validateUrl() {
|
||||
try {
|
||||
setIsLoading(true)
|
||||
const checkedFile = await getFileInfo(url, providerUri)
|
||||
const checkedFile = await getFileUrlInfo(url, providerUri)
|
||||
checkedFile && helpers.setValue([{ url, ...checkedFile[0] }])
|
||||
} catch (error) {
|
||||
toast.error('Could not fetch file info. Please check URL and try again')
|
||||
|
@ -10,13 +10,11 @@ const cx = classNames.bind(styles)
|
||||
export default function Conversion({
|
||||
price,
|
||||
className,
|
||||
hideApproximateSymbol,
|
||||
showTVLLabel
|
||||
hideApproximateSymbol
|
||||
}: {
|
||||
price: string // expects price in OCEAN, not wei
|
||||
className?: string
|
||||
hideApproximateSymbol?: boolean
|
||||
showTVLLabel?: boolean
|
||||
}): ReactElement {
|
||||
const { prices } = usePrices()
|
||||
const { currency, locale } = useUserPreferences()
|
||||
@ -29,7 +27,6 @@ export default function Conversion({
|
||||
|
||||
const styleClasses = cx({
|
||||
conversion: true,
|
||||
removeTvlPadding: showTVLLabel,
|
||||
[className]: className
|
||||
})
|
||||
|
||||
@ -39,7 +36,7 @@ export default function Conversion({
|
||||
return
|
||||
}
|
||||
|
||||
const conversionValue = (prices as any)[currency.toLowerCase()]
|
||||
const conversionValue = prices[currency.toLowerCase()]
|
||||
const converted = conversionValue * Number(price)
|
||||
const convertedFormatted = formatCurrency(
|
||||
converted,
|
||||
@ -64,7 +61,6 @@ export default function Conversion({
|
||||
className={styleClasses}
|
||||
title="Approximation based on current OCEAN spot price on Coingecko"
|
||||
>
|
||||
{showTVLLabel && 'TVL'}
|
||||
{!hideApproximateSymbol && '≈ '}
|
||||
<strong dangerouslySetInnerHTML={{ __html: priceConverted }} />{' '}
|
||||
{!isFiat && currency}
|
||||
|
@ -10,13 +10,15 @@ export default function TokenApproval({
|
||||
disabled,
|
||||
amount,
|
||||
tokenAddress,
|
||||
tokenSymbol
|
||||
tokenSymbol,
|
||||
setSubmitting
|
||||
}: {
|
||||
actionButton: JSX.Element
|
||||
disabled: boolean
|
||||
amount: string
|
||||
tokenAddress: string
|
||||
tokenSymbol: string
|
||||
setSubmitting?: (isSubmitting: boolean) => void
|
||||
}): ReactElement {
|
||||
const { asset, isAssetNetwork } = useAsset()
|
||||
const [tokenApproved, setTokenApproved] = useState(false)
|
||||
@ -50,6 +52,7 @@ export default function TokenApproval({
|
||||
|
||||
async function approveTokens(amount: string) {
|
||||
setLoading(true)
|
||||
setSubmitting(true)
|
||||
|
||||
try {
|
||||
const tx = await approve(web3, accountId, tokenAddress, spender, amount)
|
||||
@ -62,6 +65,7 @@ export default function TokenApproval({
|
||||
} finally {
|
||||
await checkTokenApproval()
|
||||
setLoading(false)
|
||||
setSubmitting(false)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -14,8 +14,8 @@
|
||||
}
|
||||
|
||||
.icon {
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
width: 0.85em;
|
||||
height: 0.85em;
|
||||
cursor: help;
|
||||
display: inline-block;
|
||||
margin-bottom: -0.1em;
|
||||
|
@ -17,7 +17,8 @@ export default function Actions({
|
||||
action,
|
||||
isDisabled,
|
||||
tokenAddress,
|
||||
tokenSymbol
|
||||
tokenSymbol,
|
||||
setSubmitting
|
||||
}: {
|
||||
isLoading: boolean
|
||||
loaderMessage: string
|
||||
@ -29,6 +30,7 @@ export default function Actions({
|
||||
isDisabled?: boolean
|
||||
tokenAddress: string
|
||||
tokenSymbol: string
|
||||
setSubmitting?: (isSubmitting: boolean) => void
|
||||
}): ReactElement {
|
||||
const { networkId } = useWeb3()
|
||||
|
||||
@ -55,6 +57,7 @@ export default function Actions({
|
||||
tokenAddress={tokenAddress}
|
||||
tokenSymbol={tokenSymbol}
|
||||
disabled={isDisabled}
|
||||
setSubmitting={setSubmitting}
|
||||
/>
|
||||
) : (
|
||||
actionButton
|
||||
|
@ -39,8 +39,11 @@ export default function FormAdd({
|
||||
const { isAssetNetwork } = useAsset()
|
||||
|
||||
// Connect with form
|
||||
const { setFieldValue, values }: FormikContextType<FormAddLiquidity> =
|
||||
useFormikContext()
|
||||
const {
|
||||
setFieldValue,
|
||||
values,
|
||||
isSubmitting
|
||||
}: FormikContextType<FormAddLiquidity> = useFormikContext()
|
||||
|
||||
useEffect(() => {
|
||||
async function calculatePoolShares() {
|
||||
@ -53,7 +56,7 @@ export default function FormAdd({
|
||||
}
|
||||
if (Number(values.amount) > Number(amountMax)) return
|
||||
|
||||
const poolInstance = new Pool(web3, LoggerInstance)
|
||||
const poolInstance = new Pool(web3)
|
||||
|
||||
const poolTokens = await poolInstance.calcPoolOutGivenSingleIn(
|
||||
poolAddress,
|
||||
@ -112,17 +115,17 @@ export default function FormAdd({
|
||||
placeholder="0"
|
||||
field={field}
|
||||
form={form}
|
||||
disabled={!isAssetNetwork}
|
||||
disabled={!isAssetNetwork || isSubmitting}
|
||||
/>
|
||||
)}
|
||||
</Field>
|
||||
|
||||
{Number(balance.ocean) && (
|
||||
{Number(balance.ocean) > 0 && (
|
||||
<Button
|
||||
className={styles.buttonMax}
|
||||
style="text"
|
||||
size="small"
|
||||
disabled={!web3}
|
||||
disabled={!web3 || isSubmitting}
|
||||
onClick={() => setFieldValue('amount', amountMax)}
|
||||
>
|
||||
Use Max
|
||||
|
@ -1,7 +1,4 @@
|
||||
.output {
|
||||
display: grid;
|
||||
gap: var(--spacer);
|
||||
grid-template-columns: 1fr 1fr;
|
||||
padding-bottom: calc(var(--spacer) / 2);
|
||||
}
|
||||
|
||||
@ -11,14 +8,6 @@
|
||||
font-size: var(--font-size-small);
|
||||
}
|
||||
|
||||
.output div:first-child [class*='token'] {
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
.output div:first-child [class*='token'] > figure {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.help {
|
||||
text-align: center;
|
||||
}
|
||||
|
@ -57,16 +57,9 @@ export default function Output({
|
||||
{help.replace('SWAPFEE', swapFee)}
|
||||
</FormHelp>
|
||||
<div className={styles.output}>
|
||||
<div>
|
||||
<p>{titleIn}</p>
|
||||
<Token symbol="pool shares" balance={newPoolTokens} />
|
||||
<Token symbol="% of pool" balance={newPoolShare} />
|
||||
</div>
|
||||
<div>
|
||||
<p>{titleOut}</p>
|
||||
<Token symbol="OCEAN" balance={poolOcean} />
|
||||
<Token symbol={datatokenSymbol} balance={poolDatatoken} />
|
||||
</div>
|
||||
<p>{titleIn}</p>
|
||||
<Token symbol="pool shares" balance={newPoolTokens} noIcon />
|
||||
<Token symbol="% of pool" balance={newPoolShare} noIcon />
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
|
@ -71,7 +71,7 @@ export default function Add({
|
||||
|
||||
async function getMaximum() {
|
||||
try {
|
||||
const poolInstance = new Pool(web3, LoggerInstance)
|
||||
const poolInstance = new Pool(web3)
|
||||
|
||||
const amountMaxPool = await poolInstance.getReserve(
|
||||
poolAddress,
|
||||
@ -99,7 +99,7 @@ export default function Add({
|
||||
|
||||
// Submit
|
||||
async function handleAddLiquidity(amount: string, resetForm: () => void) {
|
||||
const poolInstance = new Pool(web3, LoggerInstance)
|
||||
const poolInstance = new Pool(web3)
|
||||
const minPoolAmountOut = '0' // ? TODO: how to get?
|
||||
|
||||
try {
|
||||
@ -133,7 +133,7 @@ export default function Add({
|
||||
setSubmitting(false)
|
||||
}}
|
||||
>
|
||||
{({ isSubmitting, submitForm, values, isValid }) => (
|
||||
{({ isSubmitting, setSubmitting, submitForm, values, isValid }) => (
|
||||
<>
|
||||
<div className={styles.addInput}>
|
||||
{isWarningAccepted ? (
|
||||
@ -189,6 +189,7 @@ export default function Add({
|
||||
tokenAddress={tokenInAddress}
|
||||
tokenSymbol={tokenInSymbol}
|
||||
txId={txId}
|
||||
setSubmitting={setSubmitting}
|
||||
/>
|
||||
{debug && <DebugOutput output={values} />}
|
||||
</>
|
||||
|
@ -2,7 +2,11 @@ import { formatPrice } from '@shared/Price/PriceUnit'
|
||||
import { ChartOptions, TooltipItem } from 'chart.js'
|
||||
import { tooltipOptions } from './_constants'
|
||||
|
||||
export function getOptions(locale: string, isDarkMode: boolean): ChartOptions {
|
||||
export function getOptions(
|
||||
locale: string,
|
||||
isDarkMode: boolean,
|
||||
symbol: string
|
||||
): ChartOptions {
|
||||
return {
|
||||
layout: {
|
||||
padding: {
|
||||
@ -21,7 +25,7 @@ export function getOptions(locale: string, isDarkMode: boolean): ChartOptions {
|
||||
borderColor: isDarkMode ? `#41474e` : `#e2e2e2`,
|
||||
callbacks: {
|
||||
label: (tooltipItem: TooltipItem<any>) =>
|
||||
`${formatPrice(`${tooltipItem.formattedValue}`, locale)} OCEAN`
|
||||
`${formatPrice(`${tooltipItem.formattedValue}`, locale)} ${symbol}`
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -12,13 +12,15 @@ import { lineStyle, GraphType } from './_constants'
|
||||
import Nav from './Nav'
|
||||
import { getOptions } from './_utils'
|
||||
import { PoolData_poolSnapshots as PoolDataPoolSnapshots } from 'src/@types/subgraph/PoolData'
|
||||
import { usePrices } from '@context/Prices'
|
||||
|
||||
export default function Graph({
|
||||
poolSnapshots
|
||||
}: {
|
||||
poolSnapshots: PoolDataPoolSnapshots[]
|
||||
}): ReactElement {
|
||||
const { locale } = useUserPreferences()
|
||||
const { locale, currency } = useUserPreferences()
|
||||
const { prices } = usePrices()
|
||||
const darkMode = useDarkMode(false, darkModeConfig)
|
||||
|
||||
const [options, setOptions] = useState<ChartOptions<any>>()
|
||||
@ -29,10 +31,18 @@ export default function Graph({
|
||||
// 0 Get Graph options
|
||||
//
|
||||
useEffect(() => {
|
||||
if (!poolSnapshots) return
|
||||
|
||||
LoggerInstance.log('[pool graph] Fired getOptions().')
|
||||
const options = getOptions(locale, darkMode.value)
|
||||
const symbol =
|
||||
graphType === 'liquidity'
|
||||
? currency
|
||||
: // TODO: remove any once baseToken works
|
||||
// see https://github.com/oceanprotocol/ocean-subgraph/issues/312
|
||||
(poolSnapshots[0] as any)?.baseToken?.symbol
|
||||
const options = getOptions(locale, darkMode.value, symbol)
|
||||
setOptions(options)
|
||||
}, [locale, darkMode.value, graphType])
|
||||
}, [locale, darkMode.value, graphType, currency, poolSnapshots])
|
||||
|
||||
//
|
||||
// 1 Data manipulation
|
||||
@ -42,14 +52,21 @@ export default function Graph({
|
||||
|
||||
const timestamps = poolSnapshots.map((item) => {
|
||||
const date = new Date(item.date * 1000)
|
||||
return `${date.toLocaleDateString()} ${date.toLocaleTimeString()}`
|
||||
return `${date.toLocaleDateString(locale)} ${date.toLocaleTimeString(
|
||||
locale,
|
||||
{ hour: '2-digit', minute: '2-digit' }
|
||||
)}`
|
||||
})
|
||||
|
||||
let baseTokenLiquidityCumulative = '0'
|
||||
const liquidityHistory = poolSnapshots.map((item) => {
|
||||
const conversionSpotPrice = prices[currency.toLowerCase()]
|
||||
baseTokenLiquidityCumulative = new Decimal(baseTokenLiquidityCumulative)
|
||||
.add(item.baseTokenLiquidity)
|
||||
.mul(2) // double baseTokenLiquidity as we have 50/50 weight
|
||||
.mul(conversionSpotPrice) // convert to user currency
|
||||
.toString()
|
||||
|
||||
return baseTokenLiquidityCumulative
|
||||
})
|
||||
|
||||
@ -66,23 +83,23 @@ export default function Graph({
|
||||
let data
|
||||
switch (graphType) {
|
||||
case 'price':
|
||||
data = priceHistory.slice(0)
|
||||
data = priceHistory
|
||||
break
|
||||
case 'volume':
|
||||
data = volumeHistory.slice(0)
|
||||
data = volumeHistory
|
||||
break
|
||||
default:
|
||||
data = liquidityHistory.slice(0)
|
||||
data = liquidityHistory
|
||||
break
|
||||
}
|
||||
|
||||
const newGraphData = {
|
||||
labels: timestamps.slice(0),
|
||||
labels: timestamps,
|
||||
datasets: [{ ...lineStyle, data, borderColor: `#8b98a9` }]
|
||||
}
|
||||
setGraphData(newGraphData)
|
||||
LoggerInstance.log('[pool graph] New graph data created:', newGraphData)
|
||||
}, [poolSnapshots, graphType])
|
||||
}, [poolSnapshots, graphType, currency, prices, locale])
|
||||
|
||||
return (
|
||||
<div className={styles.graphWrap}>
|
||||
|
@ -1,5 +1,5 @@
|
||||
.removeInput {
|
||||
composes: addInput from './Add/index.module.css';
|
||||
composes: addInput from '../Add/index.module.css';
|
||||
padding-left: calc(var(--spacer) * 2);
|
||||
padding-right: calc(var(--spacer) * 2);
|
||||
padding-bottom: calc(var(--spacer) / 2);
|
||||
@ -46,7 +46,7 @@
|
||||
}
|
||||
|
||||
.output {
|
||||
composes: output from './Add/Output.module.css';
|
||||
composes: output from '../Add/Output.module.css';
|
||||
}
|
||||
|
||||
.output [class*='token'] {
|
||||
@ -66,5 +66,5 @@
|
||||
}
|
||||
|
||||
.slippage {
|
||||
composes: slippage from '../Trade/Slippage.module.css';
|
||||
composes: slippage from '../../Trade/Slippage.module.css';
|
||||
}
|
@ -5,22 +5,22 @@ import React, {
|
||||
useEffect,
|
||||
useRef
|
||||
} from 'react'
|
||||
import styles from './Remove.module.css'
|
||||
import Header from './Header'
|
||||
import styles from './index.module.css'
|
||||
import Header from '../Header'
|
||||
import { toast } from 'react-toastify'
|
||||
import Actions from './Actions'
|
||||
import Actions from '../Actions'
|
||||
import { LoggerInstance, Pool } from '@oceanprotocol/lib'
|
||||
import Token from './Token'
|
||||
import Token from '../Token'
|
||||
import FormHelp from '@shared/FormInput/Help'
|
||||
import Button from '@shared/atoms/Button'
|
||||
import { getMaxPercentRemove } from './utils'
|
||||
import { getMaxPercentRemove } from '../utils'
|
||||
import debounce from 'lodash.debounce'
|
||||
import UserLiquidity from '../UserLiquidity'
|
||||
import UserLiquidity from '../../UserLiquidity'
|
||||
import InputElement from '@shared/FormInput/InputElement'
|
||||
import { useWeb3 } from '@context/Web3'
|
||||
import Decimal from 'decimal.js'
|
||||
import { useAsset } from '@context/Asset'
|
||||
import content from '../../../../../content/price.json'
|
||||
import content from '../../../../../../content/price.json'
|
||||
|
||||
const slippagePresets = ['5', '10', '15', '25', '50']
|
||||
|
||||
@ -55,7 +55,7 @@ export default function Remove({
|
||||
|
||||
// TODO: precision needs to be set based on baseToken decimals
|
||||
Decimal.set({ toExpNeg: -18, precision: 18, rounding: 1 })
|
||||
const poolInstance = new Pool(web3, LoggerInstance)
|
||||
const poolInstance = new Pool(web3)
|
||||
|
||||
async function handleRemoveLiquidity() {
|
||||
setIsLoading(true)
|
||||
@ -160,7 +160,7 @@ export default function Remove({
|
||||
type="range"
|
||||
min="0"
|
||||
max={amountMaxPercent}
|
||||
disabled={!isAssetNetwork}
|
||||
disabled={!isAssetNetwork || isLoading}
|
||||
value={amountPercent}
|
||||
onChange={handleAmountPercentChange}
|
||||
/>
|
||||
@ -168,7 +168,7 @@ export default function Remove({
|
||||
style="text"
|
||||
size="small"
|
||||
className={styles.maximum}
|
||||
disabled={!isAssetNetwork}
|
||||
disabled={!isAssetNetwork || isLoading}
|
||||
onClick={handleMaxButton}
|
||||
>
|
||||
{`${amountMaxPercent}% max`}
|
||||
@ -179,14 +179,14 @@ export default function Remove({
|
||||
</div>
|
||||
</form>
|
||||
<div className={styles.output}>
|
||||
<div>
|
||||
<p>{content.pool.remove.output.titleIn}</p>
|
||||
<Token symbol="pool shares" balance={amountPoolShares} noIcon />
|
||||
</div>
|
||||
<div>
|
||||
<p>{content.pool.remove.output.titleOut} minimum</p>
|
||||
<Token symbol={tokenOutSymbol} balance={minOceanAmount} />
|
||||
</div>
|
||||
{/* <div>
|
||||
<p>{content.pool.remove.output.titleIn}</p>
|
||||
<Token symbol="pool shares" balance={amountPoolShares} noIcon />
|
||||
</div> */}
|
||||
</div>
|
||||
<div className={styles.slippage}>
|
||||
<strong>Expected price impact</strong>
|
||||
@ -197,7 +197,7 @@ export default function Remove({
|
||||
postfix="%"
|
||||
sortOptions={false}
|
||||
options={slippagePresets}
|
||||
disabled={!isAssetNetwork}
|
||||
disabled={!isAssetNetwork || isLoading}
|
||||
value={slippage}
|
||||
onChange={handleSlippageChange}
|
||||
/>
|
||||
@ -208,7 +208,7 @@ export default function Remove({
|
||||
actionName={content.pool.remove.action}
|
||||
action={handleRemoveLiquidity}
|
||||
successMessage="Successfully removed liquidity."
|
||||
isDisabled={!isAssetNetwork}
|
||||
isDisabled={!isAssetNetwork || amountOcean === '0'}
|
||||
txId={txId}
|
||||
tokenAddress={tokenOutAddress}
|
||||
tokenSymbol={tokenOutSymbol}
|
@ -20,7 +20,7 @@
|
||||
|
||||
.tokens {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr));
|
||||
}
|
||||
|
||||
.title {
|
||||
|
@ -11,42 +11,33 @@ export default function TokenList({
|
||||
baseTokenSymbol,
|
||||
datatokenValue,
|
||||
datatokenSymbol,
|
||||
poolShares,
|
||||
conversion,
|
||||
highlight,
|
||||
showTVLLabel
|
||||
highlight
|
||||
}: {
|
||||
title: string | ReactNode
|
||||
children: ReactNode
|
||||
children?: ReactNode
|
||||
baseTokenValue: string
|
||||
baseTokenSymbol: string
|
||||
datatokenValue: string
|
||||
datatokenSymbol: string
|
||||
poolShares: string
|
||||
datatokenValue?: string
|
||||
datatokenSymbol?: string
|
||||
conversion: Decimal
|
||||
highlight?: boolean
|
||||
showTVLLabel?: boolean
|
||||
}): ReactElement {
|
||||
return (
|
||||
<div className={`${styles.tokenlist} ${highlight ? styles.highlight : ''}`}>
|
||||
<h3 className={styles.title}>{title}</h3>
|
||||
<div className={styles.tokens}>
|
||||
<div>
|
||||
<Token symbol={baseTokenSymbol} balance={baseTokenValue} />
|
||||
<Token symbol={baseTokenSymbol} balance={baseTokenValue} />
|
||||
{datatokenValue && (
|
||||
<Token symbol={datatokenSymbol} balance={datatokenValue} />
|
||||
{conversion.greaterThan(0) && (
|
||||
<Conversion
|
||||
price={conversion.toString()}
|
||||
className={styles.totalLiquidity}
|
||||
showTVLLabel={showTVLLabel}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Token symbol="pool shares" balance={poolShares} noIcon />
|
||||
{children}
|
||||
</div>
|
||||
)}
|
||||
{conversion.greaterThan(0) && (
|
||||
<Conversion
|
||||
price={conversion.toString()}
|
||||
className={styles.totalLiquidity}
|
||||
/>
|
||||
)}
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
@ -1,5 +1,4 @@
|
||||
import React, { ReactElement, useCallback, useEffect, useState } from 'react'
|
||||
import { LoggerInstance } from '@oceanprotocol/lib'
|
||||
import React, { ReactElement, useState } from 'react'
|
||||
import styles from './index.module.css'
|
||||
import stylesActions from './Actions.module.css'
|
||||
import PriceUnit from '@shared/Price/PriceUnit'
|
||||
@ -8,314 +7,33 @@ import Add from './Add'
|
||||
import Remove from './Remove'
|
||||
import Tooltip from '@shared/atoms/Tooltip'
|
||||
import ExplorerLink from '@shared/ExplorerLink'
|
||||
import Token from './Token'
|
||||
import TokenList from './TokenList'
|
||||
import AssetActionHistoryTable from '../AssetActionHistoryTable'
|
||||
import Graph from './Graph'
|
||||
import { useAsset } from '@context/Asset'
|
||||
import { useWeb3 } from '@context/Web3'
|
||||
import PoolTransactions from '@shared/PoolTransactions'
|
||||
import { isValidNumber } from '@utils/numbers'
|
||||
import Decimal from 'decimal.js'
|
||||
import content from '../../../../../content/price.json'
|
||||
import { getPoolData } from '@utils/subgraph'
|
||||
import {
|
||||
PoolData_poolSnapshots as PoolDataPoolSnapshots,
|
||||
PoolData_poolData as PoolDataPoolData
|
||||
} from 'src/@types/subgraph/PoolData'
|
||||
|
||||
Decimal.set({ toExpNeg: -18, precision: 18, rounding: 1 })
|
||||
|
||||
function getWeight(weight: string) {
|
||||
return isValidNumber(weight) ? new Decimal(weight).mul(10).toString() : '0'
|
||||
}
|
||||
|
||||
interface PoolInfo {
|
||||
poolFee: string
|
||||
weightBaseToken: string
|
||||
weightDt: string
|
||||
datatokenSymbol: string
|
||||
baseTokenSymbol: string
|
||||
baseTokenAddress: string
|
||||
totalPoolTokens: string
|
||||
totalLiquidityInOcean: Decimal
|
||||
}
|
||||
|
||||
interface PoolInfoUser {
|
||||
totalLiquidityInOcean: Decimal
|
||||
liquidity: PoolBalance
|
||||
poolShares: string
|
||||
poolShare: string // in %
|
||||
}
|
||||
|
||||
const initialPoolInfo: Partial<PoolInfo> = {
|
||||
totalLiquidityInOcean: new Decimal(0)
|
||||
}
|
||||
|
||||
const initialPoolInfoUser: Partial<PoolInfoUser> = {
|
||||
totalLiquidityInOcean: new Decimal(0)
|
||||
}
|
||||
|
||||
const initialPoolInfoCreator: Partial<PoolInfoUser> = initialPoolInfoUser
|
||||
import { usePool } from '@context/Pool'
|
||||
|
||||
export default function Pool(): ReactElement {
|
||||
const { accountId } = useWeb3()
|
||||
const { isInPurgatory, asset, owner, refreshInterval, isAssetNetwork } =
|
||||
useAsset()
|
||||
const { isInPurgatory, asset, isAssetNetwork } = useAsset()
|
||||
const {
|
||||
poolData,
|
||||
poolInfo,
|
||||
poolInfoUser,
|
||||
poolInfoOwner,
|
||||
poolSnapshots,
|
||||
hasUserAddedLiquidity,
|
||||
isRemoveDisabled,
|
||||
refreshInterval,
|
||||
fetchAllData
|
||||
} = usePool()
|
||||
|
||||
const [poolData, setPoolData] = useState<PoolDataPoolData>()
|
||||
const [poolInfo, setPoolInfo] = useState<PoolInfo>(
|
||||
initialPoolInfo as PoolInfo
|
||||
)
|
||||
const [poolInfoOwner, setPoolInfoOwner] = useState<PoolInfoUser>(
|
||||
initialPoolInfoCreator as PoolInfoUser
|
||||
)
|
||||
const [poolInfoUser, setPoolInfoUser] = useState<PoolInfoUser>(
|
||||
initialPoolInfoUser as PoolInfoUser
|
||||
)
|
||||
const [poolSnapshots, setPoolSnapshots] = useState<PoolDataPoolSnapshots[]>()
|
||||
|
||||
const [hasUserAddedLiquidity, setUserHasAddedLiquidity] = useState(false)
|
||||
const [showAdd, setShowAdd] = useState(false)
|
||||
const [showRemove, setShowRemove] = useState(false)
|
||||
const [isRemoveDisabled, setIsRemoveDisabled] = useState(false)
|
||||
const [fetchInterval, setFetchInterval] = useState<NodeJS.Timeout>()
|
||||
|
||||
const fetchAllData = useCallback(async () => {
|
||||
if (!asset?.chainId || !asset?.accessDetails?.addressOrId || !owner) return
|
||||
|
||||
const response = await getPoolData(
|
||||
asset.chainId,
|
||||
asset.accessDetails.addressOrId,
|
||||
owner,
|
||||
accountId || ''
|
||||
)
|
||||
if (!response) return
|
||||
|
||||
setPoolData(response.poolData)
|
||||
setPoolInfoUser((prevState) => ({
|
||||
...prevState,
|
||||
poolShares: response.poolDataUser?.shares[0]?.shares
|
||||
}))
|
||||
setPoolSnapshots(response.poolSnapshots)
|
||||
LoggerInstance.log('[pool] Fetched pool data:', response.poolData)
|
||||
LoggerInstance.log('[pool] Fetched user data:', response.poolDataUser)
|
||||
LoggerInstance.log('[pool] Fetched pool snapshots:', response.poolSnapshots)
|
||||
}, [asset?.chainId, asset?.accessDetails?.addressOrId, owner, accountId])
|
||||
|
||||
// Helper: start interval fetching
|
||||
const initFetchInterval = useCallback(() => {
|
||||
if (fetchInterval) return
|
||||
|
||||
const newInterval = setInterval(() => {
|
||||
fetchAllData()
|
||||
LoggerInstance.log(
|
||||
`[pool] Refetch interval fired after ${refreshInterval / 1000}s`
|
||||
)
|
||||
}, refreshInterval)
|
||||
setFetchInterval(newInterval)
|
||||
}, [fetchInterval, fetchAllData, refreshInterval])
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
clearInterval(fetchInterval)
|
||||
}
|
||||
}, [fetchInterval])
|
||||
|
||||
//
|
||||
// 0 Fetch all the data on mount
|
||||
// All further effects depend on the fetched data
|
||||
// and only do further data checking and manipulation.
|
||||
//
|
||||
useEffect(() => {
|
||||
fetchAllData()
|
||||
initFetchInterval()
|
||||
}, [fetchAllData, initFetchInterval])
|
||||
|
||||
//
|
||||
// 1 General Pool Info
|
||||
//
|
||||
useEffect(() => {
|
||||
if (!poolData) return
|
||||
|
||||
// Pool Fee (swap fee)
|
||||
// poolFee is tricky: to get 0.1% you need to convert from 0.001
|
||||
const poolFee = isValidNumber(poolData.poolFee)
|
||||
? new Decimal(poolData.poolFee).mul(100).toString()
|
||||
: '0'
|
||||
|
||||
// Total Liquidity
|
||||
const totalLiquidityInOcean = isValidNumber(poolData.spotPrice)
|
||||
? new Decimal(poolData.baseTokenLiquidity).add(
|
||||
new Decimal(poolData.datatokenLiquidity).mul(poolData.spotPrice)
|
||||
)
|
||||
: new Decimal(0)
|
||||
|
||||
const newPoolInfo = {
|
||||
poolFee,
|
||||
weightBaseToken: getWeight(poolData.baseTokenWeight),
|
||||
weightDt: getWeight(poolData.datatokenWeight),
|
||||
datatokenSymbol: poolData.datatoken.symbol,
|
||||
baseTokenSymbol: poolData.baseToken.symbol,
|
||||
baseTokenAddress: poolData.baseToken.address,
|
||||
totalPoolTokens: poolData.totalShares,
|
||||
totalLiquidityInOcean
|
||||
}
|
||||
setPoolInfo(newPoolInfo)
|
||||
LoggerInstance.log('[pool] Created new pool info:', newPoolInfo)
|
||||
}, [poolData])
|
||||
|
||||
//
|
||||
// 2 Pool Creator Info
|
||||
//
|
||||
useEffect(() => {
|
||||
if (!poolData || !poolInfo?.totalPoolTokens) return
|
||||
|
||||
const ownerPoolTokens = poolData.shares[0]?.shares
|
||||
|
||||
const ownerBaseTokenBalance =
|
||||
isValidNumber(ownerPoolTokens) &&
|
||||
isValidNumber(poolInfo.totalPoolTokens) &&
|
||||
isValidNumber(poolData.baseTokenLiquidity)
|
||||
? new Decimal(ownerPoolTokens)
|
||||
.dividedBy(new Decimal(poolInfo.totalPoolTokens))
|
||||
.mul(poolData.baseTokenLiquidity)
|
||||
.toString()
|
||||
: '0'
|
||||
|
||||
const ownerDtBalance =
|
||||
isValidNumber(ownerPoolTokens) &&
|
||||
isValidNumber(poolInfo.totalPoolTokens) &&
|
||||
isValidNumber(poolData.datatokenLiquidity)
|
||||
? new Decimal(ownerPoolTokens)
|
||||
.dividedBy(new Decimal(poolInfo.totalPoolTokens))
|
||||
.mul(poolData.datatokenLiquidity)
|
||||
.toString()
|
||||
: '0'
|
||||
|
||||
const liquidity = {
|
||||
baseToken: ownerBaseTokenBalance,
|
||||
datatoken: ownerDtBalance
|
||||
}
|
||||
|
||||
const totalLiquidityInOcean =
|
||||
isValidNumber(liquidity.baseToken) &&
|
||||
isValidNumber(liquidity.datatoken) &&
|
||||
isValidNumber(poolData.spotPrice)
|
||||
? new Decimal(liquidity.baseToken).add(
|
||||
new Decimal(liquidity.datatoken).mul(
|
||||
new Decimal(poolData.spotPrice)
|
||||
)
|
||||
)
|
||||
: new Decimal(0)
|
||||
|
||||
const poolShare =
|
||||
liquidity &&
|
||||
isValidNumber(ownerPoolTokens) &&
|
||||
isValidNumber(poolInfo.totalPoolTokens)
|
||||
? new Decimal(ownerPoolTokens)
|
||||
.dividedBy(new Decimal(poolInfo.totalPoolTokens))
|
||||
.mul(100)
|
||||
.toFixed(2)
|
||||
: '0'
|
||||
|
||||
const newPoolOwnerInfo = {
|
||||
totalLiquidityInOcean,
|
||||
liquidity,
|
||||
poolShares: ownerPoolTokens,
|
||||
poolShare
|
||||
}
|
||||
setPoolInfoOwner(newPoolOwnerInfo)
|
||||
LoggerInstance.log('[pool] Created new owner pool info:', newPoolOwnerInfo)
|
||||
}, [poolData, poolInfo?.totalPoolTokens])
|
||||
|
||||
//
|
||||
// 3 User Pool Info
|
||||
//
|
||||
useEffect(() => {
|
||||
if (
|
||||
!poolData ||
|
||||
!poolInfo?.totalPoolTokens ||
|
||||
!asset?.chainId ||
|
||||
!accountId
|
||||
)
|
||||
return
|
||||
|
||||
const poolShare =
|
||||
isValidNumber(poolInfoUser.poolShares) &&
|
||||
isValidNumber(poolInfo.totalPoolTokens) &&
|
||||
new Decimal(poolInfoUser.poolShares)
|
||||
.dividedBy(new Decimal(poolInfo.totalPoolTokens))
|
||||
.mul(100)
|
||||
.toFixed(5)
|
||||
|
||||
setUserHasAddedLiquidity(Number(poolShare) > 0)
|
||||
|
||||
// calculate user's provided liquidity based on pool tokens
|
||||
const userBaseTokenBalance =
|
||||
isValidNumber(poolInfoUser.poolShares) &&
|
||||
isValidNumber(poolInfo.totalPoolTokens) &&
|
||||
isValidNumber(poolData.baseTokenLiquidity)
|
||||
? new Decimal(poolInfoUser.poolShares)
|
||||
.dividedBy(new Decimal(poolInfo.totalPoolTokens))
|
||||
.mul(poolData.baseTokenLiquidity)
|
||||
.toString()
|
||||
: '0'
|
||||
|
||||
const userDtBalance =
|
||||
isValidNumber(poolInfoUser.poolShares) &&
|
||||
isValidNumber(poolInfo.totalPoolTokens) &&
|
||||
isValidNumber(poolData.datatokenLiquidity)
|
||||
? new Decimal(poolInfoUser.poolShares)
|
||||
.dividedBy(new Decimal(poolInfo.totalPoolTokens))
|
||||
.mul(poolData.datatokenLiquidity)
|
||||
.toString()
|
||||
: '0'
|
||||
|
||||
const liquidity = {
|
||||
baseToken: userBaseTokenBalance,
|
||||
datatoken: userDtBalance
|
||||
}
|
||||
|
||||
const totalLiquidityInOcean =
|
||||
isValidNumber(liquidity.baseToken) &&
|
||||
isValidNumber(liquidity.datatoken) &&
|
||||
isValidNumber(poolData.spotPrice)
|
||||
? new Decimal(liquidity.baseToken).add(
|
||||
new Decimal(liquidity.datatoken).mul(poolData.spotPrice)
|
||||
)
|
||||
: new Decimal(0)
|
||||
|
||||
const newPoolInfoUser = {
|
||||
totalLiquidityInOcean,
|
||||
liquidity,
|
||||
poolShare
|
||||
}
|
||||
setPoolInfoUser((prevState: PoolInfoUser) => ({
|
||||
...prevState,
|
||||
...newPoolInfoUser
|
||||
}))
|
||||
|
||||
LoggerInstance.log('[pool] Created new user pool info:', {
|
||||
poolShares: poolInfoUser?.poolShares,
|
||||
...newPoolInfoUser
|
||||
})
|
||||
}, [
|
||||
poolData,
|
||||
poolInfoUser?.poolShares,
|
||||
accountId,
|
||||
asset?.chainId,
|
||||
owner,
|
||||
poolInfo?.totalPoolTokens
|
||||
])
|
||||
|
||||
//
|
||||
// Check if removing liquidity should be disabled.
|
||||
//
|
||||
useEffect(() => {
|
||||
if (!owner || !accountId) return
|
||||
setIsRemoveDisabled(isInPurgatory && owner === accountId)
|
||||
}, [isInPurgatory, owner, accountId])
|
||||
|
||||
return (
|
||||
<>
|
||||
@ -364,8 +82,8 @@ export default function Pool(): ReactElement {
|
||||
networkId={asset?.chainId}
|
||||
path={
|
||||
asset?.chainId === 2021000 || asset?.chainId === 1287
|
||||
? `tokens/${asset.services[0].datatokenAddress}`
|
||||
: `token/${asset.services[0].datatokenAddress}`
|
||||
? `tokens/${asset?.services[0].datatokenAddress}`
|
||||
: `token/${asset?.services[0].datatokenAddress}`
|
||||
}
|
||||
>
|
||||
Datatoken
|
||||
@ -383,38 +101,32 @@ export default function Pool(): ReactElement {
|
||||
poolInfo?.poolFee
|
||||
)}
|
||||
/>
|
||||
{poolInfoUser?.poolShare && (
|
||||
<span className={styles.titleInfo}>
|
||||
{poolInfoUser?.poolShare}% of pool
|
||||
</span>
|
||||
)}
|
||||
</>
|
||||
}
|
||||
baseTokenValue={`${poolInfoUser?.liquidity?.baseToken}`}
|
||||
baseTokenValue={poolInfoUser?.liquidity.toString()}
|
||||
baseTokenSymbol={poolInfo?.baseTokenSymbol}
|
||||
datatokenValue={`${poolInfoUser?.liquidity?.datatoken}`}
|
||||
datatokenSymbol={poolInfo?.datatokenSymbol}
|
||||
poolShares={poolInfoUser?.poolShares}
|
||||
conversion={poolInfoUser?.totalLiquidityInOcean}
|
||||
conversion={poolInfoUser?.liquidity}
|
||||
highlight
|
||||
>
|
||||
<Token
|
||||
symbol="% of pool"
|
||||
balance={poolInfoUser?.poolShare}
|
||||
noIcon
|
||||
/>
|
||||
</TokenList>
|
||||
/>
|
||||
|
||||
<TokenList
|
||||
title="Pool Creator Statistics"
|
||||
baseTokenValue={`${poolInfoOwner?.liquidity?.baseToken}`}
|
||||
title={
|
||||
<>
|
||||
Owner Liquidity
|
||||
<span className={styles.titleInfo}>
|
||||
{poolInfoOwner?.poolShare}% of pool
|
||||
</span>
|
||||
</>
|
||||
}
|
||||
baseTokenValue={poolInfoOwner?.liquidity.toString()}
|
||||
baseTokenSymbol={poolInfo?.baseTokenSymbol}
|
||||
datatokenValue={`${poolInfoOwner?.liquidity?.datatoken}`}
|
||||
datatokenSymbol={poolInfo?.datatokenSymbol}
|
||||
poolShares={poolInfoOwner?.poolShares}
|
||||
conversion={poolInfoOwner?.totalLiquidityInOcean}
|
||||
>
|
||||
<Token
|
||||
symbol="% of pool"
|
||||
balance={poolInfoOwner?.poolShare}
|
||||
noIcon
|
||||
/>
|
||||
</TokenList>
|
||||
conversion={poolInfoOwner?.liquidity}
|
||||
/>
|
||||
|
||||
<TokenList
|
||||
title={
|
||||
@ -435,11 +147,11 @@ export default function Pool(): ReactElement {
|
||||
baseTokenSymbol={poolInfo?.baseTokenSymbol}
|
||||
datatokenValue={`${poolData?.datatokenLiquidity}`}
|
||||
datatokenSymbol={poolInfo?.datatokenSymbol}
|
||||
poolShares={poolInfo?.totalPoolTokens}
|
||||
conversion={poolInfo?.totalLiquidityInOcean}
|
||||
showTVLLabel
|
||||
>
|
||||
<Token symbol="% pool fee" balance={poolInfo?.poolFee} noIcon />
|
||||
{/* <Token symbol="% pool fee" balance={poolInfo?.poolFee} noIcon />
|
||||
<Token symbol="% market fee" balance={poolInfo?.marketFee} noIcon />
|
||||
<Token symbol="% OPF fee" balance={poolInfo?.opfFee} noIcon /> */}
|
||||
</TokenList>
|
||||
|
||||
<div className={styles.update}>
|
||||
|
@ -106,7 +106,7 @@ export default function FormTrade({
|
||||
setSubmitting(false)
|
||||
}}
|
||||
>
|
||||
{({ isSubmitting, submitForm, values, isValid }) => (
|
||||
{({ isSubmitting, setSubmitting, submitForm, values, isValid }) => (
|
||||
<>
|
||||
{isWarningAccepted ? (
|
||||
<Swap
|
||||
@ -156,6 +156,7 @@ export default function FormTrade({
|
||||
txId={txId}
|
||||
tokenAddress={tokenAddress}
|
||||
tokenSymbol={tokenSymbol}
|
||||
setSubmitting={setSubmitting}
|
||||
/>
|
||||
|
||||
{debug && (
|
||||
|
@ -9,7 +9,7 @@ import Trade from './Trade'
|
||||
import { useAsset } from '@context/Asset'
|
||||
import { useWeb3 } from '@context/Web3'
|
||||
import Web3Feedback from '@shared/Web3Feedback'
|
||||
import { getFileInfo } from '@utils/provider'
|
||||
import { getFileDidInfo, getFileUrlInfo } from '@utils/provider'
|
||||
import { getOceanConfig } from '@utils/ocean'
|
||||
import { useCancelToken } from '@hooks/useCancelToken'
|
||||
import { useIsMounted } from '@hooks/useIsMounted'
|
||||
@ -17,6 +17,7 @@ import styles from './index.module.css'
|
||||
import { useFormikContext } from 'formik'
|
||||
import { FormPublishData } from 'src/components/Publish/_types'
|
||||
import { AssetExtended } from 'src/@types/AssetExtended'
|
||||
import PoolProvider from '@context/Pool'
|
||||
|
||||
export default function AssetActions({
|
||||
asset
|
||||
@ -67,15 +68,18 @@ export default function AssetActions({
|
||||
|
||||
async function initFileInfo() {
|
||||
setFileIsLoading(true)
|
||||
const fileUrl =
|
||||
formikState?.values?.services?.[0].files?.[0].url ||
|
||||
(asset.metadata?.links ? asset.metadata?.links[0] : ' ')
|
||||
const providerUrl =
|
||||
formikState?.values?.services[0].providerUrl.url ||
|
||||
oceanConfig.providerUri
|
||||
asset?.services[0]?.serviceEndpoint
|
||||
|
||||
try {
|
||||
const fileInfoResponse = await getFileInfo(fileUrl, providerUrl)
|
||||
const fileInfoResponse = formikState?.values?.services?.[0].files?.[0]
|
||||
.url
|
||||
? await getFileUrlInfo(
|
||||
formikState?.values?.services?.[0].files?.[0].url,
|
||||
providerUrl
|
||||
)
|
||||
: await getFileDidInfo(asset?.id, asset?.services[0]?.id, providerUrl)
|
||||
fileInfoResponse && setFileMetadata(fileInfoResponse[0])
|
||||
setFileIsLoading(false)
|
||||
} catch (error) {
|
||||
@ -171,11 +175,13 @@ export default function AssetActions({
|
||||
|
||||
return (
|
||||
<>
|
||||
<Tabs items={tabs} className={styles.actions} />
|
||||
<Web3Feedback
|
||||
networkId={asset?.chainId}
|
||||
isAssetNetwork={isAssetNetwork}
|
||||
/>
|
||||
<PoolProvider>
|
||||
<Tabs items={tabs} className={styles.actions} />
|
||||
<Web3Feedback
|
||||
networkId={asset?.chainId}
|
||||
isAssetNetwork={isAssetNetwork}
|
||||
/>
|
||||
</PoolProvider>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ export default function Menu(): ReactElement {
|
||||
<a className={styles.logo}>
|
||||
<Logo noWordmark />
|
||||
<h1 className={styles.title}>
|
||||
{siteTitle} <Badge label="v3" />
|
||||
{siteTitle} <Badge label="v4" />
|
||||
</h1>
|
||||
</a>
|
||||
</Link>
|
||||
|
@ -249,7 +249,7 @@ export async function createTokensAndPricing(
|
||||
)
|
||||
|
||||
// the spender in this case is the erc721Factory because we are delegating
|
||||
const pool = new Pool(web3, LoggerInstance)
|
||||
const pool = new Pool(web3)
|
||||
const txApprove = await approve(
|
||||
web3,
|
||||
accountId,
|
||||
|
Loading…
Reference in New Issue
Block a user