mirror of
https://github.com/oceanprotocol/market.git
synced 2024-12-02 05:57:29 +01:00
merge main
This commit is contained in:
commit
2632e7ed0f
2
.github/workflows/deploy.yml
vendored
2
.github/workflows/deploy.yml
vendored
@ -14,7 +14,7 @@ jobs:
|
|||||||
- uses: actions/setup-node@v2
|
- uses: actions/setup-node@v2
|
||||||
- run: npm ci --legacy-peer-deps
|
- run: npm ci --legacy-peer-deps
|
||||||
|
|
||||||
- run: npm run build
|
- run: npm run build:static
|
||||||
env:
|
env:
|
||||||
NEXT_PUBLIC_INFURA_PROJECT_ID: ${{ secrets.NEXT_PUBLIC_INFURA_PROJECT_ID }}
|
NEXT_PUBLIC_INFURA_PROJECT_ID: ${{ secrets.NEXT_PUBLIC_INFURA_PROJECT_ID }}
|
||||||
|
|
||||||
|
@ -50,6 +50,8 @@ cd market
|
|||||||
nvm use
|
nvm use
|
||||||
|
|
||||||
npm install
|
npm install
|
||||||
|
# in case of dependency errors, rather use:
|
||||||
|
# npm install --legacy-peer-deps
|
||||||
npm start
|
npm start
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -16,16 +16,6 @@
|
|||||||
"marketplaceFee": "Goes to the marketplace owner that is hosting and providing the marketplace and is collected when downloading or using an asset in a compute job. In Ocean Market, it is treated as network revenue that goes to the Ocean community."
|
"marketplaceFee": "Goes to the marketplace owner that is hosting and providing the marketplace and is collected when downloading or using an asset in a compute job. In Ocean Market, it is treated as network revenue that goes to the Ocean community."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dynamic": {
|
|
||||||
"title": "Dynamic",
|
|
||||||
"info": "Let's create a decentralized, automated market for your data set. The datatoken for this data set will be worth the entered amount of OCEAN. Additionally, you will provide liquidity into a Datatoken/OCEAN liquidity pool with Balancer.",
|
|
||||||
"tooltips": {
|
|
||||||
"poolInfo": "The liquidity pool provides the funds for traders to trade against. The price of the asset is determined by the ratio of OCEAN to datatokens.",
|
|
||||||
"swapFee": "Liquidity providers earn this fee on all pool trades, proportionally to their share of the pool. The fee is set by the creator of the pool and is used to incentivize liquidity providers to join the pool.",
|
|
||||||
"communityFee": "Goes to Ocean DAO for teams to improve the tools, build apps, do outreach, and more. A small fraction is used to burn OCEAN. This fee is collected when downloading or using an asset in a compute job.",
|
|
||||||
"marketplaceFee": "Goes to the marketplace owner that is hosting and providing the marketplace and is collected when downloading or using an asset in a compute job. In Ocean Market, it is treated as network revenue that goes to the Ocean community."
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"free": {
|
"free": {
|
||||||
"title": "Free",
|
"title": "Free",
|
||||||
"info": "Set your data set as free. The datatoken for this data set will be given for free via creating a faucet.",
|
"info": "Set your data set as free. The datatoken for this data set will be given for free via creating a faucet.",
|
||||||
@ -47,15 +37,6 @@
|
|||||||
"approveSpecific": "Give the smart contract permission to spend your COIN which has to be done for each transaction. You can optionally set this to infinite in your user preferences.",
|
"approveSpecific": "Give the smart contract permission to spend your COIN which has to be done for each transaction. You can optionally set this to infinite in your user preferences.",
|
||||||
"approveInfinite": "Give the smart contract permission to spend infinte amounts of your COIN so you have to do this only once. You can disable allowing infinite amounts in your user preferences."
|
"approveInfinite": "Give the smart contract permission to spend infinte amounts of your COIN so you have to do this only once. You can disable allowing infinite amounts in your user preferences."
|
||||||
},
|
},
|
||||||
"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.",
|
|
||||||
"titleIn": "You will receive",
|
|
||||||
"titleOut": "Pool conversion"
|
|
||||||
},
|
|
||||||
"action": "Supply"
|
|
||||||
},
|
|
||||||
"remove": {
|
"remove": {
|
||||||
"title": "Remove Liquidity",
|
"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.",
|
"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.",
|
||||||
|
44
package-lock.json
generated
44
package-lock.json
generated
@ -13,7 +13,7 @@
|
|||||||
"@coingecko/cryptoformat": "^0.5.4",
|
"@coingecko/cryptoformat": "^0.5.4",
|
||||||
"@loadable/component": "^5.15.2",
|
"@loadable/component": "^5.15.2",
|
||||||
"@oceanprotocol/art": "^3.2.0",
|
"@oceanprotocol/art": "^3.2.0",
|
||||||
"@oceanprotocol/lib": "^1.1.5",
|
"@oceanprotocol/lib": "^1.1.6",
|
||||||
"@oceanprotocol/typographies": "^0.1.0",
|
"@oceanprotocol/typographies": "^0.1.0",
|
||||||
"@tippyjs/react": "^4.2.6",
|
"@tippyjs/react": "^4.2.6",
|
||||||
"@urql/exchange-refocus": "^0.2.5",
|
"@urql/exchange-refocus": "^0.2.5",
|
||||||
@ -4598,9 +4598,9 @@
|
|||||||
"integrity": "sha512-rDCIooe1WHipLejuGhx2Wv/88SB7bWrN3+XHCWxXyPKTmmSQsgxKZPPzbIVBQ0ESChQZqGSBBJyqErqwwW4eBw=="
|
"integrity": "sha512-rDCIooe1WHipLejuGhx2Wv/88SB7bWrN3+XHCWxXyPKTmmSQsgxKZPPzbIVBQ0ESChQZqGSBBJyqErqwwW4eBw=="
|
||||||
},
|
},
|
||||||
"node_modules/@oceanprotocol/lib": {
|
"node_modules/@oceanprotocol/lib": {
|
||||||
"version": "1.1.5",
|
"version": "1.1.6",
|
||||||
"resolved": "https://registry.npmjs.org/@oceanprotocol/lib/-/lib-1.1.5.tgz",
|
"resolved": "https://registry.npmjs.org/@oceanprotocol/lib/-/lib-1.1.6.tgz",
|
||||||
"integrity": "sha512-quc2SGAr8G1v664ll3eOystA2v94OQleW6KGKhVWEPXDldnNAAhlG/QTi86XWRU9HmncGE7OghC5am+9DRGWcQ==",
|
"integrity": "sha512-n1ync5LYBjJDg9Znq61zajnkeXFeFGOU8dN2LCeewArljCOdfYW/SEgQtiLALQb1dgqsYSjMHym40O2jPTUxoQ==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@oceanprotocol/contracts": "^1.0.0",
|
"@oceanprotocol/contracts": "^1.0.0",
|
||||||
"bignumber.js": "^9.0.2",
|
"bignumber.js": "^9.0.2",
|
||||||
@ -35024,9 +35024,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/parse-path": {
|
"node_modules/parse-path": {
|
||||||
"version": "4.0.3",
|
"version": "4.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/parse-path/-/parse-path-4.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/parse-path/-/parse-path-4.0.4.tgz",
|
||||||
"integrity": "sha512-9Cepbp2asKnWTJ9x2kpw6Fe8y9JDbqwahGCTvklzd/cEq5C5JC59x2Xb0Kx+x0QZ8bvNquGO8/BWP0cwBHzSAA==",
|
"integrity": "sha512-Z2lWUis7jlmXC1jeOG9giRO2+FsuyNipeQ43HAjqAZjwSe3SEf+q/84FGPHoso3kyntbxa4c4i77t3m6fGf8cw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"is-ssh": "^1.3.0",
|
"is-ssh": "^1.3.0",
|
||||||
@ -35054,14 +35054,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/parse-url": {
|
"node_modules/parse-url": {
|
||||||
"version": "6.0.0",
|
"version": "6.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/parse-url/-/parse-url-6.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/parse-url/-/parse-url-6.0.2.tgz",
|
||||||
"integrity": "sha512-cYyojeX7yIIwuJzledIHeLUBVJ6COVLeT4eF+2P6aKVzwvgKQPndCBv3+yQ7pcWjqToYwaligxzSYNNmGoMAvw==",
|
"integrity": "sha512-uCSjOvD3T+6B/sPWhR+QowAZcU/o4bjPrVBQBGFxcDF6J6FraCGIaDBsdoQawiaaAVdHvtqBe3w3vKlfBKySOQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"is-ssh": "^1.3.0",
|
"is-ssh": "^1.3.0",
|
||||||
"normalize-url": "^6.1.0",
|
"normalize-url": "^6.1.0",
|
||||||
"parse-path": "^4.0.0",
|
"parse-path": "^4.0.4",
|
||||||
"protocols": "^1.4.0"
|
"protocols": "^1.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -46660,16 +46660,15 @@
|
|||||||
"integrity": "sha512-rDCIooe1WHipLejuGhx2Wv/88SB7bWrN3+XHCWxXyPKTmmSQsgxKZPPzbIVBQ0ESChQZqGSBBJyqErqwwW4eBw=="
|
"integrity": "sha512-rDCIooe1WHipLejuGhx2Wv/88SB7bWrN3+XHCWxXyPKTmmSQsgxKZPPzbIVBQ0ESChQZqGSBBJyqErqwwW4eBw=="
|
||||||
},
|
},
|
||||||
"@oceanprotocol/lib": {
|
"@oceanprotocol/lib": {
|
||||||
"version": "1.1.5",
|
"version": "1.1.6",
|
||||||
"resolved": "https://registry.npmjs.org/@oceanprotocol/lib/-/lib-1.1.5.tgz",
|
"resolved": "https://registry.npmjs.org/@oceanprotocol/lib/-/lib-1.1.6.tgz",
|
||||||
"integrity": "sha512-quc2SGAr8G1v664ll3eOystA2v94OQleW6KGKhVWEPXDldnNAAhlG/QTi86XWRU9HmncGE7OghC5am+9DRGWcQ==",
|
"integrity": "sha512-n1ync5LYBjJDg9Znq61zajnkeXFeFGOU8dN2LCeewArljCOdfYW/SEgQtiLALQb1dgqsYSjMHym40O2jPTUxoQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@oceanprotocol/contracts": "^1.0.0",
|
"@oceanprotocol/contracts": "^1.0.0",
|
||||||
"bignumber.js": "^9.0.2",
|
"bignumber.js": "^9.0.2",
|
||||||
"cross-fetch": "^3.1.5",
|
"cross-fetch": "^3.1.5",
|
||||||
"crypto-js": "^4.1.1",
|
"crypto-js": "^4.1.1",
|
||||||
"decimal.js": "^10.3.1",
|
"decimal.js": "^10.3.1",
|
||||||
"web3": "^1.7.4",
|
|
||||||
"web3-core": "^1.7.1",
|
"web3-core": "^1.7.1",
|
||||||
"web3-eth-contract": "^1.7.1"
|
"web3-eth-contract": "^1.7.1"
|
||||||
}
|
}
|
||||||
@ -46721,7 +46720,6 @@
|
|||||||
"integrity": "sha512-rmVKYEsKzurfRU0xJz+iHelbi1LGlihIWZ7Qvmb/CBz1EkhL7nOkW4SVXmG2dA5Ce0si2gr88i6q4eBOMRNJ1w==",
|
"integrity": "sha512-rmVKYEsKzurfRU0xJz+iHelbi1LGlihIWZ7Qvmb/CBz1EkhL7nOkW4SVXmG2dA5Ce0si2gr88i6q4eBOMRNJ1w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@oclif/config": "^1.18.2",
|
|
||||||
"@oclif/errors": "^1.3.5",
|
"@oclif/errors": "^1.3.5",
|
||||||
"@oclif/help": "^1.0.1",
|
"@oclif/help": "^1.0.1",
|
||||||
"@oclif/parser": "^3.8.6",
|
"@oclif/parser": "^3.8.6",
|
||||||
@ -70390,9 +70388,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"parse-path": {
|
"parse-path": {
|
||||||
"version": "4.0.3",
|
"version": "4.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/parse-path/-/parse-path-4.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/parse-path/-/parse-path-4.0.4.tgz",
|
||||||
"integrity": "sha512-9Cepbp2asKnWTJ9x2kpw6Fe8y9JDbqwahGCTvklzd/cEq5C5JC59x2Xb0Kx+x0QZ8bvNquGO8/BWP0cwBHzSAA==",
|
"integrity": "sha512-Z2lWUis7jlmXC1jeOG9giRO2+FsuyNipeQ43HAjqAZjwSe3SEf+q/84FGPHoso3kyntbxa4c4i77t3m6fGf8cw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"is-ssh": "^1.3.0",
|
"is-ssh": "^1.3.0",
|
||||||
@ -70416,14 +70414,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"parse-url": {
|
"parse-url": {
|
||||||
"version": "6.0.0",
|
"version": "6.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/parse-url/-/parse-url-6.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/parse-url/-/parse-url-6.0.2.tgz",
|
||||||
"integrity": "sha512-cYyojeX7yIIwuJzledIHeLUBVJ6COVLeT4eF+2P6aKVzwvgKQPndCBv3+yQ7pcWjqToYwaligxzSYNNmGoMAvw==",
|
"integrity": "sha512-uCSjOvD3T+6B/sPWhR+QowAZcU/o4bjPrVBQBGFxcDF6J6FraCGIaDBsdoQawiaaAVdHvtqBe3w3vKlfBKySOQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"is-ssh": "^1.3.0",
|
"is-ssh": "^1.3.0",
|
||||||
"normalize-url": "^6.1.0",
|
"normalize-url": "^6.1.0",
|
||||||
"parse-path": "^4.0.0",
|
"parse-path": "^4.0.4",
|
||||||
"protocols": "^1.4.0"
|
"protocols": "^1.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "npm run pregenerate && next dev -p 8000",
|
"start": "npm run pregenerate && next dev -p 8000",
|
||||||
"build": "npm run pregenerate && next build",
|
"build": "npm run pregenerate && next build",
|
||||||
|
"build:static": "npm run build && next export",
|
||||||
"serve": "serve -s public/",
|
"serve": "serve -s public/",
|
||||||
"pregenerate": "bash scripts/pregenerate.sh",
|
"pregenerate": "bash scripts/pregenerate.sh",
|
||||||
"test": "npm run pregenerate && npm run lint && npm run type-check && npm run jest",
|
"test": "npm run pregenerate && npm run lint && npm run type-check && npm run jest",
|
||||||
@ -25,7 +26,7 @@
|
|||||||
"@coingecko/cryptoformat": "^0.5.4",
|
"@coingecko/cryptoformat": "^0.5.4",
|
||||||
"@loadable/component": "^5.15.2",
|
"@loadable/component": "^5.15.2",
|
||||||
"@oceanprotocol/art": "^3.2.0",
|
"@oceanprotocol/art": "^3.2.0",
|
||||||
"@oceanprotocol/lib": "^1.1.5",
|
"@oceanprotocol/lib": "^1.1.6",
|
||||||
"@oceanprotocol/typographies": "^0.1.0",
|
"@oceanprotocol/typographies": "^0.1.0",
|
||||||
"@tippyjs/react": "^4.2.6",
|
"@tippyjs/react": "^4.2.6",
|
||||||
"@urql/exchange-refocus": "^0.2.5",
|
"@urql/exchange-refocus": "^0.2.5",
|
||||||
|
@ -10,7 +10,7 @@ AWS_S3_BUCKET="www-market"
|
|||||||
set -e;
|
set -e;
|
||||||
|
|
||||||
function s3sync {
|
function s3sync {
|
||||||
aws s3 sync ./public s3://"$1" \
|
aws s3 sync ./out s3://"$1" \
|
||||||
--include "*" \
|
--include "*" \
|
||||||
--exclude "*.html" \
|
--exclude "*.html" \
|
||||||
--exclude "sw.js" \
|
--exclude "sw.js" \
|
||||||
@ -24,7 +24,7 @@ function s3sync {
|
|||||||
--delete \
|
--delete \
|
||||||
--acl public-read
|
--acl public-read
|
||||||
|
|
||||||
aws s3 sync ./public s3://"$1" \
|
aws s3 sync ./out s3://"$1" \
|
||||||
--exclude "*" \
|
--exclude "*" \
|
||||||
--include "*.html" \
|
--include "*.html" \
|
||||||
--include "sw.js" \
|
--include "sw.js" \
|
||||||
|
1
src/@types/aquarius/BaseQueryParams.d.ts
vendored
1
src/@types/aquarius/BaseQueryParams.d.ts
vendored
@ -9,6 +9,7 @@ interface BaseQueryParams {
|
|||||||
nestedQuery?: any
|
nestedQuery?: any
|
||||||
esPaginationOptions?: EsPaginationOptions
|
esPaginationOptions?: EsPaginationOptions
|
||||||
sortOptions?: SortOptions
|
sortOptions?: SortOptions
|
||||||
|
aggs?: any
|
||||||
filters?: FilterTerm[]
|
filters?: FilterTerm[]
|
||||||
ignorePurgatory?: boolean
|
ignorePurgatory?: boolean
|
||||||
}
|
}
|
||||||
|
1
src/@types/aquarius/PagedAssets.d.ts
vendored
1
src/@types/aquarius/PagedAssets.d.ts
vendored
@ -3,4 +3,5 @@ interface PagedAssets {
|
|||||||
page: number
|
page: number
|
||||||
totalPages: number
|
totalPages: number
|
||||||
totalResults: number
|
totalResults: number
|
||||||
|
aggregations: any
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,8 @@ export enum SortDirectionOptions {
|
|||||||
|
|
||||||
export enum SortTermOptions {
|
export enum SortTermOptions {
|
||||||
Created = 'metadata.created',
|
Created = 'metadata.created',
|
||||||
Relevance = '_score'
|
Relevance = '_score',
|
||||||
|
Stats = 'stats.orders'
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: could not figure out how to get `enum` to be ambiant
|
// Note: could not figure out how to get `enum` to be ambiant
|
||||||
@ -43,5 +44,6 @@ declare global {
|
|||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
query: any
|
query: any
|
||||||
sort?: { [jsonPath: string]: SortDirectionOptions }
|
sort?: { [jsonPath: string]: SortDirectionOptions }
|
||||||
|
aggs?: any
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -55,6 +55,10 @@ export function generateBaseQuery(
|
|||||||
}
|
}
|
||||||
} as SearchQuery
|
} as SearchQuery
|
||||||
|
|
||||||
|
if (baseQueryParams.aggs !== undefined) {
|
||||||
|
generatedQuery.aggs = baseQueryParams.aggs
|
||||||
|
}
|
||||||
|
|
||||||
if (baseQueryParams.sortOptions !== undefined)
|
if (baseQueryParams.sortOptions !== undefined)
|
||||||
generatedQuery.sort = {
|
generatedQuery.sort = {
|
||||||
[baseQueryParams.sortOptions.sortBy]:
|
[baseQueryParams.sortOptions.sortBy]:
|
||||||
@ -74,12 +78,15 @@ export function transformQueryResult(
|
|||||||
results: [],
|
results: [],
|
||||||
page: 0,
|
page: 0,
|
||||||
totalPages: 0,
|
totalPages: 0,
|
||||||
totalResults: 0
|
totalResults: 0,
|
||||||
|
aggregations: []
|
||||||
}
|
}
|
||||||
|
|
||||||
result.results = (queryResult.hits.hits || []).map(
|
result.results = (queryResult.hits.hits || []).map(
|
||||||
(hit) => hit._source as Asset
|
(hit) => hit._source as Asset
|
||||||
)
|
)
|
||||||
|
|
||||||
|
result.aggregations = queryResult.aggregations
|
||||||
result.totalResults = queryResult.hits.total.value
|
result.totalResults = queryResult.hits.total.value
|
||||||
result.totalPages =
|
result.totalPages =
|
||||||
result.totalResults / size < 1
|
result.totalResults / size < 1
|
||||||
@ -307,6 +314,14 @@ export async function getPublishedAssets(
|
|||||||
sortBy: SortTermOptions.Created,
|
sortBy: SortTermOptions.Created,
|
||||||
sortDirection: SortDirectionOptions.Descending
|
sortDirection: SortDirectionOptions.Descending
|
||||||
},
|
},
|
||||||
|
aggs: {
|
||||||
|
totalOrders: {
|
||||||
|
sum: {
|
||||||
|
field: SortTermOptions.Stats
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ignorePurgatory: true,
|
||||||
esPaginationOptions: {
|
esPaginationOptions: {
|
||||||
from: (Number(page) - 1 || 0) * 9,
|
from: (Number(page) - 1 || 0) * 9,
|
||||||
size: 9
|
size: 9
|
||||||
@ -314,6 +329,62 @@ export async function getPublishedAssets(
|
|||||||
} as BaseQueryParams
|
} as BaseQueryParams
|
||||||
|
|
||||||
const query = generateBaseQuery(baseQueryParams)
|
const query = generateBaseQuery(baseQueryParams)
|
||||||
|
|
||||||
|
try {
|
||||||
|
const result = await queryMetadata(query, cancelToken)
|
||||||
|
return result
|
||||||
|
} catch (error) {
|
||||||
|
if (axios.isCancel(error)) {
|
||||||
|
LoggerInstance.log(error.message)
|
||||||
|
} else {
|
||||||
|
LoggerInstance.error(error.message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getTopPublishers(
|
||||||
|
chainIds: number[],
|
||||||
|
cancelToken: CancelToken,
|
||||||
|
page?: number,
|
||||||
|
type?: string,
|
||||||
|
accesType?: string
|
||||||
|
): Promise<PagedAssets> {
|
||||||
|
const filters: FilterTerm[] = []
|
||||||
|
|
||||||
|
accesType !== undefined &&
|
||||||
|
filters.push(getFilterTerm('services.type', accesType))
|
||||||
|
type !== undefined && filters.push(getFilterTerm('metadata.type', type))
|
||||||
|
|
||||||
|
const baseQueryParams = {
|
||||||
|
chainIds,
|
||||||
|
filters,
|
||||||
|
sortOptions: {
|
||||||
|
sortBy: SortTermOptions.Created,
|
||||||
|
sortDirection: SortDirectionOptions.Descending
|
||||||
|
},
|
||||||
|
aggs: {
|
||||||
|
topPublishers: {
|
||||||
|
terms: {
|
||||||
|
field: 'nft.owner.keyword',
|
||||||
|
order: { totalSales: 'desc' }
|
||||||
|
},
|
||||||
|
aggs: {
|
||||||
|
totalSales: {
|
||||||
|
sum: {
|
||||||
|
field: SortTermOptions.Stats
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
esPaginationOptions: {
|
||||||
|
from: (Number(page) - 1 || 0) * 9,
|
||||||
|
size: 9
|
||||||
|
}
|
||||||
|
} as BaseQueryParams
|
||||||
|
|
||||||
|
const query = generateBaseQuery(baseQueryParams)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const result = await queryMetadata(query, cancelToken)
|
const result = await queryMetadata(query, cancelToken)
|
||||||
return result
|
return result
|
||||||
|
@ -26,6 +26,7 @@ import { AssetSelectionAsset } from '@shared/FormFields/AssetSelection'
|
|||||||
import { transformAssetToAssetSelection } from './assetConvertor'
|
import { transformAssetToAssetSelection } from './assetConvertor'
|
||||||
import { AssetExtended } from 'src/@types/AssetExtended'
|
import { AssetExtended } from 'src/@types/AssetExtended'
|
||||||
import { ComputeEditForm } from 'src/components/Asset/Edit/_types'
|
import { ComputeEditForm } from 'src/components/Asset/Edit/_types'
|
||||||
|
import { getFileDidInfo } from './provider'
|
||||||
|
|
||||||
const getComputeOrders = gql`
|
const getComputeOrders = gql`
|
||||||
query ComputeOrders($user: String!) {
|
query ComputeOrders($user: String!) {
|
||||||
@ -352,12 +353,18 @@ export async function createTrustedAlgorithmList(
|
|||||||
tag: selectedAlgorithm.metadata.algorithm.container.tag,
|
tag: selectedAlgorithm.metadata.algorithm.container.tag,
|
||||||
checksum: selectedAlgorithm.metadata.algorithm.container.checksum
|
checksum: selectedAlgorithm.metadata.algorithm.container.checksum
|
||||||
}
|
}
|
||||||
|
const filesChecksum = await getFileDidInfo(
|
||||||
|
selectedAlgorithm?.id,
|
||||||
|
selectedAlgorithm?.services?.[0].id,
|
||||||
|
selectedAlgorithm?.services?.[0]?.serviceEndpoint,
|
||||||
|
true
|
||||||
|
)
|
||||||
const trustedAlgorithm = {
|
const trustedAlgorithm = {
|
||||||
did: selectedAlgorithm.id,
|
did: selectedAlgorithm.id,
|
||||||
containerSectionChecksum: getHash(
|
containerSectionChecksum: getHash(
|
||||||
JSON.stringify(sanitizedAlgorithmContainer)
|
JSON.stringify(sanitizedAlgorithmContainer)
|
||||||
),
|
),
|
||||||
filesChecksum: getHash(selectedAlgorithm.services[0].files)
|
filesChecksum: filesChecksum?.[0]?.checksum
|
||||||
}
|
}
|
||||||
trustedAlgorithms.push(trustedAlgorithm)
|
trustedAlgorithms.push(trustedAlgorithm)
|
||||||
}
|
}
|
||||||
|
@ -67,13 +67,15 @@ export async function getEncryptedFiles(
|
|||||||
export async function getFileDidInfo(
|
export async function getFileDidInfo(
|
||||||
did: string,
|
did: string,
|
||||||
serviceId: string,
|
serviceId: string,
|
||||||
providerUrl: string
|
providerUrl: string,
|
||||||
|
withChecksum = false
|
||||||
): Promise<FileInfo[]> {
|
): Promise<FileInfo[]> {
|
||||||
try {
|
try {
|
||||||
const response = await ProviderInstance.checkDidFiles(
|
const response = await ProviderInstance.checkDidFiles(
|
||||||
did,
|
did,
|
||||||
serviceId as any, // TODO: why does ocean.js want a number here?
|
serviceId,
|
||||||
providerUrl
|
providerUrl,
|
||||||
|
withChecksum
|
||||||
)
|
)
|
||||||
return response
|
return response
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -18,7 +18,7 @@ import { OpcFeesQuery as OpcFeesData } from '../@types/subgraph/OpcFeesQuery'
|
|||||||
import { calcSingleOutGivenPoolIn } from './pool'
|
import { calcSingleOutGivenPoolIn } from './pool'
|
||||||
import Decimal from 'decimal.js'
|
import Decimal from 'decimal.js'
|
||||||
import { MAX_DECIMALS } from './constants'
|
import { MAX_DECIMALS } from './constants'
|
||||||
|
import { getPublishedAssets, getTopPublishers } from '@utils/aquarius'
|
||||||
export interface UserLiquidity {
|
export interface UserLiquidity {
|
||||||
price: string
|
price: string
|
||||||
oceanBalance: string
|
oceanBalance: string
|
||||||
@ -172,19 +172,11 @@ const UserSalesQuery = gql`
|
|||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
// TODO: figure out some way to get this
|
|
||||||
const TopSalesQuery = gql`
|
const TopSalesQuery = gql`
|
||||||
query TopSalesQuery {
|
query TopSalesQuery {
|
||||||
users(
|
users(first: 20, orderBy: totalSales, orderDirection: desc) {
|
||||||
first: 20
|
|
||||||
orderBy: sharesOwned
|
|
||||||
orderDirection: desc
|
|
||||||
where: { tokenBalancesOwned_not: "0" }
|
|
||||||
) {
|
|
||||||
id
|
id
|
||||||
tokenBalancesOwned {
|
totalSales
|
||||||
value
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
@ -419,20 +411,10 @@ export async function getUserSales(
|
|||||||
accountId: string,
|
accountId: string,
|
||||||
chainIds: number[]
|
chainIds: number[]
|
||||||
): Promise<number> {
|
): Promise<number> {
|
||||||
const variables = { user: accountId?.toLowerCase() }
|
|
||||||
try {
|
try {
|
||||||
const userSales = await fetchDataForMultipleChains(
|
const result = await getPublishedAssets(accountId, chainIds, null)
|
||||||
UserSalesQuery,
|
const { totalOrders } = result.aggregations
|
||||||
variables,
|
return totalOrders.value
|
||||||
chainIds
|
|
||||||
)
|
|
||||||
let salesSum = 0
|
|
||||||
for (let i = 0; i < userSales.length; i++) {
|
|
||||||
if (userSales[i].users.length > 0) {
|
|
||||||
salesSum += parseInt(userSales[i].users[0].totalSales)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return salesSum
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
LoggerInstance.error('Error getUserSales', error.message)
|
LoggerInstance.error('Error getUserSales', error.message)
|
||||||
}
|
}
|
||||||
@ -442,33 +424,19 @@ export async function getTopAssetsPublishers(
|
|||||||
chainIds: number[],
|
chainIds: number[],
|
||||||
nrItems = 9
|
nrItems = 9
|
||||||
): Promise<AccountTeaserVM[]> {
|
): Promise<AccountTeaserVM[]> {
|
||||||
const publisherSales: AccountTeaserVM[] = []
|
const publishers: AccountTeaserVM[] = []
|
||||||
|
|
||||||
for (const chain of chainIds) {
|
const result = await getTopPublishers(chainIds, null)
|
||||||
const queryContext = getQueryContext(Number(chain))
|
const { topPublishers } = result.aggregations
|
||||||
const fetchedUsers: OperationResult<UsersSalesList> = await fetchData(
|
|
||||||
TopSalesQuery,
|
for (let i = 0; i < topPublishers.buckets.length; i++) {
|
||||||
null,
|
publishers.push({
|
||||||
queryContext
|
address: topPublishers.buckets[i].key,
|
||||||
)
|
nrSales: parseInt(topPublishers.buckets[i].totalSales.value)
|
||||||
for (let i = 0; i < fetchedUsers.data.users.length; i++) {
|
})
|
||||||
const publishersIndex = publisherSales.findIndex(
|
|
||||||
(user) => fetchedUsers.data.users[i].id === user.address
|
|
||||||
)
|
|
||||||
if (publishersIndex === -1) {
|
|
||||||
const publisher: AccountTeaserVM = {
|
|
||||||
address: fetchedUsers.data.users[i].id,
|
|
||||||
nrSales: fetchedUsers.data.users[i].totalSales
|
|
||||||
}
|
|
||||||
publisherSales.push(publisher)
|
|
||||||
} else {
|
|
||||||
publisherSales[publishersIndex].nrSales +=
|
|
||||||
publisherSales[publishersIndex].nrSales
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
publisherSales.sort((a, b) => b.nrSales - a.nrSales)
|
publishers.sort((a, b) => b.nrSales - a.nrSales)
|
||||||
|
|
||||||
return publisherSales.slice(0, nrItems)
|
return publishers.slice(0, nrItems)
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import React, { ReactElement } from 'react'
|
import React, { ReactElement } from 'react'
|
||||||
import styles from './AssetList.module.css'
|
import styles from './index.module.css'
|
||||||
import classNames from 'classnames/bind'
|
import classNames from 'classnames/bind'
|
||||||
import Loader from '../atoms/Loader'
|
import Loader from '../atoms/Loader'
|
||||||
import { useUserPreferences } from '@context/UserPreferences'
|
import { useUserPreferences } from '@context/UserPreferences'
|
||||||
@ -29,7 +29,7 @@ export default function AccountList({
|
|||||||
const { chainIds } = useUserPreferences()
|
const { chainIds } = useUserPreferences()
|
||||||
|
|
||||||
const styleClasses = cx({
|
const styleClasses = cx({
|
||||||
assetList: true,
|
accountList: true,
|
||||||
[className]: className
|
[className]: className
|
||||||
})
|
})
|
||||||
|
|
||||||
|
24
src/components/@shared/AccountList/index.module.css
Normal file
24
src/components/@shared/AccountList/index.module.css
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
.accountList {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
gap: calc(var(--spacer) / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (min-width: 25rem) {
|
||||||
|
.accountList {
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr));
|
||||||
|
gap: var(--spacer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty {
|
||||||
|
color: var(--color-secondary);
|
||||||
|
font-size: var(--font-size-small);
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loaderWrap {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
@ -1,46 +1,39 @@
|
|||||||
.blockies {
|
.blockies {
|
||||||
aspect-ratio: 1/1;
|
aspect-ratio: 1/1;
|
||||||
width: 13%;
|
width: calc(var(--font-size-large) * 2) !important;
|
||||||
height: 13%;
|
height: calc(var(--font-size-large) * 2) !important;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
margin-right: calc(var(--spacer) / 4);
|
margin-right: calc(var(--spacer) / 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
.teaser {
|
.teaser {
|
||||||
max-width: 40rem;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.link {
|
|
||||||
composes: box from '../atoms/Box.module.css';
|
composes: box from '../atoms/Box.module.css';
|
||||||
padding: calc(var(--spacer) / 2) !important;
|
padding: calc(var(--spacer) / 3) calc(var(--spacer) / 2);
|
||||||
font-size: var(--font-size-mini);
|
|
||||||
height: 90%;
|
|
||||||
color: var(--color-secondary);
|
color: var(--color-secondary);
|
||||||
position: relative;
|
position: relative;
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.link span {
|
|
||||||
font-size: var(--font-size-large);
|
|
||||||
margin-right: calc(var(--spacer) / 3);
|
|
||||||
}
|
|
||||||
.name {
|
|
||||||
margin-bottom: 0;
|
|
||||||
font-size: var(--font-size-base) !important;
|
|
||||||
padding-top: calc(var(--spacer) / 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
.header {
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sales {
|
.place {
|
||||||
font-size: small;
|
font-size: var(--font-size-large);
|
||||||
margin-top: -5px !important;
|
margin-right: calc(var(--spacer) / 2);
|
||||||
margin-bottom: clac(var(--spacer) / 2);
|
}
|
||||||
|
|
||||||
|
.name {
|
||||||
|
margin-bottom: 0;
|
||||||
|
font-size: var(--font-size-base);
|
||||||
|
padding-top: calc(var(--spacer) / 5);
|
||||||
|
color: var(--font-color-text);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sales {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sales span {
|
||||||
|
font-weight: var(--font-weight-bold);
|
||||||
|
color: var(--font-color-text);
|
||||||
}
|
}
|
||||||
|
@ -33,34 +33,26 @@ export default function AccountTeaser({
|
|||||||
}, [accountTeaserVM, newCancelToken])
|
}, [accountTeaserVM, newCancelToken])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<article className={styles.teaser}>
|
|
||||||
<Link href={`/profile/${accountTeaserVM.address}`}>
|
<Link href={`/profile/${accountTeaserVM.address}`}>
|
||||||
<header className={styles.header}>
|
<a className={styles.teaser}>
|
||||||
{place && <span>{place}</span>}
|
{place && <span className={styles.place}>{place}</span>}
|
||||||
{profile?.image ? (
|
|
||||||
<img src={profile.image} className={styles.blockies} />
|
|
||||||
) : (
|
|
||||||
<Blockies
|
<Blockies
|
||||||
accountId={accountTeaserVM.address}
|
accountId={accountTeaserVM.address}
|
||||||
className={styles.blockies}
|
className={styles.blockies}
|
||||||
|
image={profile?.image}
|
||||||
/>
|
/>
|
||||||
)}
|
|
||||||
<div>
|
<div>
|
||||||
<Dotdotdot clamp={3}>
|
<Dotdotdot tagName="h4" clamp={2} className={styles.name}>
|
||||||
<h3 className={styles.name}>
|
|
||||||
{profile?.name
|
{profile?.name
|
||||||
? profile?.name
|
? profile?.name
|
||||||
: accountTruncate(accountTeaserVM.address)}
|
: accountTruncate(accountTeaserVM.address)}
|
||||||
</h3>
|
|
||||||
</Dotdotdot>
|
</Dotdotdot>
|
||||||
<p className={styles.sales}>
|
<p className={styles.sales}>
|
||||||
{`${accountTeaserVM.nrSales} ${
|
<span>{accountTeaserVM.nrSales}</span>
|
||||||
accountTeaserVM.nrSales === 1 ? 'sale' : 'sales'
|
{`${accountTeaserVM.nrSales === 1 ? ' sale' : ' sales'}`}
|
||||||
}`}
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</a>
|
||||||
</Link>
|
</Link>
|
||||||
</article>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -24,14 +24,16 @@ export default function AssetTeaser({
|
|||||||
const isCompute = Boolean(getServiceByName(asset, 'compute'))
|
const isCompute = Boolean(getServiceByName(asset, 'compute'))
|
||||||
const accessType = isCompute ? 'compute' : 'access'
|
const accessType = isCompute ? 'compute' : 'access'
|
||||||
const { owner } = asset.nft
|
const { owner } = asset.nft
|
||||||
|
const { orders } = asset.stats
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<article className={`${styles.teaser} ${styles[type]}`}>
|
<article className={`${styles.teaser} ${styles[type]}`}>
|
||||||
<Link href={`/asset/${asset.id}`}>
|
<Link href={`/asset/${asset.id}`}>
|
||||||
<a className={styles.link}>
|
<a className={styles.link}>
|
||||||
<header className={styles.header}>
|
<header className={styles.header}>
|
||||||
<div className={styles.symbol}>{datatokens[0]?.symbol}</div>
|
<div className={styles.symbol}>{datatokens[0]?.symbol}</div>
|
||||||
<Dotdotdot clamp={3}>
|
<Dotdotdot tagName="h1" clamp={3} className={styles.title}>
|
||||||
<h1 className={styles.title}>{name}</h1>
|
{name}
|
||||||
</Dotdotdot>
|
</Dotdotdot>
|
||||||
{!noPublisher && (
|
{!noPublisher && (
|
||||||
<Publisher account={owner} minimal className={styles.publisher} />
|
<Publisher account={owner} minimal className={styles.publisher} />
|
||||||
@ -42,6 +44,7 @@ export default function AssetTeaser({
|
|||||||
type={type}
|
type={type}
|
||||||
accessType={accessType}
|
accessType={accessType}
|
||||||
className={styles.typeDetails}
|
className={styles.typeDetails}
|
||||||
|
totalSales={orders}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className={styles.content}>
|
<div className={styles.content}>
|
||||||
|
@ -1,26 +1,22 @@
|
|||||||
import React, { ReactElement } from 'react'
|
import React, { ReactElement } from 'react'
|
||||||
import styles from './index.module.css'
|
import styles from './index.module.css'
|
||||||
import classNames from 'classnames/bind'
|
|
||||||
import Compute from '@images/compute.svg'
|
import Compute from '@images/compute.svg'
|
||||||
import Download from '@images/download.svg'
|
import Download from '@images/download.svg'
|
||||||
import Lock from '@images/lock.svg'
|
import Lock from '@images/lock.svg'
|
||||||
|
|
||||||
const cx = classNames.bind(styles)
|
|
||||||
|
|
||||||
export default function AssetType({
|
export default function AssetType({
|
||||||
type,
|
type,
|
||||||
accessType,
|
accessType,
|
||||||
className
|
className,
|
||||||
|
totalSales
|
||||||
}: {
|
}: {
|
||||||
type: string
|
type: string
|
||||||
accessType: string
|
accessType: string
|
||||||
className?: string
|
className?: string
|
||||||
|
totalSales?: number
|
||||||
}): ReactElement {
|
}): ReactElement {
|
||||||
const styleClasses = cx({
|
|
||||||
[className]: className
|
|
||||||
})
|
|
||||||
return (
|
return (
|
||||||
<div className={styleClasses}>
|
<div className={className || null}>
|
||||||
{accessType === 'access' ? (
|
{accessType === 'access' ? (
|
||||||
<Download role="img" aria-label="Download" className={styles.icon} />
|
<Download role="img" aria-label="Download" className={styles.icon} />
|
||||||
) : accessType === 'compute' && type === 'algorithm' ? (
|
) : accessType === 'compute' && type === 'algorithm' ? (
|
||||||
@ -32,6 +28,12 @@ export default function AssetType({
|
|||||||
<div className={styles.typeLabel}>
|
<div className={styles.typeLabel}>
|
||||||
{type === 'dataset' ? 'data set' : 'algorithm'}
|
{type === 'dataset' ? 'data set' : 'algorithm'}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{totalSales ? (
|
||||||
|
<div className={styles.typeLabel}>
|
||||||
|
{`${totalSales} ${totalSales === 1 ? 'sale' : 'sales'}`}
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -5,11 +5,13 @@ import styles from './index.module.css'
|
|||||||
export interface BlockiesProps {
|
export interface BlockiesProps {
|
||||||
accountId: string
|
accountId: string
|
||||||
className?: string
|
className?: string
|
||||||
|
image?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function Blockies({
|
export default function Blockies({
|
||||||
accountId,
|
accountId,
|
||||||
className
|
className,
|
||||||
|
image
|
||||||
}: BlockiesProps): ReactElement {
|
}: BlockiesProps): ReactElement {
|
||||||
if (!accountId) return null
|
if (!accountId) return null
|
||||||
|
|
||||||
@ -18,7 +20,7 @@ export default function Blockies({
|
|||||||
return (
|
return (
|
||||||
<img
|
<img
|
||||||
className={`${className || ''} ${styles.blockies} `}
|
className={`${className || ''} ${styles.blockies} `}
|
||||||
src={blockies}
|
src={image || blockies}
|
||||||
alt="Blockies"
|
alt="Blockies"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
/>
|
/>
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
margin-top: calc(var(--spacer) / 1.5);
|
margin-top: calc(var(--spacer) / 1.5);
|
||||||
padding: calc(var(--spacer) / 1.5);
|
padding: calc(var(--spacer) / 1.5);
|
||||||
background: var(--background-highlight);
|
background: var(--background-highlight);
|
||||||
margin-bottom: -2rem;
|
margin-bottom: -1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.actions [class*='rdt_Pagination'] {
|
.actions [class*='rdt_Pagination'] {
|
||||||
|
@ -1,6 +0,0 @@
|
|||||||
.buttonMax {
|
|
||||||
position: absolute;
|
|
||||||
font-size: var(--font-size-mini);
|
|
||||||
bottom: calc(var(--spacer) / 2.6);
|
|
||||||
right: calc(var(--spacer) * 2.5);
|
|
||||||
}
|
|
@ -1,114 +0,0 @@
|
|||||||
import React, { ReactElement, useEffect } from 'react'
|
|
||||||
import styles from './FormAdd.module.css'
|
|
||||||
import Input from '@shared/FormInput'
|
|
||||||
import Error from '@shared/FormInput/Error'
|
|
||||||
import { FormikContextType, useField, useFormikContext } from 'formik'
|
|
||||||
import Button from '@shared/atoms/Button'
|
|
||||||
import { FormAddLiquidity } from '.'
|
|
||||||
import UserLiquidity from '../../UserLiquidity'
|
|
||||||
import { useWeb3 } from '@context/Web3'
|
|
||||||
import { isValidNumber } from '@utils/numbers'
|
|
||||||
import Decimal from 'decimal.js'
|
|
||||||
import { useAsset } from '@context/Asset'
|
|
||||||
import { Pool } from '@oceanprotocol/lib'
|
|
||||||
import { usePool } from '@context/Pool'
|
|
||||||
|
|
||||||
export default function FormAdd({
|
|
||||||
amountMax,
|
|
||||||
setNewPoolTokens,
|
|
||||||
setNewPoolShare
|
|
||||||
}: {
|
|
||||||
amountMax: string
|
|
||||||
setNewPoolTokens: (value: string) => void
|
|
||||||
setNewPoolShare: (value: string) => void
|
|
||||||
}): ReactElement {
|
|
||||||
const { balance, web3 } = useWeb3()
|
|
||||||
const { isAssetNetwork } = useAsset()
|
|
||||||
const { poolData, poolInfo } = usePool()
|
|
||||||
|
|
||||||
// Connect with form
|
|
||||||
const {
|
|
||||||
setFieldValue,
|
|
||||||
values,
|
|
||||||
isSubmitting
|
|
||||||
}: FormikContextType<FormAddLiquidity> = useFormikContext()
|
|
||||||
const [field, meta] = useField('amount')
|
|
||||||
useEffect(() => {
|
|
||||||
async function calculatePoolShares() {
|
|
||||||
if (!web3 || !poolData?.id || !poolInfo?.totalPoolTokens) return
|
|
||||||
|
|
||||||
if (!values.amount || !poolInfo?.baseTokenAddress) {
|
|
||||||
setNewPoolTokens('0')
|
|
||||||
setNewPoolShare('0')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (Number(values.amount) > Number(amountMax)) return
|
|
||||||
|
|
||||||
const poolInstance = new Pool(web3)
|
|
||||||
|
|
||||||
const poolTokens = await poolInstance.calcPoolOutGivenSingleIn(
|
|
||||||
poolData.id,
|
|
||||||
poolInfo.baseTokenAddress,
|
|
||||||
values.amount.toString(),
|
|
||||||
18,
|
|
||||||
poolInfo.baseTokenDecimals
|
|
||||||
)
|
|
||||||
setNewPoolTokens(poolTokens)
|
|
||||||
const newPoolShareDecimal =
|
|
||||||
isValidNumber(poolTokens) && isValidNumber(poolInfo.totalPoolTokens)
|
|
||||||
? new Decimal(poolTokens)
|
|
||||||
.dividedBy(
|
|
||||||
new Decimal(poolInfo.totalPoolTokens).plus(
|
|
||||||
new Decimal(poolTokens)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.mul(100)
|
|
||||||
.toString()
|
|
||||||
: '0'
|
|
||||||
setNewPoolShare(newPoolShareDecimal)
|
|
||||||
}
|
|
||||||
calculatePoolShares()
|
|
||||||
}, [
|
|
||||||
poolInfo?.baseTokenAddress,
|
|
||||||
poolInfo?.baseTokenDecimals,
|
|
||||||
web3,
|
|
||||||
values.amount,
|
|
||||||
poolInfo?.totalPoolTokens,
|
|
||||||
amountMax,
|
|
||||||
poolData?.id,
|
|
||||||
setNewPoolTokens,
|
|
||||||
setNewPoolShare
|
|
||||||
])
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<UserLiquidity
|
|
||||||
amount={balance.ocean}
|
|
||||||
amountMax={amountMax}
|
|
||||||
symbol={poolInfo?.baseTokenSymbol}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Input
|
|
||||||
type="number"
|
|
||||||
min="0"
|
|
||||||
prefix={poolInfo?.baseTokenSymbol}
|
|
||||||
placeholder="0"
|
|
||||||
disabled={!isAssetNetwork || isSubmitting}
|
|
||||||
{...field}
|
|
||||||
additionalComponent={<Error meta={meta} />}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{Number(balance.ocean) > 0 && (
|
|
||||||
<Button
|
|
||||||
className={styles.buttonMax}
|
|
||||||
style="text"
|
|
||||||
size="small"
|
|
||||||
disabled={!web3 || isSubmitting}
|
|
||||||
onClick={() => setFieldValue('amount', amountMax)}
|
|
||||||
>
|
|
||||||
Use Max
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
.output {
|
|
||||||
padding-bottom: calc(var(--spacer) / 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
.output p {
|
|
||||||
font-weight: var(--font-weight-bold);
|
|
||||||
margin-bottom: calc(var(--spacer) / 8);
|
|
||||||
font-size: var(--font-size-small);
|
|
||||||
}
|
|
||||||
|
|
||||||
.help {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
@ -1,30 +0,0 @@
|
|||||||
import React, { ReactElement } from 'react'
|
|
||||||
import FormHelp from '@shared/FormInput/Help'
|
|
||||||
import Token from '../../../../@shared/Token'
|
|
||||||
import styles from './Output.module.css'
|
|
||||||
import content from '../../../../../../content/price.json'
|
|
||||||
import { usePool } from '@context/Pool'
|
|
||||||
|
|
||||||
export default function Output({
|
|
||||||
newPoolTokens,
|
|
||||||
newPoolShare
|
|
||||||
}: {
|
|
||||||
newPoolTokens: string
|
|
||||||
newPoolShare: string
|
|
||||||
}): ReactElement {
|
|
||||||
const { help, titleIn } = content.pool.add.output
|
|
||||||
const { poolInfo } = usePool()
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<FormHelp className={styles.help}>
|
|
||||||
{help.replace('SWAPFEE', poolInfo?.liquidityProviderSwapFee)}
|
|
||||||
</FormHelp>
|
|
||||||
<div className={styles.output}>
|
|
||||||
<p>{titleIn}</p>
|
|
||||||
<Token symbol="pool shares" balance={newPoolTokens} noIcon />
|
|
||||||
<Token symbol="% of pool" balance={newPoolShare} noIcon />
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
@ -1,24 +0,0 @@
|
|||||||
.addInput {
|
|
||||||
margin: 0 auto calc(var(--spacer) / 1.5) auto;
|
|
||||||
background: var(--background-highlight);
|
|
||||||
padding: var(--spacer) calc(var(--spacer) * 2.5) calc(var(--spacer) * 1.2)
|
|
||||||
calc(var(--spacer) * 2.5);
|
|
||||||
border-bottom: 1px solid var(--border-color);
|
|
||||||
margin-top: -2rem;
|
|
||||||
margin-left: -2rem;
|
|
||||||
margin-right: -2rem;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.addInput input {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.addInput div[class*='field'] {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.warning {
|
|
||||||
margin-left: -3rem;
|
|
||||||
margin-right: -3rem;
|
|
||||||
}
|
|
@ -1,174 +0,0 @@
|
|||||||
import React, { ReactElement, useState, useEffect } from 'react'
|
|
||||||
import Header from '../Actions/Header'
|
|
||||||
import { toast } from 'react-toastify'
|
|
||||||
import Actions from '../Actions'
|
|
||||||
import * as Yup from 'yup'
|
|
||||||
import { Formik } from 'formik'
|
|
||||||
import FormAdd from './FormAdd'
|
|
||||||
import styles from './index.module.css'
|
|
||||||
import Alert from '@shared/atoms/Alert'
|
|
||||||
import { useUserPreferences } from '@context/UserPreferences'
|
|
||||||
import Output from './Output'
|
|
||||||
import DebugOutput from '@shared/DebugOutput'
|
|
||||||
import { useWeb3 } from '@context/Web3'
|
|
||||||
import { useAsset } from '@context/Asset'
|
|
||||||
import content from '../../../../../../content/price.json'
|
|
||||||
import { calcMaxExactIn, LoggerInstance, Pool } from '@oceanprotocol/lib'
|
|
||||||
import { usePool } from '@context/Pool'
|
|
||||||
import { MAX_DECIMALS } from '@utils/constants'
|
|
||||||
import { getMaxDecimalsValidation } from '@utils/numbers'
|
|
||||||
import Decimal from 'decimal.js'
|
|
||||||
|
|
||||||
export interface FormAddLiquidity {
|
|
||||||
amount: number
|
|
||||||
}
|
|
||||||
|
|
||||||
const initialValues: FormAddLiquidity = {
|
|
||||||
amount: 0
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function Add({
|
|
||||||
setShowAdd
|
|
||||||
}: {
|
|
||||||
setShowAdd: (show: boolean) => void
|
|
||||||
}): ReactElement {
|
|
||||||
const { accountId, balance, web3 } = useWeb3()
|
|
||||||
const { isAssetNetwork } = useAsset()
|
|
||||||
const { poolData, poolInfo, fetchAllData } = usePool()
|
|
||||||
const { debug } = useUserPreferences()
|
|
||||||
|
|
||||||
const [txId, setTxId] = useState<string>()
|
|
||||||
const [amountMax, setAmountMax] = useState<string>()
|
|
||||||
const [newPoolTokens, setNewPoolTokens] = useState('0')
|
|
||||||
const [newPoolShare, setNewPoolShare] = useState('0')
|
|
||||||
|
|
||||||
// Live validation rules
|
|
||||||
// https://github.com/jquense/yup#number
|
|
||||||
const validationSchema: Yup.SchemaOf<FormAddLiquidity> = Yup.object().shape({
|
|
||||||
amount: Yup.number()
|
|
||||||
.min(0.00001, (param) => `Must be more or equal to ${param.min}`)
|
|
||||||
.max(
|
|
||||||
Number(amountMax),
|
|
||||||
`Maximum you can add is ${Number(amountMax).toFixed(2)} OCEAN`
|
|
||||||
)
|
|
||||||
.test(
|
|
||||||
'maxDigitsAfterDecimal',
|
|
||||||
`Must have maximum ${MAX_DECIMALS} decimal digits`,
|
|
||||||
(param) =>
|
|
||||||
getMaxDecimalsValidation(MAX_DECIMALS).test(param?.toString())
|
|
||||||
)
|
|
||||||
.required('Required')
|
|
||||||
})
|
|
||||||
|
|
||||||
// Get maximum amount for OCEAN
|
|
||||||
useEffect(() => {
|
|
||||||
if (
|
|
||||||
!web3 ||
|
|
||||||
!accountId ||
|
|
||||||
!isAssetNetwork ||
|
|
||||||
!poolData?.id ||
|
|
||||||
!poolInfo?.baseTokenAddress
|
|
||||||
)
|
|
||||||
return
|
|
||||||
|
|
||||||
async function getMaximum() {
|
|
||||||
try {
|
|
||||||
const poolInstance = new Pool(web3)
|
|
||||||
|
|
||||||
const poolReserve = await poolInstance.getReserve(
|
|
||||||
poolData.id,
|
|
||||||
poolInfo.baseTokenAddress,
|
|
||||||
poolInfo.baseTokenDecimals
|
|
||||||
)
|
|
||||||
|
|
||||||
const amountMaxPool = calcMaxExactIn(poolReserve)
|
|
||||||
const oceanDecimal = new Decimal(balance.ocean)
|
|
||||||
const amountMax = oceanDecimal.greaterThan(amountMaxPool)
|
|
||||||
? amountMaxPool
|
|
||||||
: oceanDecimal
|
|
||||||
setAmountMax(amountMax.toFixed(3, Decimal.ROUND_DOWN))
|
|
||||||
} catch (error) {
|
|
||||||
LoggerInstance.error(error.message)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
getMaximum()
|
|
||||||
}, [
|
|
||||||
web3,
|
|
||||||
accountId,
|
|
||||||
isAssetNetwork,
|
|
||||||
poolData?.id,
|
|
||||||
poolInfo?.baseTokenAddress,
|
|
||||||
poolInfo?.baseTokenDecimals,
|
|
||||||
balance?.ocean
|
|
||||||
])
|
|
||||||
|
|
||||||
// Submit
|
|
||||||
async function handleAddLiquidity(amount: string, resetForm: () => void) {
|
|
||||||
const poolInstance = new Pool(web3)
|
|
||||||
const minPoolAmountOut = '0' // ? how to get? : you would get this value by using `calcPoolOutGivenSingleIn` and substracting slippage from that , like we don in trade. it is ok to be 0 here. We can change after we implement global slippage
|
|
||||||
|
|
||||||
try {
|
|
||||||
const result = await poolInstance.joinswapExternAmountIn(
|
|
||||||
accountId,
|
|
||||||
poolData?.id,
|
|
||||||
amount,
|
|
||||||
minPoolAmountOut
|
|
||||||
)
|
|
||||||
setTxId(result?.transactionHash)
|
|
||||||
fetchAllData()
|
|
||||||
resetForm()
|
|
||||||
} catch (error) {
|
|
||||||
LoggerInstance.error(error.message)
|
|
||||||
toast.error(error.message)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Header
|
|
||||||
title={content.pool.add.title}
|
|
||||||
backAction={() => {
|
|
||||||
setShowAdd(false)
|
|
||||||
fetchAllData()
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<Formik
|
|
||||||
initialValues={initialValues}
|
|
||||||
validationSchema={validationSchema}
|
|
||||||
onSubmit={async (values, { setSubmitting, resetForm }) => {
|
|
||||||
await handleAddLiquidity(values.amount.toString(), resetForm)
|
|
||||||
setSubmitting(false)
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{({ isSubmitting, setSubmitting, submitForm, values, isValid }) => (
|
|
||||||
<>
|
|
||||||
<div className={styles.addInput}>
|
|
||||||
<FormAdd
|
|
||||||
amountMax={amountMax}
|
|
||||||
setNewPoolTokens={setNewPoolTokens}
|
|
||||||
setNewPoolShare={setNewPoolShare}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* TODO: will be fixed in #1481 <Output newPoolTokens={newPoolTokens} newPoolShare={newPoolShare} /> */}
|
|
||||||
|
|
||||||
<Actions
|
|
||||||
isDisabled={!isValid || !values.amount || values.amount === 0}
|
|
||||||
isLoading={isSubmitting}
|
|
||||||
loaderMessage="Adding Liquidity..."
|
|
||||||
successMessage="Successfully added liquidity."
|
|
||||||
actionName={content.pool.add.action}
|
|
||||||
action={submitForm}
|
|
||||||
amount={values.amount.toString()}
|
|
||||||
tokenAddress={poolInfo?.baseTokenAddress}
|
|
||||||
tokenSymbol={poolInfo?.baseTokenSymbol}
|
|
||||||
txId={txId}
|
|
||||||
setSubmitting={setSubmitting}
|
|
||||||
/>
|
|
||||||
{debug && <DebugOutput output={values} />}
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</Formik>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
@ -1,5 +1,12 @@
|
|||||||
.removeInput {
|
.removeInput {
|
||||||
composes: addInput from '../Add/index.module.css';
|
background: var(--background-highlight);
|
||||||
|
padding: var(--spacer) calc(var(--spacer) * 2.5) calc(var(--spacer) * 1.2)
|
||||||
|
calc(var(--spacer) * 2.5);
|
||||||
|
border-bottom: 1px solid var(--border-color);
|
||||||
|
margin-top: -2rem;
|
||||||
|
margin-left: -2rem;
|
||||||
|
margin-right: -2rem;
|
||||||
|
position: relative;
|
||||||
padding-left: calc(var(--spacer) * 2);
|
padding-left: calc(var(--spacer) * 2);
|
||||||
padding-right: calc(var(--spacer) * 2);
|
padding-right: calc(var(--spacer) * 2);
|
||||||
padding-bottom: calc(var(--spacer) / 2);
|
padding-bottom: calc(var(--spacer) / 2);
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import React, { ReactElement, useState } from 'react'
|
import React, { ReactElement, useState } from 'react'
|
||||||
import stylesActions from './Actions/index.module.css'
|
import stylesActions from './Actions/index.module.css'
|
||||||
import Button from '@shared/atoms/Button'
|
import Button from '@shared/atoms/Button'
|
||||||
import Add from './Add'
|
|
||||||
import Remove from './Remove'
|
import Remove from './Remove'
|
||||||
import AssetActionHistoryTable from '../AssetActionHistoryTable'
|
import AssetActionHistoryTable from '../AssetActionHistoryTable'
|
||||||
import { useAsset } from '@context/Asset'
|
import { useAsset } from '@context/Asset'
|
||||||
@ -12,43 +11,33 @@ import { usePool } from '@context/Pool'
|
|||||||
import PoolSections from './Sections'
|
import PoolSections from './Sections'
|
||||||
|
|
||||||
export default function Pool(): ReactElement {
|
export default function Pool(): ReactElement {
|
||||||
const { isInPurgatory, asset, isAssetNetwork } = useAsset()
|
const { asset, isAssetNetwork } = useAsset()
|
||||||
const { hasUserAddedLiquidity } = usePool()
|
const { hasUserAddedLiquidity } = usePool()
|
||||||
const { accountId } = useWeb3()
|
const { accountId } = useWeb3()
|
||||||
|
|
||||||
const [showAdd, setShowAdd] = useState(false)
|
|
||||||
const [showRemove, setShowRemove] = useState(false)
|
const [showRemove, setShowRemove] = useState(false)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{showAdd ? (
|
{showRemove ? (
|
||||||
<Add setShowAdd={setShowAdd} />
|
|
||||||
) : showRemove ? (
|
|
||||||
<Remove setShowRemove={setShowRemove} />
|
<Remove setShowRemove={setShowRemove} />
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<PoolSections />
|
<PoolSections />
|
||||||
|
|
||||||
|
{hasUserAddedLiquidity && (
|
||||||
<div className={stylesActions.actions}>
|
<div className={stylesActions.actions}>
|
||||||
<Button
|
<Button
|
||||||
style="primary"
|
style="primary"
|
||||||
size="small"
|
|
||||||
onClick={() => setShowAdd(true)}
|
|
||||||
disabled={isInPurgatory || !isAssetNetwork}
|
|
||||||
>
|
|
||||||
Add Liquidity
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
{hasUserAddedLiquidity && (
|
|
||||||
<Button
|
|
||||||
size="small"
|
size="small"
|
||||||
onClick={() => setShowRemove(true)}
|
onClick={() => setShowRemove(true)}
|
||||||
disabled={!isAssetNetwork}
|
disabled={!isAssetNetwork}
|
||||||
>
|
>
|
||||||
Remove
|
Remove Liquidity
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
{accountId && (
|
{accountId && (
|
||||||
<AssetActionHistoryTable title="Your Pool Transactions">
|
<AssetActionHistoryTable title="Your Pool Transactions">
|
||||||
<PoolTransactions
|
<PoolTransactions
|
||||||
|
@ -137,10 +137,7 @@ export default function AssetActions({
|
|||||||
const tabs: TabsItem[] = [{ title: 'Use', content: UseContent }]
|
const tabs: TabsItem[] = [{ title: 'Use', content: UseContent }]
|
||||||
|
|
||||||
asset?.accessDetails?.type === 'dynamic' &&
|
asset?.accessDetails?.type === 'dynamic' &&
|
||||||
tabs.push(
|
tabs.push({ title: 'Pool', content: <Pool /> })
|
||||||
{ title: 'Pool', content: <Pool /> },
|
|
||||||
{ title: 'Trade', content: <Trade /> }
|
|
||||||
)
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
@ -51,7 +51,7 @@ export default function Edit({
|
|||||||
const setPriceResp = await fixedRateInstance.setRate(
|
const setPriceResp = await fixedRateInstance.setRate(
|
||||||
accountId,
|
accountId,
|
||||||
asset.accessDetails.addressOrId,
|
asset.accessDetails.addressOrId,
|
||||||
newPrice
|
newPrice.toString()
|
||||||
)
|
)
|
||||||
LoggerInstance.log('[edit] setFixedRate result', setPriceResp)
|
LoggerInstance.log('[edit] setFixedRate result', setPriceResp)
|
||||||
if (!setPriceResp) {
|
if (!setPriceResp) {
|
||||||
|
@ -1,26 +0,0 @@
|
|||||||
.tooltipStats {
|
|
||||||
margin-bottom: calc(var(--spacer) / 3);
|
|
||||||
padding-bottom: calc(var(--spacer) / 3);
|
|
||||||
border-bottom: 1px solid var(--border-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.statsList {
|
|
||||||
composes: statsList from './index.module.css';
|
|
||||||
padding-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.statsList,
|
|
||||||
.note {
|
|
||||||
padding: calc(var(--spacer) / 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
.note {
|
|
||||||
margin-bottom: 0;
|
|
||||||
padding-top: 0;
|
|
||||||
font-size: var(--font-size-mini);
|
|
||||||
color: var(--color-secondary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.network {
|
|
||||||
font-weight: var(--font-weight-bold);
|
|
||||||
}
|
|
@ -1,47 +0,0 @@
|
|||||||
import React, { ReactElement } from 'react'
|
|
||||||
import Conversion from '@shared/Price/Conversion'
|
|
||||||
import PriceUnit from '@shared/Price/PriceUnit'
|
|
||||||
import NetworkName from '@shared/NetworkName'
|
|
||||||
import styles from './Tooltip.module.css'
|
|
||||||
import { StatsValue } from './_types'
|
|
||||||
import content from '../../../../content/footer.json'
|
|
||||||
import Markdown from '@shared/Markdown'
|
|
||||||
|
|
||||||
export default function MarketStatsTooltip({
|
|
||||||
totalValueLockedInOcean,
|
|
||||||
poolCount,
|
|
||||||
totalOceanLiquidity,
|
|
||||||
mainChainIds
|
|
||||||
}: {
|
|
||||||
totalValueLockedInOcean: StatsValue
|
|
||||||
poolCount: StatsValue
|
|
||||||
totalOceanLiquidity: StatsValue
|
|
||||||
mainChainIds: number[]
|
|
||||||
}): ReactElement {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<ul className={styles.statsList}>
|
|
||||||
{mainChainIds?.map((chainId, key) => (
|
|
||||||
<li className={styles.tooltipStats} key={key}>
|
|
||||||
<NetworkName networkId={chainId} className={styles.network} />
|
|
||||||
<br />
|
|
||||||
<Conversion
|
|
||||||
price={totalValueLockedInOcean?.[chainId] || '0'}
|
|
||||||
hideApproximateSymbol
|
|
||||||
/>{' '}
|
|
||||||
<abbr title="Total Value Locked">TVL</abbr>
|
|
||||||
{' | '}
|
|
||||||
<strong>{poolCount?.[chainId] || '0'}</strong> pools
|
|
||||||
{' | '}
|
|
||||||
<PriceUnit
|
|
||||||
price={totalOceanLiquidity?.[chainId] || '0'}
|
|
||||||
symbol="OCEAN"
|
|
||||||
size="small"
|
|
||||||
/>
|
|
||||||
</li>
|
|
||||||
))}
|
|
||||||
</ul>
|
|
||||||
<Markdown className={styles.note} text={content.stats.note} />
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
@ -1,6 +1,4 @@
|
|||||||
import React, { ReactElement } from 'react'
|
import React, { ReactElement } from 'react'
|
||||||
import Conversion from '@shared/Price/Conversion'
|
|
||||||
import PriceUnit from '@shared/Price/PriceUnit'
|
|
||||||
import { StatsTotal } from './_types'
|
import { StatsTotal } from './_types'
|
||||||
|
|
||||||
export default function MarketStatsTotal({
|
export default function MarketStatsTotal({
|
||||||
@ -10,23 +8,9 @@ export default function MarketStatsTotal({
|
|||||||
}): ReactElement {
|
}): ReactElement {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<p>
|
|
||||||
<strong>{total.orders}</strong> orders across{' '}
|
<strong>{total.orders}</strong> orders across{' '}
|
||||||
<strong>{total.nfts}</strong> assets with{' '}
|
<strong>{total.nfts}</strong> assets with{' '}
|
||||||
<strong>{total.datatokens}</strong> different datatokens.
|
<strong>{total.datatokens}</strong> different datatokens.
|
||||||
</p>
|
|
||||||
<Conversion
|
|
||||||
price={`${total.totalValueLockedInOcean}`}
|
|
||||||
hideApproximateSymbol
|
|
||||||
/>{' '}
|
|
||||||
<abbr title="Total Value Locked">TVL</abbr> across{' '}
|
|
||||||
<strong>{total.pools}</strong> asset pools that contain{' '}
|
|
||||||
<PriceUnit
|
|
||||||
price={`${total.totalOceanLiquidity}`}
|
|
||||||
symbol="OCEAN"
|
|
||||||
size="small"
|
|
||||||
/>
|
|
||||||
, plus datatokens for each pool.
|
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -3,18 +3,9 @@ import { gql } from 'urql'
|
|||||||
export const queryGlobalStatistics = gql`
|
export const queryGlobalStatistics = gql`
|
||||||
query FooterStatsValues {
|
query FooterStatsValues {
|
||||||
globalStatistics {
|
globalStatistics {
|
||||||
poolCount
|
|
||||||
nftCount
|
nftCount
|
||||||
datatokenCount
|
datatokenCount
|
||||||
orderCount
|
orderCount
|
||||||
totalLiquidity {
|
|
||||||
value
|
|
||||||
token {
|
|
||||||
address
|
|
||||||
name
|
|
||||||
symbol
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
@ -3,9 +3,6 @@ export interface StatsValue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface StatsTotal {
|
export interface StatsTotal {
|
||||||
totalValueLockedInOcean: number
|
|
||||||
totalOceanLiquidity: number
|
|
||||||
pools: number
|
|
||||||
nfts: number
|
nfts: number
|
||||||
datatokens: number
|
datatokens: number
|
||||||
orders: number
|
orders: number
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import React, { ReactElement, useCallback, useEffect, useState } from 'react'
|
import React, { ReactElement, useCallback, useEffect, useState } from 'react'
|
||||||
import { OperationContext } from 'urql'
|
import { OperationContext } from 'urql'
|
||||||
import Tooltip from '@shared/atoms/Tooltip'
|
|
||||||
import { fetchData, getSubgraphUri } from '@utils/subgraph'
|
import { fetchData, getSubgraphUri } from '@utils/subgraph'
|
||||||
import useNetworkMetadata, {
|
import useNetworkMetadata, {
|
||||||
filterNetworksByType
|
filterNetworksByType
|
||||||
@ -8,19 +7,15 @@ import useNetworkMetadata, {
|
|||||||
import { LoggerInstance } from '@oceanprotocol/lib'
|
import { LoggerInstance } from '@oceanprotocol/lib'
|
||||||
import styles from './index.module.css'
|
import styles from './index.module.css'
|
||||||
import { FooterStatsValues_globalStatistics as FooterStatsValuesGlobalStatistics } from 'src/@types/subgraph/FooterStatsValues'
|
import { FooterStatsValues_globalStatistics as FooterStatsValuesGlobalStatistics } from 'src/@types/subgraph/FooterStatsValues'
|
||||||
import MarketStatsTooltip from './Tooltip'
|
|
||||||
import MarketStatsTotal from './Total'
|
import MarketStatsTotal from './Total'
|
||||||
import { queryGlobalStatistics } from './_queries'
|
import { queryGlobalStatistics } from './_queries'
|
||||||
import { usePrices } from '@context/Prices'
|
import { StatsTotal } from './_types'
|
||||||
import { useUserPreferences } from '@context/UserPreferences'
|
|
||||||
import Decimal from 'decimal.js'
|
|
||||||
import { StatsTotal, StatsValue } from './_types'
|
|
||||||
import { useMarketMetadata } from '@context/MarketMetadata'
|
import { useMarketMetadata } from '@context/MarketMetadata'
|
||||||
|
import Tooltip from '@shared/atoms/Tooltip'
|
||||||
|
import Markdown from '@shared/Markdown'
|
||||||
|
import content from '../../../../content/footer.json'
|
||||||
|
|
||||||
const initialTotal: StatsTotal = {
|
const initialTotal: StatsTotal = {
|
||||||
totalValueLockedInOcean: 0,
|
|
||||||
totalOceanLiquidity: 0,
|
|
||||||
pools: 0,
|
|
||||||
nfts: 0,
|
nfts: 0,
|
||||||
datatokens: 0,
|
datatokens: 0,
|
||||||
orders: 0
|
orders: 0
|
||||||
@ -29,17 +24,10 @@ const initialTotal: StatsTotal = {
|
|||||||
export default function MarketStats(): ReactElement {
|
export default function MarketStats(): ReactElement {
|
||||||
const { appConfig } = useMarketMetadata()
|
const { appConfig } = useMarketMetadata()
|
||||||
const { networksList } = useNetworkMetadata()
|
const { networksList } = useNetworkMetadata()
|
||||||
const { currency } = useUserPreferences()
|
|
||||||
const { prices } = usePrices()
|
|
||||||
|
|
||||||
const [mainChainIds, setMainChainIds] = useState<number[]>()
|
const [mainChainIds, setMainChainIds] = useState<number[]>()
|
||||||
const [data, setData] = useState<{
|
const [data, setData] = useState<{
|
||||||
[chainId: number]: FooterStatsValuesGlobalStatistics
|
[chainId: number]: FooterStatsValuesGlobalStatistics
|
||||||
}>()
|
}>()
|
||||||
const [totalValueLockedInOcean, setTotalValueLockedInOcean] =
|
|
||||||
useState<StatsValue>()
|
|
||||||
const [totalOceanLiquidity, setTotalOceanLiquidity] = useState<StatsValue>()
|
|
||||||
const [poolCount, setPoolCount] = useState<StatsValue>()
|
|
||||||
const [total, setTotal] = useState(initialTotal)
|
const [total, setTotal] = useState(initialTotal)
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -98,34 +86,13 @@ export default function MarketStats(): ReactElement {
|
|||||||
const newTotal: StatsTotal = {
|
const newTotal: StatsTotal = {
|
||||||
...initialTotal // always start calculating beginning from initial 0 values
|
...initialTotal // always start calculating beginning from initial 0 values
|
||||||
}
|
}
|
||||||
const newTVLInOcean: StatsValue = {}
|
|
||||||
const newTotalLiquidity: StatsValue = {}
|
|
||||||
const newPoolCount: StatsValue = {}
|
|
||||||
|
|
||||||
for (const chainId of mainChainIds) {
|
for (const chainId of mainChainIds) {
|
||||||
const baseTokenValue = data[chainId]?.totalLiquidity[0]?.value
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const totalValueLockedInOcean = baseTokenValue
|
|
||||||
? new Decimal(baseTokenValue).mul(2)
|
|
||||||
: new Decimal(0)
|
|
||||||
|
|
||||||
newTVLInOcean[chainId] = `${totalValueLockedInOcean}`
|
|
||||||
|
|
||||||
const totalOceanLiquidity = Number(baseTokenValue) || 0
|
|
||||||
|
|
||||||
newTotalLiquidity[chainId] = `${totalOceanLiquidity}`
|
|
||||||
|
|
||||||
const poolCount = data[chainId]?.poolCount || 0
|
|
||||||
|
|
||||||
newPoolCount[chainId] = `${poolCount}`
|
|
||||||
const nftCount = data[chainId]?.nftCount || 0
|
const nftCount = data[chainId]?.nftCount || 0
|
||||||
const datatokenCount = data[chainId]?.datatokenCount || 0
|
const datatokenCount = data[chainId]?.datatokenCount || 0
|
||||||
const orderCount = data[chainId]?.orderCount || 0
|
const orderCount = data[chainId]?.orderCount || 0
|
||||||
|
|
||||||
newTotal.totalValueLockedInOcean += totalValueLockedInOcean.toNumber()
|
|
||||||
newTotal.totalOceanLiquidity += totalOceanLiquidity
|
|
||||||
newTotal.pools += poolCount
|
|
||||||
newTotal.nfts += nftCount
|
newTotal.nfts += nftCount
|
||||||
newTotal.datatokens += datatokenCount
|
newTotal.datatokens += datatokenCount
|
||||||
newTotal.orders += orderCount
|
newTotal.orders += orderCount
|
||||||
@ -133,11 +100,9 @@ export default function MarketStats(): ReactElement {
|
|||||||
LoggerInstance.error('Error data manipulation: ', error.message)
|
LoggerInstance.error('Error data manipulation: ', error.message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setTotalValueLockedInOcean(newTVLInOcean)
|
|
||||||
setTotalOceanLiquidity(newTotalLiquidity)
|
|
||||||
setPoolCount(newPoolCount)
|
|
||||||
setTotal(newTotal)
|
setTotal(newTotal)
|
||||||
}, [data, mainChainIds, prices, currency])
|
}, [data, mainChainIds])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.stats}>
|
<div className={styles.stats}>
|
||||||
@ -146,12 +111,7 @@ export default function MarketStats(): ReactElement {
|
|||||||
<Tooltip
|
<Tooltip
|
||||||
className={styles.info}
|
className={styles.info}
|
||||||
content={
|
content={
|
||||||
<MarketStatsTooltip
|
<Markdown className={styles.note} text={content.stats.note} />
|
||||||
totalValueLockedInOcean={totalValueLockedInOcean}
|
|
||||||
poolCount={poolCount}
|
|
||||||
totalOceanLiquidity={totalOceanLiquidity}
|
|
||||||
mainChainIds={mainChainIds}
|
|
||||||
/>
|
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
import { useUserPreferences } from '@context/UserPreferences'
|
import { useUserPreferences } from '@context/UserPreferences'
|
||||||
|
import { LoggerInstance } from '@oceanprotocol/lib'
|
||||||
import AccountList from '@shared/AccountList/AccountList'
|
import AccountList from '@shared/AccountList/AccountList'
|
||||||
import { getTopAssetsPublishers } from '@utils/subgraph'
|
import { getTopAssetsPublishers } from '@utils/subgraph'
|
||||||
import React, { ReactElement, useEffect, useState } from 'react'
|
import React, { ReactElement, useEffect, useState } from 'react'
|
||||||
import styles from './Home.module.css'
|
import styles from './index.module.css'
|
||||||
|
|
||||||
export default function PublishersWithMostSales({
|
export default function PublishersWithMostSales({
|
||||||
title,
|
title,
|
||||||
@ -17,18 +18,19 @@ export default function PublishersWithMostSales({
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
async function init() {
|
async function init() {
|
||||||
|
setLoading(true)
|
||||||
if (chainIds.length === 0) {
|
if (chainIds.length === 0) {
|
||||||
const result: AccountTeaserVM[] = []
|
const result: AccountTeaserVM[] = []
|
||||||
setResult(result)
|
setResult(result)
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
setLoading(true)
|
|
||||||
const publishers = await getTopAssetsPublishers(chainIds)
|
const publishers = await getTopAssetsPublishers(chainIds)
|
||||||
setResult(publishers)
|
setResult(publishers)
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// Logger.error(error.message)
|
LoggerInstance.error(error.message)
|
||||||
|
setLoading(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@ import styles from './index.module.css'
|
|||||||
import { useIsMounted } from '@hooks/useIsMounted'
|
import { useIsMounted } from '@hooks/useIsMounted'
|
||||||
import { useCancelToken } from '@hooks/useCancelToken'
|
import { useCancelToken } from '@hooks/useCancelToken'
|
||||||
import { SortTermOptions } from '../../@types/aquarius/SearchQuery'
|
import { SortTermOptions } from '../../@types/aquarius/SearchQuery'
|
||||||
|
import PublishersWithMostSales from './PublishersWithMostSales'
|
||||||
|
|
||||||
async function getQueryHighest(
|
async function getQueryHighest(
|
||||||
chainIds: number[]
|
chainIds: number[]
|
||||||
@ -66,7 +67,8 @@ function SectionQueryResult({
|
|||||||
results: [],
|
results: [],
|
||||||
page: 0,
|
page: 0,
|
||||||
totalPages: 0,
|
totalPages: 0,
|
||||||
totalResults: 0
|
totalResults: 0,
|
||||||
|
aggregations: undefined
|
||||||
}
|
}
|
||||||
setResult(result)
|
setResult(result)
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
@ -153,6 +155,8 @@ export default function HomePage(): ReactElement {
|
|||||||
</Button>
|
</Button>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<PublishersWithMostSales title="Publishers With Most Sales" />
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ export default function PricingFields(): ReactElement {
|
|||||||
// Connect with main publish form
|
// Connect with main publish form
|
||||||
const { values, setFieldValue } = useFormikContext<FormPublishData>()
|
const { values, setFieldValue } = useFormikContext<FormPublishData>()
|
||||||
const { pricing } = values
|
const { pricing } = values
|
||||||
const { price, amountOcean, weightOnOcean, weightOnDataToken, type } = pricing
|
const { price, type } = pricing
|
||||||
|
|
||||||
// Switch type value upon tab change
|
// Switch type value upon tab change
|
||||||
function handleTabChange(tabName: string) {
|
function handleTabChange(tabName: string) {
|
||||||
@ -29,36 +29,11 @@ export default function PricingFields(): ReactElement {
|
|||||||
type !== 'free' && setFieldValue('pricing.amountDataToken', 1000)
|
type !== 'free' && setFieldValue('pricing.amountDataToken', 1000)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update ocean amount when price is changed
|
// Update price when price is changed
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (type === 'fixed' || type === 'free') return
|
setFieldValue('pricing.price', price)
|
||||||
|
setFieldValue('pricing.type', type)
|
||||||
const amountOcean =
|
}, [price, setFieldValue, type])
|
||||||
isValidNumber(weightOnOcean) && isValidNumber(price) && price > 0
|
|
||||||
? new Decimal(price).mul(new Decimal(weightOnOcean).mul(10)).mul(2)
|
|
||||||
: new Decimal(initialValues.pricing.amountOcean)
|
|
||||||
|
|
||||||
setFieldValue('pricing.amountOcean', amountOcean)
|
|
||||||
}, [price, weightOnOcean, type, setFieldValue])
|
|
||||||
|
|
||||||
// Update dataToken value when ocean amount is changed
|
|
||||||
useEffect(() => {
|
|
||||||
if (type === 'fixed' || type === 'free') return
|
|
||||||
|
|
||||||
const amountDataToken =
|
|
||||||
isValidNumber(amountOcean) &&
|
|
||||||
isValidNumber(weightOnOcean) &&
|
|
||||||
isValidNumber(price) &&
|
|
||||||
isValidNumber(weightOnDataToken) &&
|
|
||||||
price > 0
|
|
||||||
? new Decimal(amountOcean)
|
|
||||||
.dividedBy(new Decimal(weightOnOcean))
|
|
||||||
.dividedBy(new Decimal(price))
|
|
||||||
.mul(new Decimal(weightOnDataToken))
|
|
||||||
: new Decimal(initialValues.pricing.amountDataToken)
|
|
||||||
|
|
||||||
setFieldValue('pricing.amountDataToken', amountDataToken)
|
|
||||||
}, [amountOcean, weightOnOcean, weightOnDataToken, type, setFieldValue])
|
|
||||||
|
|
||||||
const tabs = [
|
const tabs = [
|
||||||
appConfig.allowFixedPricing === 'true'
|
appConfig.allowFixedPricing === 'true'
|
||||||
@ -67,12 +42,6 @@ export default function PricingFields(): ReactElement {
|
|||||||
content: <Fixed content={content.create.fixed} />
|
content: <Fixed content={content.create.fixed} />
|
||||||
}
|
}
|
||||||
: undefined,
|
: undefined,
|
||||||
appConfig.allowDynamicPricing === 'true'
|
|
||||||
? {
|
|
||||||
title: content.create.dynamic.title,
|
|
||||||
content: <Dynamic content={content.create.dynamic} />
|
|
||||||
}
|
|
||||||
: undefined,
|
|
||||||
appConfig.allowFreePricing === 'true'
|
appConfig.allowFreePricing === 'true'
|
||||||
? {
|
? {
|
||||||
title: content.create.free.title,
|
title: content.create.free.title,
|
||||||
@ -85,7 +54,7 @@ export default function PricingFields(): ReactElement {
|
|||||||
<Tabs
|
<Tabs
|
||||||
items={tabs}
|
items={tabs}
|
||||||
handleTabChange={handleTabChange}
|
handleTabChange={handleTabChange}
|
||||||
defaultIndex={type === 'dynamic' ? 1 : type === 'free' ? 2 : 0}
|
defaultIndex={type === 'free' ? 1 : 0}
|
||||||
className={styles.pricing}
|
className={styles.pricing}
|
||||||
showRadio
|
showRadio
|
||||||
/>
|
/>
|
||||||
|
@ -82,13 +82,8 @@ export const initialValues: FormPublishData = {
|
|||||||
],
|
],
|
||||||
pricing: {
|
pricing: {
|
||||||
price: 0,
|
price: 0,
|
||||||
type:
|
type: allowFixedPricing === 'true' ? 'fixed' : 'free',
|
||||||
allowDynamicPricing === 'true'
|
amountDataToken: 1000,
|
||||||
? 'dynamic'
|
|
||||||
: allowFixedPricing === 'true'
|
|
||||||
? 'fixed'
|
|
||||||
: 'free',
|
|
||||||
amountDataToken: allowDynamicPricing === 'true' ? 100 : 1000,
|
|
||||||
amountOcean: 100,
|
amountOcean: 100,
|
||||||
weightOnOcean: '5', // 50% on OCEAN
|
weightOnOcean: '5', // 50% on OCEAN
|
||||||
weightOnDataToken: '5', // 50% on datatoken
|
weightOnDataToken: '5', // 50% on datatoken
|
||||||
|
@ -210,7 +210,7 @@ export async function createTokensAndPricing(
|
|||||||
|
|
||||||
// TODO: cap is hardcoded for now to 1000, this needs to be discussed at some point
|
// TODO: cap is hardcoded for now to 1000, this needs to be discussed at some point
|
||||||
const ercParams: Erc20CreateParams = {
|
const ercParams: Erc20CreateParams = {
|
||||||
templateIndex: values.pricing.type === 'dynamic' ? 1 : 2,
|
templateIndex: 2,
|
||||||
minter: accountId,
|
minter: accountId,
|
||||||
paymentCollector: accountId,
|
paymentCollector: accountId,
|
||||||
mpFeeAddress: marketFeeAddress,
|
mpFeeAddress: marketFeeAddress,
|
||||||
@ -228,63 +228,6 @@ export async function createTokensAndPricing(
|
|||||||
|
|
||||||
// TODO: cleaner code for this huge switch !??!?
|
// TODO: cleaner code for this huge switch !??!?
|
||||||
switch (values.pricing.type) {
|
switch (values.pricing.type) {
|
||||||
case 'dynamic': {
|
|
||||||
// no vesting in market by default, maybe at a later time , vestingAmount and vestedBlocks are hardcoded
|
|
||||||
// we use only ocean as basetoken
|
|
||||||
// swapFeeLiquidityProvider is the swap fee of the liquidity providers
|
|
||||||
// swapFeeMarketRunner is the swap fee of the market where the swap occurs
|
|
||||||
const poolParams: PoolCreationParams = {
|
|
||||||
ssContract: config.sideStakingAddress,
|
|
||||||
baseTokenAddress: config.oceanTokenAddress,
|
|
||||||
baseTokenSender: config.erc721FactoryAddress,
|
|
||||||
publisherAddress: accountId,
|
|
||||||
marketFeeCollector: marketFeeAddress,
|
|
||||||
poolTemplateAddress: config.poolTemplateAddress,
|
|
||||||
rate: new Decimal(1).div(values.pricing.price).toString(),
|
|
||||||
baseTokenDecimals: 18,
|
|
||||||
vestingAmount: '0',
|
|
||||||
vestedBlocks: 2726000,
|
|
||||||
initialBaseTokenLiquidity: values.pricing.amountOcean.toString(),
|
|
||||||
swapFeeLiquidityProvider: (values.pricing.swapFee / 100).toString(),
|
|
||||||
swapFeeMarketRunner: publisherMarketPoolSwapFee
|
|
||||||
}
|
|
||||||
|
|
||||||
LoggerInstance.log(
|
|
||||||
'[publish] Creating dynamic pricing with poolParams',
|
|
||||||
poolParams
|
|
||||||
)
|
|
||||||
|
|
||||||
// the spender in this case is the erc721Factory because we are delegating
|
|
||||||
const txApprove = await approve(
|
|
||||||
web3,
|
|
||||||
accountId,
|
|
||||||
config.oceanTokenAddress,
|
|
||||||
config.erc721FactoryAddress,
|
|
||||||
values.pricing.amountOcean.toString(),
|
|
||||||
false
|
|
||||||
)
|
|
||||||
LoggerInstance.log('[publish] pool.approve tx', txApprove, nftFactory)
|
|
||||||
|
|
||||||
if (!txApprove) {
|
|
||||||
throw new Error(
|
|
||||||
'MetaMask Approve TX Signature: User denied transaction signature'
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = await nftFactory.createNftErc20WithPool(
|
|
||||||
accountId,
|
|
||||||
nftCreateData,
|
|
||||||
ercParams,
|
|
||||||
poolParams
|
|
||||||
)
|
|
||||||
|
|
||||||
erc721Address = result.events.NFTCreated.returnValues[0]
|
|
||||||
datatokenAddress = result.events.TokenCreated.returnValues[0]
|
|
||||||
txHash = result.transactionHash
|
|
||||||
|
|
||||||
LoggerInstance.log('[publish] createNftErcWithPool tx', txHash)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
case 'fixed': {
|
case 'fixed': {
|
||||||
const freParams: FreCreationParams = {
|
const freParams: FreCreationParams = {
|
||||||
fixedRateAddress: config.fixedRateExchangeAddress,
|
fixedRateAddress: config.fixedRateExchangeAddress,
|
||||||
|
Loading…
Reference in New Issue
Block a user