mirror of
https://github.com/oceanprotocol/market.git
synced 2024-12-02 05:57:29 +01:00
Feature/wagmi (#1912)
* wagmi + ethers + web3modal setup
* refactor wallet components
* fallback providers, more config
* kick out useWeb3
* remove all useWeb3 imports
* more web3.js usage removal
* isAddress utils replacement
* restore add token / add network
* less accountId changes
* web3 legacy tinkering, utils/web3 → utils/wallet
* legacy web3 object for ocean.js
* graph sync fix, remove custom network switching code
* package updates, merge fixes
* downgrade to ethers v5
* fix project id
* switch to ConnectKit
* connectkit theming
* add existing chains to wagmi
* rewrite getPaymentCollector()
* kick out getPaymentCollector completely, use wagmi hooks instead
* Revert "kick out getPaymentCollector completely, use wagmi hooks instead"
This reverts commit 54c7d1ef1a
.
* switch getPaymentCollector
* calcBaseInGivenDatatokensOut reorg
* wip integrate ocean lib 3.0.0
* update orbis components to use wagmi instead of web hooks
* more oceanjs integration updates
* more refactors
* fix build
* update ocean lib
* fix publish
* fix order fixed rate
* remove logs
* debug and stop infinite cycle orbis connect
* fix orbis dm connection
* mock use network and fix some more tests
* mock wagmi switch network
* mock wagmi useProvider createClient and connectKit getDefaultClient
* fix jest tests
* try storybook fix
* cleanups and bump ocean lib
* fix order
* bump lib to next.5 and add more modal style
* bump ocean.js lib to 3.0.0
---------
Co-authored-by: Matthias Kretschmann <m@kretschmann.io>
This commit is contained in:
parent
ecef35ef61
commit
165a9b0fb3
@ -1,4 +1,5 @@
|
||||
#NEXT_PUBLIC_INFURA_PROJECT_ID="xxx"
|
||||
#NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID="xxx"
|
||||
#NEXT_PUBLIC_MARKET_FEE_ADDRESS="0xxx"
|
||||
#NEXT_PUBLIC_PUBLISHER_MARKET_ORDER_FEE="1"
|
||||
#NEXT_PUBLIC_PUBLISHER_MARKET_FIXED_SWAP_FEE="1"
|
||||
|
5
.jest/__fixtures__/wagni.ts
Normal file
5
.jest/__fixtures__/wagni.ts
Normal file
@ -0,0 +1,5 @@
|
||||
export const network = {
|
||||
account: '0x123',
|
||||
chainId: 1,
|
||||
networkId: 1
|
||||
}
|
3
.jest/__mocks__/connectkit.js
Normal file
3
.jest/__mocks__/connectkit.js
Normal file
@ -0,0 +1,3 @@
|
||||
export function getDefaultClient() {
|
||||
return jest.fn()
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
import marketMetadata from '../__fixtures__/marketMetadata'
|
||||
import userPreferences from '../__fixtures__/userPreferences'
|
||||
import web3 from '../__fixtures__/web3'
|
||||
import { network } from '../__fixtures__/wagni'
|
||||
import { asset } from '../__fixtures__/datasetWithAccessDetails'
|
||||
|
||||
jest.mock('../../src/@context/MarketMetadata', () => ({
|
||||
@ -11,10 +11,13 @@ jest.mock('../../src/@context/UserPreferences', () => ({
|
||||
useUserPreferences: () => userPreferences
|
||||
}))
|
||||
|
||||
jest.mock('../../src/@context/Web3', () => ({
|
||||
useWeb3: () => web3
|
||||
}))
|
||||
|
||||
jest.mock('../../../@context/Asset', () => ({
|
||||
useAsset: () => ({ asset })
|
||||
}))
|
||||
|
||||
jest.mock('wagmi', () => ({
|
||||
useNetwork: () => ({ network }),
|
||||
useSwitchNetwork: () => ({ switchNetwork: () => jest.fn() }),
|
||||
useProvider: () => jest.fn(),
|
||||
createClient: () => jest.fn()
|
||||
}))
|
||||
|
@ -2,6 +2,7 @@ import '@testing-library/jest-dom/extend-expect'
|
||||
import { jest } from '@jest/globals'
|
||||
import './__mocks__/matchMedia'
|
||||
import './__mocks__/hooksMocks'
|
||||
import './__mocks__/connectkit'
|
||||
|
||||
jest.mock('next/router', () => ({
|
||||
useRouter: jest.fn().mockImplementation(() => ({
|
||||
|
@ -43,7 +43,10 @@ module.exports = {
|
||||
crypto: false,
|
||||
os: false,
|
||||
stream: false,
|
||||
assert: false
|
||||
assert: false,
|
||||
tls: false,
|
||||
net: false,
|
||||
zlib: false
|
||||
})
|
||||
config.resolve.fallback = fallback
|
||||
|
||||
|
14
README.md
14
README.md
@ -238,12 +238,12 @@ function Component() {
|
||||
For account purgatory:
|
||||
|
||||
```tsx
|
||||
import { useWeb3 } from '@context/Web3'
|
||||
import { useAccount } from 'wagmi'
|
||||
import { useAccountPurgatory } from '@hooks/useAccountPurgatory'
|
||||
|
||||
function Component() {
|
||||
const { accountId } = useWeb3()
|
||||
const { isInPurgatory, purgatoryData } = useAccountPurgatory(accountId)
|
||||
const { address } = useAccount()
|
||||
const { isInPurgatory, purgatoryData } = useAccountPurgatory(address)
|
||||
return isInPurgatory ? <div>{purgatoryData.reason}</div> : null
|
||||
}
|
||||
```
|
||||
@ -252,14 +252,12 @@ function Component() {
|
||||
|
||||
All displayed chain & network metadata is retrieved from `https://chainid.network` on build time and integrated into NEXT's GraphQL layer. This data source is a community-maintained GitHub repository under [ethereum-lists/chains](https://github.com/ethereum-lists/chains).
|
||||
|
||||
Within components this metadata can be queried for under `allNetworksMetadataJson`. The `useWeb3()` hook does this in the background to expose the final `networkDisplayName` for use in components:
|
||||
Within components this metadata can be queried for under `allNetworksMetadataJson`. The `useNetworkMetadata()` hook does this in the background to expose the final `networkDisplayName` for use in components:
|
||||
|
||||
```tsx
|
||||
export default function NetworkName(): ReactElement {
|
||||
const { networkId, isTestnet } = useWeb3()
|
||||
const { networksList } = useNetworkMetadata()
|
||||
const networkData = getNetworkDataById(networksList, networkId)
|
||||
const networkName = getNetworkDisplayName(networkData)
|
||||
const { isTestnet } = useNetworkMetadata()
|
||||
const { networkData, networkName } = useNetworkMetadata()
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -16,8 +16,6 @@ module.exports = {
|
||||
// List of all supported chainIds. Used to populate the Chains user preferences list.
|
||||
chainIdsSupported: [1, 137, 56, 246, 1285, 5, 80001],
|
||||
|
||||
infuraProjectId: process.env.NEXT_PUBLIC_INFURA_PROJECT_ID || 'xxx',
|
||||
|
||||
defaultDatatokenTemplateIndex: 2,
|
||||
// The ETH address the marketplace fee will be sent to.
|
||||
marketFeeAddress:
|
||||
|
@ -36,7 +36,9 @@ module.exports = (phase, { defaultConfig }) => {
|
||||
crypto: false,
|
||||
os: false,
|
||||
stream: false,
|
||||
assert: false
|
||||
assert: false,
|
||||
tls: false,
|
||||
net: false
|
||||
})
|
||||
config.resolve.fallback = fallback
|
||||
|
||||
|
11848
package-lock.json
generated
11848
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
10
package.json
10
package.json
@ -29,20 +29,20 @@
|
||||
"@coingecko/cryptoformat": "^0.5.4",
|
||||
"@loadable/component": "^5.15.2",
|
||||
"@oceanprotocol/art": "^3.2.0",
|
||||
"@oceanprotocol/lib": "^2.7.0",
|
||||
"@oceanprotocol/lib": "^3.0.0",
|
||||
"@oceanprotocol/typographies": "^0.1.0",
|
||||
"@oceanprotocol/use-dark-mode": "^2.4.3",
|
||||
"@orbisclub/orbis-sdk": "^0.4.40",
|
||||
"@tippyjs/react": "^4.2.6",
|
||||
"@uiw/react-codemirror": "^4.19.5",
|
||||
"@urql/exchange-refocus": "^1.0.0",
|
||||
"@walletconnect/web3-provider": "^1.8.0",
|
||||
"axios": "^1.2.0",
|
||||
"classnames": "^2.3.2",
|
||||
"connectkit": "^1.2.3",
|
||||
"date-fns": "^2.29.3",
|
||||
"decimal.js": "^10.4.2",
|
||||
"dom-confetti": "^0.2.2",
|
||||
"dotenv": "^16.0.3",
|
||||
"ethers": "^5.7.2",
|
||||
"filesize": "^10.0.7",
|
||||
"formik": "^2.2.9",
|
||||
"gray-matter": "^4.0.3",
|
||||
@ -52,6 +52,7 @@
|
||||
"match-sorter": "^6.3.1",
|
||||
"myetherwallet-blockies": "^0.1.1",
|
||||
"next": "13.0.5",
|
||||
"npm": "^9.6.5",
|
||||
"posthog-js": "^1.51.4",
|
||||
"query-string": "^8.1.0",
|
||||
"react": "^18.2.0",
|
||||
@ -73,8 +74,7 @@
|
||||
"slugify": "^1.6.5",
|
||||
"swr": "^1.3.0",
|
||||
"urql": "^3.0.3",
|
||||
"web3": "^1.8.1",
|
||||
"web3modal": "^1.9.12",
|
||||
"wagmi": "^0.12.12",
|
||||
"yup": "^0.32.11"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
@ -10,7 +10,6 @@ import React, {
|
||||
import { Config, LoggerInstance, Purgatory } from '@oceanprotocol/lib'
|
||||
import { CancelToken } from 'axios'
|
||||
import { getAsset } from '@utils/aquarius'
|
||||
import { useWeb3 } from './Web3'
|
||||
import { useCancelToken } from '@hooks/useCancelToken'
|
||||
import { getOceanConfig, getDevelopmentConfig } from '@utils/ocean'
|
||||
import { getAccessDetails } from '@utils/accessDetailsAndPricing'
|
||||
@ -18,6 +17,7 @@ import { useIsMounted } from '@hooks/useIsMounted'
|
||||
import { useMarketMetadata } from './MarketMetadata'
|
||||
import { assetStateToString } from '@utils/assetState'
|
||||
import { isValidDid } from '@utils/ddo'
|
||||
import { useAccount, useNetwork } from 'wagmi'
|
||||
|
||||
export interface AssetProviderValue {
|
||||
isInPurgatory: boolean
|
||||
@ -44,8 +44,9 @@ function AssetProvider({
|
||||
children: ReactNode
|
||||
}): ReactElement {
|
||||
const { appConfig } = useMarketMetadata()
|
||||
const { address: accountId } = useAccount()
|
||||
const { chain } = useNetwork()
|
||||
|
||||
const { chainId, accountId } = useWeb3()
|
||||
const [isInPurgatory, setIsInPurgatory] = useState(false)
|
||||
const [purgatoryData, setPurgatoryData] = useState<Purgatory>()
|
||||
const [asset, setAsset] = useState<AssetExtended>()
|
||||
@ -158,11 +159,11 @@ function AssetProvider({
|
||||
// Check user network against asset network
|
||||
// -----------------------------------
|
||||
useEffect(() => {
|
||||
if (!chainId || !asset?.chainId) return
|
||||
if (!chain?.id || !asset?.chainId) return
|
||||
|
||||
const isAssetNetwork = chainId === asset?.chainId
|
||||
const isAssetNetwork = chain?.id === asset?.chainId
|
||||
setIsAssetNetwork(isAssetNetwork)
|
||||
}, [chainId, asset?.chainId])
|
||||
}, [chain?.id, asset?.chainId])
|
||||
|
||||
// -----------------------------------
|
||||
// Asset owner check against wallet user
|
||||
|
@ -9,8 +9,8 @@ import React, {
|
||||
} from 'react'
|
||||
import { useInterval } from '@hooks/useInterval'
|
||||
import { Orbis } from '@orbisclub/orbis-sdk'
|
||||
import { useWeb3 } from '../Web3'
|
||||
import { accountTruncate } from '@utils/web3'
|
||||
import { accountTruncate } from '@utils/wallet'
|
||||
import { useAccount, useSigner, useProvider } from 'wagmi'
|
||||
import { didToAddress, sleep } from '@shared/DirectMessages/_utils'
|
||||
import { getEnsName } from '@utils/ens'
|
||||
import usePrevious from '@hooks/usePrevious'
|
||||
@ -32,7 +32,9 @@ const CONVERSATION_CONTEXT =
|
||||
process.env.NEXT_PUBLIC_ORBIS_CONTEXT || 'ocean_market' // Can be changed to whatever
|
||||
|
||||
function OrbisProvider({ children }: { children: ReactNode }): ReactElement {
|
||||
const { web3Provider, accountId } = useWeb3()
|
||||
const { address: accountId } = useAccount()
|
||||
const { data: signer } = useSigner()
|
||||
const web3Provider = useProvider()
|
||||
const prevAccountId = usePrevious(accountId)
|
||||
|
||||
const [ceramicSessions, setCeramicSessions] = useLocalStorage<string[]>(
|
||||
@ -81,12 +83,12 @@ function OrbisProvider({ children }: { children: ReactNode }): ReactElement {
|
||||
address: string
|
||||
lit?: boolean
|
||||
}) => {
|
||||
const signerProvide: any = signer?.provider
|
||||
const res = await orbis.connect_v2({
|
||||
provider: web3Provider,
|
||||
provider: signerProvide.provider,
|
||||
chain: 'ethereum',
|
||||
lit
|
||||
})
|
||||
|
||||
if (res.status === 200) {
|
||||
const { data } = await orbis.getProfile(res.did)
|
||||
setAccount(data)
|
||||
@ -98,7 +100,7 @@ function OrbisProvider({ children }: { children: ReactNode }): ReactElement {
|
||||
})
|
||||
return data
|
||||
} else {
|
||||
await connectOrbis({ address })
|
||||
// await connectOrbis({ address })
|
||||
}
|
||||
}
|
||||
|
||||
@ -137,8 +139,12 @@ function OrbisProvider({ children }: { children: ReactNode }): ReactElement {
|
||||
setAccount(data)
|
||||
return data
|
||||
} else if (autoConnect) {
|
||||
const data = await connectOrbis({ address, lit })
|
||||
return data
|
||||
try {
|
||||
const data = await connectOrbis({ address, lit })
|
||||
return data
|
||||
} catch (err) {
|
||||
return null
|
||||
}
|
||||
} else {
|
||||
resetStates()
|
||||
removeLitSignature()
|
||||
|
@ -7,7 +7,6 @@ export interface OpcFee {
|
||||
|
||||
export interface AppConfig {
|
||||
metadataCacheUri: string
|
||||
infuraProjectId: string
|
||||
chainIds: number[]
|
||||
chainIdsSupported: number[]
|
||||
defaultDatatokenTemplateIndex: number
|
||||
@ -49,4 +48,5 @@ export interface MarketMetadataProviderValue {
|
||||
siteContent: SiteContent
|
||||
appConfig: AppConfig
|
||||
getOpcFeeForToken: (tokenAddress: string, chainId: number) => string
|
||||
approvedBaseTokens: TokenInfo[]
|
||||
}
|
||||
|
@ -13,8 +13,13 @@ import { opcQuery } from './_queries'
|
||||
import { MarketMetadataProviderValue, OpcFee } from './_types'
|
||||
import siteContent from '../../../content/site.json'
|
||||
import appConfig from '../../../app.config'
|
||||
import { fetchData, getQueryContext } from '@utils/subgraph'
|
||||
import {
|
||||
fetchData,
|
||||
getQueryContext,
|
||||
getOpcsApprovedTokens
|
||||
} from '@utils/subgraph'
|
||||
import { LoggerInstance } from '@oceanprotocol/lib'
|
||||
import { useNetwork, useConnect } from 'wagmi'
|
||||
|
||||
const MarketMetadataContext = createContext({} as MarketMetadataProviderValue)
|
||||
|
||||
@ -23,7 +28,11 @@ function MarketMetadataProvider({
|
||||
}: {
|
||||
children: ReactNode
|
||||
}): ReactElement {
|
||||
const { isLoading } = useConnect()
|
||||
const { chain } = useNetwork()
|
||||
|
||||
const [opcFees, setOpcFees] = useState<OpcFee[]>()
|
||||
const [approvedBaseTokens, setApprovedBaseTokens] = useState<TokenInfo[]>()
|
||||
|
||||
useEffect(() => {
|
||||
async function getOpcData() {
|
||||
@ -64,6 +73,28 @@ function MarketMetadataProvider({
|
||||
},
|
||||
[opcFees]
|
||||
)
|
||||
|
||||
// -----------------------------------
|
||||
// Get and set approved base tokens list
|
||||
// -----------------------------------
|
||||
const getApprovedBaseTokens = useCallback(async (chainId: number) => {
|
||||
try {
|
||||
const approvedTokensList = await getOpcsApprovedTokens(chainId)
|
||||
setApprovedBaseTokens(approvedTokensList)
|
||||
LoggerInstance.log(
|
||||
'[MarketMetadata] Approved baseTokens',
|
||||
approvedTokensList
|
||||
)
|
||||
} catch (error) {
|
||||
LoggerInstance.error('[MarketMetadata] Error: ', error.message)
|
||||
}
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
if (isLoading) return
|
||||
getApprovedBaseTokens(chain?.id || 1)
|
||||
}, [chain?.id, getApprovedBaseTokens, isLoading])
|
||||
|
||||
return (
|
||||
<MarketMetadataContext.Provider
|
||||
value={
|
||||
@ -71,7 +102,8 @@ function MarketMetadataProvider({
|
||||
opcFees,
|
||||
siteContent,
|
||||
appConfig,
|
||||
getOpcFeeForToken
|
||||
getOpcFeeForToken,
|
||||
approvedBaseTokens
|
||||
} as MarketMetadataProviderValue
|
||||
}
|
||||
>
|
||||
|
@ -16,9 +16,9 @@ import {
|
||||
getUserSales
|
||||
} from '@utils/aquarius'
|
||||
import axios, { CancelToken } from 'axios'
|
||||
import web3 from 'web3'
|
||||
import { useMarketMetadata } from '../MarketMetadata'
|
||||
import { getEnsProfile } from '@utils/ens'
|
||||
import { isAddress } from 'ethers/lib/utils'
|
||||
|
||||
interface ProfileProviderValue {
|
||||
profile: Profile
|
||||
@ -64,7 +64,7 @@ function ProfileProvider({
|
||||
// when accountId is no ETH address
|
||||
//
|
||||
useEffect(() => {
|
||||
const isEthAddress = web3.utils.isAddress(accountId)
|
||||
const isEthAddress = isAddress(accountId)
|
||||
setIsEthAddress(isEthAddress)
|
||||
}, [accountId])
|
||||
|
||||
|
@ -1,442 +0,0 @@
|
||||
import React, {
|
||||
useContext,
|
||||
useState,
|
||||
useEffect,
|
||||
createContext,
|
||||
ReactElement,
|
||||
ReactNode,
|
||||
useCallback
|
||||
} from 'react'
|
||||
import Web3 from 'web3'
|
||||
import Web3Modal, { getProviderInfo, IProviderInfo } from 'web3modal'
|
||||
import { infuraProjectId as infuraId } from '../../app.config'
|
||||
import WalletConnectProvider from '@walletconnect/web3-provider'
|
||||
import { LoggerInstance } from '@oceanprotocol/lib'
|
||||
import { isBrowser } from '@utils/index'
|
||||
import { getEnsProfile } from '@utils/ens'
|
||||
import useNetworkMetadata, {
|
||||
getNetworkDataById,
|
||||
getNetworkDisplayName,
|
||||
getNetworkType,
|
||||
NetworkType
|
||||
} from '../@hooks/useNetworkMetadata'
|
||||
import { useMarketMetadata } from './MarketMetadata'
|
||||
import { getTokenBalance } from '@utils/web3'
|
||||
import { getOpcsApprovedTokens } from '@utils/subgraph'
|
||||
|
||||
interface Web3ProviderValue {
|
||||
web3: Web3
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
web3Provider: any
|
||||
web3Modal: Web3Modal
|
||||
web3ProviderInfo: IProviderInfo
|
||||
accountId: string
|
||||
accountEns: string
|
||||
accountEnsAvatar: string
|
||||
balance: UserBalance
|
||||
networkId: number
|
||||
chainId: number
|
||||
networkDisplayName: string
|
||||
networkData: EthereumListsChain
|
||||
block: number
|
||||
isTestnet: boolean
|
||||
web3Loading: boolean
|
||||
isSupportedOceanNetwork: boolean
|
||||
approvedBaseTokens: TokenInfo[]
|
||||
connect: () => Promise<string>
|
||||
logout: () => Promise<void>
|
||||
}
|
||||
|
||||
const web3ModalTheme = {
|
||||
background: 'var(--background-body)',
|
||||
main: 'var(--font-color-heading)',
|
||||
secondary: 'var(--brand-grey-light)',
|
||||
border: 'var(--border-color)',
|
||||
hover: 'var(--background-highlight)'
|
||||
}
|
||||
|
||||
const providerOptions = isBrowser
|
||||
? {
|
||||
walletconnect: {
|
||||
package: WalletConnectProvider,
|
||||
options: {
|
||||
infuraId,
|
||||
rpc: {
|
||||
137: 'https://polygon-rpc.com',
|
||||
80001: 'https://rpc-mumbai.matic.today'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
: {}
|
||||
|
||||
export const web3ModalOpts = {
|
||||
cacheProvider: true,
|
||||
providerOptions,
|
||||
theme: web3ModalTheme
|
||||
}
|
||||
|
||||
const refreshInterval = 20000 // 20 sec.
|
||||
|
||||
const Web3Context = createContext({} as Web3ProviderValue)
|
||||
|
||||
function Web3Provider({ children }: { children: ReactNode }): ReactElement {
|
||||
const { networksList } = useNetworkMetadata()
|
||||
const { appConfig } = useMarketMetadata()
|
||||
|
||||
const [web3, setWeb3] = useState<Web3>()
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const [web3Provider, setWeb3Provider] = useState<any>()
|
||||
|
||||
const [web3Modal, setWeb3Modal] = useState<Web3Modal>()
|
||||
const [web3ProviderInfo, setWeb3ProviderInfo] = useState<IProviderInfo>()
|
||||
const [networkId, setNetworkId] = useState<number>()
|
||||
const [chainId, setChainId] = useState<number>()
|
||||
const [networkDisplayName, setNetworkDisplayName] = useState<string>()
|
||||
const [networkData, setNetworkData] = useState<EthereumListsChain>()
|
||||
const [block, setBlock] = useState<number>()
|
||||
const [isTestnet, setIsTestnet] = useState<boolean>()
|
||||
const [accountId, setAccountId] = useState<string>()
|
||||
const [accountEns, setAccountEns] = useState<string>()
|
||||
const [accountEnsAvatar, setAccountEnsAvatar] = useState<string>()
|
||||
const [web3Loading, setWeb3Loading] = useState<boolean>(true)
|
||||
const [balance, setBalance] = useState<UserBalance>({
|
||||
eth: '0'
|
||||
})
|
||||
const [isSupportedOceanNetwork, setIsSupportedOceanNetwork] = useState(true)
|
||||
const [approvedBaseTokens, setApprovedBaseTokens] = useState<TokenInfo[]>()
|
||||
|
||||
// -----------------------------------
|
||||
// Helper: connect to web3
|
||||
// -----------------------------------
|
||||
const connect = useCallback(async () => {
|
||||
if (!web3Modal) {
|
||||
setWeb3Loading(false)
|
||||
return
|
||||
}
|
||||
try {
|
||||
setWeb3Loading(true)
|
||||
LoggerInstance.log('[web3] Connecting Web3...')
|
||||
|
||||
const provider = await web3Modal?.connect()
|
||||
setWeb3Provider(provider)
|
||||
|
||||
const web3 = new Web3(provider)
|
||||
setWeb3(web3)
|
||||
LoggerInstance.log('[web3] Web3 created.', web3)
|
||||
|
||||
const networkId = await web3.eth.net.getId()
|
||||
setNetworkId(networkId)
|
||||
LoggerInstance.log('[web3] network id ', networkId)
|
||||
|
||||
const chainId = await web3.eth.getChainId()
|
||||
setChainId(chainId)
|
||||
LoggerInstance.log('[web3] chain id ', chainId)
|
||||
|
||||
const accountId = (await web3.eth.getAccounts())[0]
|
||||
setAccountId(accountId)
|
||||
LoggerInstance.log('[web3] account id', accountId)
|
||||
return accountId
|
||||
} catch (error) {
|
||||
LoggerInstance.error('[web3] Error: ', error.message)
|
||||
return null
|
||||
} finally {
|
||||
setWeb3Loading(false)
|
||||
}
|
||||
}, [web3Modal])
|
||||
|
||||
// -----------------------------------
|
||||
// Helper: Get approved base tokens list
|
||||
// -----------------------------------
|
||||
const getApprovedBaseTokens = useCallback(async (chainId: number) => {
|
||||
try {
|
||||
const approvedTokensList = await getOpcsApprovedTokens(chainId)
|
||||
setApprovedBaseTokens(approvedTokensList)
|
||||
LoggerInstance.log('[web3] Approved baseTokens', approvedTokensList)
|
||||
} catch (error) {
|
||||
LoggerInstance.error('[web3] Error: ', error.message)
|
||||
}
|
||||
}, [])
|
||||
|
||||
// -----------------------------------
|
||||
// Helper: Get user balance
|
||||
// -----------------------------------
|
||||
const getUserBalance = useCallback(async () => {
|
||||
if (!accountId || !networkId || !web3 || !networkData) return
|
||||
|
||||
try {
|
||||
const userBalance = web3.utils.fromWei(
|
||||
await web3.eth.getBalance(accountId, 'latest')
|
||||
)
|
||||
const key = networkData.nativeCurrency.symbol.toLowerCase()
|
||||
const balance: UserBalance = { [key]: userBalance }
|
||||
|
||||
if (approvedBaseTokens?.length > 0) {
|
||||
await Promise.all(
|
||||
approvedBaseTokens.map(async (token) => {
|
||||
const { address, decimals, symbol } = token
|
||||
const tokenBalance = await getTokenBalance(
|
||||
accountId,
|
||||
decimals,
|
||||
address,
|
||||
web3
|
||||
)
|
||||
balance[symbol.toLocaleLowerCase()] = tokenBalance
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
setBalance(balance)
|
||||
LoggerInstance.log('[web3] Balance: ', balance)
|
||||
} catch (error) {
|
||||
LoggerInstance.error('[web3] Error: ', error.message)
|
||||
}
|
||||
}, [accountId, approvedBaseTokens, networkId, web3, networkData])
|
||||
|
||||
// -----------------------------------
|
||||
// Helper: Get user ENS info
|
||||
// -----------------------------------
|
||||
const getUserEns = useCallback(async () => {
|
||||
if (!accountId) return
|
||||
|
||||
try {
|
||||
const profile = await getEnsProfile(accountId)
|
||||
|
||||
if (!profile) {
|
||||
setAccountEns(null)
|
||||
setAccountEnsAvatar(null)
|
||||
return
|
||||
}
|
||||
|
||||
setAccountEns(profile.name)
|
||||
LoggerInstance.log(
|
||||
`[web3] ENS name found for ${accountId}:`,
|
||||
profile.name
|
||||
)
|
||||
|
||||
if (profile.avatar) {
|
||||
setAccountEnsAvatar(profile.avatar)
|
||||
LoggerInstance.log(
|
||||
`[web3] ENS avatar found for ${accountId}:`,
|
||||
profile.avatar
|
||||
)
|
||||
} else {
|
||||
setAccountEnsAvatar(null)
|
||||
}
|
||||
} catch (error) {
|
||||
LoggerInstance.error('[web3] Error: ', error.message)
|
||||
}
|
||||
}, [accountId])
|
||||
|
||||
// -----------------------------------
|
||||
// Create initial Web3Modal instance
|
||||
// -----------------------------------
|
||||
useEffect(() => {
|
||||
if (web3Modal) {
|
||||
setWeb3Loading(false)
|
||||
return
|
||||
}
|
||||
|
||||
async function init() {
|
||||
// note: needs artificial await here so the log message is reached and output
|
||||
const web3ModalInstance = await new Web3Modal(web3ModalOpts)
|
||||
setWeb3Modal(web3ModalInstance)
|
||||
LoggerInstance.log(
|
||||
'[web3] Web3Modal instance created.',
|
||||
web3ModalInstance
|
||||
)
|
||||
}
|
||||
init()
|
||||
}, [connect, web3Modal])
|
||||
|
||||
// -----------------------------------
|
||||
// Reconnect automatically for returning users
|
||||
// -----------------------------------
|
||||
useEffect(() => {
|
||||
if (!web3Modal?.cachedProvider) return
|
||||
|
||||
async function connectCached() {
|
||||
LoggerInstance.log(
|
||||
'[web3] Connecting to cached provider: ',
|
||||
web3Modal.cachedProvider
|
||||
)
|
||||
await connect()
|
||||
}
|
||||
connectCached()
|
||||
}, [connect, web3Modal])
|
||||
|
||||
// -----------------------------------
|
||||
// Get and set approved base tokens list
|
||||
// -----------------------------------
|
||||
useEffect(() => {
|
||||
if (web3Loading) return
|
||||
getApprovedBaseTokens(chainId || 1)
|
||||
}, [chainId, getApprovedBaseTokens, web3Loading])
|
||||
|
||||
// -----------------------------------
|
||||
// Get and set user balance
|
||||
// -----------------------------------
|
||||
useEffect(() => {
|
||||
getUserBalance()
|
||||
|
||||
// init periodic refresh of wallet balance
|
||||
const balanceInterval = setInterval(() => getUserBalance(), refreshInterval)
|
||||
|
||||
return () => {
|
||||
clearInterval(balanceInterval)
|
||||
}
|
||||
}, [getUserBalance])
|
||||
|
||||
// -----------------------------------
|
||||
// Get and set user ENS info
|
||||
// -----------------------------------
|
||||
useEffect(() => {
|
||||
getUserEns()
|
||||
}, [getUserEns])
|
||||
|
||||
// -----------------------------------
|
||||
// Get and set network metadata
|
||||
// -----------------------------------
|
||||
useEffect(() => {
|
||||
if (!networkId) return
|
||||
const networkData = getNetworkDataById(networksList, networkId)
|
||||
setNetworkData(networkData)
|
||||
LoggerInstance.log(
|
||||
networkData
|
||||
? `[web3] Network metadata found.`
|
||||
: `[web3] No network metadata found.`,
|
||||
networkData
|
||||
)
|
||||
|
||||
// Construct network display name
|
||||
const networkDisplayName = getNetworkDisplayName(networkData)
|
||||
setNetworkDisplayName(networkDisplayName)
|
||||
|
||||
setIsTestnet(getNetworkType(networkData) !== NetworkType.Mainnet)
|
||||
|
||||
LoggerInstance.log(
|
||||
`[web3] Network display name set to: ${networkDisplayName}`
|
||||
)
|
||||
}, [networkId, networksList])
|
||||
|
||||
// -----------------------------------
|
||||
// Get and set latest head block
|
||||
// -----------------------------------
|
||||
useEffect(() => {
|
||||
if (!web3) return
|
||||
|
||||
async function getBlock() {
|
||||
const block = await web3.eth.getBlockNumber()
|
||||
setBlock(block)
|
||||
LoggerInstance.log('[web3] Head block: ', block)
|
||||
}
|
||||
getBlock()
|
||||
}, [web3, networkId])
|
||||
|
||||
// -----------------------------------
|
||||
// Get and set web3 provider info
|
||||
// -----------------------------------
|
||||
// Workaround cause getInjectedProviderName() always returns `MetaMask`
|
||||
// https://github.com/oceanprotocol/market/issues/332
|
||||
useEffect(() => {
|
||||
if (!web3Provider) return
|
||||
|
||||
const providerInfo = getProviderInfo(web3Provider)
|
||||
setWeb3ProviderInfo(providerInfo)
|
||||
}, [web3Provider])
|
||||
|
||||
// -----------------------------------
|
||||
// Logout helper
|
||||
// -----------------------------------
|
||||
async function logout() {
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
if ((web3?.currentProvider as any)?.close) {
|
||||
await (web3.currentProvider as any).close()
|
||||
}
|
||||
/* eslint-enable @typescript-eslint/no-explicit-any */
|
||||
|
||||
await web3Modal.clearCachedProvider()
|
||||
}
|
||||
// -----------------------------------
|
||||
// Get valid Networks and set isSupportedOceanNetwork
|
||||
// -----------------------------------
|
||||
|
||||
useEffect(() => {
|
||||
if (appConfig.chainIdsSupported.includes(networkId)) {
|
||||
setIsSupportedOceanNetwork(true)
|
||||
} else {
|
||||
setIsSupportedOceanNetwork(false)
|
||||
}
|
||||
}, [networkId, appConfig.chainIdsSupported])
|
||||
|
||||
// -----------------------------------
|
||||
// Handle change events
|
||||
// -----------------------------------
|
||||
async function handleChainChanged(chainId: string) {
|
||||
LoggerInstance.log('[web3] Chain changed', chainId)
|
||||
const networkId = await web3.eth.net.getId()
|
||||
setChainId(Number(chainId))
|
||||
setNetworkId(Number(networkId))
|
||||
}
|
||||
|
||||
async function handleNetworkChanged(networkId: string) {
|
||||
LoggerInstance.log('[web3] Network changed', networkId)
|
||||
const chainId = await web3.eth.getChainId()
|
||||
setNetworkId(Number(networkId))
|
||||
setChainId(Number(chainId))
|
||||
}
|
||||
|
||||
async function handleAccountsChanged(accounts: string[]) {
|
||||
LoggerInstance.log('[web3] Account changed', accounts[0])
|
||||
setAccountId(accounts[0])
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (!web3Provider || !web3) return
|
||||
|
||||
web3Provider.on('chainChanged', handleChainChanged)
|
||||
web3Provider.on('networkChanged', handleNetworkChanged)
|
||||
web3Provider.on('accountsChanged', handleAccountsChanged)
|
||||
|
||||
return () => {
|
||||
web3Provider.removeListener('chainChanged', handleChainChanged)
|
||||
web3Provider.removeListener('networkChanged', handleNetworkChanged)
|
||||
web3Provider.removeListener('accountsChanged', handleAccountsChanged)
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [web3Provider, web3])
|
||||
|
||||
return (
|
||||
<Web3Context.Provider
|
||||
value={{
|
||||
web3,
|
||||
web3Provider,
|
||||
web3Modal,
|
||||
web3ProviderInfo,
|
||||
accountId,
|
||||
accountEns,
|
||||
accountEnsAvatar,
|
||||
balance,
|
||||
networkId,
|
||||
chainId,
|
||||
networkDisplayName,
|
||||
networkData,
|
||||
block,
|
||||
isTestnet,
|
||||
web3Loading,
|
||||
isSupportedOceanNetwork,
|
||||
approvedBaseTokens,
|
||||
connect,
|
||||
logout
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</Web3Context.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
// Helper hook to access the provider values
|
||||
const useWeb3 = (): Web3ProviderValue => useContext(Web3Context)
|
||||
|
||||
export { Web3Provider, useWeb3, Web3Context }
|
||||
export default Web3Provider
|
73
src/@hooks/useBalance.tsx
Normal file
73
src/@hooks/useBalance.tsx
Normal file
@ -0,0 +1,73 @@
|
||||
import { useState, useEffect, useCallback } from 'react'
|
||||
import { LoggerInstance } from '@oceanprotocol/lib'
|
||||
import { useMarketMetadata } from '../@context/MarketMetadata'
|
||||
import {
|
||||
useNetwork,
|
||||
useAccount,
|
||||
useProvider,
|
||||
useBalance as useBalanceWagmi
|
||||
} from 'wagmi'
|
||||
import { getTokenBalance } from '@utils/wallet'
|
||||
|
||||
interface BalanceProviderValue {
|
||||
balance: UserBalance
|
||||
}
|
||||
|
||||
function useBalance(): BalanceProviderValue {
|
||||
const { address } = useAccount()
|
||||
const { data: balanceNativeToken } = useBalanceWagmi({ address })
|
||||
const web3provider = useProvider()
|
||||
const { approvedBaseTokens } = useMarketMetadata()
|
||||
const { chain } = useNetwork()
|
||||
|
||||
const [balance, setBalance] = useState<UserBalance>({
|
||||
eth: '0'
|
||||
})
|
||||
|
||||
// -----------------------------------
|
||||
// Helper: Get user balance
|
||||
// -----------------------------------
|
||||
const getUserBalance = useCallback(async () => {
|
||||
if (
|
||||
!balanceNativeToken?.formatted ||
|
||||
!address ||
|
||||
!chain?.id ||
|
||||
!web3provider
|
||||
)
|
||||
return
|
||||
|
||||
try {
|
||||
const userBalance = balanceNativeToken?.formatted
|
||||
const key = balanceNativeToken?.symbol.toLowerCase()
|
||||
const newBalance: UserBalance = { [key]: userBalance }
|
||||
|
||||
if (approvedBaseTokens?.length > 0) {
|
||||
await Promise.all(
|
||||
approvedBaseTokens.map(async (token) => {
|
||||
const { address: tokenAddress, decimals, symbol } = token
|
||||
const tokenBalance = await getTokenBalance(
|
||||
address,
|
||||
decimals,
|
||||
tokenAddress,
|
||||
web3provider
|
||||
)
|
||||
newBalance[symbol.toLocaleLowerCase()] = tokenBalance
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
setBalance(newBalance)
|
||||
LoggerInstance.log('[useBalance] Balance: ', newBalance)
|
||||
} catch (error) {
|
||||
LoggerInstance.error('[useBalance] Error: ', error.message)
|
||||
}
|
||||
}, [address, approvedBaseTokens, chain?.id, web3provider, balanceNativeToken])
|
||||
|
||||
useEffect(() => {
|
||||
getUserBalance()
|
||||
}, [getUserBalance])
|
||||
|
||||
return { balance }
|
||||
}
|
||||
|
||||
export default useBalance
|
@ -1,14 +1,10 @@
|
||||
import { useState, useEffect } from 'react'
|
||||
import { useWeb3 } from '@context/Web3'
|
||||
import { Config, LoggerInstance } from '@oceanprotocol/lib'
|
||||
import Web3 from 'web3'
|
||||
import axios, { AxiosResponse } from 'axios'
|
||||
import { getOceanConfig } from '@utils/ocean'
|
||||
import { useBlockNumber } from 'wagmi'
|
||||
|
||||
const blockDifferenceThreshold = 30
|
||||
const ethGraphUrl = `https://api.thegraph.com/subgraphs/name/blocklytics/ethereum-blocks`
|
||||
const ethGraphQueryBody =
|
||||
'{"query":" query Blocks{ blocks(first: 1, skip: 0, orderBy: number, orderDirection: desc, where: {number_gt: 9300000}) { id number timestamp author difficulty gasUsed gasLimit } }","variables":{},"operationName":"Blocks"}'
|
||||
const graphQueryBody =
|
||||
'{"query": "query Meta { _meta { block { hash number } deployment hasIndexingErrors } }", "variables": {},"operationName":"Meta"}'
|
||||
|
||||
@ -30,21 +26,6 @@ async function fetchGraph(
|
||||
}
|
||||
}
|
||||
|
||||
async function getBlockHead(config: Config) {
|
||||
if (!config) return
|
||||
// for ETH main, get block from graph fetch
|
||||
if (config.network === 'mainnet') {
|
||||
const response: any = await fetchGraph(ethGraphUrl, ethGraphQueryBody)
|
||||
return Number(response?.data?.blocks[0]?.number)
|
||||
}
|
||||
|
||||
// for everything else, create new web3 instance with infura
|
||||
// TODO: this fails randomly , WHY!?!?!?!?!
|
||||
const web3Instance = new Web3(config.nodeUri)
|
||||
const blockHead = await web3Instance.eth.getBlockNumber()
|
||||
return blockHead
|
||||
}
|
||||
|
||||
async function getBlockSubgraph(subgraphUri: string) {
|
||||
const response: any = await fetchGraph(
|
||||
`${subgraphUri}/subgraphs/name/oceanprotocol/ocean-subgraph`,
|
||||
@ -55,11 +36,10 @@ async function getBlockSubgraph(subgraphUri: string) {
|
||||
}
|
||||
|
||||
export function useGraphSyncStatus(networkId: number): UseGraphSyncStatus {
|
||||
const { block, web3Loading } = useWeb3()
|
||||
const { data: blockHead, isLoading } = useBlockNumber()
|
||||
const [blockGraph, setBlockGraph] = useState<number>()
|
||||
const [blockHead, setBlockHead] = useState<number>()
|
||||
const [isGraphSynced, setIsGraphSynced] = useState(true)
|
||||
const [subgraphLoading, setSubgraphLoading] = useState(false)
|
||||
const [isSubgraphLoading, setIsSubgraphLoading] = useState(false)
|
||||
const [oceanConfig, setOceanConfig] = useState<Config>()
|
||||
|
||||
// Grab ocean config based on passed networkId
|
||||
@ -70,27 +50,21 @@ export function useGraphSyncStatus(networkId: number): UseGraphSyncStatus {
|
||||
setOceanConfig(oceanConfig)
|
||||
}, [networkId])
|
||||
|
||||
// Get and set head block
|
||||
// Log head block
|
||||
useEffect(() => {
|
||||
if (!oceanConfig?.nodeUri || web3Loading) return
|
||||
|
||||
async function initBlockHead() {
|
||||
const blockHead = block || (await getBlockHead(oceanConfig))
|
||||
setBlockHead(blockHead)
|
||||
LoggerInstance.log('[GraphStatus] Head block: ', blockHead)
|
||||
}
|
||||
initBlockHead()
|
||||
}, [web3Loading, block, oceanConfig])
|
||||
if (!blockHead) return
|
||||
LoggerInstance.log('[GraphStatus] Head block: ', blockHead)
|
||||
}, [blockHead])
|
||||
|
||||
// Get and set subgraph block
|
||||
useEffect(() => {
|
||||
if (!oceanConfig?.subgraphUri) return
|
||||
|
||||
async function initBlockSubgraph() {
|
||||
setSubgraphLoading(true)
|
||||
setIsSubgraphLoading(true)
|
||||
const blockGraph = await getBlockSubgraph(oceanConfig.subgraphUri)
|
||||
setBlockGraph(blockGraph)
|
||||
setSubgraphLoading(false)
|
||||
setIsSubgraphLoading(false)
|
||||
LoggerInstance.log(
|
||||
'[GraphStatus] Latest block from subgraph: ',
|
||||
blockGraph
|
||||
@ -101,7 +75,7 @@ export function useGraphSyncStatus(networkId: number): UseGraphSyncStatus {
|
||||
|
||||
// Set sync status
|
||||
useEffect(() => {
|
||||
if ((!blockGraph && !blockHead) || web3Loading || subgraphLoading) return
|
||||
if ((!blockGraph && !blockHead) || isLoading || isSubgraphLoading) return
|
||||
|
||||
const difference = blockHead - blockGraph
|
||||
|
||||
@ -110,7 +84,7 @@ export function useGraphSyncStatus(networkId: number): UseGraphSyncStatus {
|
||||
return
|
||||
}
|
||||
setIsGraphSynced(true)
|
||||
}, [blockGraph, blockHead, web3Loading, subgraphLoading])
|
||||
}, [blockGraph, blockHead, isLoading, isSubgraphLoading])
|
||||
|
||||
return { blockHead, blockGraph, isGraphSynced }
|
||||
}
|
||||
|
@ -1,9 +1,57 @@
|
||||
import { UseNetworkMetadata } from './types'
|
||||
import networkdata from '../../../content/networks-metadata.json'
|
||||
import { useEffect, useState } from 'react'
|
||||
import {
|
||||
getNetworkDataById,
|
||||
getNetworkDisplayName,
|
||||
getNetworkType,
|
||||
NetworkType
|
||||
} from './utils'
|
||||
import { useMarketMetadata } from '@context/MarketMetadata'
|
||||
import { useNetwork } from 'wagmi'
|
||||
|
||||
export default function useNetworkMetadata(): UseNetworkMetadata {
|
||||
const { appConfig } = useMarketMetadata()
|
||||
const { chain } = useNetwork()
|
||||
|
||||
const [networkDisplayName, setNetworkDisplayName] = useState<string>()
|
||||
const [networkData, setNetworkData] = useState<EthereumListsChain>()
|
||||
const [isTestnet, setIsTestnet] = useState<boolean>()
|
||||
const [isSupportedOceanNetwork, setIsSupportedOceanNetwork] = useState(true)
|
||||
|
||||
const networksList: EthereumListsChain[] = networkdata
|
||||
return { networksList }
|
||||
|
||||
// -----------------------------------
|
||||
// Get and set network metadata
|
||||
// -----------------------------------
|
||||
useEffect(() => {
|
||||
if (!chain?.id) return
|
||||
|
||||
const networkData = getNetworkDataById(networksList, chain.id)
|
||||
setNetworkData(networkData)
|
||||
|
||||
// Construct network display name
|
||||
const networkDisplayName = getNetworkDisplayName(networkData)
|
||||
setNetworkDisplayName(networkDisplayName)
|
||||
|
||||
// Check if network is supported by Ocean Protocol
|
||||
if (appConfig.chainIdsSupported.includes(chain.id)) {
|
||||
setIsSupportedOceanNetwork(true)
|
||||
} else {
|
||||
setIsSupportedOceanNetwork(false)
|
||||
}
|
||||
|
||||
// Check if network is testnet
|
||||
setIsTestnet(getNetworkType(networkData) !== NetworkType.Mainnet)
|
||||
}, [chain?.id, networksList, appConfig.chainIdsSupported])
|
||||
|
||||
return {
|
||||
networksList,
|
||||
networkDisplayName,
|
||||
networkData,
|
||||
isTestnet,
|
||||
isSupportedOceanNetwork
|
||||
}
|
||||
}
|
||||
|
||||
export * from './utils'
|
||||
|
@ -1,3 +1,7 @@
|
||||
export interface UseNetworkMetadata {
|
||||
networkDisplayName: string
|
||||
networkData: EthereumListsChain
|
||||
isTestnet: boolean
|
||||
isSupportedOceanNetwork: boolean
|
||||
networksList: EthereumListsChain[]
|
||||
}
|
||||
|
@ -1,18 +1,20 @@
|
||||
import { useEffect, useState } from 'react'
|
||||
import { NftFactory } from '@oceanprotocol/lib'
|
||||
import { useWeb3 } from '@context/Web3'
|
||||
import { getOceanConfig } from '@utils/ocean'
|
||||
import { useNetwork, useSigner } from 'wagmi'
|
||||
|
||||
function useNftFactory(): NftFactory {
|
||||
const { web3, chainId } = useWeb3()
|
||||
const { chain } = useNetwork()
|
||||
const { data: signer } = useSigner()
|
||||
const [nftFactory, setNftFactory] = useState<NftFactory>()
|
||||
|
||||
useEffect(() => {
|
||||
if (!web3 || !chainId) return
|
||||
const config = getOceanConfig(chainId)
|
||||
const factory = new NftFactory(config?.nftFactoryAddress, web3)
|
||||
if (!signer || !chain?.id) return
|
||||
|
||||
const config = getOceanConfig(chain.id)
|
||||
const factory = new NftFactory(config?.nftFactoryAddress, signer)
|
||||
setNftFactory(factory)
|
||||
}, [web3, chainId])
|
||||
}, [signer, chain?.id])
|
||||
|
||||
return nftFactory
|
||||
}
|
||||
|
@ -9,12 +9,13 @@ import {
|
||||
ProviderFees,
|
||||
ProviderInstance
|
||||
} from '@oceanprotocol/lib'
|
||||
import { getFixedBuyPrice } from './fixedRateExchange'
|
||||
import { getFixedBuyPrice } from './ocean/fixedRateExchange'
|
||||
import Decimal from 'decimal.js'
|
||||
import {
|
||||
consumeMarketOrderFee,
|
||||
publisherMarketOrderFee
|
||||
} from '../../app.config'
|
||||
import { Signer } from 'ethers'
|
||||
|
||||
const tokenPriceQuery = gql`
|
||||
query TokenPriceQuery($datatokenId: ID!, $account: String) {
|
||||
@ -158,7 +159,8 @@ function getAccessDetailsFromTokenPrice(
|
||||
*/
|
||||
export async function getOrderPriceAndFees(
|
||||
asset: AssetExtended,
|
||||
accountId?: string,
|
||||
accountId: string,
|
||||
signer: Signer,
|
||||
providerFees?: ProviderFees
|
||||
): Promise<OrderPriceAndFees> {
|
||||
const orderPriceAndFee = {
|
||||
@ -187,7 +189,11 @@ export async function getOrderPriceAndFees(
|
||||
|
||||
// fetch price and swap fees
|
||||
if (asset?.accessDetails?.type === 'fixed') {
|
||||
const fixed = await getFixedBuyPrice(asset?.accessDetails, asset?.chainId)
|
||||
const fixed = await getFixedBuyPrice(
|
||||
asset?.accessDetails,
|
||||
asset?.chainId,
|
||||
signer
|
||||
)
|
||||
orderPriceAndFee.price = fixed.baseTokenAmount
|
||||
orderPriceAndFee.opcFee = fixed.oceanFeeAmount
|
||||
orderPriceAndFee.publisherMarketFixedSwapFee = fixed.marketFeeAmount
|
||||
|
@ -143,12 +143,8 @@ export async function getComputeEnviroment(
|
||||
const computeEnvs = await ProviderInstance.getComputeEnvironments(
|
||||
asset.services[0].serviceEndpoint
|
||||
)
|
||||
const computeEnv = Array.isArray(computeEnvs)
|
||||
? computeEnvs[0]
|
||||
: computeEnvs[asset.chainId][0]
|
||||
|
||||
if (!computeEnv) return null
|
||||
return computeEnv
|
||||
if (!computeEnvs[asset.chainId][0]) return null
|
||||
return computeEnvs[asset.chainId][0]
|
||||
} catch (e) {
|
||||
LoggerInstance.error('[compute] Fetch compute enviroment: ', e.message)
|
||||
}
|
||||
|
@ -1,14 +1,13 @@
|
||||
import { LoggerInstance, Datatoken } from '@oceanprotocol/lib'
|
||||
import Web3 from 'web3'
|
||||
import { TransactionReceipt } from 'web3-core'
|
||||
import { Signer, ethers } from 'ethers'
|
||||
|
||||
export async function setMinterToPublisher(
|
||||
web3: Web3,
|
||||
signer: Signer,
|
||||
datatokenAddress: string,
|
||||
accountId: string,
|
||||
setError: (msg: string) => void
|
||||
): Promise<TransactionReceipt> {
|
||||
const datatokenInstance = new Datatoken(web3)
|
||||
): Promise<ethers.providers.TransactionResponse> {
|
||||
const datatokenInstance = new Datatoken(signer)
|
||||
|
||||
const response = await datatokenInstance.removeMinter(
|
||||
datatokenAddress,
|
||||
@ -24,12 +23,12 @@ export async function setMinterToPublisher(
|
||||
}
|
||||
|
||||
export async function setMinterToDispenser(
|
||||
web3: Web3,
|
||||
signer: Signer,
|
||||
datatokenAddress: string,
|
||||
accountId: string,
|
||||
setError: (msg: string) => void
|
||||
): Promise<TransactionReceipt> {
|
||||
const datatokenInstance = new Datatoken(web3)
|
||||
): Promise<ethers.providers.TransactionResponse> {
|
||||
const datatokenInstance = new Datatoken(signer)
|
||||
|
||||
const response = await datatokenInstance.addMinter(
|
||||
datatokenAddress,
|
||||
|
@ -9,8 +9,7 @@ import {
|
||||
NftCreateData
|
||||
} from '@oceanprotocol/lib'
|
||||
import { SvgWaves } from './SvgWaves'
|
||||
import Web3 from 'web3'
|
||||
import { TransactionReceipt } from 'web3-core'
|
||||
import { Signer, ethers } from 'ethers'
|
||||
|
||||
// https://docs.opensea.io/docs/metadata-standards
|
||||
export interface NftMetadata {
|
||||
@ -67,7 +66,7 @@ export function generateNftCreateData(
|
||||
nftMetadata: NftMetadata,
|
||||
accountId: string,
|
||||
transferable = true
|
||||
): any {
|
||||
): NftCreateData {
|
||||
const nftCreateData: NftCreateData = {
|
||||
name: nftMetadata.name,
|
||||
symbol: nftMetadata.symbol,
|
||||
@ -99,9 +98,9 @@ export function decodeTokenURI(tokenURI: string): NftMetadata {
|
||||
export async function setNftMetadata(
|
||||
asset: Asset | DDO,
|
||||
accountId: string,
|
||||
web3: Web3,
|
||||
signer: Signer,
|
||||
signal: AbortSignal
|
||||
): Promise<TransactionReceipt> {
|
||||
): Promise<ethers.providers.TransactionResponse> {
|
||||
const encryptedDdo = await ProviderInstance.encrypt(
|
||||
asset,
|
||||
asset.chainId,
|
||||
@ -111,7 +110,7 @@ export async function setNftMetadata(
|
||||
LoggerInstance.log('[setNftMetadata] Got encrypted DDO', encryptedDdo)
|
||||
|
||||
const metadataHash = getHash(JSON.stringify(asset))
|
||||
const nft = new Nft(web3)
|
||||
const nft = new Nft(signer)
|
||||
|
||||
// theoretically used by aquarius or provider, not implemented yet, will remain hardcoded
|
||||
const flags = '0x2'
|
||||
@ -133,10 +132,10 @@ export async function setNftMetadata(
|
||||
export async function setNFTMetadataAndTokenURI(
|
||||
asset: Asset | DDO,
|
||||
accountId: string,
|
||||
web3: Web3,
|
||||
signer: Signer,
|
||||
nftMetadata: NftMetadata,
|
||||
signal: AbortSignal
|
||||
): Promise<TransactionReceipt> {
|
||||
): Promise<ethers.providers.TransactionResponse> {
|
||||
const encryptedDdo = await ProviderInstance.encrypt(
|
||||
asset,
|
||||
asset.chainId,
|
||||
@ -159,7 +158,7 @@ export async function setNFTMetadataAndTokenURI(
|
||||
external_url: externalUrl
|
||||
})
|
||||
).toString('base64')
|
||||
const nft = new Nft(web3)
|
||||
const nft = new Nft(signer)
|
||||
|
||||
// theoretically used by aquarius or provider, not implemented yet, will remain hardcoded
|
||||
const flags = '0x02'
|
||||
|
@ -1,35 +1,30 @@
|
||||
import { FixedRateExchange, PriceAndFees } from '@oceanprotocol/lib'
|
||||
import { consumeMarketFixedSwapFee } from '../../app.config'
|
||||
import Web3 from 'web3'
|
||||
import { getOceanConfig } from './ocean'
|
||||
import { getDummyWeb3 } from './web3'
|
||||
import {
|
||||
amountToUnits,
|
||||
FixedRateExchange,
|
||||
PriceAndFees,
|
||||
unitsToAmount
|
||||
} from '@oceanprotocol/lib'
|
||||
import { ethers, Signer } from 'ethers'
|
||||
import abiFre from '@oceanprotocol/contracts/artifacts/contracts/pools/fixedRate/FixedRateExchange.sol/FixedRateExchange.json'
|
||||
import { getOceanConfig } from '.'
|
||||
import { consumeMarketFixedSwapFee } from '../../../app.config'
|
||||
|
||||
/**
|
||||
* This is used to calculate the price to buy one datatoken from a fixed rate exchange. You need to pass either a web3 object or a chainId. If you pass a chainId a dummy web3 object will be created
|
||||
* @param {AccessDetails} accessDetails
|
||||
* @param {number} chainId
|
||||
* @param {Web3?} web3
|
||||
* @return {Promise<PriceAndFees>}
|
||||
*/
|
||||
export async function getFixedBuyPrice(
|
||||
accessDetails: AccessDetails,
|
||||
chainId?: number,
|
||||
web3?: Web3
|
||||
chainId: number,
|
||||
provider: Signer
|
||||
): Promise<PriceAndFees> {
|
||||
if (!web3 && !chainId)
|
||||
throw new Error("web3 and chainId can't be undefined at the same time!")
|
||||
|
||||
if (!web3) {
|
||||
web3 = await getDummyWeb3(chainId)
|
||||
}
|
||||
|
||||
const config = getOceanConfig(chainId)
|
||||
|
||||
const fixed = new FixedRateExchange(config.fixedRateExchangeAddress, web3)
|
||||
const fixed = new FixedRateExchange(config.fixedRateExchangeAddress, provider)
|
||||
const estimatedPrice = await fixed.calcBaseInGivenDatatokensOut(
|
||||
accessDetails.addressOrId,
|
||||
'1',
|
||||
consumeMarketFixedSwapFee
|
||||
)
|
||||
|
||||
return estimatedPrice
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
import { ConfigHelper, Config } from '@oceanprotocol/lib'
|
||||
// import contractAddresses from '@oceanprotocol/contracts/artifacts/address.json'
|
||||
import { ethers } from 'ethers'
|
||||
|
||||
import abiDatatoken from '@oceanprotocol/contracts/artifacts/contracts/templates/ERC20TemplateEnterprise.sol/ERC20TemplateEnterprise.json'
|
||||
|
||||
export function getOceanConfig(network: string | number): Config {
|
||||
const config = new ConfigHelper().getConfig(
|
||||
@ -28,3 +30,18 @@ export function getDevelopmentConfig(): Config {
|
||||
subgraphUri: 'https://v4.subgraph.goerli.oceanprotocol.com'
|
||||
} as Config
|
||||
}
|
||||
|
||||
/**
|
||||
* getPaymentCollector - returns the current paymentCollector
|
||||
* @param dtAddress datatoken address
|
||||
* @param provider the ethers.js web3 provider
|
||||
* @return {Promise<string>}
|
||||
*/
|
||||
export async function getPaymentCollector(
|
||||
dtAddress: string,
|
||||
provider: ethers.providers.Provider
|
||||
): Promise<string> {
|
||||
const dtContract = new ethers.Contract(dtAddress, abiDatatoken.abi, provider)
|
||||
const paymentCollector = await dtContract.getPaymentCollector()
|
||||
return paymentCollector
|
||||
}
|
@ -13,9 +13,8 @@ import {
|
||||
ProviderInstance,
|
||||
ProviderInitialize
|
||||
} from '@oceanprotocol/lib'
|
||||
import Web3 from 'web3'
|
||||
import { Signer, ethers } from 'ethers'
|
||||
import { getOceanConfig } from './ocean'
|
||||
import { TransactionReceipt } from 'web3-eth'
|
||||
import {
|
||||
marketFeeAddress,
|
||||
consumeMarketOrderFee,
|
||||
@ -44,23 +43,24 @@ async function initializeProvider(
|
||||
}
|
||||
|
||||
/**
|
||||
* @param web3
|
||||
* @param signer
|
||||
* @param asset
|
||||
* @param orderPriceAndFees
|
||||
* @param accountId
|
||||
* @param providerFees
|
||||
* @param computeConsumerAddress
|
||||
* @returns {TransactionReceipt} receipt of the order
|
||||
* @returns {ethers.providers.TransactionResponse | BigNumber} receipt of the order
|
||||
*/
|
||||
export async function order(
|
||||
web3: Web3,
|
||||
signer: Signer,
|
||||
asset: AssetExtended,
|
||||
orderPriceAndFees: OrderPriceAndFees,
|
||||
accountId: string,
|
||||
hasDatatoken: boolean,
|
||||
providerFees?: ProviderFees,
|
||||
computeConsumerAddress?: string
|
||||
): Promise<TransactionReceipt> {
|
||||
const datatoken = new Datatoken(web3)
|
||||
): Promise<ethers.providers.TransactionResponse> {
|
||||
const datatoken = new Datatoken(signer)
|
||||
const config = getOceanConfig(asset.chainId)
|
||||
|
||||
const initializeData = await initializeProvider(
|
||||
@ -97,36 +97,38 @@ export async function order(
|
||||
} as FreOrderParams
|
||||
|
||||
if (asset.accessDetails.templateId === 1) {
|
||||
// buy datatoken
|
||||
const txApprove = await approve(
|
||||
web3,
|
||||
config,
|
||||
accountId,
|
||||
asset.accessDetails.baseToken.address,
|
||||
config.fixedRateExchangeAddress,
|
||||
await amountToUnits(
|
||||
web3,
|
||||
asset?.accessDetails?.baseToken?.address,
|
||||
orderPriceAndFees.price
|
||||
),
|
||||
false
|
||||
)
|
||||
if (!txApprove) {
|
||||
return
|
||||
if (!hasDatatoken) {
|
||||
// buy datatoken
|
||||
const txApprove = await approve(
|
||||
signer,
|
||||
config,
|
||||
accountId,
|
||||
asset.accessDetails.baseToken.address,
|
||||
config.fixedRateExchangeAddress,
|
||||
await amountToUnits(
|
||||
signer,
|
||||
asset?.accessDetails?.baseToken?.address,
|
||||
orderPriceAndFees.price
|
||||
),
|
||||
false
|
||||
)
|
||||
if (!txApprove) {
|
||||
return
|
||||
}
|
||||
const fre = new FixedRateExchange(
|
||||
config.fixedRateExchangeAddress,
|
||||
signer
|
||||
)
|
||||
const freTx = await fre.buyDatatokens(
|
||||
asset.accessDetails?.addressOrId,
|
||||
'1',
|
||||
orderPriceAndFees.price,
|
||||
marketFeeAddress,
|
||||
consumeMarketFixedSwapFee
|
||||
)
|
||||
}
|
||||
const fre = new FixedRateExchange(config.fixedRateExchangeAddress, web3)
|
||||
const freTx = await fre.buyDatatokens(
|
||||
accountId,
|
||||
asset.accessDetails?.addressOrId,
|
||||
'1',
|
||||
orderPriceAndFees.price,
|
||||
marketFeeAddress,
|
||||
consumeMarketFixedSwapFee
|
||||
)
|
||||
|
||||
return await datatoken.startOrder(
|
||||
asset.accessDetails.datatoken.address,
|
||||
accountId,
|
||||
orderParams.consumer,
|
||||
orderParams.serviceIndex,
|
||||
orderParams._providerFee,
|
||||
@ -135,13 +137,13 @@ export async function order(
|
||||
}
|
||||
if (asset.accessDetails.templateId === 2) {
|
||||
const txApprove = await approve(
|
||||
web3,
|
||||
signer,
|
||||
config,
|
||||
accountId,
|
||||
asset.accessDetails.baseToken.address,
|
||||
asset.accessDetails.datatoken.address,
|
||||
await amountToUnits(
|
||||
web3,
|
||||
signer,
|
||||
asset?.accessDetails?.baseToken?.address,
|
||||
orderPriceAndFees.price
|
||||
),
|
||||
@ -152,7 +154,6 @@ export async function order(
|
||||
}
|
||||
return await datatoken.buyFromFreAndOrder(
|
||||
asset.accessDetails.datatoken.address,
|
||||
accountId,
|
||||
orderParams,
|
||||
freParams
|
||||
)
|
||||
@ -161,16 +162,14 @@ export async function order(
|
||||
}
|
||||
case 'free': {
|
||||
if (asset.accessDetails.templateId === 1) {
|
||||
const dispenser = new Dispenser(config.dispenserAddress, web3)
|
||||
const dispenser = new Dispenser(config.dispenserAddress, signer)
|
||||
const dispenserTx = await dispenser.dispense(
|
||||
asset.accessDetails?.datatoken.address,
|
||||
accountId,
|
||||
'1',
|
||||
accountId
|
||||
)
|
||||
return await datatoken.startOrder(
|
||||
asset.accessDetails.datatoken.address,
|
||||
accountId,
|
||||
orderParams.consumer,
|
||||
orderParams.serviceIndex,
|
||||
orderParams._providerFee,
|
||||
@ -180,7 +179,6 @@ export async function order(
|
||||
if (asset.accessDetails.templateId === 2) {
|
||||
return await datatoken.buyFromDispenserAndOrder(
|
||||
asset.services[0].datatokenAddress,
|
||||
accountId,
|
||||
orderParams,
|
||||
config.dispenserAddress
|
||||
)
|
||||
@ -191,7 +189,7 @@ export async function order(
|
||||
|
||||
/**
|
||||
* called when having a valid order, but with expired provider access, requires approval of the provider fee
|
||||
* @param web3
|
||||
* @param signer
|
||||
* @param asset
|
||||
* @param accountId
|
||||
* @param validOrderTx
|
||||
@ -199,13 +197,13 @@ export async function order(
|
||||
* @returns {TransactionReceipt} receipt of the order
|
||||
*/
|
||||
export async function reuseOrder(
|
||||
web3: Web3,
|
||||
signer: Signer,
|
||||
asset: AssetExtended,
|
||||
accountId: string,
|
||||
validOrderTx: string,
|
||||
providerFees?: ProviderFees
|
||||
): Promise<TransactionReceipt> {
|
||||
const datatoken = new Datatoken(web3)
|
||||
): Promise<ethers.providers.TransactionResponse> {
|
||||
const datatoken = new Datatoken(signer)
|
||||
const initializeData = await initializeProvider(
|
||||
asset,
|
||||
accountId,
|
||||
@ -214,7 +212,6 @@ export async function reuseOrder(
|
||||
|
||||
const tx = await datatoken.reuseOrder(
|
||||
asset.accessDetails.datatoken.address,
|
||||
accountId,
|
||||
validOrderTx,
|
||||
providerFees || initializeData.providerFee
|
||||
)
|
||||
@ -225,16 +222,16 @@ export async function reuseOrder(
|
||||
async function approveProviderFee(
|
||||
asset: AssetExtended,
|
||||
accountId: string,
|
||||
web3: Web3,
|
||||
signer: Signer,
|
||||
providerFeeAmount: string
|
||||
): Promise<TransactionReceipt> {
|
||||
): Promise<ethers.providers.TransactionResponse> {
|
||||
const config = getOceanConfig(asset.chainId)
|
||||
const baseToken =
|
||||
asset?.accessDetails?.type === 'free'
|
||||
? getOceanConfig(asset.chainId).oceanTokenAddress
|
||||
: asset?.accessDetails?.baseToken?.address
|
||||
const txApproveWei = await approveWei(
|
||||
web3,
|
||||
signer,
|
||||
config,
|
||||
accountId,
|
||||
baseToken,
|
||||
@ -249,7 +246,7 @@ async function approveProviderFee(
|
||||
* - have validOrder and no providerFees -> then order is valid, providerFees are valid, it returns the valid order value
|
||||
* - have validOrder and providerFees -> then order is valid but providerFees are not valid, we need to call reuseOrder and pay only providerFees
|
||||
* - no validOrder -> we need to call order, to pay 1 DT & providerFees
|
||||
* @param web3
|
||||
* @param signer
|
||||
* @param asset
|
||||
* @param orderPriceAndFees
|
||||
* @param accountId
|
||||
@ -259,11 +256,12 @@ async function approveProviderFee(
|
||||
* @returns {Promise<string>} tx id
|
||||
*/
|
||||
export async function handleComputeOrder(
|
||||
web3: Web3,
|
||||
signer: Signer,
|
||||
asset: AssetExtended,
|
||||
orderPriceAndFees: OrderPriceAndFees,
|
||||
accountId: string,
|
||||
initializeData: ProviderComputeInitialize,
|
||||
hasDatatoken,
|
||||
computeConsumerAddress?: string
|
||||
): Promise<string> {
|
||||
LoggerInstance.log(
|
||||
@ -288,7 +286,7 @@ export async function handleComputeOrder(
|
||||
const txApproveProvider = await approveProviderFee(
|
||||
asset,
|
||||
accountId,
|
||||
web3,
|
||||
signer,
|
||||
initializeData.providerFee.providerFeeAmount
|
||||
)
|
||||
|
||||
@ -301,30 +299,33 @@ export async function handleComputeOrder(
|
||||
if (initializeData?.validOrder) {
|
||||
LoggerInstance.log('[compute] Calling reuseOrder ...', initializeData)
|
||||
const txReuseOrder = await reuseOrder(
|
||||
web3,
|
||||
signer,
|
||||
asset,
|
||||
accountId,
|
||||
initializeData.validOrder,
|
||||
initializeData.providerFee
|
||||
)
|
||||
if (!txReuseOrder) throw new Error('Failed to reuse order!')
|
||||
LoggerInstance.log('[compute] Reused order:', txReuseOrder)
|
||||
return txReuseOrder?.transactionHash
|
||||
const tx = await txReuseOrder.wait()
|
||||
LoggerInstance.log('[compute] Reused order:', tx)
|
||||
return tx?.transactionHash
|
||||
}
|
||||
|
||||
LoggerInstance.log('[compute] Calling order ...', initializeData)
|
||||
|
||||
const txStartOrder = await order(
|
||||
web3,
|
||||
signer,
|
||||
asset,
|
||||
orderPriceAndFees,
|
||||
accountId,
|
||||
hasDatatoken,
|
||||
initializeData.providerFee,
|
||||
computeConsumerAddress
|
||||
)
|
||||
|
||||
LoggerInstance.log('[compute] Order succeeded', txStartOrder)
|
||||
return txStartOrder?.transactionHash
|
||||
const tx = await txStartOrder.wait()
|
||||
LoggerInstance.log('[compute] Order succeeded', tx)
|
||||
return tx?.transactionHash
|
||||
} catch (error) {
|
||||
toast.error(error.message)
|
||||
LoggerInstance.error(`[compute] ${error.message}`)
|
||||
|
@ -11,11 +11,11 @@ import {
|
||||
LoggerInstance,
|
||||
ProviderComputeInitializeResults,
|
||||
ProviderInstance,
|
||||
UrlFile
|
||||
UrlFile,
|
||||
AbiItem
|
||||
} from '@oceanprotocol/lib'
|
||||
import { QueryHeader } from '@shared/FormInput/InputElement/Headers'
|
||||
import Web3 from 'web3'
|
||||
import { AbiItem } from 'web3-utils/types'
|
||||
import { Signer } from 'ethers'
|
||||
import { getValidUntilTime } from './compute'
|
||||
|
||||
export async function initializeProviderForCompute(
|
||||
@ -173,19 +173,18 @@ export async function getFileInfo(
|
||||
}
|
||||
|
||||
export async function downloadFile(
|
||||
web3: Web3,
|
||||
signer: Signer,
|
||||
asset: AssetExtended,
|
||||
accountId: string,
|
||||
validOrderTx?: string
|
||||
) {
|
||||
const downloadUrl = await ProviderInstance.getDownloadUrl(
|
||||
asset.id,
|
||||
accountId,
|
||||
asset.services[0].id,
|
||||
0,
|
||||
validOrderTx || asset.accessDetails.validOrderTx,
|
||||
asset.services[0].serviceEndpoint,
|
||||
web3
|
||||
signer
|
||||
)
|
||||
await downloadFileBrowser(downloadUrl)
|
||||
}
|
||||
|
84
src/@utils/wallet/chains.ts
Normal file
84
src/@utils/wallet/chains.ts
Normal file
@ -0,0 +1,84 @@
|
||||
import { Chain } from 'wagmi'
|
||||
import * as wagmiChains from 'wagmi/chains'
|
||||
|
||||
export const energyWeb = {
|
||||
id: 246,
|
||||
name: 'Energy Web Chain',
|
||||
network: 'energyweb',
|
||||
nativeCurrency: {
|
||||
decimals: 18,
|
||||
name: 'EWT',
|
||||
symbol: 'EWT'
|
||||
},
|
||||
rpcUrls: {
|
||||
public: {
|
||||
http: ['https://rpc.energyweb.org'],
|
||||
webSocket: ['wss://rpc.energyweb.org/ws']
|
||||
},
|
||||
default: {
|
||||
http: ['https://rpc.energyweb.org'],
|
||||
webSocket: ['wss://rpc.energyweb.org/ws']
|
||||
}
|
||||
},
|
||||
blockExplorers: {
|
||||
default: {
|
||||
name: 'Energy Web Chain',
|
||||
url: 'https://explorer.energyweb.org/'
|
||||
},
|
||||
blockscout: {
|
||||
name: 'Energy Web Chain',
|
||||
url: 'https://explorer.energyweb.org/'
|
||||
}
|
||||
},
|
||||
testnet: false
|
||||
} as Chain
|
||||
|
||||
// TODO: remove once moonriver is shipped in wagmi as it is already in codebase
|
||||
// https://github.com/wagmi-dev/references/blob/main/packages/chains/src/moonriver.ts
|
||||
export const moonriver = {
|
||||
id: 1285,
|
||||
name: 'Moonriver',
|
||||
network: 'moonriver',
|
||||
nativeCurrency: {
|
||||
decimals: 18,
|
||||
name: 'MOVR',
|
||||
symbol: 'MOVR'
|
||||
},
|
||||
rpcUrls: {
|
||||
public: {
|
||||
http: ['https://moonriver.public.blastapi.io'],
|
||||
webSocket: ['wss://moonriver.public.blastapi.io']
|
||||
},
|
||||
default: {
|
||||
http: ['https://moonriver.public.blastapi.io'],
|
||||
webSocket: ['wss://moonriver.public.blastapi.io']
|
||||
}
|
||||
},
|
||||
blockExplorers: {
|
||||
default: {
|
||||
name: 'Moonscan',
|
||||
url: 'https://moonriver.moonscan.io'
|
||||
},
|
||||
etherscan: {
|
||||
name: 'Moonscan',
|
||||
url: 'https://moonriver.moonscan.io'
|
||||
}
|
||||
},
|
||||
contracts: {
|
||||
multicall3: {
|
||||
address: '0xcA11bde05977b3631167028862bE2a173976CA11',
|
||||
blockCreated: 1597904
|
||||
}
|
||||
},
|
||||
testnet: false
|
||||
} as Chain
|
||||
|
||||
export const getSupportedChains = (chainIdsSupported: number[]): Chain[] => {
|
||||
const chains = [wagmiChains, energyWeb, moonriver].map((chain) => {
|
||||
return Object.values(chain).filter((chain) =>
|
||||
chainIdsSupported.includes(chain.id)
|
||||
)
|
||||
})
|
||||
console.log(chains.flat())
|
||||
return chains.flat()
|
||||
}
|
@ -1,8 +1,37 @@
|
||||
import { getNetworkDisplayName } from '@hooks/useNetworkMetadata'
|
||||
import { LoggerInstance } from '@oceanprotocol/lib'
|
||||
import Web3 from 'web3'
|
||||
import { getOceanConfig } from './ocean'
|
||||
import { AbiItem } from 'web3-utils/types'
|
||||
import { createClient, erc20ABI } from 'wagmi'
|
||||
import { mainnet, polygon, bsc, goerli, polygonMumbai } from 'wagmi/chains'
|
||||
import { ethers, Contract } from 'ethers'
|
||||
import { formatEther } from 'ethers/lib/utils'
|
||||
import { getDefaultClient } from 'connectkit'
|
||||
import { energyWeb, moonriver } from './chains'
|
||||
import { getNetworkDisplayName } from '@hooks/useNetworkMetadata'
|
||||
import { getOceanConfig } from '../ocean'
|
||||
|
||||
// Wagmi client
|
||||
export const wagmiClient = createClient(
|
||||
getDefaultClient({
|
||||
appName: 'Ocean Market',
|
||||
infuraId: process.env.NEXT_PUBLIC_INFURA_PROJECT_ID,
|
||||
// TODO: mapping between appConfig.chainIdsSupported and wagmi chainId
|
||||
chains: [mainnet, polygon, bsc, energyWeb, moonriver, goerli, polygonMumbai]
|
||||
})
|
||||
)
|
||||
|
||||
// ConnectKit CSS overrides
|
||||
// https://docs.family.co/connectkit/theming#theme-variables
|
||||
export const connectKitTheme = {
|
||||
'--ck-font-family': 'var(--font-family-base)',
|
||||
'--ck-border-radius': 'var(--border-radius)',
|
||||
'--ck-overlay-background': 'var(--background-body-transparent)',
|
||||
'--ck-modal-box-shadow': '0 0 20px 20px var(--box-shadow-color)',
|
||||
'--ck-body-background': 'var(--background-body)',
|
||||
'--ck-body-color': 'var(--font-color-text)',
|
||||
'--ck-primary-button-border-radius': 'var(--border-radius)',
|
||||
'--ck-primary-button-color': 'var(--font-color-heading)',
|
||||
'--ck-primary-button-background': 'var(--background-content)',
|
||||
'--ck-secondary-button-border-radius': 'var(--border-radius)'
|
||||
}
|
||||
|
||||
export function accountTruncate(account: string): string {
|
||||
if (!account || account === '') return
|
||||
@ -10,14 +39,41 @@ export function accountTruncate(account: string): string {
|
||||
const truncated = account.replace(middle, '…')
|
||||
return truncated
|
||||
}
|
||||
/**
|
||||
* returns a dummy web3 instance, only usable to get info from the chain
|
||||
* @param chainId
|
||||
* @returns Web3 instance
|
||||
*/
|
||||
export async function getDummyWeb3(chainId: number): Promise<Web3> {
|
||||
const config = getOceanConfig(chainId)
|
||||
return new Web3(config.nodeUri)
|
||||
|
||||
export async function addTokenToWallet(
|
||||
address: string,
|
||||
symbol: string,
|
||||
logo?: string
|
||||
): Promise<void> {
|
||||
const image =
|
||||
logo ||
|
||||
'https://raw.githubusercontent.com/oceanprotocol/art/main/logo/token.png'
|
||||
|
||||
const tokenMetadata = {
|
||||
type: 'ERC20',
|
||||
options: { address, symbol, image, decimals: 18 }
|
||||
}
|
||||
|
||||
;(window?.ethereum.request as any)(
|
||||
{
|
||||
method: 'wallet_watchAsset',
|
||||
params: tokenMetadata,
|
||||
id: Math.round(Math.random() * 100000)
|
||||
},
|
||||
(err: { code: number; message: string }, added: any) => {
|
||||
if (err || 'error' in added) {
|
||||
LoggerInstance.error(
|
||||
`Couldn't add ${tokenMetadata.options.symbol} (${
|
||||
tokenMetadata.options.address
|
||||
}) to MetaMask, error: ${err.message || added.error}`
|
||||
)
|
||||
} else {
|
||||
LoggerInstance.log(
|
||||
`Added ${tokenMetadata.options.symbol} (${tokenMetadata.options.address}) to MetaMask`
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
export async function addCustomNetwork(
|
||||
@ -75,78 +131,19 @@ export async function addCustomNetwork(
|
||||
)
|
||||
}
|
||||
|
||||
export async function addTokenToWallet(
|
||||
web3Provider: any,
|
||||
address: string,
|
||||
symbol: string,
|
||||
logo?: string
|
||||
): Promise<void> {
|
||||
const image =
|
||||
logo ||
|
||||
'https://raw.githubusercontent.com/oceanprotocol/art/main/logo/token.png'
|
||||
|
||||
const tokenMetadata = {
|
||||
type: 'ERC20',
|
||||
options: { address, symbol, image, decimals: 18 }
|
||||
}
|
||||
|
||||
web3Provider.sendAsync(
|
||||
{
|
||||
method: 'wallet_watchAsset',
|
||||
params: tokenMetadata,
|
||||
id: Math.round(Math.random() * 100000)
|
||||
},
|
||||
(err: { code: number; message: string }, added: any) => {
|
||||
if (err || 'error' in added) {
|
||||
LoggerInstance.error(
|
||||
`Couldn't add ${tokenMetadata.options.symbol} (${
|
||||
tokenMetadata.options.address
|
||||
}) to MetaMask, error: ${err.message || added.error}`
|
||||
)
|
||||
} else {
|
||||
LoggerInstance.log(
|
||||
`Added ${tokenMetadata.options.symbol} (${tokenMetadata.options.address}) to MetaMask`
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
export async function getTokenBalance(
|
||||
accountId: string,
|
||||
decimals: number,
|
||||
tokenAddress: string,
|
||||
web3: Web3
|
||||
web3Provider: ethers.providers.Provider
|
||||
): Promise<string> {
|
||||
const minABI = [
|
||||
{
|
||||
constant: true,
|
||||
inputs: [
|
||||
{
|
||||
name: '_owner',
|
||||
type: 'address'
|
||||
}
|
||||
],
|
||||
name: 'balanceOf',
|
||||
outputs: [
|
||||
{
|
||||
name: 'balance',
|
||||
type: 'uint256'
|
||||
}
|
||||
],
|
||||
payable: false,
|
||||
stateMutability: 'view',
|
||||
type: 'function'
|
||||
}
|
||||
] as AbiItem[]
|
||||
if (!web3Provider || !accountId || !tokenAddress) return
|
||||
|
||||
try {
|
||||
const token = new web3.eth.Contract(minABI, tokenAddress, {
|
||||
from: accountId
|
||||
})
|
||||
const balance = await token.methods.balanceOf(accountId).call()
|
||||
const token = new Contract(tokenAddress, erc20ABI, web3Provider)
|
||||
const balance = await token.balanceOf(accountId)
|
||||
const adjustedDecimalsBalance = `${balance}${'0'.repeat(18 - decimals)}`
|
||||
return web3.utils.fromWei(adjustedDecimalsBalance)
|
||||
return formatEther(adjustedDecimalsBalance)
|
||||
} catch (e) {
|
||||
LoggerInstance.error(`ERROR: Failed to get the balance: ${e.message}`)
|
||||
}
|
||||
@ -157,6 +154,7 @@ export function getTokenBalanceFromSymbol(
|
||||
symbol: string
|
||||
): string {
|
||||
if (!symbol) return
|
||||
|
||||
const baseTokenBalance = balance?.[symbol.toLocaleLowerCase()]
|
||||
return baseTokenBalance || '0'
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
import { isCID } from '@utils/ipfs'
|
||||
import isUrl from 'is-url-superb'
|
||||
import * as Yup from 'yup'
|
||||
import web3 from 'web3'
|
||||
import { ethers } from 'ethers'
|
||||
import { isGoogleUrl } from './url/index'
|
||||
|
||||
export function testLinks(isEdit?: boolean) {
|
||||
@ -49,7 +49,7 @@ export function testLinks(isEdit?: boolean) {
|
||||
: 'Transaction ID not valid.'
|
||||
break
|
||||
case 'smartcontract':
|
||||
validField = web3.utils.isAddress(value?.toString())
|
||||
validField = ethers.utils.isAddress(value?.toString())
|
||||
errorMessage = !value?.toString()
|
||||
? 'Address required.'
|
||||
: 'Address not valid.'
|
||||
|
@ -3,7 +3,7 @@ import React from 'react'
|
||||
import testRender from '../../../../.jest/testRender'
|
||||
import AddToken from './index'
|
||||
|
||||
jest.mock('../../../@utils/web3', () => ({ addTokenToWallet: jest.fn() }))
|
||||
jest.mock('../../../@utils/wallet', () => ({ addTokenToWallet: jest.fn() }))
|
||||
|
||||
describe('@shared/AddToken', () => {
|
||||
const propsBase = {
|
||||
|
@ -1,7 +1,6 @@
|
||||
import React, { ReactElement } from 'react'
|
||||
import classNames from 'classnames/bind'
|
||||
import { addTokenToWallet } from '@utils/web3'
|
||||
import { useWeb3 } from '@context/Web3'
|
||||
import { addTokenToWallet } from '@utils/wallet'
|
||||
import Button from '@shared/atoms/Button'
|
||||
import OceanLogo from '@images/logo.svg'
|
||||
import styles from './index.module.css'
|
||||
@ -23,8 +22,6 @@ export default function AddToken({
|
||||
className,
|
||||
minimal
|
||||
}: AddTokenProps): ReactElement {
|
||||
const { web3Provider } = useWeb3()
|
||||
|
||||
const styleClasses = cx({
|
||||
button: true,
|
||||
minimal,
|
||||
@ -32,9 +29,9 @@ export default function AddToken({
|
||||
})
|
||||
|
||||
async function handleAddToken() {
|
||||
if (!web3Provider) return
|
||||
if (!window?.ethereum) return
|
||||
|
||||
await addTokenToWallet(web3Provider, address, symbol)
|
||||
await addTokenToWallet(address, symbol)
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import Button from '@shared/atoms/Button'
|
||||
import styles from './DmButton.module.css'
|
||||
import { useWeb3 } from '@context/Web3'
|
||||
import { useAccount, useConnect } from 'wagmi'
|
||||
import { useOrbis } from '@context/DirectMessages'
|
||||
|
||||
export default function DmButton({
|
||||
@ -11,7 +11,7 @@ export default function DmButton({
|
||||
accountId: string
|
||||
text?: string
|
||||
}) {
|
||||
const { accountId: ownAccountId, connect } = useWeb3()
|
||||
const { address: ownAccountId } = useAccount()
|
||||
const {
|
||||
checkOrbisConnection,
|
||||
getConversationByDid,
|
||||
@ -24,10 +24,9 @@ export default function DmButton({
|
||||
const [isCreatingConversation, setIsCreatingConversation] = useState(false)
|
||||
|
||||
const handleActivation = async () => {
|
||||
const resConnect = await connect()
|
||||
if (resConnect) {
|
||||
if (ownAccountId) {
|
||||
await checkOrbisConnection({
|
||||
address: resConnect,
|
||||
address: ownAccountId,
|
||||
autoConnect: true,
|
||||
lit: true
|
||||
})
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React, { useEffect } from 'react'
|
||||
import styles from './Header.module.css'
|
||||
import { useWeb3 } from '@context/Web3'
|
||||
import { useAccount } from 'wagmi'
|
||||
import { useOrbis } from '@context/DirectMessages'
|
||||
import { didToAddress } from './_utils'
|
||||
import { toast } from 'react-toastify'
|
||||
@ -10,7 +10,7 @@ import ChevronUp from '@images/chevronup.svg'
|
||||
import Copy from '@images/copy.svg'
|
||||
|
||||
export default function Header() {
|
||||
const { accountId } = useWeb3()
|
||||
const { address: accountId } = useAccount()
|
||||
const {
|
||||
conversations,
|
||||
conversationId,
|
||||
|
@ -2,7 +2,7 @@ import React, { useRef } from 'react'
|
||||
import styles from './Postbox.module.css'
|
||||
import { useOrbis } from '@context/DirectMessages'
|
||||
import SendIcon from '@images/send.svg'
|
||||
import { accountTruncate } from '@utils/web3'
|
||||
import { accountTruncate } from '@utils/wallet'
|
||||
import { didToAddress } from './_utils'
|
||||
import {
|
||||
IOrbisMessage,
|
||||
|
@ -2,19 +2,18 @@ import React from 'react'
|
||||
import styles from './index.module.css'
|
||||
import Conversation from './Conversation'
|
||||
import { useOrbis } from '@context/DirectMessages'
|
||||
import { useWeb3 } from '@context/Web3'
|
||||
import { useAccount, useConnect } from 'wagmi'
|
||||
import Header from './Header'
|
||||
import List from './List'
|
||||
import walletStyles from '../../Header/Wallet/Account.module.css'
|
||||
|
||||
const BodyContent = () => {
|
||||
const { account, conversationId, checkOrbisConnection } = useOrbis()
|
||||
const { accountId, connect } = useWeb3()
|
||||
const { address: accountId } = useAccount()
|
||||
|
||||
const handleActivation = async (e: React.MouseEvent) => {
|
||||
e.preventDefault()
|
||||
const resConnect = await connect()
|
||||
if (resConnect) {
|
||||
if (accountId) {
|
||||
await checkOrbisConnection({
|
||||
address: accountId,
|
||||
autoConnect: true,
|
||||
|
@ -7,7 +7,7 @@ import { getFileInfo, checkValidProvider } from '@utils/provider'
|
||||
import { LoggerInstance, FileInfo } from '@oceanprotocol/lib'
|
||||
import { useAsset } from '@context/Asset'
|
||||
import styles from './index.module.css'
|
||||
import { useWeb3 } from '@context/Web3'
|
||||
import { useNetwork } from 'wagmi'
|
||||
import InputHeaders from '../Headers'
|
||||
import Button from '@shared/atoms/Button'
|
||||
import Loader from '@shared/atoms/Loader'
|
||||
@ -21,7 +21,8 @@ export default function FilesInput(props: InputProps): ReactElement {
|
||||
const [isLoading, setIsLoading] = useState(false)
|
||||
const [disabledButton, setDisabledButton] = useState(true)
|
||||
const { asset } = useAsset()
|
||||
const { chainId } = useWeb3()
|
||||
const { chain } = useNetwork()
|
||||
const chainId = chain?.id
|
||||
|
||||
const providerUrl = props.form?.values?.services
|
||||
? props.form?.values?.services[0].providerUrl.url
|
||||
@ -60,7 +61,7 @@ export default function FilesInput(props: InputProps): ReactElement {
|
||||
query,
|
||||
headers,
|
||||
abi,
|
||||
chainId,
|
||||
chain?.id,
|
||||
method
|
||||
)
|
||||
|
||||
|
@ -8,12 +8,12 @@ import Button from '@shared/atoms/Button'
|
||||
import { LoggerInstance, ProviderInstance } from '@oceanprotocol/lib'
|
||||
import { FormPublishData } from '@components/Publish/_types'
|
||||
import { getOceanConfig } from '@utils/ocean'
|
||||
import { useWeb3 } from '@context/Web3'
|
||||
import axios from 'axios'
|
||||
import { useCancelToken } from '@hooks/useCancelToken'
|
||||
import { useNetwork } from 'wagmi'
|
||||
|
||||
export default function CustomProvider(props: InputProps): ReactElement {
|
||||
const { chainId } = useWeb3()
|
||||
const { chain } = useNetwork()
|
||||
const newCancelToken = useCancelToken()
|
||||
const { initialValues, setFieldError } = useFormikContext<FormPublishData>()
|
||||
const [field, meta, helpers] = useField(props.name)
|
||||
@ -40,7 +40,7 @@ export default function CustomProvider(props: InputProps): ReactElement {
|
||||
const providerResponse = await axios.get(field.value.url, {
|
||||
cancelToken: newCancelToken()
|
||||
})
|
||||
const userChainId = chainId || 1
|
||||
const userChainId = chain?.id || 1
|
||||
const providerChain =
|
||||
providerResponse?.data?.chainId || providerResponse?.data?.chainIds
|
||||
|
||||
@ -71,7 +71,7 @@ export default function CustomProvider(props: InputProps): ReactElement {
|
||||
function handleDefault(e: React.SyntheticEvent) {
|
||||
e.preventDefault()
|
||||
|
||||
const oceanConfig = getOceanConfig(chainId)
|
||||
const oceanConfig = getOceanConfig(chain?.id)
|
||||
const providerUrl =
|
||||
oceanConfig?.providerUri || initialValues.services[0].providerUrl.url
|
||||
|
||||
|
@ -7,7 +7,6 @@ import InputGroup from '@shared/FormInput/InputGroup'
|
||||
import InputElement from '@shared/FormInput/InputElement'
|
||||
import isUrl from 'is-url-superb'
|
||||
import { isCID } from '@utils/ipfs'
|
||||
import web3 from 'web3'
|
||||
export interface URLInputProps {
|
||||
submitText: string
|
||||
handleButtonClick(e: React.SyntheticEvent, data: string): void
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React, { ReactElement, useEffect, useState } from 'react'
|
||||
import styles from './index.module.css'
|
||||
import Link from 'next/link'
|
||||
import { accountTruncate } from '@utils/web3'
|
||||
import { accountTruncate } from '@utils/wallet'
|
||||
import { getEnsName } from '@utils/ens'
|
||||
import { useIsMounted } from '@hooks/useIsMounted'
|
||||
|
||||
|
@ -2,7 +2,7 @@ import { render, fireEvent, screen } from '@testing-library/react'
|
||||
import React from 'react'
|
||||
import WalletNetworkSwitcher from './'
|
||||
|
||||
jest.mock('../../../@utils/web3', () => ({
|
||||
jest.mock('../../../@utils/wallet', () => ({
|
||||
addCustomNetwork: () => jest.fn()
|
||||
}))
|
||||
|
||||
|
@ -1,21 +1,21 @@
|
||||
import React, { ReactElement } from 'react'
|
||||
import { useWeb3 } from '@context/Web3'
|
||||
import Button from '@shared/atoms/Button'
|
||||
import styles from './index.module.css'
|
||||
import { addCustomNetwork } from '@utils/web3'
|
||||
import useNetworkMetadata, {
|
||||
getNetworkDataById,
|
||||
getNetworkDisplayName
|
||||
} from '@hooks/useNetworkMetadata'
|
||||
import { useAsset } from '@context/Asset'
|
||||
import { useNetwork, useSwitchNetwork } from 'wagmi'
|
||||
|
||||
export default function WalletNetworkSwitcher(): ReactElement {
|
||||
const { networkId, web3Provider } = useWeb3()
|
||||
const { chain } = useNetwork()
|
||||
const { asset } = useAsset()
|
||||
const { switchNetwork } = useSwitchNetwork({ chainId: asset?.chainId })
|
||||
const { networksList } = useNetworkMetadata()
|
||||
|
||||
const ddoNetworkData = getNetworkDataById(networksList, asset.chainId)
|
||||
const walletNetworkData = getNetworkDataById(networksList, networkId)
|
||||
const walletNetworkData = getNetworkDataById(networksList, chain?.id)
|
||||
|
||||
const ddoNetworkName = (
|
||||
<strong>{getNetworkDisplayName(ddoNetworkData)}</strong>
|
||||
@ -24,13 +24,6 @@ export default function WalletNetworkSwitcher(): ReactElement {
|
||||
<strong>{getNetworkDisplayName(walletNetworkData)}</strong>
|
||||
)
|
||||
|
||||
async function switchWalletNetwork() {
|
||||
const networkNode = await networksList.find(
|
||||
(data) => data.chainId === asset.chainId
|
||||
)
|
||||
addCustomNetwork(web3Provider, networkNode)
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<p className={styles.text}>
|
||||
@ -38,7 +31,7 @@ export default function WalletNetworkSwitcher(): ReactElement {
|
||||
to {walletNetworkName}. Connect to {ddoNetworkName} to interact with
|
||||
this asset.
|
||||
</p>
|
||||
<Button size="small" onClick={() => switchWalletNetwork()}>
|
||||
<Button size="small" onClick={() => switchNetwork()}>
|
||||
Switch to {ddoNetworkName}
|
||||
</Button>
|
||||
</>
|
||||
|
@ -33,11 +33,11 @@ export default function Web3Feedback({
|
||||
if (!accountId) {
|
||||
setState('error')
|
||||
setTitle('No account connected')
|
||||
setMessage('Please connect your Web3 wallet.')
|
||||
setMessage('Please connect your wallet.')
|
||||
} else if (isAssetNetwork === false) {
|
||||
setState('error')
|
||||
setTitle('Not connected to asset network')
|
||||
setMessage('Please connect your Web3 wallet.')
|
||||
setMessage('Please connect your wallet.')
|
||||
} else if (isGraphSynced === false) {
|
||||
setState('warning')
|
||||
setTitle('Data out of sync')
|
||||
|
@ -2,7 +2,6 @@ import React, { ReactElement } from 'react'
|
||||
import Alert from '@shared/atoms/Alert'
|
||||
import Footer from '../Footer/Footer'
|
||||
import Header from '../Header'
|
||||
import { useWeb3 } from '@context/Web3'
|
||||
import { useAccountPurgatory } from '@hooks/useAccountPurgatory'
|
||||
import AnnouncementBanner from '@shared/AnnouncementBanner'
|
||||
import PrivacyPreferenceCenter from '../Privacy/PrivacyPreferenceCenter'
|
||||
@ -10,6 +9,7 @@ import styles from './index.module.css'
|
||||
import { ToastContainer } from 'react-toastify'
|
||||
import contentPurgatory from '../../../content/purgatory.json'
|
||||
import { useMarketMetadata } from '@context/MarketMetadata'
|
||||
import { useAccount } from 'wagmi'
|
||||
|
||||
export default function App({
|
||||
children
|
||||
@ -17,8 +17,8 @@ export default function App({
|
||||
children: ReactElement
|
||||
}): ReactElement {
|
||||
const { siteContent, appConfig } = useMarketMetadata()
|
||||
const { accountId } = useWeb3()
|
||||
const { isInPurgatory, purgatoryData } = useAccountPurgatory(accountId)
|
||||
const { address } = useAccount()
|
||||
const { isInPurgatory, purgatoryData } = useAccountPurgatory(address)
|
||||
|
||||
return (
|
||||
<div className={styles.app}>
|
||||
|
@ -1,16 +1,16 @@
|
||||
import { useAsset } from '@context/Asset'
|
||||
import { useUserPreferences } from '@context/UserPreferences'
|
||||
import { useWeb3 } from '@context/Web3'
|
||||
import Tooltip from '@shared/atoms/Tooltip'
|
||||
import { formatNumber } from '@utils/numbers'
|
||||
import { getNftOwnAllocation } from '@utils/veAllocation'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import { useAccount } from 'wagmi'
|
||||
import styles from './index.module.css'
|
||||
|
||||
export default function AssetStats() {
|
||||
const { locale } = useUserPreferences()
|
||||
const { asset } = useAsset()
|
||||
const { accountId } = useWeb3()
|
||||
const { address: accountId } = useAccount()
|
||||
|
||||
const [ownAllocation, setOwnAllocation] = useState(0)
|
||||
|
||||
|
@ -16,7 +16,8 @@ const downloadProps: ButtonBuyProps = {
|
||||
priceType: 'fixed',
|
||||
isConsumable: true,
|
||||
isBalanceSufficient: true,
|
||||
consumableFeedback: 'TEST: consumableFeedback'
|
||||
consumableFeedback: 'TEST: consumableFeedback',
|
||||
isAccountConnected: true
|
||||
}
|
||||
|
||||
const computeProps: ButtonBuyProps = {
|
||||
@ -114,7 +115,7 @@ describe('Asset/AssetActions/ButtonBuy', () => {
|
||||
render(<ButtonBuy {...computeProps} />)
|
||||
expect(
|
||||
screen.getByText(
|
||||
'To use this algorithm, you will buy 1 dtSymbol and immediately send it back to the publisher. Connect to the correct network to interact with this asset. The C2D resources required to start the job are available, no payment is required for them. Please note that network gas fees still apply, even when using free assets.'
|
||||
'To use this algorithm, you will buy 1 dtSymbol and immediately send it back to the publisher. Additionally, the selected selectedComputeAssetType is free to use. The C2D resources required to start the job are available, no payment is required for them. Please note that network gas fees still apply, even when using free assets.'
|
||||
)
|
||||
).toBeInTheDocument()
|
||||
})
|
||||
@ -123,7 +124,7 @@ describe('Asset/AssetActions/ButtonBuy', () => {
|
||||
render(<ButtonBuy {...computeProps} priceType="free" />)
|
||||
expect(
|
||||
screen.getByText(
|
||||
'This algorithm is free to use. Connect to the correct network to interact with this asset. The C2D resources required to start the job are available, no payment is required for them. Please note that network gas fees still apply, even when using free assets.'
|
||||
'This algorithm is free to use. Additionally, the selected selectedComputeAssetType is free to use. The C2D resources required to start the job are available, no payment is required for them. Please note that network gas fees still apply, even when using free assets.'
|
||||
)
|
||||
).toBeInTheDocument()
|
||||
})
|
||||
@ -132,7 +133,7 @@ describe('Asset/AssetActions/ButtonBuy', () => {
|
||||
render(<ButtonBuy {...computeProps} algorithmPriceType="fixed" />)
|
||||
expect(
|
||||
screen.getByText(
|
||||
'To use this algorithm, you will buy 1 dtSymbol and immediately send it back to the publisher. Connect to the correct network to interact with this asset. The C2D resources required to start the job are available, no payment is required for them.'
|
||||
'To use this algorithm, you will buy 1 dtSymbol and immediately send it back to the publisher. Additionally, you will buy 1 dtSymbol for the selectedComputeAssetType and send it back to the publisher. The C2D resources required to start the job are available, no payment is required for them.'
|
||||
)
|
||||
).toBeInTheDocument()
|
||||
})
|
||||
|
@ -2,8 +2,6 @@ import React, { FormEvent, ReactElement } from 'react'
|
||||
import Button from '../../../@shared/atoms/Button'
|
||||
import styles from './index.module.css'
|
||||
import Loader from '../../../@shared/atoms/Loader'
|
||||
import { useWeb3 } from '@context/Web3'
|
||||
import Web3 from 'web3'
|
||||
|
||||
export interface ButtonBuyProps {
|
||||
action: 'download' | 'compute'
|
||||
@ -31,6 +29,7 @@ export interface ButtonBuyProps {
|
||||
algorithmPriceType?: string
|
||||
isAlgorithmConsumable?: boolean
|
||||
isSupportedOceanNetwork?: boolean
|
||||
isAccountConnected?: boolean
|
||||
hasProviderFee?: boolean
|
||||
retry?: boolean
|
||||
}
|
||||
@ -46,13 +45,13 @@ function getConsumeHelpText(
|
||||
isBalanceSufficient: boolean,
|
||||
consumableFeedback: string,
|
||||
isSupportedOceanNetwork: boolean,
|
||||
web3: Web3,
|
||||
isAccountConnected: boolean,
|
||||
priceType: string
|
||||
) {
|
||||
const text =
|
||||
isConsumable === false
|
||||
? consumableFeedback
|
||||
: hasPreviousOrder && web3 && isSupportedOceanNetwork
|
||||
: hasPreviousOrder && isAccountConnected && isSupportedOceanNetwork
|
||||
? `You bought this ${assetType} already allowing you to use it without paying again.`
|
||||
: hasDatatoken
|
||||
? `You own ${dtBalance} ${dtSymbol} allowing you to use this dataset by spending 1 ${dtSymbol}, but without paying ${btSymbol} again.`
|
||||
@ -74,7 +73,7 @@ function getAlgoHelpText(
|
||||
hasDatatokenSelectedComputeAsset: boolean,
|
||||
isBalanceSufficient: boolean,
|
||||
isSupportedOceanNetwork: boolean,
|
||||
web3: Web3,
|
||||
isAccountConnected: boolean,
|
||||
algorithmPriceType: string
|
||||
) {
|
||||
const text =
|
||||
@ -82,11 +81,13 @@ function getAlgoHelpText(
|
||||
isConsumable === false ||
|
||||
isAlgorithmConsumable === false
|
||||
? ''
|
||||
: hasPreviousOrderSelectedComputeAsset && web3 && isSupportedOceanNetwork
|
||||
: hasPreviousOrderSelectedComputeAsset &&
|
||||
isAccountConnected &&
|
||||
isSupportedOceanNetwork
|
||||
? `You already bought the selected ${selectedComputeAssetType}, allowing you to use it without paying again.`
|
||||
: hasDatatokenSelectedComputeAsset
|
||||
? `You own ${dtBalanceSelectedComputeAsset} ${dtSymbolSelectedComputeAsset} allowing you to use the selected ${selectedComputeAssetType} by spending 1 ${dtSymbolSelectedComputeAsset}, but without paying OCEAN again.`
|
||||
: web3 && !isSupportedOceanNetwork
|
||||
: isAccountConnected && !isSupportedOceanNetwork
|
||||
? `Connect to the correct network to interact with this asset.`
|
||||
: isBalanceSufficient === false
|
||||
? ''
|
||||
@ -115,7 +116,7 @@ function getComputeAssetHelpText(
|
||||
selectedComputeAssetType?: string,
|
||||
isAlgorithmConsumable?: boolean,
|
||||
isSupportedOceanNetwork?: boolean,
|
||||
web3?: Web3,
|
||||
isAccountConnected?: boolean,
|
||||
hasProviderFee?: boolean
|
||||
) {
|
||||
const computeAssetHelpText = getConsumeHelpText(
|
||||
@ -129,7 +130,7 @@ function getComputeAssetHelpText(
|
||||
isBalanceSufficient,
|
||||
consumableFeedback,
|
||||
isSupportedOceanNetwork,
|
||||
web3,
|
||||
isAccountConnected,
|
||||
priceType
|
||||
)
|
||||
|
||||
@ -143,7 +144,7 @@ function getComputeAssetHelpText(
|
||||
hasDatatokenSelectedComputeAsset,
|
||||
isBalanceSufficient,
|
||||
isSupportedOceanNetwork,
|
||||
web3,
|
||||
isAccountConnected,
|
||||
algorithmPriceType
|
||||
)
|
||||
|
||||
@ -183,9 +184,9 @@ export default function ButtonBuy({
|
||||
isAlgorithmConsumable,
|
||||
hasProviderFee,
|
||||
retry,
|
||||
isSupportedOceanNetwork
|
||||
isSupportedOceanNetwork,
|
||||
isAccountConnected
|
||||
}: ButtonBuyProps): ReactElement {
|
||||
const { web3 } = useWeb3()
|
||||
const buttonText = retry
|
||||
? 'Retry'
|
||||
: action === 'download'
|
||||
@ -216,7 +217,7 @@ export default function ButtonBuy({
|
||||
isBalanceSufficient,
|
||||
consumableFeedback,
|
||||
isSupportedOceanNetwork,
|
||||
web3,
|
||||
isAccountConnected,
|
||||
priceType
|
||||
)
|
||||
} else {
|
||||
@ -239,7 +240,7 @@ export default function ButtonBuy({
|
||||
selectedComputeAssetType,
|
||||
isAlgorithmConsumable,
|
||||
isSupportedOceanNetwork,
|
||||
web3,
|
||||
isAccountConnected,
|
||||
hasProviderFee
|
||||
)
|
||||
}
|
||||
|
@ -7,15 +7,17 @@ import { compareAsBN } from '@utils/numbers'
|
||||
import ButtonBuy from '../ButtonBuy'
|
||||
import PriceOutput from './PriceOutput'
|
||||
import { useAsset } from '@context/Asset'
|
||||
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 { useMarketMetadata } from '@context/MarketMetadata'
|
||||
import Alert from '@shared/atoms/Alert'
|
||||
import { getTokenBalanceFromSymbol } from '@utils/web3'
|
||||
import { getTokenBalanceFromSymbol } from '@utils/wallet'
|
||||
import { MAX_DECIMALS } from '@utils/constants'
|
||||
import Decimal from 'decimal.js'
|
||||
import { useAccount } from 'wagmi'
|
||||
import useBalance from '@hooks/useBalance'
|
||||
import useNetworkMetadata from '@hooks/useNetworkMetadata'
|
||||
|
||||
export default function FormStartCompute({
|
||||
algorithms,
|
||||
@ -77,7 +79,9 @@ export default function FormStartCompute({
|
||||
retry: boolean
|
||||
}): ReactElement {
|
||||
const { siteContent } = useMarketMetadata()
|
||||
const { accountId, balance, isSupportedOceanNetwork } = useWeb3()
|
||||
const { address: accountId, isConnected } = useAccount()
|
||||
const { balance } = useBalance()
|
||||
const { isSupportedOceanNetwork } = useNetworkMetadata()
|
||||
const { isValid, values }: FormikContextType<{ algorithm: string }> =
|
||||
useFormikContext()
|
||||
const { asset, isAssetNetwork } = useAsset()
|
||||
@ -303,6 +307,7 @@ export default function FormStartCompute({
|
||||
isSupportedOceanNetwork={isSupportedOceanNetwork}
|
||||
hasProviderFee={providerFeeAmount && providerFeeAmount !== '0'}
|
||||
retry={retry}
|
||||
isAccountConnected={isConnected}
|
||||
/>
|
||||
</Form>
|
||||
)
|
||||
|
@ -5,7 +5,7 @@ import Tooltip from '@shared/atoms/Tooltip'
|
||||
import styles from './PriceOutput.module.css'
|
||||
import { MAX_DECIMALS } from '@utils/constants'
|
||||
import Decimal from 'decimal.js'
|
||||
import { useWeb3 } from '@context/Web3'
|
||||
import useNetworkMetadata from '@hooks/useNetworkMetadata'
|
||||
|
||||
interface PriceOutputProps {
|
||||
hasPreviousOrder: boolean
|
||||
|
@ -20,7 +20,6 @@ import { toast } from 'react-toastify'
|
||||
import Price from '@shared/Price'
|
||||
import FileIcon from '@shared/FileIcon'
|
||||
import Alert from '@shared/atoms/Alert'
|
||||
import { useWeb3 } from '@context/Web3'
|
||||
import { Formik } from 'formik'
|
||||
import { getInitialValues, validationSchema } from './_constants'
|
||||
import FormStartComputeDataset from './FormComputeDataset'
|
||||
@ -44,12 +43,12 @@ import { useAbortController } from '@hooks/useAbortController'
|
||||
import { getOrderPriceAndFees } from '@utils/accessDetailsAndPricing'
|
||||
import { handleComputeOrder } from '@utils/order'
|
||||
import { getComputeFeedback } from '@utils/feedback'
|
||||
import { getDummyWeb3 } from '@utils/web3'
|
||||
import { initializeProviderForCompute } from '@utils/provider'
|
||||
import { useUserPreferences } from '@context/UserPreferences'
|
||||
import { useAsset } from '@context/Asset'
|
||||
import { useAccount, useSigner } from 'wagmi'
|
||||
|
||||
const refreshInterval = 10000 // 10 sec.
|
||||
|
||||
export default function Compute({
|
||||
asset,
|
||||
dtBalance,
|
||||
@ -63,9 +62,9 @@ export default function Compute({
|
||||
fileIsLoading?: boolean
|
||||
consumableFeedback?: string
|
||||
}): ReactElement {
|
||||
const { accountId, web3, isSupportedOceanNetwork, networkId } = useWeb3()
|
||||
const { address: accountId } = useAccount()
|
||||
const { chainIds } = useUserPreferences()
|
||||
const { isAssetNetwork } = useAsset()
|
||||
const { data: signer } = useSigner()
|
||||
|
||||
const newAbortController = useAbortController()
|
||||
const newCancelToken = useCancelToken()
|
||||
@ -116,10 +115,9 @@ export default function Compute({
|
||||
|
||||
const isUnsupportedPricing = asset?.accessDetails?.type === 'NOT_SUPPORTED'
|
||||
|
||||
async function checkAssetDTBalance(asset: DDO): Promise<boolean> {
|
||||
async function checkAssetDTBalance(asset: DDO) {
|
||||
if (!asset?.services[0].datatokenAddress) return
|
||||
const web3 = await getDummyWeb3(asset?.chainId)
|
||||
const datatokenInstance = new Datatoken(web3)
|
||||
const datatokenInstance = new Datatoken(signer)
|
||||
const dtBalance = await datatokenInstance.balance(
|
||||
asset?.services[0].datatokenAddress,
|
||||
accountId || ZERO_ADDRESS // if the user is not connected, we use ZERO_ADDRESS as accountId
|
||||
@ -127,7 +125,6 @@ export default function Compute({
|
||||
setAlgorithmDTBalance(new Decimal(dtBalance).toString())
|
||||
const hasAlgoDt = Number(dtBalance) >= 1
|
||||
setHasAlgoAssetDatatoken(hasAlgoDt)
|
||||
return hasAlgoDt
|
||||
}
|
||||
|
||||
async function setComputeFees(
|
||||
@ -145,21 +142,22 @@ export default function Compute({
|
||||
const feeValidity = providerData?.datasets?.[0]?.providerFee?.validUntil
|
||||
|
||||
const feeAmount = await unitsToAmount(
|
||||
!isSupportedOceanNetwork || !isAssetNetwork
|
||||
? await getDummyWeb3(asset?.chainId)
|
||||
: web3,
|
||||
// !isSupportedOceanNetwork || !isAssetNetwork
|
||||
// ? await getDummyWeb3(asset?.chainId)
|
||||
// : web3,
|
||||
signer,
|
||||
providerFeeToken,
|
||||
providerFeeAmount
|
||||
)
|
||||
setProviderFeeAmount(feeAmount)
|
||||
|
||||
const datatoken = new Datatoken(
|
||||
await getDummyWeb3(asset?.chainId),
|
||||
null,
|
||||
null,
|
||||
minAbi
|
||||
)
|
||||
|
||||
const datatoken = new Datatoken(signer)
|
||||
// const datatoken = new Datatoken(
|
||||
// await getDummyWeb3(asset?.chainId),
|
||||
// null,
|
||||
// null,
|
||||
// minAbi
|
||||
// )
|
||||
setProviderFeesSymbol(await datatoken.getSymbol(providerFeeToken))
|
||||
|
||||
const computeDuration = asset.accessDetails.validProviderFees
|
||||
@ -179,6 +177,7 @@ export default function Compute({
|
||||
const algorithmOrderPriceAndFees = await getOrderPriceAndFees(
|
||||
selectedAlgorithmAsset,
|
||||
ZERO_ADDRESS,
|
||||
signer,
|
||||
algoProviderFees
|
||||
)
|
||||
if (!algorithmOrderPriceAndFees)
|
||||
@ -197,6 +196,7 @@ export default function Compute({
|
||||
const datasetPriceAndFees = await getOrderPriceAndFees(
|
||||
asset,
|
||||
ZERO_ADDRESS,
|
||||
signer,
|
||||
datasetProviderFees
|
||||
)
|
||||
if (!datasetPriceAndFees)
|
||||
@ -373,11 +373,12 @@ export default function Compute({
|
||||
)
|
||||
|
||||
const algorithmOrderTx = await handleComputeOrder(
|
||||
web3,
|
||||
signer,
|
||||
selectedAlgorithmAsset,
|
||||
algoOrderPriceAndFees,
|
||||
accountId,
|
||||
initializedProviderResponse.algorithm,
|
||||
hasAlgoAssetDatatoken,
|
||||
computeEnv.consumerAddress
|
||||
)
|
||||
if (!algorithmOrderTx) throw new Error('Failed to order algorithm.')
|
||||
@ -391,11 +392,12 @@ export default function Compute({
|
||||
)
|
||||
|
||||
const datasetOrderTx = await handleComputeOrder(
|
||||
web3,
|
||||
signer,
|
||||
asset,
|
||||
datasetOrderPriceAndFees,
|
||||
accountId,
|
||||
initializedProviderResponse.datasets[0],
|
||||
hasDatatoken,
|
||||
computeEnv.consumerAddress
|
||||
)
|
||||
if (!datasetOrderTx) throw new Error('Failed to order dataset.')
|
||||
@ -414,8 +416,7 @@ export default function Compute({
|
||||
setComputeStatusText(getComputeFeedback()[4])
|
||||
const response = await ProviderInstance.computeStart(
|
||||
asset.services[0].serviceEndpoint,
|
||||
web3,
|
||||
accountId,
|
||||
signer,
|
||||
computeEnv?.id,
|
||||
computeAsset,
|
||||
computeAlgorithm,
|
||||
|
@ -2,7 +2,6 @@ import React, { ReactElement, useEffect, useState } from 'react'
|
||||
import FileIcon from '@shared/FileIcon'
|
||||
import Price from '@shared/Price'
|
||||
import { useAsset } from '@context/Asset'
|
||||
import { useWeb3 } from '@context/Web3'
|
||||
import ButtonBuy from './ButtonBuy'
|
||||
import { secondsToString } from '@utils/ddo'
|
||||
import AlgorithmDatasetsListForCompute from './Compute/AlgorithmDatasetsListForCompute'
|
||||
@ -17,6 +16,8 @@ import { useIsMounted } from '@hooks/useIsMounted'
|
||||
import { useMarketMetadata } from '@context/MarketMetadata'
|
||||
import Alert from '@shared/atoms/Alert'
|
||||
import Loader from '@shared/atoms/Loader'
|
||||
import { useAccount, useSigner } from 'wagmi'
|
||||
import useNetworkMetadata from '@hooks/useNetworkMetadata'
|
||||
|
||||
export default function Download({
|
||||
asset,
|
||||
@ -33,7 +34,9 @@ export default function Download({
|
||||
fileIsLoading?: boolean
|
||||
consumableFeedback?: string
|
||||
}): ReactElement {
|
||||
const { accountId, web3, isSupportedOceanNetwork } = useWeb3()
|
||||
const { address: accountId, isConnected } = useAccount()
|
||||
const { data: signer } = useSigner()
|
||||
const { isSupportedOceanNetwork } = useNetworkMetadata()
|
||||
const { getOpcFeeForToken } = useMarketMetadata()
|
||||
const { isInPurgatory, isAssetNetwork } = useAsset()
|
||||
const isMounted = useIsMounted()
|
||||
@ -72,16 +75,24 @@ export default function Download({
|
||||
async function init() {
|
||||
if (
|
||||
asset.accessDetails.addressOrId === ZERO_ADDRESS ||
|
||||
asset.accessDetails.type === 'free' ||
|
||||
isLoading
|
||||
asset.accessDetails.type === 'free'
|
||||
)
|
||||
return
|
||||
|
||||
!orderPriceAndFees && setIsPriceLoading(true)
|
||||
try {
|
||||
!orderPriceAndFees && setIsPriceLoading(true)
|
||||
|
||||
const _orderPriceAndFees = await getOrderPriceAndFees(asset, ZERO_ADDRESS)
|
||||
setOrderPriceAndFees(_orderPriceAndFees)
|
||||
!orderPriceAndFees && setIsPriceLoading(false)
|
||||
const _orderPriceAndFees = await getOrderPriceAndFees(
|
||||
asset,
|
||||
ZERO_ADDRESS,
|
||||
signer
|
||||
)
|
||||
setOrderPriceAndFees(_orderPriceAndFees)
|
||||
!orderPriceAndFees && setIsPriceLoading(false)
|
||||
} catch (error) {
|
||||
LoggerInstance.error('getOrderPriceAndFees', error)
|
||||
setIsPriceLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
init()
|
||||
@ -92,7 +103,7 @@ export default function Download({
|
||||
* Not adding isLoading and getOpcFeeForToken because we set these here. It is a compromise
|
||||
*/
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [asset, accountId, getOpcFeeForToken, isUnsupportedPricing])
|
||||
}, [asset, getOpcFeeForToken, isUnsupportedPricing])
|
||||
|
||||
useEffect(() => {
|
||||
setHasDatatoken(Number(dtBalance) >= 1)
|
||||
@ -144,7 +155,7 @@ export default function Download({
|
||||
)[3]
|
||||
)
|
||||
|
||||
await downloadFile(web3, asset, accountId, validOrderTx)
|
||||
await downloadFile(signer, asset, accountId, validOrderTx)
|
||||
} else {
|
||||
setStatusText(
|
||||
getOrderFeedback(
|
||||
@ -152,12 +163,19 @@ export default function Download({
|
||||
asset.accessDetails.datatoken?.symbol
|
||||
)[asset.accessDetails.type === 'fixed' ? 2 : 1]
|
||||
)
|
||||
const orderTx = await order(web3, asset, orderPriceAndFees, accountId)
|
||||
if (!orderTx) {
|
||||
const orderTx = await order(
|
||||
signer,
|
||||
asset,
|
||||
orderPriceAndFees,
|
||||
accountId,
|
||||
hasDatatoken
|
||||
)
|
||||
const tx = await orderTx.wait()
|
||||
if (!tx) {
|
||||
throw new Error()
|
||||
}
|
||||
setIsOwned(true)
|
||||
setValidOrderTx(orderTx.transactionHash)
|
||||
setValidOrderTx(tx?.transactionHash)
|
||||
}
|
||||
} catch (error) {
|
||||
LoggerInstance.error(error)
|
||||
@ -190,6 +208,7 @@ export default function Download({
|
||||
consumableFeedback={consumableFeedback}
|
||||
retry={retry}
|
||||
isSupportedOceanNetwork={isSupportedOceanNetwork}
|
||||
isAccountConnected={isConnected}
|
||||
/>
|
||||
)
|
||||
|
||||
|
@ -4,7 +4,6 @@ import Download from './Download'
|
||||
import { FileInfo, LoggerInstance, Datatoken } from '@oceanprotocol/lib'
|
||||
import { compareAsBN } from '@utils/numbers'
|
||||
import { useAsset } from '@context/Asset'
|
||||
import { useWeb3 } from '@context/Web3'
|
||||
import Web3Feedback from '@shared/Web3Feedback'
|
||||
import { getFileDidInfo, getFileInfo } from '@utils/provider'
|
||||
import { getOceanConfig } from '@utils/ocean'
|
||||
@ -13,15 +12,20 @@ import { useIsMounted } from '@hooks/useIsMounted'
|
||||
import styles from './index.module.css'
|
||||
import { useFormikContext } from 'formik'
|
||||
import { FormPublishData } from '@components/Publish/_types'
|
||||
import { getTokenBalanceFromSymbol } from '@utils/web3'
|
||||
import { getTokenBalanceFromSymbol } from '@utils/wallet'
|
||||
import AssetStats from './AssetStats'
|
||||
import { useAccount, useProvider, useNetwork } from 'wagmi'
|
||||
import useBalance from '@hooks/useBalance'
|
||||
|
||||
export default function AssetActions({
|
||||
asset
|
||||
}: {
|
||||
asset: AssetExtended
|
||||
}): ReactElement {
|
||||
const { accountId, balance, web3, chainId } = useWeb3()
|
||||
const { address: accountId } = useAccount()
|
||||
const { balance } = useBalance()
|
||||
const { chain } = useNetwork()
|
||||
const web3Provider = useProvider()
|
||||
const { isAssetNetwork } = useAsset()
|
||||
const newCancelToken = useCancelToken()
|
||||
const isMounted = useIsMounted()
|
||||
@ -72,7 +76,7 @@ export default function AssetActions({
|
||||
query,
|
||||
headers,
|
||||
abi,
|
||||
chainId,
|
||||
chain?.id,
|
||||
method
|
||||
)
|
||||
: await getFileDidInfo(asset?.id, asset?.services[0]?.id, providerUrl)
|
||||
@ -100,11 +104,11 @@ export default function AssetActions({
|
||||
|
||||
// Get and set user DT balance
|
||||
useEffect(() => {
|
||||
if (!web3 || !accountId || !isAssetNetwork) return
|
||||
if (!web3Provider || !accountId || !isAssetNetwork) return
|
||||
|
||||
async function init() {
|
||||
try {
|
||||
const datatokenInstance = new Datatoken(web3)
|
||||
const datatokenInstance = new Datatoken(web3Provider as any)
|
||||
const dtBalance = await datatokenInstance.balance(
|
||||
asset.services[0].datatokenAddress,
|
||||
accountId
|
||||
@ -115,7 +119,7 @@ export default function AssetActions({
|
||||
}
|
||||
}
|
||||
init()
|
||||
}, [web3, accountId, asset, isAssetNetwork])
|
||||
}, [web3Provider, accountId, asset, isAssetNetwork])
|
||||
|
||||
// Check user balance against price
|
||||
useEffect(() => {
|
||||
|
@ -3,28 +3,35 @@ import MetaItem from './MetaItem'
|
||||
import styles from './MetaFull.module.css'
|
||||
import Publisher from '@shared/Publisher'
|
||||
import { useAsset } from '@context/Asset'
|
||||
import { getDummyWeb3 } from '@utils/web3'
|
||||
import { Asset, Datatoken, LoggerInstance } from '@oceanprotocol/lib'
|
||||
import { Asset, LoggerInstance } from '@oceanprotocol/lib'
|
||||
import { getPaymentCollector } from '@utils/ocean'
|
||||
import { useProvider } from 'wagmi'
|
||||
|
||||
export default function MetaFull({ ddo }: { ddo: Asset }): ReactElement {
|
||||
const [paymentCollector, setPaymentCollector] = useState<string>()
|
||||
const { isInPurgatory, assetState } = useAsset()
|
||||
const provider = useProvider()
|
||||
|
||||
const [paymentCollector, setPaymentCollector] = useState<string>()
|
||||
|
||||
useEffect(() => {
|
||||
if (!ddo || !provider) return
|
||||
|
||||
async function getInitialPaymentCollector() {
|
||||
try {
|
||||
if (!ddo) return
|
||||
const web3 = await getDummyWeb3(ddo.chainId)
|
||||
const datatoken = new Datatoken(web3)
|
||||
setPaymentCollector(
|
||||
await datatoken.getPaymentCollector(ddo.datatokens[0].address)
|
||||
const paymentCollector = await getPaymentCollector(
|
||||
ddo.datatokens[0].address,
|
||||
provider
|
||||
)
|
||||
setPaymentCollector(paymentCollector)
|
||||
} catch (error) {
|
||||
LoggerInstance.error('[MetaFull: getInitialPaymentCollector]', error)
|
||||
LoggerInstance.error(
|
||||
'[MetaFull: getInitialPaymentCollector]',
|
||||
error.message
|
||||
)
|
||||
}
|
||||
}
|
||||
getInitialPaymentCollector()
|
||||
}, [ddo])
|
||||
}, [ddo, provider])
|
||||
|
||||
function DockerImage() {
|
||||
const containerInfo = ddo?.metadata?.algorithm?.container
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { useAsset } from '@context/Asset'
|
||||
import { useWeb3 } from '@context/Web3'
|
||||
import { Asset } from '@oceanprotocol/lib'
|
||||
import AddToken from '@shared/AddToken'
|
||||
import ExplorerLink from '@shared/ExplorerLink'
|
||||
import Publisher from '@shared/Publisher'
|
||||
import React, { ReactElement } from 'react'
|
||||
import { useAccount } from 'wagmi'
|
||||
import styles from './MetaAsset.module.css'
|
||||
|
||||
export default function MetaAsset({
|
||||
@ -15,7 +15,7 @@ export default function MetaAsset({
|
||||
isBlockscoutExplorer: boolean
|
||||
}): ReactElement {
|
||||
const { isAssetNetwork } = useAsset()
|
||||
const { web3ProviderInfo } = useWeb3()
|
||||
const { connector: activeConnector } = useAccount()
|
||||
|
||||
const dataTokenSymbol = asset?.datatokens[0]?.symbol
|
||||
|
||||
@ -36,7 +36,7 @@ export default function MetaAsset({
|
||||
>
|
||||
{`Accessed with ${dataTokenSymbol}`}
|
||||
</ExplorerLink>
|
||||
{web3ProviderInfo?.name === 'MetaMask' && isAssetNetwork && (
|
||||
{activeConnector?.name === 'MetaMask' && isAssetNetwork && (
|
||||
<span className={styles.addWrap}>
|
||||
<AddToken
|
||||
address={asset?.services[0].datatokenAddress}
|
||||
|
@ -5,7 +5,7 @@ import { NftMetadata } from '@utils/nft'
|
||||
import React, { ReactElement } from 'react'
|
||||
import styles from './NftTooltip.module.css'
|
||||
import explorerLinkStyles from '@shared/ExplorerLink/index.module.css'
|
||||
import { accountTruncate } from '@utils/web3'
|
||||
import { accountTruncate } from '@utils/wallet'
|
||||
|
||||
// Supported OpenSea networks:
|
||||
// https://support.opensea.io/hc/en-us/articles/4404027708051-Which-blockchains-does-OpenSea-support-
|
||||
|
@ -13,12 +13,11 @@ import EditHistory from './EditHistory'
|
||||
import styles from './index.module.css'
|
||||
import NetworkName from '@shared/NetworkName'
|
||||
import content from '../../../../content/purgatory.json'
|
||||
import Web3 from 'web3'
|
||||
import Button from '@shared/atoms/Button'
|
||||
import RelatedAssets from '../RelatedAssets'
|
||||
import DmButton from '@shared/DirectMessages/DmButton'
|
||||
import Web3Feedback from '@components/@shared/Web3Feedback'
|
||||
import { useWeb3 } from '@context/Web3'
|
||||
import { useAccount } from 'wagmi'
|
||||
|
||||
export default function AssetContent({
|
||||
asset
|
||||
@ -26,17 +25,17 @@ export default function AssetContent({
|
||||
asset: AssetExtended
|
||||
}): ReactElement {
|
||||
const { isInPurgatory, purgatoryData, isOwner, isAssetNetwork } = useAsset()
|
||||
const { accountId } = useWeb3()
|
||||
const { address: accountId } = useAccount()
|
||||
const { debug } = useUserPreferences()
|
||||
const [receipts, setReceipts] = useState([])
|
||||
const [nftPublisher, setNftPublisher] = useState<string>()
|
||||
|
||||
useEffect(() => {
|
||||
setNftPublisher(
|
||||
Web3.utils.toChecksumAddress(
|
||||
receipts?.find((e) => e.type === 'METADATA_CREATED')?.nft?.owner
|
||||
)
|
||||
)
|
||||
if (!receipts.length) return
|
||||
|
||||
const publisher = receipts?.find((e) => e.type === 'METADATA_CREATED')?.nft
|
||||
?.owner
|
||||
setNftPublisher(publisher)
|
||||
}, [receipts])
|
||||
|
||||
return (
|
||||
|
@ -1,4 +1,3 @@
|
||||
import { useWeb3 } from '@context/Web3'
|
||||
import { Formik } from 'formik'
|
||||
import React, { ReactElement, useState } from 'react'
|
||||
import FormEditComputeDataset from './FormEditComputeDataset'
|
||||
@ -24,6 +23,7 @@ import { useAsset } from '@context/Asset'
|
||||
import EditFeedback from './EditFeedback'
|
||||
import { setNftMetadata } from '@utils/nft'
|
||||
import { ComputeEditForm } from './_types'
|
||||
import { useAccount, useSigner } from 'wagmi'
|
||||
|
||||
export default function EditComputeDataset({
|
||||
asset
|
||||
@ -31,8 +31,10 @@ export default function EditComputeDataset({
|
||||
asset: AssetExtended
|
||||
}): ReactElement {
|
||||
const { debug } = useUserPreferences()
|
||||
const { accountId, web3 } = useWeb3()
|
||||
const { address: accountId } = useAccount()
|
||||
const { data: signer } = useSigner()
|
||||
const { fetchAsset, isAssetNetwork } = useAsset()
|
||||
|
||||
const [success, setSuccess] = useState<string>()
|
||||
const [error, setError] = useState<string>()
|
||||
const newAbortController = useAbortController()
|
||||
@ -46,7 +48,7 @@ export default function EditComputeDataset({
|
||||
asset?.accessDetails?.isPurchasable
|
||||
) {
|
||||
const tx = await setMinterToPublisher(
|
||||
web3,
|
||||
signer,
|
||||
asset?.accessDetails?.datatoken?.address,
|
||||
accountId,
|
||||
setError
|
||||
@ -84,7 +86,7 @@ export default function EditComputeDataset({
|
||||
const setMetadataTx = await setNftMetadata(
|
||||
updatedAsset,
|
||||
accountId,
|
||||
web3,
|
||||
signer,
|
||||
newAbortController()
|
||||
)
|
||||
|
||||
@ -97,7 +99,7 @@ export default function EditComputeDataset({
|
||||
} else {
|
||||
if (asset.accessDetails.type === 'free') {
|
||||
const tx = await setMinterToDispenser(
|
||||
web3,
|
||||
signer,
|
||||
asset?.accessDetails?.datatoken?.address,
|
||||
accountId,
|
||||
setError
|
||||
|
@ -12,7 +12,6 @@ import {
|
||||
import { validationSchema } from './_validation'
|
||||
import { getInitialValues } from './_constants'
|
||||
import { MetadataEditForm } from './_types'
|
||||
import { useWeb3 } from '@context/Web3'
|
||||
import { useUserPreferences } from '@context/UserPreferences'
|
||||
import Web3Feedback from '@shared/Web3Feedback'
|
||||
import FormEditMetadata from './FormEditMetadata'
|
||||
@ -21,13 +20,14 @@ import styles from './index.module.css'
|
||||
import content from '../../../../content/pages/editMetadata.json'
|
||||
import { useAbortController } from '@hooks/useAbortController'
|
||||
import DebugEditMetadata from './DebugEditMetadata'
|
||||
import { getOceanConfig } from '@utils/ocean'
|
||||
import { getOceanConfig, getPaymentCollector } from '@utils/ocean'
|
||||
import EditFeedback from './EditFeedback'
|
||||
import { useAsset } from '@context/Asset'
|
||||
import { setNftMetadata } from '@utils/nft'
|
||||
import { sanitizeUrl } from '@utils/url'
|
||||
import { getEncryptedFiles } from '@utils/provider'
|
||||
import { assetStateToNumber } from '@utils/assetState'
|
||||
import { useAccount, useProvider, useNetwork, useSigner } from 'wagmi'
|
||||
|
||||
export default function Edit({
|
||||
asset
|
||||
@ -36,8 +36,12 @@ export default function Edit({
|
||||
}): ReactElement {
|
||||
const { debug } = useUserPreferences()
|
||||
const { fetchAsset, isAssetNetwork, assetState } = useAsset()
|
||||
const { accountId, web3, chainId } = useWeb3()
|
||||
const { address: accountId } = useAccount()
|
||||
const { chain } = useNetwork()
|
||||
const provider = useProvider()
|
||||
const { data: signer } = useSigner()
|
||||
const newAbortController = useAbortController()
|
||||
|
||||
const [success, setSuccess] = useState<string>()
|
||||
const [paymentCollector, setPaymentCollector] = useState<string>()
|
||||
const [error, setError] = useState<string>()
|
||||
@ -45,12 +49,15 @@ export default function Edit({
|
||||
const hasFeedback = error || success
|
||||
|
||||
useEffect(() => {
|
||||
if (!asset || !provider) return
|
||||
|
||||
async function getInitialPaymentCollector() {
|
||||
try {
|
||||
const datatoken = new Datatoken(web3)
|
||||
setPaymentCollector(
|
||||
await datatoken.getPaymentCollector(asset?.datatokens[0].address)
|
||||
const paymentCollector = await getPaymentCollector(
|
||||
asset.datatokens[0].address,
|
||||
provider
|
||||
)
|
||||
setPaymentCollector(paymentCollector)
|
||||
} catch (error) {
|
||||
LoggerInstance.error(
|
||||
'[EditMetadata: getInitialPaymentCollector]',
|
||||
@ -59,18 +66,17 @@ export default function Edit({
|
||||
}
|
||||
}
|
||||
getInitialPaymentCollector()
|
||||
}, [asset, web3])
|
||||
}, [asset, provider])
|
||||
|
||||
async function updateFixedPrice(newPrice: string) {
|
||||
const config = getOceanConfig(asset.chainId)
|
||||
|
||||
const fixedRateInstance = new FixedRateExchange(
|
||||
config.fixedRateExchangeAddress,
|
||||
web3
|
||||
signer
|
||||
)
|
||||
|
||||
const setPriceResp = await fixedRateInstance.setRate(
|
||||
accountId,
|
||||
asset.accessDetails.addressOrId,
|
||||
newPrice.toString()
|
||||
)
|
||||
@ -103,7 +109,7 @@ export default function Edit({
|
||||
(await updateFixedPrice(values.price))
|
||||
|
||||
if (values.paymentCollector !== paymentCollector) {
|
||||
const datatoken = new Datatoken(web3)
|
||||
const datatoken = new Datatoken(signer)
|
||||
await datatoken.setPaymentCollector(
|
||||
asset?.datatokens[0].address,
|
||||
accountId,
|
||||
@ -115,7 +121,9 @@ export default function Edit({
|
||||
const file = {
|
||||
nftAddress: asset.nftAddress,
|
||||
datatokenAddress: asset.services[0].datatokenAddress,
|
||||
files: [normalizeFile(values.files[0].type, values.files[0], chainId)]
|
||||
files: [
|
||||
normalizeFile(values.files[0].type, values.files[0], chain?.id)
|
||||
]
|
||||
}
|
||||
|
||||
const filesEncrypted = await getEncryptedFiles(
|
||||
@ -146,12 +154,12 @@ export default function Edit({
|
||||
const setMetadataTx = await setNftMetadata(
|
||||
updatedAsset,
|
||||
accountId,
|
||||
web3,
|
||||
signer,
|
||||
newAbortController()
|
||||
)
|
||||
|
||||
if (values.assetState !== assetState) {
|
||||
const nft = new Nft(web3)
|
||||
const nft = new Nft(signer)
|
||||
|
||||
await nft.setMetadataState(
|
||||
asset?.nftAddress,
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { FileInfo } from '@oceanprotocol/lib'
|
||||
import * as Yup from 'yup'
|
||||
import web3 from 'web3'
|
||||
import { isAddress } from 'ethers/lib/utils'
|
||||
import { testLinks } from '../../../@utils/yup'
|
||||
|
||||
export const validationSchema = Yup.object().shape({
|
||||
@ -41,7 +41,7 @@ export const validationSchema = Yup.object().shape({
|
||||
'ValidAddress',
|
||||
'Must be a valid Ethereum Address.',
|
||||
(value) => {
|
||||
return web3.utils.isAddress(value)
|
||||
return isAddress(value)
|
||||
}
|
||||
),
|
||||
retireAsset: Yup.string()
|
||||
|
@ -1,30 +1,38 @@
|
||||
import React, { FormEvent } from 'react'
|
||||
import Caret from '@images/caret.svg'
|
||||
import { accountTruncate } from '@utils/web3'
|
||||
import Loader from '@shared/atoms/Loader'
|
||||
import { accountTruncate } from '@utils/wallet'
|
||||
// import Loader from '@shared/atoms/Loader'
|
||||
import styles from './Account.module.css'
|
||||
import { useWeb3 } from '@context/Web3'
|
||||
import Avatar from '@shared/atoms/Avatar'
|
||||
import { useAccount, useEnsName, useEnsAvatar } from 'wagmi'
|
||||
import { useModal } from 'connectkit'
|
||||
|
||||
// Forward ref for Tippy.js
|
||||
// eslint-disable-next-line
|
||||
const Account = React.forwardRef((props, ref: any) => {
|
||||
const { accountId, accountEns, accountEnsAvatar, web3Modal, connect } =
|
||||
useWeb3()
|
||||
const { address: accountId } = useAccount()
|
||||
const { data: accountEns } = useEnsName({ address: accountId, chainId: 1 })
|
||||
const { data: accountEnsAvatar } = useEnsAvatar({
|
||||
address: accountId,
|
||||
chainId: 1
|
||||
})
|
||||
const { setOpen } = useModal()
|
||||
|
||||
async function handleActivation(e: FormEvent<HTMLButtonElement>) {
|
||||
// prevent accidentially submitting a form the button might be in
|
||||
e.preventDefault()
|
||||
|
||||
await connect()
|
||||
setOpen(true)
|
||||
}
|
||||
|
||||
return !accountId && web3Modal?.cachedProvider ? (
|
||||
// Improve user experience for cached provider when connecting takes some time
|
||||
<button className={styles.button} onClick={(e) => e.preventDefault()}>
|
||||
<Loader />
|
||||
</button>
|
||||
) : accountId ? (
|
||||
// return
|
||||
// !accountId && provider ? (
|
||||
// // Improve user experience for cached provider when connecting takes some time
|
||||
// <button className={styles.button} onClick={(e) => e.preventDefault()}>
|
||||
// <Loader />
|
||||
// </button>
|
||||
// ) :
|
||||
return accountId ? (
|
||||
<button
|
||||
className={styles.button}
|
||||
aria-label="Account"
|
||||
|
@ -4,24 +4,24 @@ import { useUserPreferences } from '@context/UserPreferences'
|
||||
import Button from '@shared/atoms/Button'
|
||||
import AddToken from '@shared/AddToken'
|
||||
import Conversion from '@shared/Price/Conversion'
|
||||
import { useWeb3 } from '@context/Web3'
|
||||
import { useOrbis } from '@context/DirectMessages'
|
||||
import { getOceanConfig } from '@utils/ocean'
|
||||
import { useNetwork, useDisconnect, useAccount, useConnect } from 'wagmi'
|
||||
import { useModal } from 'connectkit'
|
||||
import styles from './Details.module.css'
|
||||
import useBalance from '@hooks/useBalance'
|
||||
import useNetworkMetadata from '@hooks/useNetworkMetadata'
|
||||
|
||||
export default function Details(): ReactElement {
|
||||
const {
|
||||
accountId,
|
||||
web3ProviderInfo,
|
||||
web3Modal,
|
||||
connect,
|
||||
logout,
|
||||
networkData,
|
||||
networkId,
|
||||
balance
|
||||
} = useWeb3()
|
||||
const { checkOrbisConnection, disconnectOrbis } = useOrbis()
|
||||
const { chain } = useNetwork()
|
||||
const { connector: activeConnector, address: accountId } = useAccount()
|
||||
const { connect } = useConnect()
|
||||
const { setOpen } = useModal()
|
||||
const { disconnect } = useDisconnect()
|
||||
const { balance } = useBalance()
|
||||
const { networkData } = useNetworkMetadata()
|
||||
const { locale } = useUserPreferences()
|
||||
const { checkOrbisConnection, disconnectOrbis } = useOrbis()
|
||||
|
||||
const [mainCurrency, setMainCurrency] = useState<string>()
|
||||
const [oceanTokenMetadata, setOceanTokenMetadata] = useState<{
|
||||
@ -30,19 +30,19 @@ export default function Details(): ReactElement {
|
||||
}>()
|
||||
|
||||
useEffect(() => {
|
||||
if (!networkId) return
|
||||
if (!chain?.id) return
|
||||
|
||||
const symbol = networkData?.nativeCurrency.symbol
|
||||
setMainCurrency(symbol)
|
||||
|
||||
const oceanConfig = getOceanConfig(networkId)
|
||||
const oceanConfig = getOceanConfig(chain.id)
|
||||
|
||||
oceanConfig &&
|
||||
setOceanTokenMetadata({
|
||||
address: oceanConfig.oceanTokenAddress,
|
||||
symbol: oceanConfig.oceanTokenSymbol
|
||||
})
|
||||
}, [networkData, networkId])
|
||||
}, [networkData, chain?.id])
|
||||
|
||||
return (
|
||||
<div className={styles.details}>
|
||||
@ -68,10 +68,10 @@ export default function Details(): ReactElement {
|
||||
<li className={styles.actions}>
|
||||
<div title="Connected provider" className={styles.walletInfo}>
|
||||
<span className={styles.walletLogoWrap}>
|
||||
<img className={styles.walletLogo} src={web3ProviderInfo?.logo} />
|
||||
{web3ProviderInfo?.name}
|
||||
{/* <img className={styles.walletLogo} src={activeConnector?.logo} /> */}
|
||||
{activeConnector?.name}
|
||||
</span>
|
||||
{web3ProviderInfo?.name === 'MetaMask' && (
|
||||
{activeConnector?.name === 'MetaMask' && (
|
||||
<AddToken
|
||||
address={oceanTokenMetadata?.address}
|
||||
symbol={oceanTokenMetadata?.symbol}
|
||||
@ -84,7 +84,6 @@ export default function Details(): ReactElement {
|
||||
style="text"
|
||||
size="small"
|
||||
onClick={async () => {
|
||||
await web3Modal?.clearCachedProvider()
|
||||
connect()
|
||||
checkOrbisConnection({ address: accountId })
|
||||
}}
|
||||
@ -95,7 +94,7 @@ export default function Details(): ReactElement {
|
||||
style="text"
|
||||
size="small"
|
||||
onClick={() => {
|
||||
logout()
|
||||
disconnect()
|
||||
disconnectOrbis(accountId)
|
||||
location.reload()
|
||||
}}
|
||||
|
@ -2,21 +2,23 @@ import React, { ReactElement } from 'react'
|
||||
import Status from '@shared/atoms/Status'
|
||||
import Badge from '@shared/atoms/Badge'
|
||||
import Tooltip from '@shared/atoms/Tooltip'
|
||||
import { useWeb3 } from '@context/Web3'
|
||||
import NetworkName from '@shared/NetworkName'
|
||||
import styles from './Network.module.css'
|
||||
import { useNetwork } from 'wagmi'
|
||||
import useNetworkMetadata from '@hooks/useNetworkMetadata'
|
||||
|
||||
export default function Network(): ReactElement {
|
||||
const { networkId, isTestnet, isSupportedOceanNetwork } = useWeb3()
|
||||
const { chain } = useNetwork()
|
||||
const { isTestnet, isSupportedOceanNetwork } = useNetworkMetadata()
|
||||
|
||||
return networkId ? (
|
||||
return chain?.id ? (
|
||||
<div className={styles.network}>
|
||||
{!isSupportedOceanNetwork && (
|
||||
<Tooltip content="No Ocean Protocol contracts are deployed to this network.">
|
||||
<Status state="error" className={styles.warning} />
|
||||
</Tooltip>
|
||||
)}
|
||||
<NetworkName className={styles.name} networkId={networkId} minimal />
|
||||
<NetworkName className={styles.name} networkId={chain.id} minimal />
|
||||
{isTestnet && <Badge label="Test" className={styles.badge} />}
|
||||
</div>
|
||||
) : null
|
||||
|
@ -4,10 +4,10 @@ import Details from './Details'
|
||||
import Tooltip from '@shared/atoms/Tooltip'
|
||||
import Network from './Network'
|
||||
import styles from './index.module.css'
|
||||
import { useWeb3 } from '@context/Web3'
|
||||
import { useAccount } from 'wagmi'
|
||||
|
||||
export default function Wallet(): ReactElement {
|
||||
const { accountId } = useWeb3()
|
||||
const { address: accountId } = useAccount()
|
||||
|
||||
return (
|
||||
<div className={styles.wallet}>
|
||||
|
@ -1,5 +1,4 @@
|
||||
import React, { ReactElement, useEffect, useState } from 'react'
|
||||
import { useWeb3 } from '@context/Web3'
|
||||
import { AssetWithOwnAllocation, getOwnAllocations } from '@utils/veAllocation'
|
||||
import styles from './index.module.css'
|
||||
import {
|
||||
@ -12,9 +11,10 @@ import { useCancelToken } from '@hooks/useCancelToken'
|
||||
import { useIsMounted } from '@hooks/useIsMounted'
|
||||
import { LoggerInstance } from '@oceanprotocol/lib'
|
||||
import AssetListTable from './AssetListTable'
|
||||
import { useAccount } from 'wagmi'
|
||||
|
||||
export default function Allocations(): ReactElement {
|
||||
const { accountId } = useWeb3()
|
||||
const { address: accountId } = useAccount()
|
||||
const { chainIds } = useUserPreferences()
|
||||
const isMounted = useIsMounted()
|
||||
const newCancelToken = useCancelToken()
|
||||
|
@ -7,8 +7,8 @@ import Tooltip from '@shared/atoms/Tooltip'
|
||||
import AssetTitle from '@shared/AssetListTitle'
|
||||
import { getAssetsFromDids } from '@utils/aquarius'
|
||||
import { useCancelToken } from '@hooks/useCancelToken'
|
||||
import { useWeb3 } from '@context/Web3'
|
||||
import { useMarketMetadata } from '@context/MarketMetadata'
|
||||
import { useAccount } from 'wagmi'
|
||||
|
||||
const columns: TableOceanColumn<AssetExtended>[] = [
|
||||
{
|
||||
@ -38,7 +38,7 @@ const columns: TableOceanColumn<AssetExtended>[] = [
|
||||
|
||||
export default function Bookmarks(): ReactElement {
|
||||
const { appConfig } = useMarketMetadata()
|
||||
const { accountId } = useWeb3()
|
||||
const { address: accountId } = useAccount()
|
||||
const { bookmarks } = useUserPreferences()
|
||||
|
||||
const [pinned, setPinned] = useState<AssetExtended[]>()
|
||||
|
@ -2,7 +2,7 @@ import React, { ReactElement, useEffect, useState } from 'react'
|
||||
import Dotdotdot from 'react-dotdotdot'
|
||||
import Link from 'next/link'
|
||||
import styles from './index.module.css'
|
||||
import { accountTruncate } from '@utils/web3'
|
||||
import { accountTruncate } from '@utils/wallet'
|
||||
import Avatar from '../../../@shared/atoms/Avatar'
|
||||
import { getEnsProfile } from '@utils/ens'
|
||||
import { UserSales } from '@utils/aquarius'
|
||||
|
@ -7,7 +7,7 @@ import Copy from '@shared/atoms/Copy'
|
||||
import Avatar from '@shared/atoms/Avatar'
|
||||
import styles from './Account.module.css'
|
||||
import { useProfile } from '@context/Profile'
|
||||
import { accountTruncate } from '@utils/web3'
|
||||
import { accountTruncate } from '@utils/wallet'
|
||||
|
||||
export default function Account({
|
||||
accountId
|
||||
|
@ -8,14 +8,14 @@ import { useProfile } from '@context/Profile'
|
||||
import { getLocked } from '@utils/veAllocation'
|
||||
import PriceUnit from '@shared/Price/PriceUnit'
|
||||
import Button from '@shared/atoms/Button'
|
||||
import { useWeb3 } from '@context/Web3'
|
||||
import { useAccount } from 'wagmi'
|
||||
|
||||
export default function Stats({
|
||||
accountId
|
||||
}: {
|
||||
accountId: string
|
||||
}): ReactElement {
|
||||
const web3 = useWeb3()
|
||||
const { address } = useAccount()
|
||||
const { chainIds } = useUserPreferences()
|
||||
const { assets, assetsTotal, sales } = useProfile()
|
||||
|
||||
@ -73,7 +73,7 @@ export default function Stats({
|
||||
<NumberUnit label="Published" value={assetsTotal} />
|
||||
<NumberUnit
|
||||
label={
|
||||
lockedOcean === 0 && accountId === web3.accountId ? (
|
||||
lockedOcean === 0 && accountId === address ? (
|
||||
<Button
|
||||
className={styles.link}
|
||||
style="text"
|
||||
|
@ -10,9 +10,9 @@ import Button from '@shared/atoms/Button'
|
||||
import styles from './Results.module.css'
|
||||
import FormHelp from '@shared/FormInput/Help'
|
||||
import content from '../../../../../content/pages/history.json'
|
||||
import { useWeb3 } from '@context/Web3'
|
||||
import { useCancelToken } from '@hooks/useCancelToken'
|
||||
import { getAsset } from '@utils/aquarius'
|
||||
import { useAccount, useSigner } from 'wagmi'
|
||||
|
||||
export default function Results({
|
||||
job
|
||||
@ -20,12 +20,14 @@ export default function Results({
|
||||
job: ComputeJobMetaData
|
||||
}): ReactElement {
|
||||
const providerInstance = new Provider()
|
||||
const { accountId, web3 } = useWeb3()
|
||||
const isFinished = job.dateFinished !== null
|
||||
const { address: accountId } = useAccount()
|
||||
const { data: signer } = useSigner()
|
||||
|
||||
const [datasetProvider, setDatasetProvider] = useState<string>()
|
||||
const newCancelToken = useCancelToken()
|
||||
|
||||
const isFinished = job.dateFinished !== null
|
||||
|
||||
useEffect(() => {
|
||||
async function getAssetMetadata() {
|
||||
const ddo = await getAsset(job.inputDID[0], newCancelToken())
|
||||
@ -62,8 +64,7 @@ export default function Results({
|
||||
try {
|
||||
const jobResult = await providerInstance.getComputeResultUrl(
|
||||
datasetProvider,
|
||||
web3,
|
||||
accountId,
|
||||
signer,
|
||||
job.jobId,
|
||||
resultIndex
|
||||
)
|
||||
|
@ -2,13 +2,13 @@ import React, { ReactElement, useState } from 'react'
|
||||
import Time from '@shared/atoms/Time'
|
||||
import Table, { TableOceanColumn } from '@shared/atoms/Table'
|
||||
import Button from '@shared/atoms/Button'
|
||||
import { useWeb3 } from '@context/Web3'
|
||||
import Details from './Details'
|
||||
import Refresh from '@images/refresh.svg'
|
||||
import { useUserPreferences } from '@context/UserPreferences'
|
||||
import NetworkName from '@shared/NetworkName'
|
||||
import styles from './index.module.css'
|
||||
import AssetListTitle from '@shared/AssetListTitle'
|
||||
import { useAccount } from 'wagmi'
|
||||
|
||||
export function Status({ children }: { children: string }): ReactElement {
|
||||
return <div className={styles.status}>{children}</div>
|
||||
@ -55,7 +55,7 @@ export default function ComputeJobs({
|
||||
isLoading?: boolean
|
||||
refetchJobs?: any
|
||||
}): ReactElement {
|
||||
const { accountId } = useWeb3()
|
||||
const { address: accountId } = useAccount()
|
||||
const { chainIds } = useUserPreferences()
|
||||
const [columnsMinimal] = useState([columns[4], columns[5], columns[3]])
|
||||
|
||||
@ -84,6 +84,6 @@ export default function ComputeJobs({
|
||||
/>
|
||||
</>
|
||||
) : (
|
||||
<div>Please connect your Web3 wallet.</div>
|
||||
<div>Please connect your wallet.</div>
|
||||
)
|
||||
}
|
||||
|
@ -42,6 +42,6 @@ export default function ComputeDownloads({
|
||||
emptyMessage={chainIds.length === 0 ? 'No network selected' : null}
|
||||
/>
|
||||
) : (
|
||||
<div>Please connect your Web3 wallet.</div>
|
||||
<div>Please connect your wallet.</div>
|
||||
)
|
||||
}
|
||||
|
@ -97,6 +97,6 @@ export default function PublishedList({
|
||||
/>
|
||||
</>
|
||||
) : (
|
||||
<div>Please connect your Web3 wallet.</div>
|
||||
<div>Please connect your wallet.</div>
|
||||
)
|
||||
}
|
||||
|
@ -4,11 +4,11 @@ import PublishedList from './PublishedList'
|
||||
import Downloads from './Downloads'
|
||||
import ComputeJobs from './ComputeJobs'
|
||||
import styles from './index.module.css'
|
||||
import { useWeb3 } from '@context/Web3'
|
||||
import { getComputeJobs } from '@utils/compute'
|
||||
import { useUserPreferences } from '@context/UserPreferences'
|
||||
import { useCancelToken } from '@hooks/useCancelToken'
|
||||
import { LoggerInstance } from '@oceanprotocol/lib'
|
||||
import { useAccount } from 'wagmi'
|
||||
|
||||
interface HistoryTab {
|
||||
title: string
|
||||
@ -56,7 +56,7 @@ export default function HistoryPage({
|
||||
}: {
|
||||
accountIdentifier: string
|
||||
}): ReactElement {
|
||||
const { accountId } = useWeb3()
|
||||
const { address: accountId } = useAccount()
|
||||
const { chainIds } = useUserPreferences()
|
||||
const newCancelToken = useCancelToken()
|
||||
|
||||
|
@ -5,12 +5,12 @@ import { FormikContextType, useFormikContext } from 'formik'
|
||||
import { FormPublishData } from '../_types'
|
||||
import { wizardSteps } from '../_constants'
|
||||
import SuccessConfetti from '@shared/SuccessConfetti'
|
||||
import { useWeb3 } from '@context/Web3'
|
||||
import { useRouter } from 'next/router'
|
||||
import Tooltip from '@shared/atoms/Tooltip'
|
||||
import AvailableNetworks from '@components/Publish/AvailableNetworks'
|
||||
import Info from '@images/info.svg'
|
||||
import Loader from '@shared/atoms/Loader'
|
||||
import useNetworkMetadata from '@hooks/useNetworkMetadata'
|
||||
|
||||
export default function Actions({
|
||||
scrollToRef,
|
||||
@ -20,21 +20,19 @@ export default function Actions({
|
||||
did: string
|
||||
}): ReactElement {
|
||||
const router = useRouter()
|
||||
const { isSupportedOceanNetwork } = useWeb3()
|
||||
const { isSupportedOceanNetwork } = useNetworkMetadata()
|
||||
const {
|
||||
values,
|
||||
errors,
|
||||
isValid,
|
||||
isSubmitting
|
||||
}: FormikContextType<FormPublishData> = useFormikContext()
|
||||
const { connect, accountId } = useWeb3()
|
||||
// async function handleActivation(e: FormEvent<HTMLButtonElement>) {
|
||||
// // prevent accidentially submitting a form the button might be in
|
||||
// e.preventDefault()
|
||||
|
||||
async function handleActivation(e: FormEvent<HTMLButtonElement>) {
|
||||
// prevent accidentially submitting a form the button might be in
|
||||
e.preventDefault()
|
||||
|
||||
await connect()
|
||||
}
|
||||
// await connect()
|
||||
// }
|
||||
|
||||
function handleAction(action: string) {
|
||||
const currentStep: string = router.query.step as string
|
||||
@ -92,11 +90,12 @@ export default function Actions({
|
||||
>
|
||||
Continue
|
||||
</Button>
|
||||
) : !accountId ? (
|
||||
<Button type="submit" style="primary" onClick={handleActivation}>
|
||||
Connect Wallet
|
||||
</Button>
|
||||
) : !isSupportedOceanNetwork ? (
|
||||
) : // !address ? (
|
||||
// <Button type="submit" style="primary" onClick={handleActivation}>
|
||||
// Connect Wallet
|
||||
// </Button>
|
||||
// ) :
|
||||
!isSupportedOceanNetwork ? (
|
||||
<Tooltip content={<AvailableNetworks />}>
|
||||
<Button
|
||||
type="submit"
|
||||
|
@ -3,8 +3,7 @@ import NetworkName from '@shared/NetworkName'
|
||||
import styles from './Network.module.css'
|
||||
import Button from '@shared/atoms/Button'
|
||||
import useNetworkMetadata from '@hooks/useNetworkMetadata'
|
||||
import { addCustomNetwork } from '@utils/web3'
|
||||
import { useWeb3 } from '@context/Web3'
|
||||
// TODO: import { addCustomNetwork } from '@utils/wallet'
|
||||
|
||||
export default function Network({
|
||||
chainId
|
||||
@ -12,11 +11,10 @@ export default function Network({
|
||||
chainId: number
|
||||
}): ReactElement {
|
||||
const { networksList } = useNetworkMetadata()
|
||||
const { web3Provider } = useWeb3()
|
||||
|
||||
function changeNetwork(chainId: number) {
|
||||
const networkNode = networksList.find((data) => data.chainId === chainId)
|
||||
addCustomNetwork(web3Provider, networkNode)
|
||||
// addCustomNetwork(networkNode)
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -6,18 +6,18 @@ import { transformPublishFormToDdo } from '../_utils'
|
||||
import styles from './index.module.css'
|
||||
import { DDO } from '@oceanprotocol/lib'
|
||||
import { previewDebugPatch } from '@utils/ddo'
|
||||
import { useWeb3 } from '@context/Web3'
|
||||
import { useNetwork } from 'wagmi'
|
||||
|
||||
export default function Debug(): ReactElement {
|
||||
const { values } = useFormikContext<FormPublishData>()
|
||||
const [valuePreview, setValuePreview] = useState({})
|
||||
const [ddo, setDdo] = useState<DDO>()
|
||||
const { chainId } = useWeb3()
|
||||
const { chain } = useNetwork()
|
||||
|
||||
useEffect(() => {
|
||||
async function makeDdo() {
|
||||
const ddo = await transformPublishFormToDdo(values)
|
||||
setValuePreview(previewDebugPatch(values, chainId))
|
||||
setValuePreview(previewDebugPatch(values, chain?.id))
|
||||
setDdo(ddo)
|
||||
}
|
||||
makeDdo()
|
||||
|
@ -4,9 +4,9 @@ import styles from './Fees.module.css'
|
||||
import Input from '@shared/FormInput'
|
||||
import { getOpcFees } from '@utils/subgraph'
|
||||
import { OpcFeesQuery_opc as OpcFeesData } from '../../../@types/subgraph/OpcFeesQuery'
|
||||
import { useWeb3 } from '@context/Web3'
|
||||
import { useMarketMetadata } from '@context/MarketMetadata'
|
||||
import Decimal from 'decimal.js'
|
||||
import { useNetwork } from 'wagmi'
|
||||
|
||||
const Default = ({
|
||||
title,
|
||||
@ -40,18 +40,18 @@ export default function Fees({
|
||||
tooltips: { [key: string]: string }
|
||||
}): ReactElement {
|
||||
const [oceanCommunitySwapFee, setOceanCommunitySwapFee] = useState<string>('')
|
||||
const { chainId } = useWeb3()
|
||||
const { chain } = useNetwork()
|
||||
const { appConfig } = useMarketMetadata()
|
||||
|
||||
useEffect(() => {
|
||||
getOpcFees(chainId || 1).then((response: OpcFeesData) => {
|
||||
getOpcFees(chain?.id || 1).then((response: OpcFeesData) => {
|
||||
setOceanCommunitySwapFee(
|
||||
response?.swapOceanFee
|
||||
? new Decimal(response.swapOceanFee).mul(100).toString()
|
||||
: '0'
|
||||
)
|
||||
})
|
||||
}, [chainId])
|
||||
}, [chain?.id])
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -7,11 +7,13 @@ import Free from './Free'
|
||||
import content from '../../../../content/price.json'
|
||||
import styles from './index.module.css'
|
||||
import { useMarketMetadata } from '@context/MarketMetadata'
|
||||
import { useWeb3 } from '@context/Web3'
|
||||
import { useNetwork } from 'wagmi'
|
||||
|
||||
export default function PricingFields(): ReactElement {
|
||||
const { appConfig } = useMarketMetadata()
|
||||
const { approvedBaseTokens, chainId } = useWeb3()
|
||||
const { chain } = useNetwork()
|
||||
const { approvedBaseTokens } = useMarketMetadata()
|
||||
|
||||
// Connect with main publish form
|
||||
const { values, setFieldValue } = useFormikContext<FormPublishData>()
|
||||
const { pricing } = values
|
||||
@ -22,6 +24,23 @@ export default function PricingFields(): ReactElement {
|
||||
token.name.toLowerCase().includes('ocean')
|
||||
) || approvedBaseTokens?.[0]
|
||||
|
||||
const isBaseTokenSet = !!approvedBaseTokens?.find(
|
||||
(token) => token?.address === values?.pricing?.baseToken?.address
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
if (!approvedBaseTokens?.length) return
|
||||
if (isBaseTokenSet) return
|
||||
setFieldValue('pricing.baseToken', defaultBaseToken)
|
||||
}, [
|
||||
approvedBaseTokens,
|
||||
chain?.id,
|
||||
defaultBaseToken,
|
||||
isBaseTokenSet,
|
||||
setFieldValue,
|
||||
values.pricing.baseToken
|
||||
])
|
||||
|
||||
// Switch type value upon tab change
|
||||
function handleTabChange(tabName: string) {
|
||||
const type = tabName.toLowerCase()
|
||||
|
@ -1,28 +1,31 @@
|
||||
import { ReactElement, useEffect } from 'react'
|
||||
import { useFormikContext } from 'formik'
|
||||
import { wizardSteps, initialPublishFeedback } from './_constants'
|
||||
import { useWeb3 } from '@context/Web3'
|
||||
import { FormPublishData, PublishFeedback } from './_types'
|
||||
import { getOceanConfig } from '@utils/ocean'
|
||||
import { useAccount, useNetwork } from 'wagmi'
|
||||
import { useMarketMetadata } from '@context/MarketMetadata'
|
||||
|
||||
export function Steps({
|
||||
feedback
|
||||
}: {
|
||||
feedback: PublishFeedback
|
||||
}): ReactElement {
|
||||
const { chainId, accountId, approvedBaseTokens } = useWeb3()
|
||||
const { address: accountId } = useAccount()
|
||||
const { chain } = useNetwork()
|
||||
const { approvedBaseTokens } = useMarketMetadata()
|
||||
const { values, setFieldValue, touched, setTouched } =
|
||||
useFormikContext<FormPublishData>()
|
||||
|
||||
const isCustomProviderUrl = values?.services?.[0]?.providerUrl.custom
|
||||
|
||||
// auto-sync user chainId & account into form data values
|
||||
// auto-sync user chain?.id & account into form data values
|
||||
useEffect(() => {
|
||||
if (!chainId || !accountId) return
|
||||
if (!chain?.id || !accountId) return
|
||||
|
||||
setFieldValue('user.chainId', chainId)
|
||||
setFieldValue('user.chainId', chain?.id)
|
||||
setFieldValue('user.accountId', accountId)
|
||||
}, [chainId, accountId, setFieldValue])
|
||||
}, [chain?.id, accountId, setFieldValue])
|
||||
|
||||
useEffect(() => {
|
||||
if (!approvedBaseTokens?.length) return
|
||||
@ -37,7 +40,7 @@ export function Steps({
|
||||
if (isBaseTokenSet) return
|
||||
|
||||
setFieldValue('pricing.baseToken', defaultBaseToken)
|
||||
}, [approvedBaseTokens])
|
||||
}, [approvedBaseTokens, values?.pricing?.baseToken?.address])
|
||||
|
||||
// auto-sync publish feedback into form data values
|
||||
useEffect(() => {
|
||||
|
@ -3,16 +3,19 @@ import NetworkName from '@shared/NetworkName'
|
||||
import Tooltip from '@shared/atoms/Tooltip'
|
||||
import styles from './index.module.css'
|
||||
import content from '../../../../content/publish/index.json'
|
||||
import { useWeb3 } from '@context/Web3'
|
||||
import Info from '@images/info.svg'
|
||||
import AvailableNetworks from '@components/Publish/AvailableNetworks'
|
||||
import useNetworkMetadata from '@hooks/useNetworkMetadata'
|
||||
import { useAccount } from 'wagmi'
|
||||
|
||||
export default function Title({
|
||||
networkId
|
||||
}: {
|
||||
networkId: number
|
||||
}): ReactElement {
|
||||
const { isSupportedOceanNetwork, accountId } = useWeb3()
|
||||
const { address: accountId } = useAccount()
|
||||
const { isSupportedOceanNetwork } = useNetworkMetadata()
|
||||
|
||||
return (
|
||||
<>
|
||||
{content.title}{' '}
|
||||
|
@ -11,13 +11,13 @@ import {
|
||||
NftCreateData,
|
||||
NftFactory,
|
||||
Service,
|
||||
ZERO_ADDRESS
|
||||
ZERO_ADDRESS,
|
||||
getEventFromTx
|
||||
} from '@oceanprotocol/lib'
|
||||
import { mapTimeoutStringToSeconds, normalizeFile } from '@utils/ddo'
|
||||
import { generateNftCreateData } from '@utils/nft'
|
||||
import { getEncryptedFiles } from '@utils/provider'
|
||||
import slugify from 'slugify'
|
||||
import Web3 from 'web3'
|
||||
import { algorithmContainerPresets } from './_constants'
|
||||
import { FormPublishData, MetadataAlgorithmContainer } from './_types'
|
||||
import {
|
||||
@ -28,6 +28,7 @@ import {
|
||||
} from '../../../app.config'
|
||||
import { sanitizeUrl } from '@utils/url'
|
||||
import { getContainerChecksum } from '@utils/docker'
|
||||
import { parseEther } from 'ethers/lib/utils'
|
||||
|
||||
function getUrlFileExtension(fileUrl: string): string {
|
||||
const splittedFileUrl = fileUrl.split('.')
|
||||
@ -193,8 +194,7 @@ export async function createTokensAndPricing(
|
||||
values: FormPublishData,
|
||||
accountId: string,
|
||||
config: Config,
|
||||
nftFactory: NftFactory,
|
||||
web3: Web3
|
||||
nftFactory: NftFactory
|
||||
) {
|
||||
const nftCreateData: NftCreateData = generateNftCreateData(
|
||||
values.metadata.nft,
|
||||
@ -241,15 +241,18 @@ export async function createTokensAndPricing(
|
||||
)
|
||||
|
||||
const result = await nftFactory.createNftWithDatatokenWithFixedRate(
|
||||
accountId,
|
||||
nftCreateData,
|
||||
ercParams,
|
||||
freParams
|
||||
)
|
||||
|
||||
erc721Address = result.events.NFTCreated.returnValues[0]
|
||||
datatokenAddress = result.events.TokenCreated.returnValues[0]
|
||||
txHash = result.transactionHash
|
||||
const trxReceipt = await result.wait()
|
||||
const nftCreatedEvent = getEventFromTx(trxReceipt, 'NFTCreated')
|
||||
const tokenCreatedEvent = getEventFromTx(trxReceipt, 'TokenCreated')
|
||||
|
||||
erc721Address = nftCreatedEvent.args.newTokenAddress
|
||||
datatokenAddress = tokenCreatedEvent.args.newTokenAddress
|
||||
txHash = trxReceipt.transactionHash
|
||||
|
||||
LoggerInstance.log('[publish] createNftErcWithFixedRate tx', txHash)
|
||||
|
||||
@ -261,8 +264,8 @@ export async function createTokensAndPricing(
|
||||
// both will be just 1 for the market
|
||||
const dispenserParams: DispenserCreationParams = {
|
||||
dispenserAddress: config.dispenserAddress,
|
||||
maxTokens: web3.utils.toWei('1'),
|
||||
maxBalance: web3.utils.toWei('1'),
|
||||
maxTokens: parseEther('1').toString(),
|
||||
maxBalance: parseEther('1').toString(),
|
||||
withMint: true,
|
||||
allowedSwapper: ZERO_ADDRESS
|
||||
}
|
||||
@ -273,14 +276,17 @@ export async function createTokensAndPricing(
|
||||
)
|
||||
|
||||
const result = await nftFactory.createNftWithDatatokenWithDispenser(
|
||||
accountId,
|
||||
nftCreateData,
|
||||
ercParams,
|
||||
dispenserParams
|
||||
)
|
||||
erc721Address = result.events.NFTCreated.returnValues[0]
|
||||
datatokenAddress = result.events.TokenCreated.returnValues[0]
|
||||
txHash = result.transactionHash
|
||||
const trxReceipt = await result.wait()
|
||||
const nftCreatedEvent = getEventFromTx(trxReceipt, 'NFTCreated')
|
||||
const tokenCreatedEvent = getEventFromTx(trxReceipt, 'TokenCreated')
|
||||
|
||||
erc721Address = nftCreatedEvent.args.newTokenAddress
|
||||
datatokenAddress = tokenCreatedEvent.args.newTokenAddress
|
||||
txHash = trxReceipt.transactionHash
|
||||
|
||||
LoggerInstance.log('[publish] createNftErcWithDispenser tx', txHash)
|
||||
|
||||
|
@ -2,7 +2,6 @@ import React, { ReactElement, useState, useRef } from 'react'
|
||||
import { Form, Formik } from 'formik'
|
||||
import { initialPublishFeedback, initialValues } from './_constants'
|
||||
import { useAccountPurgatory } from '@hooks/useAccountPurgatory'
|
||||
import { useWeb3 } from '@context/Web3'
|
||||
import { createTokensAndPricing, transformPublishFormToDdo } from './_utils'
|
||||
import PageHeader from '@shared/Page/PageHeader'
|
||||
import Title from './Title'
|
||||
@ -19,6 +18,7 @@ import { getOceanConfig } from '@utils/ocean'
|
||||
import { validationSchema } from './_validation'
|
||||
import { useAbortController } from '@hooks/useAbortController'
|
||||
import { setNFTMetadataAndTokenURI } from '@utils/nft'
|
||||
import { useAccount, useNetwork, useSigner } from 'wagmi'
|
||||
|
||||
export default function PublishPage({
|
||||
content
|
||||
@ -26,7 +26,9 @@ export default function PublishPage({
|
||||
content: { title: string; description: string; warning: string }
|
||||
}): ReactElement {
|
||||
const { debug } = useUserPreferences()
|
||||
const { accountId, web3, chainId } = useWeb3()
|
||||
const { address: accountId } = useAccount()
|
||||
const { data: signer } = useSigner()
|
||||
const { chain } = useNetwork()
|
||||
const { isInPurgatory, purgatoryData } = useAccountPurgatory(accountId)
|
||||
const scrollToRef = useRef()
|
||||
const nftFactory = useNftFactory()
|
||||
@ -60,17 +62,11 @@ export default function PublishPage({
|
||||
}))
|
||||
|
||||
try {
|
||||
const config = getOceanConfig(chainId)
|
||||
const config = getOceanConfig(chain?.id)
|
||||
LoggerInstance.log('[publish] using config: ', config)
|
||||
|
||||
const { erc721Address, datatokenAddress, txHash } =
|
||||
await createTokensAndPricing(
|
||||
values,
|
||||
accountId,
|
||||
config,
|
||||
nftFactory,
|
||||
web3
|
||||
)
|
||||
await createTokensAndPricing(values, accountId, config, nftFactory)
|
||||
|
||||
const isSuccess = Boolean(erc721Address && datatokenAddress && txHash)
|
||||
if (!isSuccess) throw new Error('No Token created. Please try again.')
|
||||
@ -197,23 +193,24 @@ export default function PublishPage({
|
||||
const res = await setNFTMetadataAndTokenURI(
|
||||
ddo,
|
||||
accountId,
|
||||
web3,
|
||||
signer,
|
||||
values.metadata.nft,
|
||||
newAbortController()
|
||||
)
|
||||
if (!res?.transactionHash)
|
||||
const tx = await res.wait()
|
||||
if (!tx?.transactionHash)
|
||||
throw new Error(
|
||||
'Metadata could not be written into the NFT. Please try again.'
|
||||
)
|
||||
|
||||
LoggerInstance.log('[publish] setMetadata result', res)
|
||||
LoggerInstance.log('[publish] setMetadata result', tx)
|
||||
|
||||
setFeedback((prevState) => ({
|
||||
...prevState,
|
||||
'3': {
|
||||
...prevState['3'],
|
||||
status: res ? 'success' : 'error',
|
||||
txHash: res?.transactionHash
|
||||
status: tx ? 'success' : 'error',
|
||||
txHash: tx?.transactionHash
|
||||
}
|
||||
}))
|
||||
|
||||
|
@ -1,18 +1,19 @@
|
||||
// import App from "next/app";
|
||||
import React, { ReactElement, useEffect } from 'react'
|
||||
import type { AppProps /*, AppContext */ } from 'next/app'
|
||||
import Web3Provider from '@context/Web3'
|
||||
import { UserPreferencesProvider } from '@context/UserPreferences'
|
||||
import PricesProvider from '@context/Prices'
|
||||
import UrqlProvider from '@context/UrqlProvider'
|
||||
import ConsentProvider from '@context/CookieConsent'
|
||||
import App from '../../src/components/App'
|
||||
import { OrbisProvider } from '@context/DirectMessages'
|
||||
import App from 'src/components/App'
|
||||
|
||||
import '@oceanprotocol/typographies/css/ocean-typo.css'
|
||||
import '../stylesGlobal/styles.css'
|
||||
import Decimal from 'decimal.js'
|
||||
import MarketMetadataProvider from '@context/MarketMetadata'
|
||||
import { WagmiConfig } from 'wagmi'
|
||||
import { ConnectKitProvider } from 'connectkit'
|
||||
import { connectKitTheme, wagmiClient } from '@utils/wallet'
|
||||
import posthog from 'posthog-js'
|
||||
import { PostHogProvider } from 'posthog-js/react'
|
||||
import { useRouter } from 'next/router'
|
||||
@ -40,25 +41,32 @@ function MyApp({ Component, pageProps }: AppProps): ReactElement {
|
||||
}, [router.events])
|
||||
|
||||
return (
|
||||
<MarketMetadataProvider>
|
||||
<Web3Provider>
|
||||
<UrqlProvider>
|
||||
<UserPreferencesProvider>
|
||||
<PricesProvider>
|
||||
<ConsentProvider>
|
||||
<OrbisProvider>
|
||||
<PostHogProvider client={posthog}>
|
||||
<App>
|
||||
<Component {...pageProps} />
|
||||
</App>
|
||||
</PostHogProvider>
|
||||
</OrbisProvider>
|
||||
</ConsentProvider>
|
||||
</PricesProvider>
|
||||
</UserPreferencesProvider>
|
||||
</UrqlProvider>
|
||||
</Web3Provider>
|
||||
</MarketMetadataProvider>
|
||||
<>
|
||||
<WagmiConfig client={wagmiClient}>
|
||||
<ConnectKitProvider
|
||||
options={{ initialChainId: 0 }}
|
||||
customTheme={connectKitTheme}
|
||||
>
|
||||
<MarketMetadataProvider>
|
||||
<UrqlProvider>
|
||||
<UserPreferencesProvider>
|
||||
<PricesProvider>
|
||||
<ConsentProvider>
|
||||
<OrbisProvider>
|
||||
<PostHogProvider client={posthog}>
|
||||
<App>
|
||||
<Component {...pageProps} />
|
||||
</App>
|
||||
</PostHogProvider>
|
||||
</OrbisProvider>
|
||||
</ConsentProvider>
|
||||
</PricesProvider>
|
||||
</UserPreferencesProvider>
|
||||
</UrqlProvider>
|
||||
</MarketMetadataProvider>
|
||||
</ConnectKitProvider>
|
||||
</WagmiConfig>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -1,19 +1,21 @@
|
||||
import React, { ReactElement, useEffect, useState } from 'react'
|
||||
import Page from '@shared/Page'
|
||||
import ProfilePage from '../../components/Profile'
|
||||
import { accountTruncate } from '@utils/web3'
|
||||
import { useWeb3 } from '@context/Web3'
|
||||
import { accountTruncate } from '@utils/wallet'
|
||||
import ProfileProvider from '@context/Profile'
|
||||
import { getEnsAddress, getEnsName } from '@utils/ens'
|
||||
import { useRouter } from 'next/router'
|
||||
import web3 from 'web3'
|
||||
import { useAccount, useEnsName } from 'wagmi'
|
||||
import { isAddress } from 'ethers/lib/utils'
|
||||
|
||||
export default function PageProfile(): ReactElement {
|
||||
const router = useRouter()
|
||||
const { accountId, accountEns } = useWeb3()
|
||||
const { address: accountId } = useAccount()
|
||||
const { data: accountEns } = useEnsName({ address: accountId })
|
||||
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() {
|
||||
@ -30,7 +32,7 @@ export default function PageProfile(): ReactElement {
|
||||
const pathAccount = router.query.account as string
|
||||
|
||||
// Path has ETH address
|
||||
if (web3.utils.isAddress(pathAccount)) {
|
||||
if (isAddress(pathAccount)) {
|
||||
setOwnAccount(pathAccount === accountId)
|
||||
const finalAccountId = pathAccount || accountId
|
||||
setFinalAccountId(finalAccountId)
|
||||
|
@ -1,10 +1,10 @@
|
||||
import React, { ReactElement, useState } from 'react'
|
||||
import Search from '../components/Search'
|
||||
import Page from '@shared/Page'
|
||||
import { accountTruncate } from '@utils/web3'
|
||||
import { accountTruncate } from '@utils/wallet'
|
||||
import { MAXIMUM_NUMBER_OF_PAGES_WITH_RESULTS } from '@utils/aquarius'
|
||||
import { useRouter } from 'next/router'
|
||||
import web3 from 'web3'
|
||||
import { isAddress } from 'ethers/lib/utils'
|
||||
|
||||
export default function PageSearch(): ReactElement {
|
||||
const router = useRouter()
|
||||
@ -13,7 +13,7 @@ export default function PageSearch(): ReactElement {
|
||||
const [totalResults, setTotalResults] = useState<number>()
|
||||
const [totalPagesNumber, setTotalPagesNumber] = useState<number>()
|
||||
|
||||
const isETHAddress = web3.utils.isAddress(text as string)
|
||||
const isETHAddress = isAddress(text as string)
|
||||
const searchValue =
|
||||
(isETHAddress ? accountTruncate(text as string) : text) ||
|
||||
tags ||
|
||||
|
@ -1,151 +0,0 @@
|
||||
div.web3modal-modal-lightbox,
|
||||
div.walletconnect-qrcode__base {
|
||||
background: var(--background-body-transparent);
|
||||
backdrop-filter: blur(3px);
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
animation: fadeIn 0.2s ease-out backwards;
|
||||
}
|
||||
|
||||
div.web3modal-modal-card {
|
||||
border-radius: var(--border-radius);
|
||||
padding: var(--spacer);
|
||||
margin: var(--spacer) auto;
|
||||
max-width: 100%;
|
||||
border: 1px solid var(--border-color);
|
||||
box-shadow: 0 6px 15px 0 var(--box-shadow-color);
|
||||
animation: moveUp 0.2s ease-out backwards;
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
div.web3modal-provider-wrapper {
|
||||
border: 0;
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
div.web3modal-provider-wrapper:last-child {
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
div.web3modal-provider-container {
|
||||
border-radius: 0;
|
||||
padding: var(--spacer);
|
||||
}
|
||||
|
||||
@media (min-width: 40rem) {
|
||||
div.web3modal-modal-card {
|
||||
grid-template-columns: 1fr 1fr;
|
||||
max-width: var(--break-point--small);
|
||||
}
|
||||
|
||||
div.web3modal-provider-wrapper {
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
div.web3modal-provider-wrapper:nth-child(1),
|
||||
div.web3modal-provider-wrapper:nth-child(2) {
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
div.web3modal-provider-wrapper:nth-child(2n + 1) {
|
||||
border-right: 1px solid var(--border-color);
|
||||
}
|
||||
}
|
||||
|
||||
div.web3modal-provider-icon {
|
||||
filter: grayscale(1) contrast(150%);
|
||||
transition: filter 0.2s ease-out;
|
||||
}
|
||||
|
||||
div.web3modal-provider-wrapper:hover div.web3modal-provider-icon {
|
||||
filter: none;
|
||||
}
|
||||
|
||||
div.web3modal-provider-name {
|
||||
font-size: var(--font-size-large);
|
||||
font-weight: var(--font-weight-bold);
|
||||
font-family: var(--font-family-heading);
|
||||
}
|
||||
|
||||
div.web3modal-provider-description {
|
||||
font-size: var(--font-size-base);
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
div.walletconnect-modal__base {
|
||||
background: var(--background-body);
|
||||
border-radius: var(--border-radius);
|
||||
border: 1px solid var(--border-color);
|
||||
box-shadow: 0 6px 17px 0 var(--box-shadow-color);
|
||||
}
|
||||
|
||||
div.walletconnect-modal__mobile__toggle {
|
||||
width: 95%;
|
||||
text-transform: uppercase;
|
||||
cursor: pointer;
|
||||
background: var(--background-body);
|
||||
border: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
div.walletconnect-modal__mobile__toggle a {
|
||||
color: var(--color-secondary);
|
||||
font-weight: var(--font-weight-bold);
|
||||
font-size: var(--font-size-small);
|
||||
padding: calc(var(--spacer) / 12) var(--spacer);
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
div.walletconnect-modal__mobile__toggle_selector {
|
||||
background: var(--font-color-heading);
|
||||
color: var(--background-body);
|
||||
border-color: var(--font-color-heading);
|
||||
height: calc(100% - calc(var(--spacer) / 12));
|
||||
top: calc(var(--spacer) / 24);
|
||||
}
|
||||
|
||||
div.walletconnect-modal__header p {
|
||||
color: var(--font-color-heading);
|
||||
}
|
||||
|
||||
p.walletconnect-qrcode__text {
|
||||
color: var(--color-secondary);
|
||||
}
|
||||
|
||||
h3.walletconnect-modal__base__row__h3 {
|
||||
font-size: var(--font-size-base);
|
||||
color: var(--font-color-text);
|
||||
}
|
||||
|
||||
svg.walletconnect-qrcode__image path:first-child {
|
||||
fill: var(--background-body);
|
||||
}
|
||||
|
||||
svg.walletconnect-qrcode__image path:last-child {
|
||||
stroke: var(--font-color-heading);
|
||||
}
|
||||
|
||||
#torusIframe {
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes moveUp {
|
||||
from {
|
||||
transform: translate3d(0, 1rem, 0);
|
||||
}
|
||||
|
||||
to {
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
}
|
@ -162,7 +162,6 @@ table th {
|
||||
|
||||
@import '_code.css';
|
||||
@import '_toast.css';
|
||||
@import '_web3modal.css';
|
||||
@import '_emojipicker.css';
|
||||
|
||||
/* prevent background scrolling */
|
||||
|
Loading…
Reference in New Issue
Block a user