Skip to content

Commit

Permalink
feat: deposit flow
Browse files Browse the repository at this point in the history
  • Loading branch information
scolear committed Nov 8, 2024
1 parent 1619577 commit 6242fcf
Show file tree
Hide file tree
Showing 8 changed files with 92 additions and 39 deletions.
2 changes: 1 addition & 1 deletion config.devnet.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"appEnvironment": "devnet",
"coordinatorURL": "https://devnet.dlc.link/attestor-1",
"coordinatorURL": "http://localhost:8811",
"enabledEthereumNetworkIDs": ["421614", "84532", "11155111"],
"enabledRippleNetworkIDs": ["1"],
"bitcoinNetwork": "regtest",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import React, { useState } from 'react';
import { useSelector } from 'react-redux';

import { HStack, Text, VStack } from '@chakra-ui/react';
import { Vault } from '@models/vault';
import { BitcoinWalletContextState } from '@providers/bitcoin-wallet-context-provider';
import { RootState } from '@store/index';
import { useForm } from '@tanstack/react-form';

import { TransactionScreenWalletInformation } from '../../../transaction-screen/transaction-screen.transaction-form/components/transaction-screen.transaction-form/components/transaction-screen.transaction-form.wallet-information';
Expand Down Expand Up @@ -70,7 +72,7 @@ interface BitcoinWalletInformation {
}

