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 { weiToNumber, compactNumber } from 'kraiken-lib/format'; import { getTaxRateOptionByIndex } 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; 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 weiToNumber(stakingAmount.value, 18); }, // setter set(newValue) { stakingAmount.value = BigInt(newValue * 10 ** 18); }, }); // const stakingAmountNumber = computed(() => return staking) async function snatch(stakingAmount: bigint, taxRateIndex: number, positions: Array = []) { const account = getAccount(wagmiConfig); const taxRateOption = getTaxRateOptionByIndex(taxRateIndex); if (!taxRateOption) { throw new Error(`Invalid tax rate index: ${taxRateIndex}`); } try { const assets: bigint = stakingAmount; // 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 ); const typedData: TypedDataDefinition = { domain, message, primaryType, types, }; const signature = await signTypedData(wagmiConfig, typedData); const { r, s, v } = getSignatureRSV(signature); loading.value = true; const hash = await permitAndSnatch(assets, account.address!, taxRateOption.index, positions, deadline, v, r, s); 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 amount = compactNumber(weiToNumber(eventArgs.harbergDeposit, wallet.balance.decimals)); contractToast.showSuccessToast(amount, 'Success!', 'You Staked', 'Check your positions on the
Staker Dashboard', '$KRK'); waiting.value = false; await getNonce(); } catch (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 }); }