diff --git a/src/components/@shared/Onboarding/index.tsx b/src/components/@shared/Onboarding/index.tsx
index c9695ddc8..dd3ed9438 100644
--- a/src/components/@shared/Onboarding/index.tsx
+++ b/src/components/@shared/Onboarding/index.tsx
@@ -15,6 +15,7 @@ import useBalance from '@hooks/useBalance'
import ImportWallet from './Steps/ImportWallet'
import AutomationWalletState from './Steps/AutomationWalletState'
import { getSupportedChainIds } from '../../../../chains.config'
+import Faucet from './Steps/Faucet'
export interface OnboardingStep {
title: string
@@ -31,6 +32,7 @@ const steps = [
{ shortLabel: 'Tokens', component:
},
{ shortLabel: 'Import', component:
},
{ shortLabel: 'Automation', component:
},
+ { shortLabel: 'Faucet', component:
},
{ shortLabel: 'Ready', component:
}
]
diff --git a/src/components/App/index.tsx b/src/components/App/index.tsx
index 084fc14b1..976272466 100644
--- a/src/components/App/index.tsx
+++ b/src/components/App/index.tsx
@@ -28,7 +28,7 @@ export default function App({
return (
{siteContent?.announcement !== '' && (
-
+
)}
{appConfig.showPreviewAlert === 'true' &&
devPreviewAnnouncementText !== '' && (
diff --git a/src/components/Faucet/index.module.css b/src/components/Faucet/index.module.css
new file mode 100644
index 000000000..bddaa9a8a
--- /dev/null
+++ b/src/components/Faucet/index.module.css
@@ -0,0 +1,96 @@
+.card {
+ max-width: 800px;
+ margin: auto;
+ margin-top: 50px;
+ padding: 30px;
+ border: 1px solid #e0e0e0;
+ border-radius: 12px;
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
+ background-color: #f9f9f9;
+}
+
+.title {
+ font-size: 32px;
+ margin-bottom: 10px;
+ color: #2c3e50;
+}
+
+.description {
+ font-size: 18px;
+ margin-bottom: 20px;
+ color: #34495e;
+ line-height: 1.6;
+}
+
+.instructions {
+ margin-bottom: 20px;
+ background-color: #ffffff;
+ padding: 20px;
+ border-radius: 8px;
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
+}
+
+.instructions h3 {
+ font-size: 22px;
+ margin-bottom: 15px;
+ color: #2c3e50;
+}
+
+.instructions ol {
+ padding-left: 20px;
+ margin-bottom: 10px;
+ color: #34495e;
+}
+
+.instructions ol li {
+ margin-bottom: 10px;
+ font-size: 16px;
+}
+
+.address,
+.network {
+ font-size: 16px;
+ word-break: break-all;
+ margin-bottom: 20px;
+ color: #34495e;
+}
+
+.form {
+ display: flex;
+ flex-direction: column;
+}
+
+.button {
+ background-color: #007bff;
+ border: none;
+ color: white;
+ padding: 12px 24px;
+ text-align: center;
+ text-decoration: none;
+ display: inline-block;
+ font-size: 16px;
+ margin: 8px 2px;
+ cursor: pointer;
+ border-radius: 6px;
+ transition: background-color 0.3s ease, transform 0.3s ease;
+}
+
+.button:hover {
+ background-color: #0056b3;
+ transform: scale(1.05);
+}
+
+.disabledButton {
+ background-color: grey !important;
+ cursor: not-allowed !important;
+}
+
+.errorContainer,
+.successContainer {
+ margin-top: 20px;
+ width: 100%;
+}
+
+.textStrong {
+ color: #2c3e50;
+}
diff --git a/src/components/Faucet/index.tsx b/src/components/Faucet/index.tsx
new file mode 100644
index 000000000..ebc1c1e19
--- /dev/null
+++ b/src/components/Faucet/index.tsx
@@ -0,0 +1,210 @@
+import { ReactElement, useCallback, useEffect, useState } from 'react'
+import { LoggerInstance } from '@oceanprotocol/lib'
+import styles from './index.module.css'
+import Button from '@components/@shared/atoms/Button'
+import Loader from '@components/@shared/atoms/Loader'
+import Alert from '@components/@shared/atoms/Alert'
+import content from '../../../content/pages/faucet.json'
+import { ethers } from 'ethers'
+import { getMessage, requestTokens } from '../../@utils/faucet'
+import { useAccount, useSignMessage } from 'wagmi'
+import { toast } from 'react-toastify'
+
+interface Content {
+ title: string
+ description: string
+ input: {
+ label: string
+ placeholder: string
+ buttonLabel: string
+ }
+}
+
+const networkNameMap: { [key: number]: string } = {
+ 32456: 'Pontus-X Devnet',
+ 32457: 'Pontus-X Testnet'
+}
+
+const FaucetPage = (): ReactElement => {
+ const { input }: Content = content
+ const { label, buttonLabel } = input
+
+ const [isLoading, setIsLoading] = useState(false)
+ const [isRequestingTokens, setIsRequestingTokens] = useState(false)
+ const [address, setAddress] = useState
('')
+ const [network, setNetwork] = useState('Unknown')
+ const [message, setMessage] = useState()
+ const [error, setError] = useState()
+
+ const { address: accountAddress } = useAccount()
+
+ const {
+ data: signMessageData,
+ error: signMessageError,
+ isLoading: signMessageLoading,
+ isSuccess: signMessageSuccess,
+ signMessage
+ } = useSignMessage()
+
+ const handleVerify = useCallback(async () => {
+ setIsLoading(true)
+ setError(undefined)
+ setMessage(undefined)
+
+ try {
+ const message = await getMessage(accountAddress)
+ signMessage({ message })
+ } catch (error) {
+ LoggerInstance.error(error)
+ setError(error.message || 'Error generating message.')
+ } finally {
+ setIsLoading(false)
+ }
+ }, [accountAddress, signMessage])
+
+ const handleSearchStart = useCallback(
+ (e: React.FormEvent) => {
+ e.preventDefault()
+ handleVerify()
+ },
+ [handleVerify]
+ )
+
+ const faucetTokenRequest = useCallback(async () => {
+ setIsRequestingTokens(true)
+ try {
+ const hashes = await requestTokens(accountAddress, signMessageData)
+ toast.success(`Successfully requested test tokens: ${hashes.join(', ')}`)
+ setMessage(
+ 'Tokens successfully requested. It can take up to 30 seconds until tokens show up in your wallet.'
+ )
+ } catch (error) {
+ const errorMessage =
+ error.message || 'Unable to request tokens. Please try again later.'
+ setError(errorMessage)
+ LoggerInstance.error('[Onboarding] Error requesting tokens', error)
+ } finally {
+ setIsRequestingTokens(false)
+ }
+ }, [accountAddress, signMessageData])
+
+ useEffect(() => {
+ if (signMessageLoading) return
+
+ if (signMessageError) {
+ toast.error('Unable to sign message. Please try again.')
+ LoggerInstance.error(
+ '[Onboarding] Error signing message',
+ signMessageError
+ )
+ return
+ }
+
+ if (signMessageSuccess && signMessageData) {
+ faucetTokenRequest()
+ }
+ }, [
+ signMessageSuccess,
+ signMessageData,
+ signMessageError,
+ signMessageLoading,
+ faucetTokenRequest
+ ])
+
+ useEffect(() => {
+ const fetchAddressAndNetwork = async () => {
+ try {
+ const provider = new ethers.providers.Web3Provider(window.ethereum)
+ const signer = provider.getSigner()
+ const address = await signer.getAddress()
+ const network = await provider.getNetwork()
+ setAddress(address)
+ setNetwork(networkNameMap[network.chainId] || 'Unknown')
+ } catch (error) {
+ LoggerInstance.error(error)
+ }
+ }
+
+ fetchAddressAndNetwork()
+
+ if (window.ethereum) {
+ window.ethereum.on('accountsChanged', fetchAddressAndNetwork)
+ window.ethereum.on('chainChanged', fetchAddressAndNetwork)
+ }
+
+ return () => {
+ if (window.ethereum) {
+ window.ethereum.removeListener(
+ 'accountsChanged',
+ fetchAddressAndNetwork
+ )
+ window.ethereum.removeListener('chainChanged', fetchAddressAndNetwork)
+ }
+ }
+ }, [])
+
+ return (
+
+
Welcome to the Pontus-X Faucet
+
+ A faucet is a service that provides free tokens for testing purposes.
+ Known accounts can request 10 EUROe fee tokens and 1000 EUROe payment
+ tokens to use on the Pontus-X network. These tokens are available every
+ 12 hours.
+
+
+
How to Request Tokens:
+
+ - Ensure you have a web3 wallet (e.g. MetaMask) connected.
+ -
+ Your wallet address will be automatically detected and displayed
+ below.
+
+ -
+ Click the "Get Tokens" button to request your free tokens.
+
+ - Wait for a few seconds while the request is processed.
+ -
+ You will receive a confirmation once the tokens are successfully
+ added to your wallet.
+
+
+
+ Note: You can only request tokens once every 12
+ hours. If you encounter any issues, please try again later.
+
+
+
+ {label}: {address}
+
+
+ Connected Network: {network}
+
+
+ {!isLoading && error && (
+
+ )}
+ {!isLoading && message && (
+
+ )}
+
+ )
+}
+
+export default FaucetPage
diff --git a/src/components/Publish/Pricing/index.tsx b/src/components/Publish/Pricing/index.tsx
index 79a481e5f..a6a8d6548 100644
--- a/src/components/Publish/Pricing/index.tsx
+++ b/src/components/Publish/Pricing/index.tsx
@@ -21,7 +21,7 @@ export default function PricingFields(): ReactElement {
const defaultBaseToken =
approvedBaseTokens?.find((token) =>
- token.name.toLowerCase().includes('ocean')
+ token.name.toLowerCase().includes('euro')
) || approvedBaseTokens?.[0]
const isBaseTokenSet = !!approvedBaseTokens?.find(
diff --git a/src/components/Publish/Steps.tsx b/src/components/Publish/Steps.tsx
index 5c6b845e8..fcde86aed 100644
--- a/src/components/Publish/Steps.tsx
+++ b/src/components/Publish/Steps.tsx
@@ -32,7 +32,7 @@ export function Steps({
const defaultBaseToken =
approvedBaseTokens?.find((token) =>
- token.name.toLowerCase().includes('ocean')
+ token.name.toLowerCase().includes('euro')
) || approvedBaseTokens?.[0]
const isBaseTokenSet = !!approvedBaseTokens?.find(
(token) => token?.address === values?.pricing?.baseToken?.address
diff --git a/src/components/Publish/_constants.tsx b/src/components/Publish/_constants.tsx
index 9d1348057..26c61affc 100644
--- a/src/components/Publish/_constants.tsx
+++ b/src/components/Publish/_constants.tsx
@@ -52,7 +52,7 @@ const computeOptions: ServiceComputeOptions = {
export const initialValues: FormPublishData = {
user: {
stepCurrent: 1,
- chainId: 100,
+ chainId: 32457,
accountId: ''
},
metadata: {
@@ -84,13 +84,13 @@ export const initialValues: FormPublishData = {
},
services: [
{
- files: [{ url: '', type: 'ipfs' }],
+ files: [{ url: '', type: 'url' }],
links: [{ url: '', type: 'url' }],
dataTokenOptions: { name: '', symbol: '' },
timeout: '',
access: 'access',
providerUrl: {
- url: 'https://provider.mainnet.oceanprotocol.com',
+ url: 'https://provider.test.pontus-x.eu',
valid: true,
custom: false
},
@@ -102,7 +102,7 @@ export const initialValues: FormPublishData = {
}
],
pricing: {
- baseToken: { address: '', name: '', symbol: 'OCEAN', decimals: 18 },
+ baseToken: { address: '', name: '', symbol: 'EUROe', decimals: 6 },
price: 0,
type: allowFixedPricing === 'true' ? 'fixed' : 'free',
freeAgreement: false
diff --git a/src/pages/faucet.tsx b/src/pages/faucet.tsx
new file mode 100644
index 000000000..c73c19e40
--- /dev/null
+++ b/src/pages/faucet.tsx
@@ -0,0 +1,12 @@
+import { ReactElement } from 'react'
+import Verify from '../components/Faucet'
+import content from '../../content/pages/faucet.json'
+import Page from '@components/@shared/Page'
+
+export default function PageVerify(): ReactElement {
+ return (
+
+
+
+ )
+}