interface ButtonGroupFunctions {
handleSubmitButtonClick: (assetValue: number) => Promise<void>;
handleSubmitButtonClick: (assetValue: number, vaultUUID?: string) => Promise<void>;
handleCancelButtonClick: () => void;
isSubmitting: boolean;
}
Expand Down Expand Up @@ -108,6 +110,8 @@ export function OneClickYieldTransactionForm({

const [currentFieldValue, setCurrentFieldValue] = useState<number>(minimumDeposit);

const { burnTransactionState } = useSelector((state: RootState) => state.oneClickYield);

// const confirmations = useContext(
// BitcoinTransactionConfirmationsContext
// ).bitcoinTransactionConfirmations.find(v => v[0] === vault.uuid)?.[1];
Expand All @@ -117,17 +121,22 @@ export function OneClickYieldTransactionForm({
bitcoinAmount: minimumDeposit,
},
onSubmit: async ({ value }) => {
await handleSubmitButtonClick(value.bitcoinAmount);
await handleSubmitButtonClick(value.bitcoinAmount, burnTransactionState.vault?.uuid);
},
validators: {
onChange: ({ value }) => {
setCurrentFieldValue(value.bitcoinAmount);
return {
fields: {
bitcoinAmount: validateFormAmount(value.bitcoinAmount, transactionType, {
minimumDeposit,
maximumDeposit,
}),
bitcoinAmount: validateFormAmount(
value.bitcoinAmount,
transactionType,
{
minimumDeposit,
maximumDeposit,
},
burnTransactionState.vault
),
},
};
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,10 @@ export function OneClickYieldContainer(): React.JSX.Element {
}
}

async function handleWithdraw(withdrawAmount: number): Promise<void> {
async function handleWithdraw(withdrawAmount: number, vaultUUID: string): Promise<void> {
try {
setIsSubmitting(true);
await handleSignWithdrawTransaction(withdrawAmount);
await handleSignWithdrawTransaction(withdrawAmount, vaultUUID);
} catch (error: any) {
setIsSubmitting(false);
toast(createWithdrawErrorToast(error.message));
Expand Down Expand Up @@ -100,14 +100,14 @@ export function OneClickYieldContainer(): React.JSX.Element {
}
}

async function handleButtonClick(assetAmount: number) {
async function handleButtonClick(assetAmount: number, vaultUUID?: string) {
if (bitcoinWalletContextState !== BitcoinWalletContextState.READY) return handleConnect();

switch (activeTransaction) {
case 'mint':
return handleDeposit(assetAmount);
case 'burn':
return handleWithdraw(assetAmount);
return handleWithdraw(assetAmount, vaultUUID!);
default:
throw new Error('Invalid Transaction Type');
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,20 @@ export function OneClickYieldVaultBox({
const { bitcoinPrice } = useContext(ProofOfReserveContext);
const [isVaultExpanded, setIsVaultExpanded] = useState(false);

const handleDepositClick = (vaultUUID: string, vaultType: string) => {
const handleDepositClick = (vault: Vault, vaultType: string) => {
const transactionState: TransactionState = {
transactionStep: 1,
vaultType: vaultType,
vaultUUID: vaultUUID,
vault: vault,
};
dispatch(oneClickYieldActions.setActiveTransaction('mint'));
dispatch(oneClickYieldActions.setMintTransactionStep(transactionState));
};
const handleWithdrawClick = (vaultUUID: string, vaultType: string) => {
const handleWithdrawClick = (vault: Vault, vaultType: string) => {
const transactionState: TransactionState = {
transactionStep: 1,
vaultType: vaultType,
vaultUUID: vaultUUID,
vault: vault,
};
dispatch(oneClickYieldActions.setActiveTransaction('burn'));
dispatch(oneClickYieldActions.setBurnTransactionStep(transactionState));
Expand Down Expand Up @@ -125,8 +125,8 @@ export function OneClickYieldVaultBox({
vaultState={oneClickYieldVault.state}
vaultTotalLockedValue={oneClickYieldVault.valueLocked}
vaultTotalMintedValue={oneClickYieldVault.valueMinted}
handleDepositClick={() => handleDepositClick('vaultUUID', 'vaultType')}
handleWithdrawClick={() => handleWithdrawClick('vaultUUID', 'vaultType')}
handleDepositClick={() => handleDepositClick(oneClickYieldVault, 'vaultType')}
handleWithdrawClick={() => handleWithdrawClick(oneClickYieldVault, 'vaultType')}
handleResumeClick={() => handleResumeClick()}
/>
</VStack>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import React, { useContext, useState } from 'react';
import { useSelector } from 'react-redux';

import { VStack } from '@chakra-ui/react';
import { RiskBox } from '@components/mint-unmint/components/risk-box/risk-box';
import { TransactionFormAPI } from '@models/form.models';
import { Vault } from '@models/vault';
import { BitcoinTransactionConfirmationsContext } from '@providers/bitcoin-query-provider';
import { BitcoinWalletContextState } from '@providers/bitcoin-wallet-context-provider';
import { RootState } from '@store/index';
import { useForm } from '@tanstack/react-form';
import Decimal from 'decimal.js';

Expand Down
37 changes: 35 additions & 2 deletions src/app/functions/icy.functions.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { VaultDetails } from '@models/one-click-yield.models';
import { RawVault } from 'dlc-btc-lib/models';
import { unshiftValue } from 'dlc-btc-lib/utilities';
import { ethers } from 'ethers';

const integrationSampleABI = [
Expand Down Expand Up @@ -631,6 +632,24 @@ export interface IntegrationInfo {
rewardTokenAddress: string;
}

export const fetchICYVault = async (vaultUUID: string): Promise<RawVault> => {
try {
const provider = new ethers.providers.StaticJsonRpcProvider('http://127.0.0.1:8545', undefined);

const dlcManagerContract = new ethers.Contract(
'0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9',
dlcManagerABI,
provider
);

return await dlcManagerContract.getVault(vaultUUID);
} catch (error) {
throw new Error(
`Error fetching Attestor Group Public Key from Ethereum Network [hardhat]: ${error}`
);
}
};

export const fetchAllICYVaultsForUser = async (taprootPubKey: string): Promise<VaultDetails[]> => {
try {
const provider = new ethers.providers.StaticJsonRpcProvider('http://127.0.0.1:8545', undefined);
Expand All @@ -648,10 +667,24 @@ export const fetchAllICYVaultsForUser = async (taprootPubKey: string): Promise<V
);

const allVaultUUIDs = await poolMerchantContract.getVaultsByTaprootPubKey(taprootPubKey);
// const allIntegrations = await poolMerchantContract.getAllActiveIntegrations();
// const integrationVaults = await poolMerchantContract.getIntegrationVaults(allIntegrations[0]);

// const vaultUUID = integrationVaults[0];
// const vaultDetails = await poolMerchantContract.getVaultDetails(vaultUUID);
// console.log('Vault Details:', vaultDetails);
// const dlcVault: RawVault = await dlcManagerContract.getVault(vaultUUID);
// console.log('DLC Vault:', dlcVault);

// console.log('integrationVaults:', integrationVaults);
// console.log('active integrations:', allIntegrations);
// console.log('All Vault UUIDs:', allVaultUUIDs);

const vaultDetailsPromises = allVaultUUIDs.map(async (vaultUUID: string) => {
const details = await poolMerchantContract.getVaultDetails(vaultUUID);
const dlcVault: RawVault = await dlcManagerContract.getVault(vaultUUID);
console.log('Vault Details:', details);
console.log('DLC Vault:', dlcVault);
return {
uuid: vaultUUID,
integration: details.integration.toString(),
Expand All @@ -667,8 +700,8 @@ export const fetchAllICYVaultsForUser = async (taprootPubKey: string): Promise<V
uuid: dlcVault.uuid,
protocolContract: dlcVault.protocolContract,
timestamp: Number(dlcVault.timestamp),
valueLocked: Number(dlcVault.valueLocked),
valueMinted: Number(dlcVault.valueMinted),
valueLocked: unshiftValue(dlcVault.valueLocked.toNumber()),
valueMinted: unshiftValue(dlcVault.valueMinted.toNumber()),
creator: dlcVault.creator,
status: Number(dlcVault.status),
fundingTxId: dlcVault.fundingTxId,
Expand Down
35 changes: 20 additions & 15 deletions src/app/hooks/use-icy-psbt.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useContext, useState } from 'react';

import { fetchICYVault } from '@functions/icy.functions';
import { BitcoinError } from '@models/error-types';
import { BitcoinWalletContext } from '@providers/bitcoin-wallet-context-provider';
import { EthereumNetworkConfigurationContext } from '@providers/ethereum-network-configuration.provider';
Expand All @@ -14,16 +15,12 @@ import { useLeather } from './use-leather';

interface UseOneClickYieldPSBTReturnType {
handleSignFundingTransaction: (depositAmount: number) => Promise<void>;
handleSignWithdrawTransaction: (withdrawAmount: number) => Promise<void>;
handleSignWithdrawTransaction: (withdrawAmount: number, vaultUUID: string) => Promise<void>;
bitcoinDepositAmount: number;
isLoading: [boolean, string];
}

export function useOneClickYieldPSBT(): UseOneClickYieldPSBTReturnType {
const {
ethereumNetworkConfiguration: { dlcManagerContract, ethereumAttestorChainID },
} = useContext(EthereumNetworkConfigurationContext);

const { bitcoinWalletType, dlcHandler, resetBitcoinWalletContext } =
useContext(BitcoinWalletContext);

Expand All @@ -36,7 +33,7 @@ export function useOneClickYieldPSBT(): UseOneClickYieldPSBTReturnType {

const [bitcoinDepositAmount, setBitcoinDepositAmount] = useState(0);

const paddedHexString = '0x' + '259F05AC8216f0A522AAE4EdE5A9F54FDd9FC41b'.padStart(64, '0');
const paddedHexString = '0x' + '610178dA211FEF7D417bC0e6FeD39F05609AD788'.padStart(64, '0');

const mockVault: RawVault = {
uuid: paddedHexString,
Expand All @@ -61,7 +58,9 @@ export function useOneClickYieldPSBT(): UseOneClickYieldPSBTReturnType {

const feeRateMultiplier = import.meta.env.VITE_FEE_RATE_MULTIPLIER;

const attestorGroupPublicKey = await getAttestorGroupPublicKey(dlcManagerContract);
// const attestorGroupPublicKey = await getAttestorGroupPublicKey(dlcManagerContract);
const attestorGroupPublicKey =
'tpubDC3tidhtKQei2UkDcSc5k3vZ9myJAh8d2BKEQkYMqH2adg71ePjK9T38wxFu1YgrZ52jpPhrJSgxWHUAyedV5ZEpavhmWDFk9zSGsQzwbDZ';

console.log('attestorGroupPublicKey', attestorGroupPublicKey);

Expand Down Expand Up @@ -97,26 +96,32 @@ export function useOneClickYieldPSBT(): UseOneClickYieldPSBTReturnType {
await submit1CYWithdrawDepositPSBT([appConfiguration.coordinatorURL], {
vaultUUID: '',
withdrawDepositPSBT: bytesToHex(fundingTransaction.toPSBT()).slice(2),
attestorChainID: ethereumAttestorChainID,
attestorChainID: 'evm-hardhat-arb',
userBitcoinTaprootPublicKey: dlcHandler.getTaprootDerivedPublicKey(),
valueLocked: mockVault.valueLocked.toString(),
integrationAddress: paddedHexString,
integrationAddress: paddedHexString.slice(2),
});

setBitcoinDepositAmount(depositAmount);
resetBitcoinWalletContext();
// resetBitcoinWalletContext();
} catch (error) {
throw new BitcoinError(`Error signing Funding Transaction: ${error}`);
}
}

async function handleSignWithdrawTransaction(withdrawAmount: number): Promise<void> {
async function handleSignWithdrawTransaction(
withdrawAmount: number,
vaultUUID: string
): Promise<void> {
try {
const rawVault = await fetchICYVault(vaultUUID);
if (!dlcHandler) throw new Error('DLC Handler is not setup');

const feeRateMultiplier = import.meta.env.VITE_FEE_RATE_MULTIPLIER;

const attestorGroupPublicKey = await getAttestorGroupPublicKey(dlcManagerContract);
// const attestorGroupPublicKey = await getAttestorGroupPublicKey(dlcManagerContract);
const attestorGroupPublicKey =
'tpubDC3tidhtKQei2UkDcSc5k3vZ9myJAh8d2BKEQkYMqH2adg71ePjK9T38wxFu1YgrZ52jpPhrJSgxWHUAyedV5ZEpavhmWDFk9zSGsQzwbDZ';

let withdrawalTransactionHex: string;
switch (bitcoinWalletType) {
Expand All @@ -125,7 +130,7 @@ export function useOneClickYieldPSBT(): UseOneClickYieldPSBTReturnType {
dlcHandler as SoftwareWalletDLCHandler,
withdrawAmount,
attestorGroupPublicKey,
mockVault,
rawVault,
feeRateMultiplier
);
break;
Expand All @@ -136,13 +141,13 @@ export function useOneClickYieldPSBT(): UseOneClickYieldPSBTReturnType {
await submit1CYWithdrawDepositPSBT([appConfiguration.coordinatorURL], {
vaultUUID: mockVault.uuid,
withdrawDepositPSBT: withdrawalTransactionHex,
attestorChainID: ethereumAttestorChainID,
attestorChainID: 'evm-hardhat-arb',
userBitcoinTaprootPublicKey: dlcHandler.getTaprootDerivedPublicKey(),
valueLocked: mockVault.valueLocked.toString(),
integrationAddress: paddedHexString,
});

resetBitcoinWalletContext();
// resetBitcoinWalletContext();
} catch (error) {
throw new BitcoinError(`Error signing Withdraw Transaction: ${error}`);
}
Expand Down
14 changes: 9 additions & 5 deletions src/app/hooks/use-icy-vaults.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useContext, useMemo, useState } from 'react';
import { useDispatch } from 'react-redux';

import { fetchAllICYVaultsForUser } from '@functions/icy.functions';
import { VaultDetails } from '@models/one-click-yield.models';
import { Vault } from '@models/vault';
import {
Expand Down Expand Up @@ -61,24 +62,27 @@ export function useICYVaults(): useEVMVaultsReturnType {

const [isLoading, setIsLoading] = useState(true);

const { bitcoinWalletContextState } = useContext(BitcoinWalletContext);
const { bitcoinWalletContextState, dlcHandler } = useContext(BitcoinWalletContext);

const { data: icyVaults } = useQuery({
queryKey: ['icy-vaults'],
initialData: [],
queryFn: fetchICYVaults,
queryFn: fetchIcyVaults,
refetchInterval: 10000,
enabled: bitcoinWalletContextState === BitcoinWalletContextState.READY,
});

async function fetchICYVaults(): Promise<VaultDetails[]> {
async function fetchIcyVaults(): Promise<VaultDetails[]> {
setIsLoading(true);

const previousVaults: VaultDetails[] | undefined = queryClient.getQueryData(['icy-vaults']);

const taprootPubKey = dlcHandler?.getTaprootDerivedPublicKey();
const slicedTaprootPubKey = taprootPubKey?.slice(2)!;
try {
const icyVaults: VaultDetails[] = await fetchICYVaults();
console.log('taproot derived public key', slicedTaprootPubKey);
const icyVaults: VaultDetails[] = await fetchAllICYVaultsForUser(slicedTaprootPubKey);

console.log('ICY Vaults', icyVaults);
if (
previousVaults?.length === 0 &&
icyVaults.length === 1 &&
Expand Down

0 comments on commit 6242fcf

Please sign in to comment.