import { ref, onMounted, reactive, computed } from 'vue'; import { type ComputedRef } from 'vue'; import { config } from '@/wagmi'; import { decodeEventLog, type Hex, type DecodeEventLogReturnType, type TypedDataDefinition } from 'viem'; import { getAccount, signTypedData, waitForTransactionReceipt, type Config } from '@wagmi/core'; import { HarbContract } from '@/contracts/harb'; import { StakeContract, permitAndSnatch, minStake } from '@/contracts/stake'; import { getNonce, nonce, getName } from '@/contracts/harb'; import { useWallet } from '@/composables/useWallet'; import { createPermitObject, getSignatureRSV } from '@/utils/blockchain'; import { formatBigIntDivision, compactNumber } from '@/utils/helper'; import { taxRates } from '@/composables/useAdjustTaxRates'; import { useContractToast } from './useContractToast'; const wallet = useWallet(); const contractToast = useContractToast(); const wagmiConfig: Config = config; enum StakeState { NoBalance = 'NoBalance', StakeAble = 'StakeAble', SignTransaction = 'SignTransaction', Waiting = 'Waiting', NotEnoughApproval = 'NotEnoughApproval', } interface PositionCreatedArgs { creationTime: number; owner: Hex; harbergDeposit: bigint; positionId: bigint; share: bigint; taxRate: number; } // const state = ref(StakeState.NoBalance); export function useStake() { const stakingAmountRaw = ref(); const stakingAmountShares = ref(); const loading = ref(false); const waiting = ref(false); onMounted(async () => {}); const state: ComputedRef = computed(() => { const balance = wallet.balance.value; // console.log("balance123", balance); // console.log("wallet", wallet); if (loading.value) { return StakeState.SignTransaction; } else if (minStake.value > balance || stakingAmount.value > balance) { return StakeState.NoBalance; } else if (waiting.value) { return StakeState.Waiting; } else { return StakeState.StakeAble; } }); const stakingAmount = computed({ // getter get() { return stakingAmountRaw.value || minStake.value; }, // setter set(newValue) { stakingAmountRaw.value = newValue; }, }); const stakingAmountNumber = computed({ // getter get() { return formatBigIntDivision(stakingAmount.value, 10n ** 18n); }, // setter set(newValue) { stakingAmount.value = BigInt(newValue * 10 ** 18); }, }); // const stakingAmountNumber = computed(() => return staking) async function snatch(stakingAmount: bigint, taxRate: number, positions: Array = []) { // console.log("snatch", { stakingAmount, taxRate, positions }); const account = getAccount(wagmiConfig); const taxRateObj = taxRates.find(obj => obj.year === taxRate); try { const assets: bigint = stakingAmount; // console.log("receiver", receiver); // await snatchService(assets, receiver, taxRate, []); // assets: BigInt, receiver: Address, taxRate: Number, positionsToSnatch: Array const deadline = BigInt(Date.now()) / 1000n + 1200n; const name = await getName(); const { types, message, domain, primaryType } = createPermitObject( HarbContract.contractAddress, account.address!, StakeContract.contractAddress, nonce.value, deadline, assets, account.chainId!, name ); // console.log("resultPermitObject", { types, message, domain, primaryType }); const typedData: TypedDataDefinition = { domain, message, primaryType, types, }; const signature = await signTypedData(wagmiConfig, typedData); // console.log("signature", { // domain, // message, // primaryType, // types, // }); const { r, s, v } = getSignatureRSV(signature); loading.value = true; // console.log("permitAndSnatch", assets, account.address!, taxRateObj?.index!, positions, deadline, v, r, s); const taxRateIndex = taxRateObj?.index ?? 0; const hash = await permitAndSnatch(assets, account.address!, taxRateIndex, positions, deadline, v, r, s); // console.log("hash", hash); loading.value = false; waiting.value = true; const data = await waitForTransactionReceipt(wagmiConfig, { hash: hash, }); const topics = decodeEventLog({ abi: StakeContract.abi, data: data.logs[3].data, topics: data.logs[3].topics, }) as DecodeEventLogReturnType & { args: PositionCreatedArgs }; const eventArgs: PositionCreatedArgs = topics.args; const decimalsAsBigInt = typeof wallet.balance.decimals === 'bigint' ? wallet.balance.decimals : BigInt(wallet.balance.decimals); const amount = compactNumber(formatBigIntDivision(eventArgs.harbergDeposit, 10n ** decimalsAsBigInt)); contractToast.showSuccessToast(amount, 'Success!', 'You Staked', 'Check your positions on the
Staker Dashboard', '$KRK'); waiting.value = false; await getNonce(); } catch (error) { // console.error("error", error); // console.log(JSON.parse(JSON.stringify(error))); const message = error instanceof Error ? error.name : 'Transaction failed'; contractToast.showFailToast(message); } finally { loading.value = false; waiting.value = false; } } return reactive({ stakingAmount, stakingAmountShares, stakingAmountNumber, state, snatch }); }