Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Development to Main #641

Merged
merged 3 commits into from
Dec 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion app.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,11 @@ module.exports = {
// Display alert banner for the developer preview deployment
showPreviewAlert: process.env.NEXT_PUBLIC_SHOW_PREVIEW_ALERT || 'false',

contractingProvider: {
enable: true,
endpoint: 'https://contracting.demo.delta-dao.com'
},

networkAlertConfig: {
// Refresh interval for network status - 30 sec
refreshInterval: 30000,
Expand All @@ -109,5 +114,8 @@ module.exports = {

faucet: {
baseUri: 'https://faucet.api.pontus-x.eu'
}
},

showOnboardingModuleByDefault:
process.env.NEXT_PUBLIC_SHOW_ONBOARDING_MODULE_BY_DEFAULT === 'true'
}
5 changes: 5 additions & 0 deletions src/@context/MarketMetadata/_types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ export interface AppConfig {
roughTxGasEstimate: number
}
showPreviewAlert: string
contractingProvider: {
enable: boolean
endpoint: string
}
networkAlertConfig: {
// Refresh interval for network status - 30 sec
refreshInterval: number
Expand All @@ -49,6 +53,7 @@ export interface AppConfig {
faucet: {
baseUri: string
}
showOnboardingModuleByDefault: boolean
}
export interface SiteContent {
siteTitle: string
Expand Down
6 changes: 2 additions & 4 deletions src/@context/UserPreferences.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ function UserPreferencesProvider({
const [chainIds, setChainIds] = useState(
localStorage?.chainIds || appConfig.chainIds
)
const { defaultPrivacyPolicySlug } = appConfig
const { defaultPrivacyPolicySlug, showOnboardingModuleByDefault } = appConfig

const [privacyPolicySlug, setPrivacyPolicySlug] = useState<string>(
localStorage?.privacyPolicySlug || defaultPrivacyPolicySlug
Expand All @@ -96,9 +96,7 @@ function UserPreferencesProvider({
)

const [showOnboardingModule, setShowOnboardingModule] = useState<boolean>(
localStorage?.showOnboardingModule === undefined
? false
: localStorage?.showOnboardingModule
localStorage?.showOnboardingModule ?? showOnboardingModuleByDefault
)

const [onboardingStep, setOnboardingStep] = useState<number>(
Expand Down
4 changes: 4 additions & 0 deletions src/components/@shared/Publisher/index.module.css
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
.publisher {
max-width: 100%;
margin: 0;
margin-right: 1rem;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}

@media (min-width: 32rem) {
Expand Down
4 changes: 1 addition & 3 deletions src/components/@shared/Publisher/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,7 @@ export default function Publisher({
// to avoid side effect (UI not updating on account's change)
if (showName && isMounted() && addresses[account]) {
const accountName = addresses[account]
accountName.length > 15
? setName(accountTruncate(accountName, 15))
: setName(accountName)
setName(accountName)
} else if (verifiedServiceProviderName && isMounted())
setName(verifiedServiceProviderName || accountTruncate(account))
}, [showName, account, isMounted, verifiedServiceProviderName])
Expand Down
15 changes: 12 additions & 3 deletions src/components/Asset/AssetActions/ButtonBuy/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { FormEvent, ReactElement } from 'react'
import Button from '../../../@shared/atoms/Button'
import styles from './index.module.css'
import Loader from '../../../@shared/atoms/Loader'
import { PAYMENT_MODES, PaymentMode } from '../Download/ContractingProvider'
import styles from './index.module.css'

export interface ButtonBuyProps {
action: 'download' | 'compute'
Expand Down Expand Up @@ -32,6 +33,7 @@ export interface ButtonBuyProps {
isAccountConnected?: boolean
hasProviderFee?: boolean
retry?: boolean
paymentMode?: PaymentMode
}

function getConsumeHelpText(
Expand Down Expand Up @@ -166,6 +168,7 @@ export default function ButtonBuy({
dtSymbol,
dtBalance,
assetType,
paymentMode,
assetTimeout,
isConsumable,
consumableFeedback,
Expand All @@ -191,13 +194,19 @@ export default function ButtonBuy({
? 'Retry'
: action === 'download'
? hasPreviousOrder && assetType === 'saas'
? 'Go to service'
? paymentMode === PAYMENT_MODES.PAYPERUSE
? `Buy access credit`
: 'Go to service'
: hasPreviousOrder
? 'Download'
: priceType === 'free'
? 'Get'
: assetType === 'saas'
? `Subscribe ${assetTimeout === 'Forever' ? '' : ` for ${assetTimeout}`}`
? paymentMode === PAYMENT_MODES.PAYPERUSE
? `Buy access credit`
: `Subscribe ${
assetTimeout === 'Forever' ? '' : ` for ${assetTimeout}`
}`
: `Buy ${assetTimeout === 'Forever' ? '' : ` for ${assetTimeout}`}`
: hasPreviousOrder &&
hasPreviousOrderSelectedComputeAsset &&
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
.container {
display: flex;
flex-direction: column;
margin-top: calc(var(--spacer) / 1.5);
margin-bottom: -1rem;
margin-left: calc(var(--spacer) / -1.5);
margin-right: calc(var(--spacer) / -1.5);
padding: calc(var(--spacer) / 1.5);
border-top: 1px solid var(--border-color);
}

.help {
composes: help from '../../ButtonBuy/index.module.css';
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import { ReactElement, useCallback, useEffect, useState } from 'react'
import styles from './index.module.css'
import Button from '../../../../@shared/atoms/Button'
import { useAccount, useSignMessage } from 'wagmi'
import { getContractingProviderNonce, getPayPerUseCount } from '../../utils'
import Alert from '../../../../@shared/atoms/Alert'
import { useMarketMetadata } from '../../../../../@context/MarketMetadata'
import { useAutomation } from '../../../../../@context/Automation/AutomationProvider'

export enum PAYMENT_MODES {
SUBSCRIPTION = 'subscription',
PAYPERUSE = 'payperuse'
}

export type PaymentMode = `${PAYMENT_MODES}`

export default function ContractingProvider(props: {
did: string
}): ReactElement {
const { did } = props
const { address } = useAccount()
const [isRequesting, setIsRequesting] = useState(false)
const [accessCreditsCount, setAccessCreditsCount] = useState<number>()
const {
signMessage,
data: signMessageData,
isSuccess,
isError
} = useSignMessage()
const {
appConfig: {
contractingProvider: { endpoint: contractingProviderEndpoint }
}
} = useMarketMetadata()

const { autoWallet, isAutomationEnabled } = useAutomation()

const [activeAddress, setActiveAddress] = useState<string>()
const [signature, setSignature] = useState<string>()

useEffect(() => {
if (isAutomationEnabled) setActiveAddress(autoWallet.address)
else setActiveAddress(address)
}, [address, autoWallet?.address, isAutomationEnabled])

const checkAccessCredits = async () => {
setIsRequesting(true)

const nonce = await getContractingProviderNonce(
contractingProviderEndpoint,
activeAddress
)
if (isAutomationEnabled) {
try {
const autoWalletSignature = await autoWallet.signMessage(nonce)
setSignature(autoWalletSignature)
} catch (e) {
setIsRequesting(false)
console.error(e)
}
} else {
signMessage({ message: nonce })
}
}

const updateCount = useCallback(async () => {
const count = await getPayPerUseCount(
contractingProviderEndpoint,
activeAddress,
signature,
did
)
setAccessCreditsCount(count)
setIsRequesting(false)
}, [contractingProviderEndpoint, activeAddress, signature, did])

useEffect(() => {
if (isError) setIsRequesting(false)
if (isSuccess) {
setSignature(signMessageData)
}
}, [isSuccess, isError])

useEffect(() => {
if (!signature) return
updateCount()
}, [signature])

return (
<div className={styles.container}>
{accessCreditsCount ? (
<Alert
state="info"
text={`You purchased access to this service **${accessCreditsCount} time${
accessCreditsCount > 1 ? 's' : ''
}**`}
action={{
name: 'Re-run',
handleAction: (e) => {
setAccessCreditsCount(undefined) // force visible re-render
e.preventDefault()
checkAccessCredits()
}
}}
/>
) : (
<Button
style="text"
onClick={(e) => {
e.preventDefault()
checkAccessCredits()
}}
disabled={isRequesting}
>
Check Access Credits
</Button>
)}
<div className={styles.help}>
You can validate your purchase count of this SaaS Offering against a
contracting provider instance.
</div>
</div>
)
}
64 changes: 56 additions & 8 deletions src/components/Asset/AssetActions/Download/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ import WhitelistIndicator from '../Compute/WhitelistIndicator'
import { Signer } from 'ethers'
import SuccessConfetti from '@components/@shared/SuccessConfetti'
import Input from '@components/@shared/FormInput'
import ContractingProvider, { PAYMENT_MODES } from './ContractingProvider'
import Button from '@components/@shared/atoms/Button'

export default function Download({
accountId,
Expand All @@ -61,7 +63,12 @@ export default function Download({
}): ReactElement {
const { isConnected } = useAccount()
const { isSupportedOceanNetwork } = useNetworkMetadata()
const { getOpcFeeForToken } = useMarketMetadata()
const {
getOpcFeeForToken,
appConfig: {
contractingProvider: { enable: isContractingFeatureEnabled }
}
} = useMarketMetadata()
const { isInPurgatory, isAssetNetwork } = useAsset()
const isMounted = useIsMounted()

Expand Down Expand Up @@ -171,16 +178,21 @@ export default function Download({
isAccountIdWhitelisted
])

function redirectToSaasUrl() {
window.open(asset.metadata.additionalInformation.saas.redirectUrl, '_blank')
}

async function handleOrderOrDownload(dataParams?: UserCustomParameters) {
setIsLoading(true)
setRetry(false)
try {
if (isOwned) {
if (
isOwned &&
asset?.metadata?.additionalInformation?.saas?.paymentMode !==
PAYMENT_MODES.PAYPERUSE
) {
if (asset?.metadata?.additionalInformation?.saas?.redirectUrl) {
window.open(
asset.metadata.additionalInformation.saas.redirectUrl,
'_blank'
)
redirectToSaasUrl()
setIsLoading(false)
return
}
Expand Down Expand Up @@ -236,12 +248,22 @@ export default function Download({
dtSymbol={asset?.datatokens[0]?.symbol}
dtBalance={dtBalance}
type="submit"
assetTimeout={secondsToString(asset?.services?.[0]?.timeout)}
assetTimeout={
asset?.metadata?.additionalInformation?.saas?.paymentMode ===
PAYMENT_MODES.PAYPERUSE
? // we dont have a timeout on payperuse
// as this is handled by service operators utilizing contracting provider
secondsToString(0)
: secondsToString(asset?.services?.[0]?.timeout)
}
assetType={
asset?.metadata?.additionalInformation?.saas
? 'saas'
: asset?.metadata?.type
}
paymentMode={
asset?.metadata?.additionalInformation?.saas?.paymentMode ?? undefined
}
stepText={statusText}
isLoading={isLoading}
priceType={asset.accessDetails?.type}
Expand Down Expand Up @@ -284,7 +306,28 @@ export default function Download({
size="large"
/>
)}
{!isInPurgatory && <PurchaseButton isValid={isValid} />}
{!isInPurgatory && (
<>
{asset?.metadata?.additionalInformation?.saas
?.paymentMode === PAYMENT_MODES.PAYPERUSE &&
asset?.metadata?.additionalInformation?.saas
?.redirectUrl && (
<div className={styles.payPerUseBtn}>
<Button
style="primary"
onClick={(e) => {
e.preventDefault()
redirectToSaasUrl()
}}
disabled={!isValid}
>
Go to service
</Button>
</div>
)}
<PurchaseButton isValid={isValid} />
</>
)}
<Field
component={Input}
name="termsAndConditions"
Expand Down Expand Up @@ -360,6 +403,11 @@ export default function Download({
asset={asset}
/>
)}
{isContractingFeatureEnabled &&
asset?.metadata?.additionalInformation?.saas?.paymentMode ===
PAYMENT_MODES.PAYPERUSE &&
accountId &&
isAccountIdWhitelisted && <ContractingProvider did={asset.id} />}
{accountId && (
<WhitelistIndicator
accountId={accountId}
Expand Down
Loading
Loading