From 9a506acfa68a6d9993d3b392e956efbdcf4c17e3 Mon Sep 17 00:00:00 2001 From: Jefferson Mantovani Date: Fri, 14 Nov 2025 10:01:24 -0300 Subject: [PATCH] feat: show the reputation limit in the buy input --- .../BuyerSteps/BuyerSearchComponent.vue | 109 +++++++++++++++++- 1 file changed, 108 insertions(+), 1 deletion(-) diff --git a/src/components/BuyerSteps/BuyerSearchComponent.vue b/src/components/BuyerSteps/BuyerSearchComponent.vue index 12cad5f..06d86bc 100644 --- a/src/components/BuyerSteps/BuyerSearchComponent.vue +++ b/src/components/BuyerSteps/BuyerSearchComponent.vue @@ -11,6 +11,9 @@ import { getTokenImage, getNetworkImage } from "@/utils/imagesPath"; import { onClickOutside } from "@vueuse/core"; import { Networks } from "@/config/networks"; import { TokenEnum } from "@/model/NetworkEnum"; +import { getContract } from "@/blockchain/provider"; +import { reputationAbi } from "@/blockchain/abi"; +import { type Address } from "viem"; // Store reference const user = useUser(); @@ -34,6 +37,8 @@ const hasLiquidity = ref(true); const validDecimals = ref(true); const identification = ref(""); const selectedDeposits = ref(); +const reputationLimit = ref(null); +const exceedsReputationLimit = ref(false); import ChevronDown from "@/assets/chevronDown.svg"; import { useOnboard } from "@web3-onboard/vue"; @@ -42,6 +47,96 @@ import { getParticipantID } from "@/blockchain/events"; // Emits const emit = defineEmits(["tokenBuy"]); +const castAddrToKey = (address: Address): bigint => { + return BigInt(address) << BigInt(12); +}; + +const getUserCredit = async (userAddress: Address): Promise => { + try { + const { address, abi, client } = await getContract(true); + const userKey = castAddrToKey(userAddress); + + const userCredit = await client.readContract({ + address, + abi, + functionName: "userRecord", + args: [userKey], + }); + + return userCredit as bigint; + } catch (error) { + console.error("Error fetching user credit:", error); + return BigInt(0); + } +}; + +const getReputationAddress = async (): Promise
=> { + try { + const { address, abi, client } = await getContract(true); + + const reputationAddr = await client.readContract({ + address, + abi, + functionName: "reputation", + }); + + return reputationAddr as Address; + } catch (error) { + console.error("Error fetching reputation address:", error); + return null; + } +}; + +const getSpendLimit = async (userCredit: bigint): Promise => { + try { + const reputationAddr = await getReputationAddress(); + if (!reputationAddr) return BigInt(0); + + const { client } = await getContract(true); + + const spendLimit = await client.readContract({ + address: reputationAddr, + abi: reputationAbi, + functionName: "limiter", + args: [userCredit], + }); + + return spendLimit as bigint; + } catch (error) { + console.error("Error fetching spend limit:", error); + return BigInt(0); + } +}; + +const checkReputationLimit = async (inputValue: number): Promise => { + exceedsReputationLimit.value = false; + + if (!walletAddress.value) { + reputationLimit.value = null; + return; + } + + if (inputValue === 0) { + return; + } + + try { + const userCredit = await getUserCredit(walletAddress.value); + const spendLimitRaw = await getSpendLimit(userCredit); + + const spendLimitNumber = Number(spendLimitRaw); + reputationLimit.value = spendLimitNumber; + + exceedsReputationLimit.value = spendLimitNumber < inputValue; + enableConfirmButton.value = !exceedsReputationLimit.value; + + } catch (error) { + console.error("Error checking reputation limit:", error); + reputationLimit.value = null; + exceedsReputationLimit.value = false; + } +}; + // Blockchain methods const connectAccount = async (): Promise => { const { connectWallet } = useOnboard(); @@ -70,6 +165,7 @@ const handleInputEvent = (event: any): void => { } validDecimals.value = true; + checkReputationLimit(tokenValue.value); verifyLiquidity(); }; @@ -268,7 +364,7 @@ const handleSubmit = async (e: Event): Promise => {
=> { demanda
+
+ O valor excede o limite permitido pela sua reputação. Limite máximo: {{ reputationLimit }} {{ selectedToken }} +
=> { v-if="walletAddress" type="submit" text="Confirmar Oferta" + :isDisabled="!enableConfirmButton" />