diff --git a/packages/backend/src/entity/Deployer.ts b/packages/backend/src/entity/Deployer.ts index 854ab1dd..4328a122 100644 --- a/packages/backend/src/entity/Deployer.ts +++ b/packages/backend/src/entity/Deployer.ts @@ -15,6 +15,9 @@ export class Deployer { @Column('varchar') baseDomain!: string; + @Column('varchar', { nullable: true }) + minimumPayment!: string | null; + @ManyToMany(() => Project, (project) => project.deployers) projects!: Project[]; } diff --git a/packages/backend/src/schema.gql b/packages/backend/src/schema.gql index 593682ed..3f7a615d 100644 --- a/packages/backend/src/schema.gql +++ b/packages/backend/src/schema.gql @@ -139,6 +139,7 @@ type Deployer { deployerLrn: String! deployerId: String! deployerApiUrl: String! + minimumPayment: String createdAt: String! updatedAt: String! } diff --git a/packages/backend/src/service.ts b/packages/backend/src/service.ts index f55e854d..417e3cfb 100644 --- a/packages/backend/src/service.ts +++ b/packages/backend/src/service.ts @@ -1384,13 +1384,15 @@ export class Service { const deployerId = record.id; const deployerLrn = record.names[0]; const deployerApiUrl = record.attributes.apiUrl; + const minimumPayment = record.attributes.minimumPayment const baseDomain = deployerApiUrl.substring(deployerApiUrl.indexOf('.') + 1); const deployerData = { deployerLrn, deployerId, deployerApiUrl, - baseDomain + baseDomain, + minimumPayment }; // TODO: Update deployers table in a separate job diff --git a/packages/backend/src/types.ts b/packages/backend/src/types.ts index 3223067d..83c810ae 100644 --- a/packages/backend/src/types.ts +++ b/packages/backend/src/types.ts @@ -94,6 +94,7 @@ export interface DeployerRecord { expiryTime: string; attributes: { apiUrl: string; + minimumPayment: string | null; name: string; paymentAddress: string; publicKey: string; diff --git a/packages/frontend/src/components/projects/create/Configure.tsx b/packages/frontend/src/components/projects/create/Configure.tsx index b89e5dbf..d6d8dacb 100644 --- a/packages/frontend/src/components/projects/create/Configure.tsx +++ b/packages/frontend/src/components/projects/create/Configure.tsx @@ -152,41 +152,62 @@ const Configure = () => { } }; - // const verifyTx = async ( - // senderAddress: string, - // txHash: string, - // ): Promise => { - // const isValid = await client.verifyTx( - // txHash, - // `${amount.toString()}alnt`, - // senderAddress, - // ); - // return isValid; - // }; + const verifyTx = async ( + senderAddress: string, + txHash: string, + amount: string + ): Promise => { + const isValid = await client.verifyTx( + txHash, + `${amount.toString()}alnt`, + senderAddress, + ); + return isValid; + }; const handleFormSubmit = useCallback( async (createFormData: FieldValues) => { - // Send tx request to wallet -> amount = createFormData.maxPrice * createFormData.numProviders - // Get address of sender account(from wallet connect session) and txHash(result.signature) if (!selectedAccount) { return; } const senderAddress = selectedAccount; - const amount = createFormData.numProviders * createFormData.maxPrice; + let amount: string; + if(createFormData.option === 'LRN') { + const deployerLrn = createFormData.lrn; + const deployer = deployers.find(deployer => deployer.deployerLrn === deployerLrn); + if (!deployer?.minimumPayment) { + toast({ + id: 'no-payment-required', + title: 'No payment', + variant: 'info', + onDismiss: dismiss, + }); + + amount = '' + } else { + amount = deployer!.minimumPayment + } + } else { + amount = (createFormData.numProviders * createFormData.maxPrice).toString(); + } + const txHash = await cosmosSendTokensHandler( selectedAccount, - String(amount), + amount, ); - console.log(txHash); + if(!txHash) { + console.error('Tx not successful'); + return; + } - // const isTxHashValid = verifyTx(senderAddress, txHash); - // if (!isTxHashValid) { - // console.error("Invalid Tx hash", txHash) - // return - // } + const isTxHashValid = verifyTx(senderAddress, txHash, amount.toString()); + if (!isTxHashValid) { + console.error("Invalid Tx hash", txHash) + return + } const environmentVariables = createFormData.variables.map( (variable: any) => { @@ -352,7 +373,7 @@ const Configure = () => { key={deployer.deployerLrn} value={deployer.deployerLrn} > - {deployer.deployerLrn} + {deployer.deployerLrn} {deployer.minimumPayment} ))} diff --git a/packages/frontend/src/pages/auth/CreatePasskey.tsx b/packages/frontend/src/pages/auth/CreatePasskey.tsx deleted file mode 100644 index b976f973..00000000 --- a/packages/frontend/src/pages/auth/CreatePasskey.tsx +++ /dev/null @@ -1,83 +0,0 @@ -import { Button } from 'components/shared/Button'; -import { LoaderIcon } from 'components/shared/CustomIcon'; -import { KeyIcon } from 'components/shared/CustomIcon/KeyIcon'; -import { InlineNotification } from 'components/shared/InlineNotification'; -import { Input } from 'components/shared/Input'; -import { WavyBorder } from 'components/shared/WavyBorder'; -import { useState } from 'react'; -import { IconRight } from 'react-day-picker'; -import { useSnowball } from 'utils/use-snowball'; - -type Props = { - onDone: () => void; -}; - -export const CreatePasskey = ({}: Props) => { - const snowball = useSnowball(); - const [name, setName] = useState(''); - - const auth = snowball.auth.passkey; - const loading = !!auth.state.loading; - - async function createPasskey() { - await auth.register(name); - } - - return ( -
-
-
- -
-
-
- Create a passkey -
-
- Passkeys allow you to sign in securely without using passwords. -
-
-
- -
-
-
-
-
- Give it a name -
-
- { - setName(e.target.value); - }} - /> -
- - {auth.state.error ? ( - - ) : ( - - )} -
- -
-
- ); -}; diff --git a/packages/frontend/src/pages/components/modals.tsx b/packages/frontend/src/pages/components/modals.tsx index 91d5f29b..cf75a813 100644 --- a/packages/frontend/src/pages/components/modals.tsx +++ b/packages/frontend/src/pages/components/modals.tsx @@ -40,6 +40,7 @@ const deployment: Deployment = { deployerApiUrl: 'https://webapp-deployer-api.example.com', deployerId: 'bafyreicrtgmkir4evvvysxdqxddf2ftdq2wrzuodgvwnxr4rmubi4obdfu', deployerLrn: 'lrn://example/deployers/webapp-deployer-api.example.com', + minimumPayment: '1000units' }, status: DeploymentStatus.Ready, createdBy: { diff --git a/packages/frontend/src/stories/MockStoriesData.ts b/packages/frontend/src/stories/MockStoriesData.ts index 09959838..750b36b4 100644 --- a/packages/frontend/src/stories/MockStoriesData.ts +++ b/packages/frontend/src/stories/MockStoriesData.ts @@ -106,6 +106,7 @@ export const deployment0: Deployment = { deployerApiUrl: 'https://webapp-deployer-api.example.com', deployerId: 'bafyreicrtgmkir4evvvysxdqxddf2ftdq2wrzuodgvwnxr4rmubi4obdfu', deployerLrn: 'lrn://deployer.apps.snowballtools.com ', + minimumPayment: '1000units' }, applicationDeploymentRequestId: 'bafyreiaycvq6imoppnpwdve4smj6t6ql5svt5zl3x6rimu4qwyzgjorize', @@ -132,6 +133,7 @@ export const project: Project = { deployerApiUrl: 'https://webapp-deployer-api.example.com', deployerId: 'bafyreicrtgmkir4evvvysxdqxddf2ftdq2wrzuodgvwnxr4rmubi4obdfu', deployerLrn: 'lrn://deployer.apps.snowballtools.com ', + minimumPayment: '1000units' }, ], paymentAddress: '0x657868687686rb4787987br8497298r79284797487', diff --git a/packages/frontend/src/utils/use-snowball.ts b/packages/frontend/src/utils/use-snowball.ts deleted file mode 100644 index 179f4d8a..00000000 --- a/packages/frontend/src/utils/use-snowball.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { useEffect, useState } from 'react'; -import { Snowball, SnowballChain } from '@snowballtools/js-sdk'; -import { - // LitAppleAuth, - LitGoogleAuth, - LitPasskeyAuth, -} from '@snowballtools/auth-lit'; -import { VITE_LIT_RELAY_API_KEY } from './constants'; - -export const snowball = Snowball.withAuth({ - google: LitGoogleAuth.configure({ - litRelayApiKey: VITE_LIT_RELAY_API_KEY!, - }), - // apple: LitAppleAuth.configure({ - // litRelayApiKey: VITE_LIT_RELAY_API_KEY!, - // }), - passkey: LitPasskeyAuth.configure({ - litRelayApiKey: VITE_LIT_RELAY_API_KEY!, - }), -}).create({ - initialChain: SnowballChain.sepolia, -}); - -export function useSnowball() { - const [state, setState] = useState(100); - - useEffect(() => { - // Subscribe and directly return the unsubscribe function - return snowball.subscribe(() => setState(state + 1)); - }, [state]); - - return snowball; -} diff --git a/packages/gql-client/src/queries.ts b/packages/gql-client/src/queries.ts index 815fa073..467e0583 100644 --- a/packages/gql-client/src/queries.ts +++ b/packages/gql-client/src/queries.ts @@ -28,6 +28,7 @@ query ($projectId: String!) { deployerLrn deployerId deployerApiUrl + minimumPayment } paymentAddress txHash @@ -86,6 +87,7 @@ query ($organizationSlug: String!) { deployerLrn deployerId deployerApiUrl + minimumPayment } paymentAddress txHash @@ -152,6 +154,7 @@ query ($projectId: String!) { deployerLrn deployerId deployerApiUrl + minimumPayment } environment isCurrent @@ -215,6 +218,7 @@ query ($searchText: String!) { deployerLrn deployerId deployerApiUrl + minimumPayment } paymentAddress txHash @@ -320,6 +324,7 @@ query { deployerLrn deployerId deployerApiUrl + minimumPayment } } `; diff --git a/packages/gql-client/src/types.ts b/packages/gql-client/src/types.ts index 2e879913..b4685706 100644 --- a/packages/gql-client/src/types.ts +++ b/packages/gql-client/src/types.ts @@ -119,6 +119,7 @@ export type Deployer = { deployerLrn: string; deployerId: string; deployerApiUrl: string; + minimumPayment: string | null; } export type OrganizationMember = {