From a15f39bf5ff09b58d78c3748c8d3ec0f874c27a5 Mon Sep 17 00:00:00 2001 From: Polybius93 Date: Thu, 7 Nov 2024 21:51:37 +0100 Subject: [PATCH] feat: add initial icy psbt hook --- package.json | 2 +- .../one-click-yield-container.tsx | 8 +- src/app/hooks/use-icy-psbt.ts | 156 ++++++++++++++++++ src/app/hooks/use-leather.ts | 1 + yarn.lock | 12 +- 5 files changed, 167 insertions(+), 12 deletions(-) create mode 100644 src/app/hooks/use-icy-psbt.ts diff --git a/package.json b/package.json index 5569f4fa..813c749b 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "concurrently": "^8.2.2", "d3": "^7.9.0", "decimal.js": "^10.4.3", - "dlc-btc-lib": "2.4.8", + "dlc-btc-lib": "file:../dlc-btc-lib", "dotenv": "^16.3.1", "ethers": "5.7.2", "formik": "^2.4.5", diff --git a/src/app/components/one-click-yield-container/one-click-yield-container.tsx b/src/app/components/one-click-yield-container/one-click-yield-container.tsx index 4e66fa11..27eb6107 100644 --- a/src/app/components/one-click-yield-container/one-click-yield-container.tsx +++ b/src/app/components/one-click-yield-container/one-click-yield-container.tsx @@ -3,6 +3,7 @@ import { useContext, useState } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { Button, HStack, Image, Text, UseToastOptions, VStack, useToast } from '@chakra-ui/react'; +import { useOneClickYieldPSBT } from '@hooks/use-icy-psbt.ts'; import { usePSBT } from '@hooks/use-psbt'; import { BitcoinWalletContext, @@ -54,15 +55,14 @@ export function OneClickYieldContainer(): React.JSX.Element { handleSignFundingTransaction, handleSignWithdrawTransaction, isLoading: isBitcoinWalletLoading, - } = usePSBT(); + } = useOneClickYieldPSBT(); const [isSubmitting, setIsSubmitting] = useState(false); async function handleDeposit(depositAmount: number) { try { setIsSubmitting(true); - const vaultUUID = '0x1234567890'; - await handleSignFundingTransaction(vaultUUID, depositAmount); + await handleSignFundingTransaction(depositAmount); setIsSubmitting(false); } catch (error: any) { setIsSubmitting(false); @@ -73,7 +73,7 @@ export function OneClickYieldContainer(): React.JSX.Element { async function handleWithdraw(withdrawAmount: number, vaultUUID: string): Promise { try { setIsSubmitting(true); - await handleSignWithdrawTransaction(vaultUUID, withdrawAmount); + await handleSignWithdrawTransaction(withdrawAmount); } catch (error: any) { setIsSubmitting(false); toast(createWithdrawErrorToast(error.message)); diff --git a/src/app/hooks/use-icy-psbt.ts b/src/app/hooks/use-icy-psbt.ts new file mode 100644 index 00000000..0115410f --- /dev/null +++ b/src/app/hooks/use-icy-psbt.ts @@ -0,0 +1,156 @@ +import { useContext, useState } from 'react'; + +import { BitcoinError } from '@models/error-types'; +import { BitcoinWalletContext } from '@providers/bitcoin-wallet-context-provider'; +import { EthereumNetworkConfigurationContext } from '@providers/ethereum-network-configuration.provider'; +import { SoftwareWalletDLCHandler } from 'dlc-btc-lib'; +import { submit1CYWithdrawDepositPSBT } from 'dlc-btc-lib/attestor-request-functions'; +import { getAttestorGroupPublicKey } from 'dlc-btc-lib/ethereum-functions'; +import { RawVault, Transaction } from 'dlc-btc-lib/models'; +import { BigNumber } from 'ethers'; + +import { useLeather } from './use-leather'; + +interface UseOneClickYieldPSBTReturnType { + handleSignFundingTransaction: (depositAmount: number) => Promise; + handleSignWithdrawTransaction: (withdrawAmount: number) => Promise; + bitcoinDepositAmount: number; + isLoading: [boolean, string]; +} + +export function useOneClickYieldPSBT(): UseOneClickYieldPSBTReturnType { + const { + ethereumNetworkConfiguration: { dlcManagerContract, ethereumAttestorChainID }, + } = useContext(EthereumNetworkConfigurationContext); + + const { bitcoinWalletType, dlcHandler, resetBitcoinWalletContext } = + useContext(BitcoinWalletContext); + + const { + handleFundingTransaction: handleFundingTransactionWithLeather, + handleWithdrawalTransaction: handleWithdrawalTransactionWithLeather, + handleDepositTransaction: handleDepositTransactionWithLeather, + isLoading: isLeatherLoading, + } = useLeather(); + + const [bitcoinDepositAmount, setBitcoinDepositAmount] = useState(0); + + const paddedHexString = '0x' + '259F05AC8216f0A522AAE4EdE5A9F54FDd9FC41b'.padStart(64, '0'); + + const mockVault: RawVault = { + uuid: paddedHexString, + protocolContract: '', + timestamp: BigNumber.from(0), + valueLocked: BigNumber.from(0), + valueMinted: BigNumber.from(0), + creator: '', + status: 0, + fundingTxId: '', + closingTxId: '', + wdTxId: '', + btcFeeRecipient: '031131cd88bcea8c1d84da8e034bb24c2f6e748c571922dc363e7e088f5df0436c', + btcMintFeeBasisPoints: BigNumber.from(12), + btcRedeemFeeBasisPoints: BigNumber.from(15), + taprootPubKey: '', + }; + + async function handleSignFundingTransaction(depositAmount: number): Promise { + try { + if (!dlcHandler) throw new Error('DLC Handler is not setup'); + + const feeRateMultiplier = import.meta.env.VITE_FEE_RATE_MULTIPLIER; + + const attestorGroupPublicKey = await getAttestorGroupPublicKey(dlcManagerContract); + + console.log('attestorGroupPublicKey', attestorGroupPublicKey); + + console.log('dlcHandler', dlcHandler); + let fundingTransaction: Transaction; + switch (bitcoinWalletType) { + case 'Leather': + switch (mockVault.valueLocked.toNumber()) { + case 0: + fundingTransaction = await handleFundingTransactionWithLeather( + dlcHandler as SoftwareWalletDLCHandler, + mockVault, + depositAmount, + attestorGroupPublicKey, + feeRateMultiplier + ); + break; + default: + fundingTransaction = await handleDepositTransactionWithLeather( + dlcHandler as SoftwareWalletDLCHandler, + mockVault, + depositAmount, + attestorGroupPublicKey, + feeRateMultiplier + ); + break; + } + break; + default: + throw new BitcoinError('Invalid Bitcoin Wallet Type'); + } + + await submit1CYWithdrawDepositPSBT([appConfiguration.coordinatorURL], { + vaultUUID: mockVault.uuid, + withdrawDepositPSBT: fundingTransaction.hex, + attestorChainID: ethereumAttestorChainID, + userBitcoinTaprootPublicKey: dlcHandler.getTaprootDerivedPublicKey(), + valueLocked: mockVault.valueLocked.toString(), + integrationAddress: '0x259F05AC8216f0A522AAE4EdE5A9F54FDd9FC41b', + }); + + setBitcoinDepositAmount(depositAmount); + resetBitcoinWalletContext(); + } catch (error) { + throw new BitcoinError(`Error signing Funding Transaction: ${error}`); + } + } + + async function handleSignWithdrawTransaction(withdrawAmount: number): Promise { + try { + if (!dlcHandler) throw new Error('DLC Handler is not setup'); + + const feeRateMultiplier = import.meta.env.VITE_FEE_RATE_MULTIPLIER; + + const attestorGroupPublicKey = await getAttestorGroupPublicKey(dlcManagerContract); + + let withdrawalTransactionHex: string; + switch (bitcoinWalletType) { + case 'Leather': + withdrawalTransactionHex = await handleWithdrawalTransactionWithLeather( + dlcHandler as SoftwareWalletDLCHandler, + withdrawAmount, + attestorGroupPublicKey, + mockVault, + feeRateMultiplier + ); + break; + default: + throw new BitcoinError('Invalid Bitcoin Wallet Type'); + } + + await submit1CYWithdrawDepositPSBT([appConfiguration.coordinatorURL], { + vaultUUID: mockVault.uuid, + withdrawDepositPSBT: withdrawalTransactionHex, + attestorChainID: ethereumAttestorChainID, + userBitcoinTaprootPublicKey: dlcHandler.getTaprootDerivedPublicKey(), + valueLocked: mockVault.valueLocked.toString(), + integrationAddress: '0x259F05AC8216f0A522AAE4EdE5A9F54FDd9FC41b', + }); + + resetBitcoinWalletContext(); + } catch (error) { + throw new BitcoinError(`Error signing Withdraw Transaction: ${error}`); + } + } + + return { + handleSignFundingTransaction, + handleSignWithdrawTransaction, + bitcoinDepositAmount, + isLoading: isLeatherLoading, + }; +} diff --git a/src/app/hooks/use-leather.ts b/src/app/hooks/use-leather.ts index 32add3c7..3742ceb8 100644 --- a/src/app/hooks/use-leather.ts +++ b/src/app/hooks/use-leather.ts @@ -163,6 +163,7 @@ export function useLeather(): UseLeatherReturnType { feeRateMultiplier: number ): Promise { try { + console.log('vault', vault); setIsLoading([true, 'Creating Funding Transaction']); // ==> Create Funding Transaction diff --git a/yarn.lock b/yarn.lock index f62573c4..9c2d02d5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5195,10 +5195,8 @@ dir-glob@^3.0.1: dependencies: path-type "^4.0.0" -dlc-btc-lib@2.4.8: - version "2.4.8" - resolved "https://registry.yarnpkg.com/dlc-btc-lib/-/dlc-btc-lib-2.4.8.tgz#dd59f49b5f3df6a788843b2501a60f7048fbc304" - integrity sha512-06SAymipYWEvb/23JUs+iU6hF7qmBs+ck6iI2kQoZT9dsqDre7w6JcmSGtzPFzwupycfV/z8S8XRJ1eR02lNgw== +"dlc-btc-lib@file:../dlc-btc-lib": + version "2.4.10" dependencies: "@gemwallet/api" "3.8.0" "@ledgerhq/hw-app-btc" "10.4.1" @@ -5286,9 +5284,9 @@ elliptic@6.5.4: minimalistic-crypto-utils "^1.0.1" elliptic@^6.4.0: - version "6.5.7" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.7.tgz#8ec4da2cb2939926a1b9a73619d768207e647c8b" - integrity sha512-ESVCtTwiA+XhY3wyh24QqRGBoP3rEdDUl3EDUUo9tft074fi19IrdpH7hLCMMP3CIj7jb3W96rn8lt/BqIlt5Q== + version "6.6.0" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.6.0.tgz#5919ec723286c1edf28685aa89261d4761afa210" + integrity sha512-dpwoQcLc/2WLQvJvLRHKZ+f9FgOdjnq11rurqwekGQygGPsYSK29OMMD2WalatiqQ+XGFDglTNixpPfI+lpaAA== dependencies: bn.js "^4.11.9" brorand "^1.1.0"