The AgrospAI Data Space Portal provides a comprehensive data marketplace where users can discover, purchase, and monetize data assets and algorithms. Built on Ocean Protocol, the marketplace enables secure and transparent data exchange with built-in privacy and compliance features.
Marketplace Overview
The marketplace supports multiple asset types and pricing models, enabling flexible data monetization strategies:
Datasets Upload and sell agricultural data, research datasets, and analytics
Algorithms Publish and monetize AI/ML algorithms for compute-to-data
SaaS Services Offer software services with flexible payment models
Asset Discovery
Browse and Search
The marketplace homepage displays featured assets, recent publications, and top-selling datasets:
// From: src/components/Home/index.tsx
export default function HomePage () : ReactElement {
const { chainIds } = useUserPreferences ()
const { featured , hasFeaturedAssets } = useAddressConfig ()
const [ queryRecent , setQueryRecent ] = useState < SearchQuery >()
const [ queryMostSales , setQueryMostSales ] = useState < SearchQuery >()
useEffect (() => {
const baseParams = {
chainIds ,
esPaginationOptions: {
size: 4
},
sortOptions: {
sortBy: SortTermOptions . Created
} as SortOptions
} as BaseQueryParams
setQueryRecent ( generateBaseQuery ( baseParams ))
// Query for most sales
const baseParamsSales = {
... baseParams ,
sortOptions: {
sortBy: SortTermOptions . Orders
}
}
setQueryMostSales ( generateBaseQuery ( baseParamsSales ))
}, [ chainIds ])
return (
<>
< SectionQueryResult title = "Recently Published" query = { queryRecent } />
< SectionQueryResult title = "Most Sales" query = { queryMostSales } />
</>
)
}
Advanced Search
Users can filter and search assets using multiple criteria:
// From: src/components/Search/index.tsx
export default function SearchPage ({
setTotalResults ,
setTotalPagesNumber
} : {
setTotalResults : ( totalResults : number ) => void
setTotalPagesNumber : ( totalPagesNumber : number ) => void
}) : ReactElement {
const router = useRouter ()
const [ parsed , setParsed ] = useState < queryString . ParsedQuery < string >>()
const { chainIds } = useUserPreferences ()
const [ queryResult , setQueryResult ] = useState < PagedAssets >()
const [ loading , setLoading ] = useState < boolean >( true )
const fetchAssets = useDebouncedCallback (
async ( parsed : queryString . ParsedQuery < string >, chainIds : number []) => {
setLoading ( true )
const queryResult = await getResults ( parsed , chainIds , newCancelToken ())
setQueryResult ( queryResult )
setTotalResults ( queryResult ?. totalResults || 0 )
setTotalPagesNumber ( queryResult ?. totalPages || 0 )
setLoading ( false )
},
500
)
return (
< div className = { styles . container } >
< div className = { styles . filterContainer } >
< Filter addFiltersToUrl expanded />
< Sort expanded />
</ div >
< div className = { styles . results } >
< AssetList
assets = { queryResult ?. results }
showPagination
isLoading = { loading }
page = { queryResult ?. page }
totalPages = { queryResult ?. totalPages }
onPageChange = { updatePage }
/>
</ div >
</ div >
)
}
Search results are debounced by 500ms to optimize performance and reduce unnecessary API calls.
Pricing Models
The marketplace supports two pricing strategies:
Fixed Price Assets
Assets with fixed pricing require payment in a specific base token:
// From: src/components/Publish/Pricing/Fixed.tsx
export default function Fixed ({
approvedBaseTokens ,
content
} : {
approvedBaseTokens : TokenInfo []
content : FormContent
}) : ReactElement {
return (
<>
< Field
{ ... getFieldContent ( 'price' , content . fields ) }
component = { Input }
name = "pricing.price"
type = "number"
min = "0"
step = "0.01"
/>
< Field
{ ... getFieldContent ( 'baseToken' , content . fields ) }
component = { Input }
name = "pricing.baseToken"
options = { approvedBaseTokens }
/>
< Field
{ ... getFieldContent ( 'amountDataToken' , content . fields ) }
component = { Input }
name = "pricing.amountDataToken"
type = "number"
min = "1"
/>
</>
)
}
Free Assets
Free assets can be accessed without payment, ideal for open data initiatives:
// From: src/components/Publish/Pricing/Free.tsx
export default function Free ({
content
} : {
content : FormContent
}) : ReactElement {
return (
< Field
{ ... getFieldContent ( 'freeAgreement' , content . fields ) }
component = { Input }
name = "pricing.freeAgreement"
/>
)
}
Fixed Pricing
Free Pricing
Best for commercial datasets and premium algorithms. Publishers receive payment in their chosen base token (e.g., OCEAN, USDC). Key Features:
Set your own price
Choose payment token
Earn immediately on purchase
Configurable datatoken supply
Ideal for open data sharing and building reputation. Users can access without payment. Key Features:
No payment required
Wider distribution
Build community trust
Still maintains access control
Asset Purchase Flow
Step 1: Asset Selection
Users browse the marketplace and select an asset to view its details:
// From: src/components/Asset/index.tsx
export default function AssetDetails ({ uri } : { uri : string }) : ReactElement {
const { asset , title , error , isInPurgatory , loading } = useAsset ()
return asset && pageTitle !== undefined && ! loading ? (
< Page title = { pageTitle } uri = { uri } >
< AssetContent asset = { asset } />
</ Page >
) : error ? (
< Page title = { pageTitle } noPageHeader uri = { uri } >
< Alert title = { pageTitle } text = { error } state = { 'error' } />
</ Page >
) : (
< Page title = { undefined } uri = { uri } >
< Loader />
</ Page >
)
}
Step 2: Price Calculation
The system calculates the full price including all fees:
// From: src/components/Asset/AssetActions/Download/index.tsx
useEffect (() => {
if ( isUnsupportedPricing ) return
setIsOwned ( asset ?. accessDetails ?. isOwned || false )
setValidOrderTx ( asset ?. accessDetails ?. validOrderTx || '' )
// Get full price and fees
async function init () {
if (
asset . accessDetails . addressOrId === ZERO_ADDRESS ||
asset . accessDetails . type === 'free'
)
return
try {
! orderPriceAndFees && setIsPriceLoading ( true )
const _orderPriceAndFees = await getOrderPriceAndFees (
asset ,
accountId || ZERO_ADDRESS
)
setOrderPriceAndFees ( _orderPriceAndFees )
! orderPriceAndFees && setIsPriceLoading ( false )
} catch ( error ) {
LoggerInstance . error ( 'getOrderPriceAndFees' , error )
setIsPriceLoading ( false )
}
}
init ()
}, [ asset , isUnsupportedPricing ])
Step 3: Order Execution
The order is processed through smart contracts:
// From: src/@utils/order.ts
export async function order (
signer : Signer ,
asset : AssetExtended ,
orderPriceAndFees : OrderPriceAndFees ,
accountId : string ,
hasDatatoken : boolean
) : Promise < ethers . providers . TransactionResponse > {
const datatoken = new Datatoken ( signer )
const config = getOceanConfig ( asset . chainId )
const initializeData = await initializeProvider (
asset ,
accountId
)
const orderParams = {
consumer: accountId ,
serviceIndex: 0 ,
_providerFee: initializeData . providerFee ,
_consumeMarketFee: {
consumeMarketFeeAddress: marketFeeAddress ,
consumeMarketFeeAmount: consumeMarketOrderFee ,
consumeMarketFeeToken:
asset ?. accessDetails ?. baseToken ?. address ||
'0x0000000000000000000000000000000000000000'
}
} as OrderParams
switch ( asset . accessDetails ?. type ) {
case 'fixed' : {
// Approve base token spending
const tx = await approve (
signer ,
config ,
accountId ,
asset . accessDetails . baseToken . address ,
config . fixedRateExchangeAddress ,
orderPriceAndFees . price ,
false
)
// Buy datatokens from fixed rate exchange
const fre = new FixedRateExchange (
config . fixedRateExchangeAddress ,
signer
)
const freTx = await fre . buyDatatokens (
asset . accessDetails ?. addressOrId ,
'1' ,
orderPriceAndFees . price ,
marketFeeAddress ,
consumeMarketFixedSwapFee
)
// Start the order
return await datatoken . startOrder (
asset . accessDetails . datatoken . address ,
orderParams . consumer ,
orderParams . serviceIndex ,
orderParams . _providerFee ,
orderParams . _consumeMarketFee
)
}
case 'free' : {
// Dispense free datatokens
const dispenser = new Dispenser ( config . dispenserAddress , signer )
await dispenser . dispense (
asset . accessDetails ?. datatoken . address ,
'1' ,
accountId
)
return await datatoken . startOrder (
asset . accessDetails . datatoken . address ,
orderParams . consumer ,
orderParams . serviceIndex ,
orderParams . _providerFee ,
orderParams . _consumeMarketFee
)
}
}
}
Initialize Provider
The provider is initialized to verify access permissions and calculate fees.
Approve Token Spending
For fixed-price assets, approve the base token contract to spend tokens on your behalf.
Purchase Datatokens
Buy datatokens from the fixed rate exchange or dispense free datatokens.
Start Order
Execute the order transaction to gain access to the asset.
Market Statistics
The marketplace displays real-time statistics about the ecosystem:
// Display total assets, sales, and market activity
< MarketStats >
< Total label = "Total Assets" value = { totalAssets } />
< Total label = "Total Sales" value = { totalSales } />
< Total label = "Total Volume" value = { totalVolume } />
</ MarketStats >
Always verify asset details and publisher information before making a purchase. Check the asset’s edit history and metadata for authenticity.
See Also
Asset Publishing Learn how to publish your own assets to the marketplace
Asset Discovery Explore advanced search and filtering capabilities
Wallet Integration Set up your wallet for marketplace transactions
Compute-to-Data Run algorithms on datasets without downloading data