Integrate wallet IFrame for payments #42
@ -20,10 +20,9 @@ import { Button } from '../../shared/Button';
|
|||||||
import { Input } from 'components/shared/Input';
|
import { Input } from 'components/shared/Input';
|
||||||
import { useToast } from 'components/shared/Toast';
|
import { useToast } from 'components/shared/Toast';
|
||||||
import { useGQLClient } from '../../../context/GQLClientContext';
|
import { useGQLClient } from '../../../context/GQLClientContext';
|
||||||
|
import IFrame from './IFrame';
|
||||||
import EnvironmentVariablesForm from 'pages/org-slug/projects/id/settings/EnvironmentVariablesForm';
|
import EnvironmentVariablesForm from 'pages/org-slug/projects/id/settings/EnvironmentVariablesForm';
|
||||||
import { EnvironmentVariablesFormValues } from 'types/types';
|
import { EnvironmentVariablesFormValues } from 'types/types';
|
||||||
import IFrame from './IFrame';
|
|
||||||
import { useWalletConnectClient } from 'context/WalletConnectContext';
|
|
||||||
import { VITE_LACONICD_CHAIN_ID } from 'utils/constants';
|
import { VITE_LACONICD_CHAIN_ID } from 'utils/constants';
|
||||||
|
|
||||||
type ConfigureDeploymentFormValues = {
|
type ConfigureDeploymentFormValues = {
|
||||||
@ -39,8 +38,6 @@ type ConfigureFormValues = ConfigureDeploymentFormValues &
|
|||||||
const DEFAULT_MAX_PRICE = '10000';
|
const DEFAULT_MAX_PRICE = '10000';
|
||||||
|
|
||||||
const Configure = () => {
|
const Configure = () => {
|
||||||
const { signClient, session } = useWalletConnectClient();
|
|
||||||
|
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
const [deployers, setDeployers] = useState<Deployer[]>([]);
|
const [deployers, setDeployers] = useState<Deployer[]>([]);
|
||||||
const [selectedAccount, setSelectedAccount] = useState<string>();
|
const [selectedAccount, setSelectedAccount] = useState<string>();
|
||||||
@ -49,8 +46,6 @@ const Configure = () => {
|
|||||||
const [isPaymentLoading, setIsPaymentLoading] = useState(false);
|
const [isPaymentLoading, setIsPaymentLoading] = useState(false);
|
||||||
const [isPaymentDone, setIsPaymentDone] = useState(false);
|
const [isPaymentDone, setIsPaymentDone] = useState(false);
|
||||||
const [isFrameVisible, setIsFrameVisible] = useState(false);
|
const [isFrameVisible, setIsFrameVisible] = useState(false);
|
||||||
const [txHashr, setTxHash] = useState<string | null>(null);
|
|
||||||
const [isTransactionPending, setIsTransactionPending] = useState<boolean>(false);
|
|
||||||
|
|
||||||
const [searchParams] = useSearchParams();
|
const [searchParams] = useSearchParams();
|
||||||
const templateId = searchParams.get('templateId');
|
const templateId = searchParams.get('templateId');
|
||||||
@ -188,7 +183,7 @@ const Configure = () => {
|
|||||||
|
|
||||||
let amount: string;
|
let amount: string;
|
||||||
let senderAddress: string;
|
let senderAddress: string;
|
||||||
let txHash: string;
|
let txHash;
|
||||||
if (createFormData.option === 'LRN' && !deployer?.minimumPayment) {
|
if (createFormData.option === 'LRN' && !deployer?.minimumPayment) {
|
||||||
toast({
|
toast({
|
||||||
id: 'no-payment-required',
|
id: 'no-payment-required',
|
||||||
@ -202,7 +197,7 @@ const Configure = () => {
|
|||||||
} else {
|
} else {
|
||||||
if (!selectedAccount) return;
|
if (!selectedAccount) return;
|
||||||
|
|
||||||
senderAddress = selectedAccount.split(':')[2];
|
senderAddress = selectedAccount;
|
||||||
|
|
||||||
if (createFormData.option === 'LRN') {
|
if (createFormData.option === 'LRN') {
|
||||||
amount = deployer?.minimumPayment!;
|
amount = deployer?.minimumPayment!;
|
||||||
@ -214,30 +209,10 @@ const Configure = () => {
|
|||||||
|
|
||||||
const amountToBePaid = amount.replace(/\D/g, '').toString();
|
const amountToBePaid = amount.replace(/\D/g, '').toString();
|
||||||
|
|
||||||
await cosmosSendTokensHandler(
|
txHash = await cosmosSendTokensHandler(
|
||||||
selectedAccount,
|
senderAddress,
|
||||||
amountToBePaid,
|
amountToBePaid,
|
||||||
);
|
);
|
||||||
|
|
||||||
await new Promise((resolve) => setTimeout(resolve, 3000));
|
|
||||||
|
|
||||||
if (!txHashr) {
|
|
||||||
console.error('Tx not successful');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
txHash = txHashr;
|
|
||||||
|
|
||||||
const isTxHashValid = await verifyTx(
|
|
||||||
senderAddress,
|
|
||||||
txHash,
|
|
||||||
amountToBePaid.toString(),
|
|
||||||
);
|
|
||||||
|
|
||||||
if (isTxHashValid === false) {
|
|
||||||
console.error('Invalid Tx hash', txHash);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const environmentVariables = createFormData.variables.map(
|
const environmentVariables = createFormData.variables.map(
|
||||||
@ -256,7 +231,7 @@ const Configure = () => {
|
|||||||
createFormData,
|
createFormData,
|
||||||
environmentVariables,
|
environmentVariables,
|
||||||
senderAddress,
|
senderAddress,
|
||||||
txHash,
|
txHash!,
|
||||||
);
|
);
|
||||||
|
|
||||||
await client.getEnvironmentVariables(projectId);
|
await client.getEnvironmentVariables(projectId);
|
||||||
@ -264,19 +239,19 @@ const Configure = () => {
|
|||||||
if (templateId) {
|
if (templateId) {
|
||||||
createFormData.option === 'Auction'
|
createFormData.option === 'Auction'
|
||||||
? navigate(
|
? navigate(
|
||||||
`/${orgSlug}/projects/create/success/${projectId}?isAuction=true`,
|
`/${orgSlug}/projects/create/success/${projectId}?isAuction=true`,
|
||||||
)
|
)
|
||||||
: navigate(
|
: navigate(
|
||||||
`/${orgSlug}/projects/create/template/deploy?projectId=${projectId}&templateId=${templateId}`,
|
`/${orgSlug}/projects/create/template/deploy?projectId=${projectId}&templateId=${templateId}`,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
createFormData.option === 'Auction'
|
createFormData.option === 'Auction'
|
||||||
? navigate(
|
? navigate(
|
||||||
`/${orgSlug}/projects/create/success/${projectId}?isAuction=true`,
|
`/${orgSlug}/projects/create/success/${projectId}?isAuction=true`,
|
||||||
)
|
)
|
||||||
: navigate(
|
: navigate(
|
||||||
`/${orgSlug}/projects/create/deploy?projectId=${projectId}`,
|
`/${orgSlug}/projects/create/deploy?projectId=${projectId}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
@ -332,27 +307,72 @@ const Configure = () => {
|
|||||||
onDismiss: dismiss,
|
onDismiss: dismiss,
|
||||||
});
|
});
|
||||||
|
|
||||||
await requestTx(senderAddress, snowballAddress, amount)
|
await requestTx(senderAddress, snowballAddress, amount);
|
||||||
|
|
||||||
await new Promise((resolve) => setTimeout(resolve, 10000));
|
const txHash = await new Promise<string>((resolve, reject) => {
|
||||||
return;
|
const handleTxStatus = async (event: MessageEvent) => {
|
||||||
} catch (error: any) {
|
if (event.origin !== 'http://localhost:3001') return;
|
||||||
console.error('Error sending tokens', error);
|
|
||||||
|
|
||||||
toast({
|
if (event.data.type === 'TRANSACTION_SUCCESS') {
|
||||||
id: 'error-sending-tokens',
|
const txResponse = event.data.data;
|
||||||
title: 'Error sending tokens',
|
|
||||||
variant: 'error',
|
setIsFrameVisible(false);
|
||||||
onDismiss: dismiss,
|
|
||||||
|
// Validate transaction hash
|
||||||
|
const isTxHashValid = await verifyTx(
|
||||||
|
senderAddress,
|
||||||
|
txResponse,
|
||||||
|
amount,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (isTxHashValid) {
|
||||||
|
resolve(txResponse);
|
||||||
|
toast({
|
||||||
|
id: 'payment-successful',
|
||||||
|
title: 'Payment successful',
|
||||||
|
variant: 'success',
|
||||||
|
onDismiss: dismiss,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
reject(new Error('Invalid transaction hash'));
|
||||||
|
toast({
|
||||||
|
id: 'invalid-tx-hash',
|
||||||
|
title: 'Transaction validation failed',
|
||||||
|
variant: 'error',
|
||||||
|
onDismiss: dismiss,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else if (event.data.type === 'ERROR') {
|
||||||
|
console.error('Error from wallet:', event.data.message);
|
||||||
|
reject(new Error('Transaction failed'));
|
||||||
|
toast({
|
||||||
|
id: 'error-transaction',
|
||||||
|
title: 'Error during transaction',
|
||||||
|
variant: 'error',
|
||||||
|
onDismiss: dismiss,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
window.removeEventListener('message', handleTxStatus);
|
||||||
|
};
|
||||||
|
|
||||||
|
window.addEventListener('message', handleTxStatus);
|
||||||
|
|
||||||
|
// Set a timeout, consider unsuccessful after 1 min
|
||||||
|
setTimeout(() => {
|
||||||
|
reject(new Error('Transaction timeout'));
|
||||||
|
window.removeEventListener('message', handleTxStatus);
|
||||||
|
}, 60000);
|
||||||
});
|
});
|
||||||
|
return txHash;
|
||||||
setIsPaymentDone(false);
|
} catch (error) {
|
||||||
// should return the txhash but we arw checking for it in the gettxstatus useeffect.. how do i return it after it is found?
|
console.error('Error in transaction:', error);
|
||||||
|
return;
|
||||||
} finally {
|
} finally {
|
||||||
setIsPaymentLoading(false);
|
setIsPaymentLoading(false);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[session, signClient, toast],
|
[client, dismiss, toast],
|
||||||
);
|
);
|
||||||
|
|
||||||
const requestTx = async (sender: string, recipient: string, amount: string,) => {
|
const requestTx = async (sender: string, recipient: string, amount: string,) => {
|
||||||
@ -375,42 +395,6 @@ const Configure = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
// Define the event listener to listen for transaction status
|
|
||||||
const getTxStatus = (event: MessageEvent) => {
|
|
||||||
// Ensure you're handling the message only from the correct origin
|
|
||||||
if (event.origin !== 'http://localhost:3001') return;
|
|
||||||
|
|
||||||
if (event.data.type === 'TRANSACTION_SUCCESS') {
|
|
||||||
console.log('Transaction Success:', event.data.transactionHash);
|
|
||||||
setTxHash(event.data.transactionHash);
|
|
||||||
console.log(event.data.transactionHash)
|
|
||||||
setIsTransactionPending(false);
|
|
||||||
|
|
||||||
console.log({txHashr})
|
|
||||||
toast({
|
|
||||||
id: 'payment-successful',
|
|
||||||
title: 'Payment successful',
|
|
||||||
variant: 'success',
|
|
||||||
onDismiss: dismiss,
|
|
||||||
});
|
|
||||||
|
|
||||||
setIsPaymentDone(true);
|
|
||||||
} else if (event.data.type === 'ERROR') {
|
|
||||||
console.error('Error from wallet:', event.data.message);
|
|
||||||
setIsTransactionPending(false); // Mark the transaction as failed
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Add the event listener to listen for 'message' events
|
|
||||||
window.addEventListener('message', getTxStatus);
|
|
||||||
|
|
||||||
// Cleanup: Remove the event listener when the component unmounts
|
|
||||||
return () => {
|
|
||||||
window.removeEventListener('message', getTxStatus);
|
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchDeployers();
|
fetchDeployers();
|
||||||
}, []);
|
}, []);
|
||||||
|
Loading…
Reference in New Issue
Block a user