1
0
mirror of https://github.com/oceanprotocol/market.git synced 2024-12-02 05:57:29 +01:00

Merge branch 'main' into feature/account_page

This commit is contained in:
Matthias Kretschmann 2021-09-01 11:19:06 +02:00
commit 3112a10930
Signed by: m
GPG Key ID: 606EEEF3C479A91F
18 changed files with 1392 additions and 1426 deletions

View File

@ -13,7 +13,7 @@ module.exports = {
chainIds: [1, 137, 56],
// List of all supported chainIds. Used to populate the Chains user preferences list.
chainIdsSupported: [1, 3, 4, 137, 80001, 1287, 56],
chainIdsSupported: [1, 3, 4, 137, 80001, 1287, 56, 2021000],
rbacUrl: process.env.GATSBY_RBAC_URL,

2584
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -25,22 +25,22 @@
"graphql:graphTypes": "graphql-codegen --config codegen.yml"
},
"dependencies": {
"@coingecko/cryptoformat": "^0.4.2",
"@coingecko/cryptoformat": "^0.4.4",
"@loadable/component": "^5.15.0",
"@oceanprotocol/art": "^3.0.0",
"@oceanprotocol/lib": "^0.17.0",
"@oceanprotocol/art": "^3.2.0",
"@oceanprotocol/lib": "^0.17.3",
"@oceanprotocol/typographies": "^0.1.0",
"@portis/web3": "^4.0.4",
"@portis/web3": "^4.1.0",
"@sindresorhus/slugify": "^2.1.0",
"@tippyjs/react": "^4.2.5",
"@urql/introspection": "^0.3.0",
"@walletconnect/web3-provider": "^1.5.2",
"@walletconnect/web3-provider": "^1.6.5",
"axios": "^0.21.1",
"chart.js": "^2.9.4",
"classnames": "^2.3.1",
"cross-fetch": "^3.1.4",
"date-fns": "^2.22.1",
"decimal.js": "^10.2.1",
"date-fns": "^2.23.0",
"decimal.js": "^10.3.1",
"dom-confetti": "^0.2.2",
"dotenv": "^10.0.0",
"ethereum-address": "0.0.4",
@ -86,8 +86,8 @@
"swr": "^0.5.6",
"urql": "^2.0.3",
"use-dark-mode": "^2.3.1",
"web3": "^1.5.0",
"web3modal": "^1.9.3",
"web3": "^1.5.2",
"web3modal": "^1.9.4",
"yup": "^0.32.9"
},
"devDependencies": {

View File

@ -21,6 +21,7 @@ interface ButtonBuyProps {
dtBalanceSelectedComputeAsset?: string
selectedComputeAssetLowPoolLiquidity?: boolean
selectedComputeAssetType?: string
isBalanceSufficient: boolean
isLoading: boolean
onClick?: (e: FormEvent<HTMLButtonElement>) => void
stepText?: string
@ -38,6 +39,7 @@ function getConsumeHelpText(
lowPoolLiquidity: boolean,
assetType: string,
isConsumable: boolean,
isBalanceSufficient: boolean,
consumableFeedback: string
) {
const text =
@ -49,6 +51,8 @@ function getConsumeHelpText(
? `You own ${dtBalance} ${dtSymbol} allowing you to use this data set by spending 1 ${dtSymbol}, but without paying OCEAN again.`
: lowPoolLiquidity
? `There are not enought ${dtSymbol} available in the pool for the transaction to take place`
: isBalanceSufficient === false
? 'You do not have enough OCEAN in your wallet to purchase this asset.'
: `For using this ${assetType}, you will buy 1 ${dtSymbol} and immediately spend it back to the publisher and pool.`
return text
}
@ -62,6 +66,7 @@ function getComputeAssetHelpText(
assetType: string,
isConsumable: boolean,
consumableFeedback: string,
isBalanceSufficient: boolean,
hasPreviousOrderSelectedComputeAsset?: boolean,
hasDatatokenSelectedComputeAsset?: boolean,
dtSymbolSelectedComputeAsset?: string,
@ -78,6 +83,7 @@ function getComputeAssetHelpText(
lowPoolLiquidity,
assetType,
isConsumable,
isBalanceSufficient,
consumableFeedback
)
const computeAlgoHelpText =
@ -96,6 +102,8 @@ function getComputeAssetHelpText(
? `You own ${dtBalanceSelectedComputeAsset} ${dtSymbolSelectedComputeAsset} allowing you to use the selected ${selectedComputeAssetType} by spending 1 ${dtSymbolSelectedComputeAsset}, but without paying OCEAN again.`
: selectedComputeAssettLowPoolLiquidity
? `There are not enought ${dtSymbolSelectedComputeAsset} available in the pool for the transaction to take place`
: isBalanceSufficient === false
? ''
: `Additionally, you will buy 1 ${dtSymbolSelectedComputeAsset} for the ${selectedComputeAssetType} and spend it back to its publisher and pool.`
const computeHelpText = selectedComputeAssettLowPoolLiquidity
? computeAlgoHelpText
@ -117,6 +125,7 @@ export default function ButtonBuy({
assetTimeout,
isConsumable,
consumableFeedback,
isBalanceSufficient,
hasPreviousOrderSelectedComputeAsset,
hasDatatokenSelectedComputeAsset,
dtSymbolSelectedComputeAsset,
@ -168,6 +177,7 @@ export default function ButtonBuy({
datasetLowPoolLiquidity,
assetType,
isConsumable,
isBalanceSufficient,
consumableFeedback
)
: getComputeAssetHelpText(
@ -179,6 +189,7 @@ export default function ButtonBuy({
assetType,
isConsumable,
consumableFeedback,
isBalanceSufficient,
hasPreviousOrderSelectedComputeAsset,
hasDatatokenSelectedComputeAsset,
dtSymbolSelectedComputeAsset,

View File

@ -46,7 +46,10 @@ const AssetTeaser: React.FC<AssetTeaserProps> = ({
<div className={styles.content}>
<Dotdotdot tagName="p" clamp={3}>
{removeMarkdown(
attributes?.additionalInformation?.description || ''
attributes?.additionalInformation?.description.substring(
0,
300
) || ''
)}
</Dotdotdot>
</div>

View File

@ -16,7 +16,7 @@ export function filterNetworksByType(
type: 'mainnet' | 'testnet',
chainIds: number[],
networksList: { node: EthereumListsChain }[]
) {
): number[] {
const finalNetworks = chainIds.filter((chainId: number) => {
const networkData = getNetworkDataById(networksList, chainId)

View File

@ -1,4 +1,4 @@
import React, { ReactElement } from 'react'
import React, { ReactElement, useEffect, useState } from 'react'
import { useWeb3 } from '../../providers/Web3'
import Status from '../atoms/Status'
import styles from './Web3Feedback.module.css'
@ -12,46 +12,42 @@ export declare type Web3Error = {
}
export default function Web3Feedback({
isBalanceSufficient,
isAssetNetwork
}: {
isBalanceSufficient?: boolean
isAssetNetwork?: boolean
}): ReactElement {
const { accountId } = useWeb3()
const { isGraphSynced, blockGraph, blockHead } = useGraphSyncStatus()
const showFeedback =
!accountId ||
isBalanceSufficient === false ||
isAssetNetwork === false ||
isGraphSynced === false
const [state, setState] = useState<string>()
const [title, setTitle] = useState<string>()
const [message, setMessage] = useState<string>()
const [showFeedback, setShowFeedback] = useState<boolean>(false)
const state =
!accountId || !isGraphSynced
? 'error'
: accountId && isBalanceSufficient && isAssetNetwork
? 'success'
: 'warning'
const title = !accountId
? 'No account connected'
: accountId && isAssetNetwork === false
? 'Not connected to asset network'
: isGraphSynced === false
? `Data out of sync`
: accountId
? isBalanceSufficient === false
? 'Insufficient balance'
: 'Connected to Ocean'
: 'Something went wrong'
const message = !accountId
? 'Please connect your Web3 wallet.'
: isBalanceSufficient === false
? 'You do not have enough OCEAN in your wallet to purchase this asset.'
: isGraphSynced === false
? `The data for this network has only synced to Ethereum block ${blockGraph} (out of ${blockHead}). Transactions may fail! Please check back soon`
: 'Something went wrong.'
useEffect(() => {
setShowFeedback(
!accountId || isAssetNetwork === false || isGraphSynced === false
)
if (accountId && isAssetNetwork && isGraphSynced) return
if (!accountId) {
setState('error')
setTitle('No account connected')
setMessage('Please connect your Web3 wallet.')
} else if (isAssetNetwork === false) {
setState('error')
setTitle('Not connected to asset network')
setMessage('Please connect your Web3 wallet.')
} else if (isGraphSynced === false) {
setState('warning')
setTitle('Data out of sync')
setMessage(
`The data for this network has only synced to Ethereum block ${blockGraph} (out of ${blockHead}). Transactions may fail! Please check back soon.`
)
} else {
setState('warning')
setTitle('Something went wrong.')
setMessage('Something went wrong.')
}
}, [accountId, isGraphSynced, isAssetNetwork])
return showFeedback ? (
<section className={styles.feedback}>

View File

@ -6,6 +6,7 @@ import { FormFieldProps } from '../../../../@types/Form'
import { useStaticQuery, graphql } from 'gatsby'
import { DDO, BestPrice } from '@oceanprotocol/lib'
import { AssetSelectionAsset } from '../../../molecules/FormFields/AssetSelection'
import compareAsBN from '../../../../utils/compareAsBN'
import ButtonBuy from '../../../atoms/ButtonBuy'
import PriceOutput from './PriceOutput'
import { useAsset } from '../../../../providers/Asset'
@ -96,7 +97,8 @@ export default function FormStartCompute({
useFormikContext()
const { price, ddo, isAssetNetwork } = useAsset()
const [totalPrice, setTotalPrice] = useState(price?.value)
const { accountId } = useWeb3()
const [isBalanceSufficient, setIsBalanceSufficient] = useState<boolean>(false)
const { accountId, balance } = useWeb3()
const { ocean } = useOcean()
const [algorithmConsumableStatus, setAlgorithmConsumableStatus] =
useState<number>()
@ -148,6 +150,13 @@ export default function FormStartCompute({
hasDatatokenSelectedComputeAsset
])
useEffect(() => {
if (!totalPrice) return
setIsBalanceSufficient(
compareAsBN(balance.ocean, `${totalPrice}`) || Number(dtBalance) >= 1
)
}, [totalPrice])
return (
<Form className={styles.form}>
{content.form.data.map((field: FormFieldProps) => (
@ -177,6 +186,7 @@ export default function FormStartCompute({
disabled={
isComputeButtonDisabled ||
!isValid ||
!isBalanceSufficient ||
!isAssetNetwork ||
algorithmConsumableStatus > 0
}
@ -202,6 +212,7 @@ export default function FormStartCompute({
type="submit"
priceType={price?.type}
algorithmPriceType={algorithmPrice?.type}
isBalanceSufficient={isBalanceSufficient}
isConsumable={isConsumable}
consumableFeedback={consumableFeedback}
algorithmConsumableStatus={algorithmConsumableStatus}

View File

@ -12,9 +12,5 @@ export default {
}
export const Default = (): ReactElement => (
<Compute
dtBalance="1"
isBalanceSufficient
file={ddo.service[0].attributes.main.files[0]}
/>
<Compute dtBalance="1" file={ddo.service[0].attributes.main.files[0]} />
)

View File

@ -48,14 +48,12 @@ const SuccessAction = () => (
)
export default function Compute({
isBalanceSufficient,
dtBalance,
file,
fileIsLoading,
isConsumable,
consumableFeedback
}: {
isBalanceSufficient: boolean
dtBalance: string
file: FileMetadata
fileIsLoading?: boolean
@ -65,7 +63,7 @@ export default function Compute({
const { appConfig } = useSiteMetadata()
const { accountId } = useWeb3()
const { ocean, account } = useOcean()
const { price, type, ddo, isAssetNetwork } = useAsset()
const { price, type, ddo } = useAsset()
const { buyDT, pricingError, pricingStepText } = usePricing()
const [isJobStarting, setIsJobStarting] = useState(false)
const [error, setError] = useState<string>()
@ -94,7 +92,6 @@ export default function Compute({
isJobStarting === true ||
file === null ||
!ocean ||
!isBalanceSufficient ||
(!hasPreviousDatasetOrder && !hasDatatoken && !(datasetMaxDT >= 1)) ||
(!hasPreviousAlgorithmOrder && !hasAlgoAssetDatatoken && !(algoMaxDT >= 1))

View File

@ -183,6 +183,7 @@ export default function Consume({
isLoading={pricingIsLoading || isLoading}
priceType={price?.type}
isConsumable={isConsumable}
isBalanceSufficient={isBalanceSufficient}
consumableFeedback={consumableFeedback}
/>
)

View File

@ -67,6 +67,18 @@ const poolLiquidityQuery = gql`
}
`
const userPoolShareQuery = gql`
query PoolShare($id: ID!, $shareId: ID) {
pool(id: $id) {
id
shares(where: { id: $shareId }) {
id
balance
}
}
}
`
export default function Pool(): ReactElement {
const data = useStaticQuery(contentQuery)
const content = data.content.edges[0].node.childContentJson.pool
@ -124,6 +136,21 @@ export default function Pool(): ReactElement {
setdataLiquidity(queryResult?.data)
}
async function getUserPoolShareBalance() {
const queryContext = getQueryContext(ddo.chainId)
const queryVariables = {
id: price.address.toLowerCase(),
shareId: `${price.address.toLowerCase()}-${accountId.toLowerCase()}`
}
const queryResult: OperationResult<PoolLiquidity> = await fetchData(
userPoolShareQuery,
queryVariables,
queryContext
)
return queryResult?.data.pool.shares[0].balance
}
function refetchLiquidity() {
if (!liquidityFetchInterval) {
setLiquidityFetchInterval(
@ -245,6 +272,7 @@ export default function Pool(): ReactElement {
}, [isInPurgatory, owner, accountId])
useEffect(() => {
if (!dataLiquidity) return
const poolShare =
isValidNumber(poolTokens) &&
isValidNumber(totalPoolTokens) &&
@ -261,9 +289,11 @@ export default function Pool(): ReactElement {
const totalUserLiquidityInOcean =
isValidNumber(userLiquidity?.ocean) &&
isValidNumber(userLiquidity?.datatoken) &&
isValidNumber(price?.value)
isValidNumber(dataLiquidity.pool.spotPrice)
? new Decimal(userLiquidity?.ocean).add(
new Decimal(userLiquidity?.datatoken).mul(price?.value)
new Decimal(userLiquidity?.datatoken).mul(
dataLiquidity.pool.spotPrice
)
)
: new Decimal(0)
@ -272,9 +302,9 @@ export default function Pool(): ReactElement {
const totalLiquidityInOcean =
isValidNumber(price?.ocean) &&
isValidNumber(price?.datatoken) &&
isValidNumber(price?.value)
isValidNumber(dataLiquidity.pool.spotPrice)
? new Decimal(price?.ocean).add(
new Decimal(price?.datatoken).mul(price?.value)
new Decimal(price?.datatoken).mul(dataLiquidity.pool.spotPrice)
)
: new Decimal(0)
@ -282,16 +312,13 @@ export default function Pool(): ReactElement {
}, [userLiquidity, price, poolTokens, totalPoolTokens])
useEffect(() => {
if (!ocean || !accountId || !price) return
if (!accountId || !price) return
async function init() {
try {
//
// Get everything the user has put into the pool
//
const poolTokens = await ocean.pool.sharesBalance(
accountId,
price.address
)
const poolTokens = await getUserPoolShareBalance()
setPoolTokens(poolTokens)
// calculate user's provided liquidity based on pool tokens
@ -326,7 +353,7 @@ export default function Pool(): ReactElement {
}
}
init()
}, [ocean, accountId, price, ddo, refreshPool, owner, totalPoolTokens])
}, [accountId, price, ddo, refreshPool, owner, totalPoolTokens])
const refreshInfo = async () => {
setRefreshPool(!refreshPool)

View File

@ -63,7 +63,7 @@ export default function FormTrade({
ocean: Yup.number()
.max(
Number(maximumOcean),
(param) => `Must be more or equal to ${param.max}`
(param) => `Must be less or equal to ${param.max}`
)
.min(0.001, (param) => `Must be more or equal to ${param.min}`)
.required('Required')
@ -71,7 +71,7 @@ export default function FormTrade({
datatoken: Yup.number()
.max(
Number(maximumDt),
(param) => `Must be less or equal than ${param.max}`
(param) => `Must be less or equal to ${param.max}`
)
.min(0.00001, (param) => `Must be more or equal to ${param.min}`)
.required('Required')

View File

@ -111,7 +111,6 @@ export default function AssetActions(): ReactElement {
const UseContent = isCompute ? (
<Compute
dtBalance={dtBalance}
isBalanceSufficient={isBalanceSufficient}
file={fileMetadata}
fileIsLoading={fileIsLoading}
isConsumable={isConsumable}
@ -153,10 +152,7 @@ export default function AssetActions(): ReactElement {
<Permission eventType="consume">
<Tabs items={tabs} className={styles.actions} />
</Permission>
<Web3Feedback
isBalanceSufficient={isBalanceSufficient}
isAssetNetwork={isAssetNetwork}
/>
<Web3Feedback isAssetNetwork={isAssetNetwork} />
</>
)
}

View File

@ -24,12 +24,12 @@ async function getQueryHighest(
const [dids, didsLength] = await getHighestLiquidityDIDs(chainIds)
const queryHighest = {
page: 1,
offset: didsLength,
offset: didsLength > 0 ? didsLength : 1,
query: {
query_string: {
query: `(${dids}) AND (${transformChainIdsListToQuery(
query: `${dids && `(${dids}) AND`}(${transformChainIdsListToQuery(
chainIds
)}) AND -isInPurgatory:true`,
)}) AND -isInPurgatory:true `,
fields: ['dataToken']
}
}

View File

@ -28,9 +28,9 @@ function getCredentialList(
(credential) => credential.type === credentialType
)
return credentialByType &&
credentialByType.value &&
credentialByType.value.length > 0
? credentialByType.value
credentialByType.values &&
credentialByType.values.length > 0
? credentialByType.values
: []
}

View File

@ -1,4 +1,5 @@
import { PriceOptionsMarket } from '../@types/MetaData'
import { allowDynamicPricing, allowFixedPricing } from '../../app.config'
import * as Yup from 'yup'
export const validationSchema: Yup.SchemaOf<PriceOptionsMarket> =
@ -26,8 +27,13 @@ export const validationSchema: Yup.SchemaOf<PriceOptionsMarket> =
export const initialValues: PriceOptionsMarket = {
price: 1,
type: 'dynamic',
dtAmount: 9,
type:
allowDynamicPricing === 'true'
? 'dynamic'
: allowFixedPricing === 'true'
? 'fixed'
: 'free',
dtAmount: allowDynamicPricing === 'true' ? 9 : 1000,
oceanAmount: 21,
weightOnOcean: '7', // 70% on OCEAN
weightOnDataToken: '3', // 30% on datatoken

View File

@ -1,4 +1,5 @@
import { Logger } from '@oceanprotocol/lib'
import { getOceanConfig } from './ocean'
export interface EthereumListsChain {
name: string
@ -19,6 +20,24 @@ export interface NetworkObject {
urlList: string[]
}
const configGaiaX = getOceanConfig(2021000)
export const networkDataGaiaX = {
name: 'GAIA-X Testnet',
chainId: 2021000,
shortName: 'GAIA-X',
chain: 'GAIA-X',
network: 'testnet',
networkId: 2021000,
nativeCurrency: { name: 'Gaia-X', symbol: 'GX', decimals: 18 },
rpc: [configGaiaX.nodeUri],
faucets: [
'https://faucet.gaiaxtestnet.oceanprotocol.com/',
'https://faucet.gx.gaiaxtestnet.oceanprotocol.com/'
],
infoURL: 'https://www.gaia-x.eu'
}
export function getNetworkConfigObject(node: any): NetworkObject {
const networkConfig = {
name: node.chain,
@ -55,9 +74,6 @@ export function getNetworkDisplayName(
case 8996:
displayName = 'Development'
break
case 2021000:
displayName = 'GAIA-X'
break
default:
displayName = data
? `${data.chain} ${data.network === 'mainnet' ? '' : data.network}`
@ -77,7 +93,7 @@ export function getNetworkDataById(
({ node }: { node: EthereumListsChain }) => node.chainId === networkId
)
return networkData[0]?.node
return networkId === 2021000 ? networkDataGaiaX : networkData[0]?.node
}
export async function addCustomNetwork(
@ -106,7 +122,7 @@ export async function addCustomNetwork(
Logger.error(
`Couldn't add ${network.name} (0x${
network.chainId
}) netowrk to MetaMask, error: ${err || added.error}`
}) network to MetaMask, error: ${err || added.error}`
)
} else {
Logger.log(
@ -117,7 +133,7 @@ export async function addCustomNetwork(
)
} else {
Logger.error(
`Couldn't add ${network.name} (0x${network.chainId}) netowrk to MetaMask, error: ${switchError}`
`Couldn't add ${network.name} (0x${network.chainId}) network to MetaMask, error: ${switchError}`
)
}
}