mirror of
https://github.com/oceanprotocol/market.git
synced 2024-12-02 05:57:29 +01:00
Merge branch 'main' into fix/issue-1069-c2d-unsupported-networks
This commit is contained in:
commit
983d460614
@ -14,7 +14,7 @@ module.exports = {
|
||||
chainIds: [1, 137, 56, 246, 1285],
|
||||
|
||||
// List of all supported chainIds. Used to populate the Chains user preferences list.
|
||||
chainIdsSupported: [1, 137, 56, 246, 1285, 5, 80001, 1287],
|
||||
chainIdsSupported: [1, 137, 56, 246, 1285, 5, 80001],
|
||||
|
||||
infuraProjectId: process.env.NEXT_PUBLIC_INFURA_PROJECT_ID || 'xxx',
|
||||
|
||||
|
9329
package-lock.json
generated
9329
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
12
package.json
12
package.json
@ -26,13 +26,13 @@
|
||||
"@coingecko/cryptoformat": "^0.5.4",
|
||||
"@loadable/component": "^5.15.2",
|
||||
"@oceanprotocol/art": "^3.2.0",
|
||||
"@oceanprotocol/lib": "^2.2.3",
|
||||
"@oceanprotocol/lib": "^2.4.0",
|
||||
"@oceanprotocol/typographies": "^0.1.0",
|
||||
"@oceanprotocol/use-dark-mode": "^2.4.3",
|
||||
"@tippyjs/react": "^4.2.6",
|
||||
"@urql/exchange-refocus": "^1.0.0",
|
||||
"@walletconnect/web3-provider": "^1.8.0",
|
||||
"axios": "^0.27.2",
|
||||
"axios": "^1.1.3",
|
||||
"classnames": "^2.3.2",
|
||||
"date-fns": "^2.29.3",
|
||||
"decimal.js": "^10.3.1",
|
||||
@ -74,9 +74,9 @@
|
||||
"devDependencies": {
|
||||
"@storybook/addon-essentials": "^6.5.12",
|
||||
"@storybook/builder-webpack5": "^6.5.12",
|
||||
"@storybook/manager-webpack5": "^6.5.12",
|
||||
"@storybook/react": "^6.5.12",
|
||||
"@svgr/webpack": "^6.3.1",
|
||||
"@storybook/manager-webpack5": "^6.5.13",
|
||||
"@storybook/react": "^6.5.13",
|
||||
"@svgr/webpack": "^6.5.1",
|
||||
"@testing-library/jest-dom": "^5.16.5",
|
||||
"@testing-library/react": "^13.4.0",
|
||||
"@types/js-cookie": "^3.0.2",
|
||||
@ -104,7 +104,7 @@
|
||||
"https-browserify": "^1.0.0",
|
||||
"husky": "^8.0.1",
|
||||
"jest": "^29.1.2",
|
||||
"jest-environment-jsdom": "^29.0.3",
|
||||
"jest-environment-jsdom": "^29.2.2",
|
||||
"prettier": "^2.7.1",
|
||||
"pretty-quick": "^3.1.3",
|
||||
"process": "^0.11.10",
|
||||
|
@ -77,8 +77,8 @@ function AssetProvider({
|
||||
return
|
||||
}
|
||||
|
||||
if (asset.nft.state) {
|
||||
// handle nft states as documented in https://docs.oceanprotocol.com/concepts/did-ddo/#state
|
||||
if ([1, 2, 3].includes(asset.nft.state)) {
|
||||
// handle nft states as documented in https://docs.oceanprotocol.com/core-concepts/did-ddo/#state
|
||||
let state
|
||||
switch (asset.nft.state) {
|
||||
case 1:
|
||||
@ -120,7 +120,7 @@ function AssetProvider({
|
||||
// Helper: Get and set asset access details
|
||||
// -----------------------------------
|
||||
const fetchAccessDetails = useCallback(async (): Promise<void> => {
|
||||
if (!asset?.chainId || !asset?.services) return
|
||||
if (!asset?.chainId || !asset?.services?.length) return
|
||||
|
||||
const accessDetails = await getAccessDetails(
|
||||
asset.chainId,
|
||||
|
@ -29,6 +29,7 @@ interface ProfileProviderValue {
|
||||
downloadsTotal: number
|
||||
isDownloadsLoading: boolean
|
||||
sales: number
|
||||
ownAccount: boolean
|
||||
}
|
||||
|
||||
const ProfileContext = createContext({} as ProfileProviderValue)
|
||||
@ -46,17 +47,18 @@ const clearedProfile: Profile = {
|
||||
function ProfileProvider({
|
||||
accountId,
|
||||
accountEns,
|
||||
ownAccount,
|
||||
children
|
||||
}: {
|
||||
accountId: string
|
||||
accountEns: string
|
||||
ownAccount: boolean
|
||||
children: ReactNode
|
||||
}): ReactElement {
|
||||
const { chainIds } = useUserPreferences()
|
||||
const { appConfig } = useMarketMetadata()
|
||||
|
||||
const [isEthAddress, setIsEthAddress] = useState<boolean>()
|
||||
|
||||
//
|
||||
// Do nothing in all following effects
|
||||
// when accountId is no ETH address
|
||||
@ -111,7 +113,8 @@ function ProfileProvider({
|
||||
const result = await getPublishedAssets(
|
||||
accountId,
|
||||
chainIds,
|
||||
cancelTokenSource.token
|
||||
cancelTokenSource.token,
|
||||
ownAccount
|
||||
)
|
||||
setAssets(result.results)
|
||||
setAssetsTotal(result.totalResults)
|
||||
@ -134,7 +137,13 @@ function ProfileProvider({
|
||||
return () => {
|
||||
cancelTokenSource.cancel()
|
||||
}
|
||||
}, [accountId, appConfig.metadataCacheUri, chainIds, isEthAddress])
|
||||
}, [
|
||||
accountId,
|
||||
appConfig.metadataCacheUri,
|
||||
chainIds,
|
||||
isEthAddress,
|
||||
ownAccount
|
||||
])
|
||||
|
||||
//
|
||||
// DOWNLOADS
|
||||
@ -154,11 +163,13 @@ function ProfileProvider({
|
||||
for (let i = 0; i < tokenOrders?.length; i++) {
|
||||
dtList.push(tokenOrders[i].datatoken.address)
|
||||
}
|
||||
|
||||
const downloads = await getDownloadAssets(
|
||||
dtList,
|
||||
tokenOrders,
|
||||
chainIds,
|
||||
cancelToken
|
||||
cancelToken,
|
||||
ownAccount
|
||||
)
|
||||
setDownloads(downloads)
|
||||
setDownloadsTotal(downloads.length)
|
||||
@ -167,7 +178,7 @@ function ProfileProvider({
|
||||
downloads
|
||||
)
|
||||
},
|
||||
[accountId, chainIds]
|
||||
[accountId, chainIds, ownAccount]
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
@ -230,6 +241,7 @@ function ProfileProvider({
|
||||
downloads,
|
||||
downloadsTotal,
|
||||
isDownloadsLoading,
|
||||
ownAccount,
|
||||
sales
|
||||
}}
|
||||
>
|
||||
|
5
src/@types/Compute.d.ts
vendored
5
src/@types/Compute.d.ts
vendored
@ -27,4 +27,9 @@ declare global {
|
||||
computeJobs: ComputeJobMetaData[]
|
||||
isLoaded: boolean
|
||||
}
|
||||
|
||||
interface totalPriceMap {
|
||||
value: string
|
||||
symbol: string
|
||||
}
|
||||
}
|
||||
|
1
src/@types/aquarius/BaseQueryParams.d.ts
vendored
1
src/@types/aquarius/BaseQueryParams.d.ts
vendored
@ -12,4 +12,5 @@ interface BaseQueryParams {
|
||||
aggs?: any
|
||||
filters?: FilterTerm[]
|
||||
ignorePurgatory?: boolean
|
||||
ignoreState?: boolean
|
||||
}
|
||||
|
@ -59,7 +59,22 @@ export function generateBaseQuery(
|
||||
getFilterTerm('_index', 'aquarius'),
|
||||
...(baseQueryParams.ignorePurgatory
|
||||
? []
|
||||
: [getFilterTerm('purgatory.state', false)])
|
||||
: [getFilterTerm('purgatory.state', false)]),
|
||||
...(baseQueryParams.ignoreState
|
||||
? []
|
||||
: [
|
||||
{
|
||||
bool: {
|
||||
must_not: [
|
||||
{
|
||||
term: {
|
||||
'nft.state': 5
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
])
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -177,7 +192,7 @@ export async function getAssetsFromDidList(
|
||||
cancelToken: CancelToken
|
||||
): Promise<PagedAssets> {
|
||||
try {
|
||||
if (!(didList.length > 0)) return
|
||||
if (!didList.length) return
|
||||
|
||||
const baseParams = {
|
||||
chainIds,
|
||||
@ -199,7 +214,7 @@ export async function getAssetsFromDtList(
|
||||
cancelToken: CancelToken
|
||||
): Promise<Asset[]> {
|
||||
try {
|
||||
if (!(dtList.length > 0)) return
|
||||
if (!dtList.length) return
|
||||
|
||||
const baseParams = {
|
||||
chainIds,
|
||||
@ -304,6 +319,7 @@ export async function getPublishedAssets(
|
||||
accountId: string,
|
||||
chainIds: number[],
|
||||
cancelToken: CancelToken,
|
||||
ignoreState = false,
|
||||
page?: number,
|
||||
type?: string,
|
||||
accesType?: string
|
||||
@ -332,6 +348,7 @@ export async function getPublishedAssets(
|
||||
}
|
||||
},
|
||||
ignorePurgatory: true,
|
||||
ignoreState,
|
||||
esPaginationOptions: {
|
||||
from: (Number(page) - 1 || 0) * 9,
|
||||
size: 9
|
||||
@ -445,14 +462,17 @@ export async function getDownloadAssets(
|
||||
dtList: string[],
|
||||
tokenOrders: OrdersData[],
|
||||
chainIds: number[],
|
||||
cancelToken: CancelToken
|
||||
cancelToken: CancelToken,
|
||||
ignoreState = false
|
||||
): Promise<DownloadedAsset[]> {
|
||||
const baseQueryparams = {
|
||||
chainIds,
|
||||
filters: [
|
||||
getFilterTerm('services.datatokenAddress', dtList),
|
||||
getFilterTerm('services.type', 'access')
|
||||
]
|
||||
],
|
||||
ignorePurgatory: true,
|
||||
ignoreState
|
||||
} as BaseQueryParams
|
||||
const query = generateBaseQuery(baseQueryparams)
|
||||
try {
|
||||
|
@ -1,18 +1,13 @@
|
||||
import { LoggerInstance, Dispenser, Datatoken } from '@oceanprotocol/lib'
|
||||
import { LoggerInstance, Datatoken } from '@oceanprotocol/lib'
|
||||
import Web3 from 'web3'
|
||||
import { TransactionReceipt } from 'web3-core'
|
||||
|
||||
export async function setMinterToPublisher(
|
||||
web3: Web3,
|
||||
dispenserAddress: string,
|
||||
datatokenAddress: string,
|
||||
accountId: string,
|
||||
setError: (msg: string) => void
|
||||
): Promise<TransactionReceipt> {
|
||||
const dispenserInstance = new Dispenser(dispenserAddress, web3)
|
||||
const status = await dispenserInstance.status(datatokenAddress)
|
||||
if (!status?.active) return
|
||||
|
||||
const datatokenInstance = new Datatoken(web3)
|
||||
|
||||
const response = await datatokenInstance.removeMinter(
|
||||
@ -20,6 +15,7 @@ export async function setMinterToPublisher(
|
||||
accountId,
|
||||
accountId
|
||||
)
|
||||
|
||||
if (!response) {
|
||||
setError('Updating DDO failed.')
|
||||
LoggerInstance.error('Failed at cancelMinter')
|
||||
|
@ -6,7 +6,8 @@ import {
|
||||
FileInfo,
|
||||
LoggerInstance,
|
||||
ProviderComputeInitializeResults,
|
||||
ProviderInstance
|
||||
ProviderInstance,
|
||||
UrlFile
|
||||
} from '@oceanprotocol/lib'
|
||||
import Web3 from 'web3'
|
||||
import { getValidUntilTime } from './compute'
|
||||
@ -87,7 +88,13 @@ export async function getFileUrlInfo(
|
||||
providerUrl: string
|
||||
): Promise<FileInfo[]> {
|
||||
try {
|
||||
const response = await ProviderInstance.checkFileUrl(url, providerUrl)
|
||||
const fileUrl: UrlFile = {
|
||||
type: 'url',
|
||||
index: 0,
|
||||
url,
|
||||
method: 'get'
|
||||
}
|
||||
const response = await ProviderInstance.getFileInfo(fileUrl, providerUrl)
|
||||
return response
|
||||
} catch (error) {
|
||||
LoggerInstance.error(error.message)
|
||||
|
@ -58,7 +58,7 @@ export default function AssetTeaser({
|
||||
{removeMarkdown(description?.substring(0, 300) || '')}
|
||||
</Dotdotdot>
|
||||
</div>
|
||||
{isUnsupportedPricing ? (
|
||||
{isUnsupportedPricing || !asset.services.length ? (
|
||||
<strong>No pricing schema available</strong>
|
||||
) : (
|
||||
<Price accessDetails={asset.accessDetails} size="small" />
|
||||
|
@ -30,9 +30,9 @@ export default function FileIcon({
|
||||
|
||||
return (
|
||||
<ul className={styleClasses}>
|
||||
{!isLoading && file ? (
|
||||
{!isLoading ? (
|
||||
<>
|
||||
{file.contentType || file.contentLength ? (
|
||||
{file?.contentType || file?.contentLength ? (
|
||||
<>
|
||||
<li>{cleanupContentType(file.contentType)}</li>
|
||||
<li>
|
||||
|
@ -31,6 +31,11 @@
|
||||
padding-right: calc(var(--spacer) / 2);
|
||||
}
|
||||
|
||||
.hideUrl {
|
||||
filter: blur(0.2rem);
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.warning {
|
||||
margin-top: calc(var(--spacer) / 3);
|
||||
margin-left: 0;
|
||||
|
@ -15,9 +15,13 @@ export default function FileInfo({
|
||||
? cleanupContentType(file.contentType)
|
||||
: null
|
||||
|
||||
const hideUrl = file.type === 'hidden' || false
|
||||
|
||||
return (
|
||||
<div className={styles.info}>
|
||||
<h3 className={styles.url}>{file.url}</h3>
|
||||
<div className={`${styles.info}`}>
|
||||
<h3 className={`${styles.url} ${hideUrl ? styles.hideUrl : null}`}>
|
||||
{hideUrl ? 'https://oceanprotocol/placeholder' : file.url}
|
||||
</h3>
|
||||
<ul>
|
||||
<li className={styles.success}>✓ URL confirmed</li>
|
||||
{file.contentLength && <li>{prettySize(+file.contentLength)}</li>}
|
||||
|
@ -16,7 +16,7 @@ export default function FilesInput(props: InputProps): ReactElement {
|
||||
|
||||
async function handleValidation(e: React.SyntheticEvent, url: string) {
|
||||
// File example 'https://oceanprotocol.com/tech-whitepaper.pdf'
|
||||
e.preventDefault()
|
||||
e?.preventDefault()
|
||||
|
||||
try {
|
||||
const providerUrl = values?.services
|
||||
@ -43,13 +43,14 @@ export default function FilesInput(props: InputProps): ReactElement {
|
||||
}
|
||||
|
||||
function handleClose() {
|
||||
helpers.setValue(meta.initialValue)
|
||||
helpers.setTouched(false)
|
||||
helpers.setValue(meta.initialValue)
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{field?.value?.[0]?.valid === true ? (
|
||||
{field?.value?.[0]?.valid === true ||
|
||||
field?.value?.[0]?.type === 'hidden' ? (
|
||||
<FileInfo file={field.value[0]} handleClose={handleClose} />
|
||||
) : (
|
||||
<UrlInput
|
||||
|
@ -11,11 +11,11 @@ import { useWeb3 } from '@context/Web3'
|
||||
import content from '../../../../../content/pages/startComputeDataset.json'
|
||||
import { Asset, ZERO_ADDRESS } from '@oceanprotocol/lib'
|
||||
import { getAccessDetails } from '@utils/accessDetailsAndPricing'
|
||||
import Decimal from 'decimal.js'
|
||||
import { MAX_DECIMALS } from '@utils/constants'
|
||||
import { useMarketMetadata } from '@context/MarketMetadata'
|
||||
import Alert from '@shared/atoms/Alert'
|
||||
import { getTokenBalanceFromSymbol } from '@utils/web3'
|
||||
import { MAX_DECIMALS } from '@utils/constants'
|
||||
import Decimal from 'decimal.js'
|
||||
|
||||
export default function FormStartCompute({
|
||||
algorithms,
|
||||
@ -31,7 +31,8 @@ export default function FormStartCompute({
|
||||
assetTimeout,
|
||||
hasPreviousOrderSelectedComputeAsset,
|
||||
hasDatatokenSelectedComputeAsset,
|
||||
oceanSymbol,
|
||||
datasetSymbol,
|
||||
algorithmSymbol,
|
||||
dtSymbolSelectedComputeAsset,
|
||||
dtBalanceSelectedComputeAsset,
|
||||
selectedComputeAssetType,
|
||||
@ -57,7 +58,8 @@ export default function FormStartCompute({
|
||||
assetTimeout: string
|
||||
hasPreviousOrderSelectedComputeAsset?: boolean
|
||||
hasDatatokenSelectedComputeAsset?: boolean
|
||||
oceanSymbol?: string
|
||||
datasetSymbol?: string
|
||||
algorithmSymbol?: string
|
||||
dtSymbolSelectedComputeAsset?: string
|
||||
dtBalanceSelectedComputeAsset?: string
|
||||
selectedComputeAssetType?: string
|
||||
@ -76,14 +78,14 @@ export default function FormStartCompute({
|
||||
useFormikContext()
|
||||
const { asset, isAssetNetwork } = useAsset()
|
||||
|
||||
const [totalPrice, setTotalPrice] = useState('0')
|
||||
const [datasetOrderPrice, setDatasetOrderPrice] = useState(
|
||||
asset?.accessDetails?.price
|
||||
)
|
||||
const [algoOrderPrice, setAlgoOrderPrice] = useState(
|
||||
selectedAlgorithmAsset?.accessDetails?.price
|
||||
)
|
||||
const [isBalanceSufficient, setIsBalanceSufficient] = useState<boolean>(false)
|
||||
const [totalPrices, setTotalPrices] = useState([])
|
||||
const [isBalanceSufficient, setIsBalanceSufficient] = useState<boolean>(true)
|
||||
|
||||
function getAlgorithmAsset(algorithmId: string): Asset {
|
||||
let assetDdo = null
|
||||
@ -119,40 +121,80 @@ export default function FormStartCompute({
|
||||
useEffect(() => {
|
||||
if (!asset?.accessDetails || !selectedAlgorithmAsset?.accessDetails) return
|
||||
|
||||
const priceDataset = new Decimal(
|
||||
isAssetNetwork
|
||||
? hasPreviousOrder || hasDatatoken
|
||||
? 0
|
||||
: datasetOrderPriceAndFees?.price || asset.accessDetails.price
|
||||
: datasetOrderPriceAndFees?.price || asset.accessDetails.price
|
||||
).toDecimalPlaces(MAX_DECIMALS)
|
||||
|
||||
setDatasetOrderPrice(priceDataset.toString())
|
||||
|
||||
const priceAlgo = new Decimal(
|
||||
isAssetNetwork
|
||||
? hasPreviousOrderSelectedComputeAsset ||
|
||||
hasDatatokenSelectedComputeAsset
|
||||
? 0
|
||||
: algoOrderPriceAndFees?.price ||
|
||||
selectedAlgorithmAsset.accessDetails.price
|
||||
: algoOrderPriceAndFees?.price ||
|
||||
selectedAlgorithmAsset.accessDetails.price
|
||||
).toDecimalPlaces(MAX_DECIMALS)
|
||||
|
||||
setAlgoOrderPrice(priceAlgo.toString())
|
||||
|
||||
setDatasetOrderPrice(
|
||||
datasetOrderPriceAndFees?.price || asset.accessDetails.price
|
||||
)
|
||||
setAlgoOrderPrice(
|
||||
algoOrderPriceAndFees?.price ||
|
||||
selectedAlgorithmAsset?.accessDetails.price
|
||||
)
|
||||
const totalPrices: totalPriceMap[] = []
|
||||
const priceDataset =
|
||||
!datasetOrderPrice || hasPreviousOrder || hasDatatoken
|
||||
? new Decimal(0)
|
||||
: new Decimal(datasetOrderPrice).toDecimalPlaces(MAX_DECIMALS)
|
||||
const priceAlgo =
|
||||
!algoOrderPrice ||
|
||||
hasPreviousOrderSelectedComputeAsset ||
|
||||
hasDatatokenSelectedComputeAsset
|
||||
? new Decimal(0)
|
||||
: new Decimal(algoOrderPrice).toDecimalPlaces(MAX_DECIMALS)
|
||||
const providerFees = providerFeeAmount
|
||||
? new Decimal(providerFeeAmount).toDecimalPlaces(MAX_DECIMALS)
|
||||
: new Decimal(0)
|
||||
|
||||
const totalPrice = priceDataset
|
||||
.plus(priceAlgo)
|
||||
.plus(providerFees)
|
||||
.toDecimalPlaces(MAX_DECIMALS)
|
||||
.toString()
|
||||
|
||||
setTotalPrice(totalPrice)
|
||||
if (algorithmSymbol === 'OCEAN') {
|
||||
let sum = providerFees.add(priceAlgo)
|
||||
totalPrices.push({
|
||||
value: sum.toDecimalPlaces(MAX_DECIMALS).toString(),
|
||||
symbol: algorithmSymbol
|
||||
})
|
||||
if (algorithmSymbol === datasetSymbol) {
|
||||
sum = sum.add(priceDataset)
|
||||
totalPrices[0].value = sum.toDecimalPlaces(MAX_DECIMALS).toString()
|
||||
} else {
|
||||
totalPrices.push({
|
||||
value: priceDataset.toDecimalPlaces(MAX_DECIMALS).toString(),
|
||||
symbol: datasetSymbol
|
||||
})
|
||||
}
|
||||
} else {
|
||||
if (datasetSymbol === 'OCEAN') {
|
||||
const sum = providerFees.add(priceDataset)
|
||||
totalPrices.push({
|
||||
value: sum.toDecimalPlaces(MAX_DECIMALS).toString(),
|
||||
symbol: datasetSymbol
|
||||
})
|
||||
totalPrices.push({
|
||||
value: priceAlgo.toDecimalPlaces(MAX_DECIMALS).toString(),
|
||||
symbol: algorithmSymbol
|
||||
})
|
||||
} else if (datasetSymbol === algorithmSymbol) {
|
||||
const sum = priceAlgo.add(priceDataset)
|
||||
totalPrices.push({
|
||||
value: sum.toDecimalPlaces(MAX_DECIMALS).toString(),
|
||||
symbol: algorithmSymbol
|
||||
})
|
||||
totalPrices.push({
|
||||
value: providerFees.toDecimalPlaces(MAX_DECIMALS).toString(),
|
||||
symbol: 'OCEAN'
|
||||
})
|
||||
} else {
|
||||
totalPrices.push({
|
||||
value: priceDataset.toDecimalPlaces(MAX_DECIMALS).toString(),
|
||||
symbol: datasetSymbol
|
||||
})
|
||||
totalPrices.push({
|
||||
value: providerFees.toDecimalPlaces(MAX_DECIMALS).toString(),
|
||||
symbol: 'OCEAN'
|
||||
})
|
||||
totalPrices.push({
|
||||
value: priceAlgo.toDecimalPlaces(MAX_DECIMALS).toString(),
|
||||
symbol: algorithmSymbol
|
||||
})
|
||||
}
|
||||
}
|
||||
setTotalPrices(totalPrices)
|
||||
}, [
|
||||
asset,
|
||||
hasPreviousOrder,
|
||||
@ -166,18 +208,18 @@ export default function FormStartCompute({
|
||||
])
|
||||
|
||||
useEffect(() => {
|
||||
const baseTokenBalance = getTokenBalanceFromSymbol(
|
||||
balance,
|
||||
asset?.accessDetails?.baseToken?.symbol
|
||||
)
|
||||
|
||||
if (!totalPrice || !baseTokenBalance || !dtBalance) return
|
||||
setIsBalanceSufficient(
|
||||
compareAsBN(baseTokenBalance, `${totalPrice}`) || Number(dtBalance) >= 1
|
||||
)
|
||||
}, [totalPrice, balance, dtBalance, asset?.accessDetails?.baseToken?.symbol])
|
||||
|
||||
console.log(totalPrice, datasetOrderPrice, algoOrderPrice)
|
||||
totalPrices.forEach((price) => {
|
||||
const baseTokenBalance = getTokenBalanceFromSymbol(balance, price.symbol)
|
||||
if (!baseTokenBalance) {
|
||||
setIsBalanceSufficient(false)
|
||||
return
|
||||
}
|
||||
// if one comparison of baseTokenBalance and token price comparison is false then the state will be false
|
||||
setIsBalanceSufficient(
|
||||
isBalanceSufficient && compareAsBN(baseTokenBalance, `${price.value}`)
|
||||
)
|
||||
})
|
||||
}, [balance, dtBalance, datasetSymbol, algorithmSymbol])
|
||||
|
||||
return (
|
||||
<Form className={styles.form}>
|
||||
@ -208,12 +250,13 @@ export default function FormStartCompute({
|
||||
selectedComputeAssetTimeout={selectedComputeAssetTimeout}
|
||||
hasDatatokenSelectedComputeAsset={hasDatatokenSelectedComputeAsset}
|
||||
algorithmConsumeDetails={selectedAlgorithmAsset?.accessDetails}
|
||||
symbol={oceanSymbol}
|
||||
totalPrice={totalPrice}
|
||||
symbol={datasetSymbol}
|
||||
algorithmSymbol={algorithmSymbol}
|
||||
datasetOrderPrice={datasetOrderPrice}
|
||||
algoOrderPrice={algoOrderPrice}
|
||||
providerFeeAmount={providerFeeAmount}
|
||||
validUntil={validUntil}
|
||||
totalPrices={totalPrices}
|
||||
/>
|
||||
|
||||
<ButtonBuy
|
||||
|
@ -8,7 +8,6 @@ import Decimal from 'decimal.js'
|
||||
import { useWeb3 } from '@context/Web3'
|
||||
|
||||
interface PriceOutputProps {
|
||||
totalPrice: string
|
||||
hasPreviousOrder: boolean
|
||||
hasDatatoken: boolean
|
||||
symbol: string
|
||||
@ -16,11 +15,13 @@ interface PriceOutputProps {
|
||||
hasPreviousOrderSelectedComputeAsset: boolean
|
||||
hasDatatokenSelectedComputeAsset: boolean
|
||||
algorithmConsumeDetails: AccessDetails
|
||||
algorithmSymbol: string
|
||||
selectedComputeAssetTimeout: string
|
||||
datasetOrderPrice?: string
|
||||
algoOrderPrice?: string
|
||||
providerFeeAmount?: string
|
||||
validUntil?: string
|
||||
totalPrices?: totalPriceMap[]
|
||||
}
|
||||
|
||||
function Row({
|
||||
@ -71,7 +72,6 @@ function Row({
|
||||
}
|
||||
|
||||
export default function PriceOutput({
|
||||
totalPrice,
|
||||
hasPreviousOrder,
|
||||
hasDatatoken,
|
||||
assetTimeout,
|
||||
@ -79,18 +79,30 @@ export default function PriceOutput({
|
||||
hasPreviousOrderSelectedComputeAsset,
|
||||
hasDatatokenSelectedComputeAsset,
|
||||
algorithmConsumeDetails,
|
||||
algorithmSymbol,
|
||||
selectedComputeAssetTimeout,
|
||||
datasetOrderPrice,
|
||||
algoOrderPrice,
|
||||
providerFeeAmount,
|
||||
validUntil
|
||||
validUntil,
|
||||
totalPrices
|
||||
}: PriceOutputProps): ReactElement {
|
||||
const { asset } = useAsset()
|
||||
|
||||
return (
|
||||
<div className={styles.priceComponent}>
|
||||
You will pay{' '}
|
||||
<PriceUnit price={Number(totalPrice)} symbol={symbol} size="small" />
|
||||
{totalPrices.map((item, index) => (
|
||||
<div key={item.symbol}>
|
||||
<PriceUnit
|
||||
price={Number(item.value)}
|
||||
symbol={
|
||||
index < totalPrices.length - 1 ? `${item.symbol} & ` : item.symbol
|
||||
}
|
||||
size="small"
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
<Tooltip
|
||||
content={
|
||||
<div className={styles.calculation}>
|
||||
@ -115,18 +127,25 @@ export default function PriceOutput({
|
||||
.toDecimalPlaces(MAX_DECIMALS)
|
||||
.toString()}
|
||||
timeout={selectedComputeAssetTimeout}
|
||||
symbol={symbol}
|
||||
symbol={algorithmSymbol}
|
||||
sign="+"
|
||||
type="ALGORITHM"
|
||||
/>
|
||||
<Row
|
||||
price={providerFeeAmount} // initializeCompute.provider fee amount
|
||||
timeout={`${validUntil} seconds`} // valid until value
|
||||
symbol={symbol}
|
||||
symbol={'OCEAN'} // we assume that provider fees will always be in OCEAN token
|
||||
sign="+"
|
||||
type="C2D RESOURCES"
|
||||
/>
|
||||
<Row price={totalPrice} symbol={symbol} sign="=" />
|
||||
{totalPrices.map((item, index) => (
|
||||
<Row
|
||||
price={item.value}
|
||||
symbol={item.symbol}
|
||||
sign={index === 0 ? '=' : '&'}
|
||||
key={item.symbol}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
|
@ -465,8 +465,8 @@ export default function Compute({
|
||||
assetTimeout={secondsToString(asset?.services[0].timeout)}
|
||||
hasPreviousOrderSelectedComputeAsset={!!validAlgorithmOrderTx}
|
||||
hasDatatokenSelectedComputeAsset={hasAlgoAssetDatatoken}
|
||||
oceanSymbol={
|
||||
asset?.accessDetails?.baseToken?.symbol ||
|
||||
datasetSymbol={asset?.accessDetails?.baseToken?.symbol || 'OCEAN'}
|
||||
algorithmSymbol={
|
||||
selectedAlgorithmAsset?.accessDetails?.baseToken?.symbol ||
|
||||
'OCEAN'
|
||||
}
|
||||
|
@ -45,11 +45,15 @@ export default function Download({
|
||||
const [isPriceLoading, setIsPriceLoading] = useState(false)
|
||||
const [isOwned, setIsOwned] = useState(false)
|
||||
const [validOrderTx, setValidOrderTx] = useState('')
|
||||
const [isOrderDisabled, setIsOrderDisabled] = useState(false)
|
||||
const [orderPriceAndFees, setOrderPriceAndFees] =
|
||||
useState<OrderPriceAndFees>()
|
||||
|
||||
const isUnsupportedPricing = asset?.accessDetails?.type === 'NOT_SUPPORTED'
|
||||
|
||||
useEffect(() => {
|
||||
Number(asset?.nft.state) === 4 && setIsOrderDisabled(true)
|
||||
}, [asset?.nft.state])
|
||||
useEffect(() => {
|
||||
if (!asset?.accessDetails || isUnsupportedPricing) return
|
||||
|
||||
@ -169,7 +173,7 @@ export default function Download({
|
||||
dtSymbol={asset?.datatokens[0]?.symbol}
|
||||
dtBalance={dtBalance}
|
||||
onClick={handleOrderOrDownload}
|
||||
assetTimeout={secondsToString(asset.services[0].timeout)}
|
||||
assetTimeout={secondsToString(asset?.services?.[0]?.timeout)}
|
||||
assetType={asset?.metadata?.type}
|
||||
stepText={statusText}
|
||||
isLoading={isLoading}
|
||||
@ -184,26 +188,36 @@ export default function Download({
|
||||
const AssetAction = ({ asset }: { asset: AssetExtended }) => {
|
||||
return (
|
||||
<div>
|
||||
{isUnsupportedPricing ? (
|
||||
{isOrderDisabled ? (
|
||||
<Alert
|
||||
className={styles.fieldWarning}
|
||||
state="info"
|
||||
text={`No pricing schema available for this asset.`}
|
||||
text={`The publisher temporarily disabled ordering for this asset`}
|
||||
/>
|
||||
) : (
|
||||
<>
|
||||
{isPriceLoading ? (
|
||||
<Loader message="Calculating full price (including fees)" />
|
||||
) : (
|
||||
<Price
|
||||
accessDetails={asset.accessDetails}
|
||||
orderPriceAndFees={orderPriceAndFees}
|
||||
conversion
|
||||
size="large"
|
||||
{isUnsupportedPricing || !asset.services.length ? (
|
||||
<Alert
|
||||
className={styles.fieldWarning}
|
||||
state="info"
|
||||
text={`No pricing schema available for this asset.`}
|
||||
/>
|
||||
)}
|
||||
) : (
|
||||
<>
|
||||
{isPriceLoading ? (
|
||||
<Loader message="Calculating full price (including fees)" />
|
||||
) : (
|
||||
<Price
|
||||
accessDetails={asset.accessDetails}
|
||||
orderPriceAndFees={orderPriceAndFees}
|
||||
conversion
|
||||
size="large"
|
||||
/>
|
||||
)}
|
||||
|
||||
{!isInPurgatory && <PurchaseButton />}
|
||||
{!isInPurgatory && <PurchaseButton />}
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
@ -30,8 +30,8 @@ export default function MetaAsset({
|
||||
networkId={asset?.chainId}
|
||||
path={
|
||||
isBlockscoutExplorer
|
||||
? `tokens/${asset?.services[0].datatokenAddress}`
|
||||
: `token/${asset?.services[0].datatokenAddress}`
|
||||
? `tokens/${asset?.services?.[0]?.datatokenAddress}`
|
||||
: `token/${asset?.services?.[0]?.datatokenAddress}`
|
||||
}
|
||||
>
|
||||
{`Accessed with ${dataTokenSymbol}`}
|
||||
|
@ -41,10 +41,12 @@ export default function EditComputeDataset({
|
||||
|
||||
async function handleSubmit(values: ComputeEditForm, resetForm: () => void) {
|
||||
try {
|
||||
if (asset?.accessDetails?.type === 'free') {
|
||||
if (
|
||||
asset?.accessDetails?.type === 'free' &&
|
||||
asset?.accessDetails?.isPurchasable
|
||||
) {
|
||||
const tx = await setMinterToPublisher(
|
||||
web3,
|
||||
asset?.accessDetails?.addressOrId,
|
||||
asset?.accessDetails?.datatoken?.address,
|
||||
accountId,
|
||||
setError
|
||||
|
@ -1,8 +1,10 @@
|
||||
import React, { ReactElement } from 'react'
|
||||
import { Field, Form } from 'formik'
|
||||
import React, { ReactElement, useEffect } from 'react'
|
||||
import { Field, Form, useField, useFormikContext } from 'formik'
|
||||
import Input, { InputProps } from '@shared/FormInput'
|
||||
import FormActions from './FormActions'
|
||||
import { useAsset } from '@context/Asset'
|
||||
import { FormPublishData } from 'src/components/Publish/_types'
|
||||
import { getFileUrlInfo } from '@utils/provider'
|
||||
|
||||
export function checkIfTimeoutInPredefinedValues(
|
||||
timeout: string,
|
||||
@ -23,7 +25,8 @@ export default function FormEditMetadata({
|
||||
showPrice: boolean
|
||||
isComputeDataset: boolean
|
||||
}): ReactElement {
|
||||
const { oceanConfig } = useAsset()
|
||||
const { oceanConfig, asset } = useAsset()
|
||||
const { values, setFieldValue } = useFormikContext<FormPublishData>()
|
||||
|
||||
// This component is handled by Formik so it's not rendered like a "normal" react component,
|
||||
// so handleTimeoutCustomOption is called only once.
|
||||
@ -41,6 +44,34 @@ export default function FormEditMetadata({
|
||||
timeoutOptionsArray.push('Forever')
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
// let's initiate files with empty url (we can't access the asset url) with type hidden (for UI frontend)
|
||||
setFieldValue('files', [
|
||||
{
|
||||
url: '',
|
||||
type: 'hidden'
|
||||
}
|
||||
])
|
||||
|
||||
const providerUrl = values?.services
|
||||
? values?.services[0].providerUrl.url
|
||||
: asset.services[0].serviceEndpoint
|
||||
// if we have a sample file, we need to get the files' info before setting defaults links value
|
||||
asset?.metadata?.links?.[0] &&
|
||||
getFileUrlInfo(asset.metadata.links[0], providerUrl).then(
|
||||
(checkedFile) => {
|
||||
console.log(checkedFile)
|
||||
// initiate link with values from asset metadata
|
||||
setFieldValue('links', [
|
||||
{
|
||||
url: asset.metadata.links[0],
|
||||
...checkedFile[0]
|
||||
}
|
||||
])
|
||||
}
|
||||
)
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<Form>
|
||||
{data.map(
|
||||
|
@ -11,7 +11,7 @@ export function getInitialValues(
|
||||
name: metadata?.name,
|
||||
description: metadata?.description,
|
||||
price,
|
||||
links: metadata?.links as any,
|
||||
links: [{ url: '', type: '' }],
|
||||
files: [{ url: '', type: '' }],
|
||||
timeout: secondsToString(timeout),
|
||||
author: metadata?.author,
|
||||
|
@ -10,7 +10,15 @@ export const validationSchema = Yup.object().shape({
|
||||
files: Yup.array<FileInfo[]>()
|
||||
.of(
|
||||
Yup.object().shape({
|
||||
url: Yup.string().url('Must be a valid URL.'),
|
||||
url: Yup.string()
|
||||
.url('Must be a valid URL.')
|
||||
.test(
|
||||
'GoogleNotSupported',
|
||||
'Google Drive is not a supported hosting service. Please use an alternative.',
|
||||
(value) => {
|
||||
return !value?.toString().includes('drive.google')
|
||||
}
|
||||
),
|
||||
valid: Yup.boolean().isTrue()
|
||||
})
|
||||
)
|
||||
@ -18,7 +26,15 @@ export const validationSchema = Yup.object().shape({
|
||||
links: Yup.array<FileInfo[]>()
|
||||
.of(
|
||||
Yup.object().shape({
|
||||
url: Yup.string().url('Must be a valid URL.'),
|
||||
url: Yup.string()
|
||||
.url('Must be a valid URL.')
|
||||
.test(
|
||||
'GoogleNotSupported',
|
||||
'Google Drive is not a supported hosting service. Please use an alternative.',
|
||||
(value) => {
|
||||
return !value?.toString().includes('drive.google')
|
||||
}
|
||||
),
|
||||
valid: Yup.boolean().isTrue()
|
||||
})
|
||||
)
|
||||
|
@ -8,6 +8,7 @@ import { useCancelToken } from '@hooks/useCancelToken'
|
||||
import Filters from '../../Search/Filters'
|
||||
import { useMarketMetadata } from '@context/MarketMetadata'
|
||||
import { CancelToken } from 'axios'
|
||||
import { useProfile } from '@context/Profile'
|
||||
|
||||
export default function PublishedList({
|
||||
accountId
|
||||
@ -16,7 +17,7 @@ export default function PublishedList({
|
||||
}): ReactElement {
|
||||
const { appConfig } = useMarketMetadata()
|
||||
const { chainIds } = useUserPreferences()
|
||||
|
||||
const { ownAccount } = useProfile()
|
||||
const [queryResult, setQueryResult] = useState<PagedAssets>()
|
||||
const [isLoading, setIsLoading] = useState(false)
|
||||
const [page, setPage] = useState<number>(1)
|
||||
@ -39,6 +40,7 @@ export default function PublishedList({
|
||||
accountId.toLowerCase(),
|
||||
chainIds,
|
||||
cancelToken,
|
||||
ownAccount,
|
||||
page,
|
||||
service,
|
||||
access
|
||||
@ -50,7 +52,7 @@ export default function PublishedList({
|
||||
setIsLoading(false)
|
||||
}
|
||||
},
|
||||
[]
|
||||
[ownAccount]
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -32,7 +32,17 @@ const validationService = {
|
||||
files: Yup.array<FileInfo[]>()
|
||||
.of(
|
||||
Yup.object().shape({
|
||||
url: Yup.string().url('Must be a valid URL.').required('Required'),
|
||||
url: Yup.string()
|
||||
.test(
|
||||
'GoogleNotSupported',
|
||||
'Google Drive is not a supported hosting service. Please use an alternative.',
|
||||
(value) => {
|
||||
return !value?.toString().includes('drive.google')
|
||||
}
|
||||
)
|
||||
.url('Must be a valid URL.')
|
||||
.required('Required'),
|
||||
|
||||
valid: Yup.boolean().isTrue().required('File must be valid.')
|
||||
})
|
||||
)
|
||||
@ -41,7 +51,15 @@ const validationService = {
|
||||
links: Yup.array<FileInfo[]>()
|
||||
.of(
|
||||
Yup.object().shape({
|
||||
url: Yup.string().url('Must be a valid URL.'),
|
||||
url: Yup.string()
|
||||
.url('Must be a valid URL.')
|
||||
.test(
|
||||
'GoogleNotSupported',
|
||||
'Google Drive is not a supported hosting service. Please use an alternative.',
|
||||
(value) => {
|
||||
return !value?.toString().includes('drive.google')
|
||||
}
|
||||
),
|
||||
// TODO: require valid file only when URL is given
|
||||
valid: Yup.boolean()
|
||||
// valid: Yup.boolean().isTrue('File must be valid.')
|
||||
|
@ -13,7 +13,7 @@ export default function PageProfile(): ReactElement {
|
||||
const { accountId, accountEns } = useWeb3()
|
||||
const [finalAccountId, setFinalAccountId] = useState<string>()
|
||||
const [finalAccountEns, setFinalAccountEns] = useState<string>()
|
||||
|
||||
const [ownAccount, setOwnAccount] = useState(false)
|
||||
// Have accountId in path take over, if not present fall back to web3
|
||||
useEffect(() => {
|
||||
async function init() {
|
||||
@ -23,6 +23,7 @@ export default function PageProfile(): ReactElement {
|
||||
if (router.asPath === '/profile') {
|
||||
setFinalAccountEns(accountEns)
|
||||
setFinalAccountId(accountId)
|
||||
setOwnAccount(true)
|
||||
return
|
||||
}
|
||||
|
||||
@ -30,6 +31,7 @@ export default function PageProfile(): ReactElement {
|
||||
|
||||
// Path has ETH address
|
||||
if (web3.utils.isAddress(pathAccount)) {
|
||||
setOwnAccount(pathAccount === accountId)
|
||||
const finalAccountId = pathAccount || accountId
|
||||
setFinalAccountId(finalAccountId)
|
||||
|
||||
@ -45,6 +47,7 @@ export default function PageProfile(): ReactElement {
|
||||
resolvedAccountId === '0x0000000000000000000000000000000000000000'
|
||||
)
|
||||
return
|
||||
setOwnAccount(resolvedAccountId === accountId)
|
||||
setFinalAccountId(resolvedAccountId)
|
||||
}
|
||||
}
|
||||
@ -66,7 +69,11 @@ export default function PageProfile(): ReactElement {
|
||||
title={accountTruncate(finalAccountId)}
|
||||
noPageHeader
|
||||
>
|
||||
<ProfileProvider accountId={finalAccountId} accountEns={finalAccountEns}>
|
||||
<ProfileProvider
|
||||
accountId={finalAccountId}
|
||||
accountEns={finalAccountEns}
|
||||
ownAccount={ownAccount}
|
||||
>
|
||||
<ProfilePage accountId={finalAccountId} />
|
||||
</ProfileProvider>
|
||||
</Page>
|
||||
|
Loading…
Reference in New Issue
Block a user