Correct bugs and adjust Buyer form.

This commit is contained in:
Filipe Soccol 2024-12-03 16:18:10 -03:00
parent c90f468d3c
commit 0f17a67e00
9 changed files with 113 additions and 59 deletions

View File

@ -1,28 +1,22 @@
import { getContract, getProvider } from "./provider";
import { getP2PixAddress, getTokenAddress } from "./addresses";
import { encodeBytes32String, Signature, Contract, parseEther } from "ethers";
import p2pix from "@/utils/smart_contract_files/P2PIX.json";
import {
solidityPackedKeccak256,
encodeBytes32String,
Signature,
Contract,
getBytes,
Wallet,
parseEther,
} from "ethers";
import type { TokenEnum } from "@/model/NetworkEnum";
import { createSolicitation } from "../utils/bbPay";
import type { Offer } from "../utils/bbPay";
const addLock = async (
seller: string,
sellerId: string,
token: string,
amount: number
): Promise<string> => {
const p2pContract = await getContract();
const lock = await p2pContract.lock(
seller,
sellerId,
token,
parseEther(String(amount)), // BigNumber
[],
@ -32,26 +26,29 @@ const addLock = async (
const lock_rec = await lock.wait();
const [t] = lock_rec.events;
return String(t.args.lockID);
const offer: Offer = {
amount,
lockId: String(t.args.lockID),
sellerId: sellerId,
};
const solicitation = await createSolicitation(offer);
return;
};
const releaseLock = async (
pixKey: string,
amount: number,
e2eId: string,
lockId: string
): Promise<any> => {
const mockBacenSigner = new Wallet(
"0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"
);
const releaseLock = async (solicitation: any): Promise<any> => {
// const mockBacenSigner = new Wallet(
// "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"
// );
const messageToSign = solidityPackedKeccak256(
["bytes32", "uint256", "bytes32"],
[pixKey, parseEther(String(amount)), encodeBytes32String(e2eId)]
);
// const messageToSign = solidityPackedKeccak256(
// ["bytes32", "uint256", "bytes32"],
// [sellerId, parseEther(String(amount)), encodeBytes32String(signature)]
// );
// const messageHashBytes = getBytes(messageToSign);
// const flatSig = await mockBacenSigner.signMessage(messageHashBytes);
const messageHashBytes = getBytes(messageToSign);
const flatSig = await mockBacenSigner.signMessage(messageHashBytes);
const provider = getProvider();
const sig = Signature.from(flatSig);

View File

@ -5,7 +5,8 @@ import { encodeBytes32String, Contract, parseEther } from "ethers";
import mockToken from "../utils/smart_contract_files/MockToken.json";
import { useEtherStore } from "@/store/ether";
import { createParticipant, Participant } from "@/utils/bbPay";
import { createParticipant } from "@/utils/bbPay";
import type { Participant } from "@/utils/bbPay";
const approveTokens = async (participant: Participant): Promise<any> => {
const provider = getProvider();

View File

@ -1,13 +1,14 @@
<script setup lang="ts">
import { pix } from "@/utils/QrCodePix";
import { onMounted, onUnmounted, ref } from "vue";
import CustomButton from "@/components/CustomButton/CustomButton.vue";
import CustomModal from "@/components//CustomModal/CustomModal.vue";
import QRCode from "qrcode";
// props and store references
const props = defineProps({
sellerId: String,
amount: Number,
qrcode: String,
});
const windowSize = ref<number>(window.innerWidth);

View File

@ -34,6 +34,7 @@ const tokenValue = ref<number>(0);
const enableConfirmButton = ref<boolean>(false);
const hasLiquidity = ref<boolean>(true);
const validDecimals = ref<boolean>(true);
const identification = ref<string>("");
const selectedDeposits = ref<ValidDeposit[]>();
import ChevronDown from "@/assets/chevronDown.svg";
@ -104,9 +105,17 @@ const verifyLiquidity = (): void => {
};
const enableOrDisableConfirmButton = (): void => {
enableConfirmButton.value =
!!selectedDeposits.value &&
!!selectedDeposits.value.find((d) => d.network === networkName.value);
if (!selectedDeposits.value) {
enableConfirmButton.value = false;
return;
}
if (!selectedDeposits.value.find((d) => d.network === networkName.value)) {
enableConfirmButton.value = false;
return;
}
enableConfirmButton.value = true;
};
watch(networkName, (): void => {
@ -117,6 +126,18 @@ watch(networkName, (): void => {
watch(walletAddress, (): void => {
verifyLiquidity();
});
// Add form submission handler
const handleSubmit = async (e: Event): Promise<void> => {
e.preventDefault();
if (!enableConfirmButton.value) return;
if (walletAddress.value) {
await emitConfirmButton();
} else {
await connectAccount();
}
};
</script>
<template>
@ -132,7 +153,7 @@ watch(walletAddress, (): void => {
tokens após realizar o Pix</span
>
</div>
<div class="main-container">
<form class="main-container" @submit="handleSubmit">
<div class="backdrop-blur -z-10 w-full h-full"></div>
<div
class="flex flex-col w-full bg-white sm:px-10 px-6 py-5 rounded-lg border-y-10"
@ -140,6 +161,7 @@ watch(walletAddress, (): void => {
<div class="flex justify-between sm:w-full items-center">
<input
type="number"
name="tokenAmount"
class="border-none outline-none text-lg text-gray-900"
v-bind:class="{
'font-semibold': tokenValue != undefined,
@ -148,6 +170,7 @@ watch(walletAddress, (): void => {
@input="debounce(handleInputEvent, 500)($event)"
placeholder="0"
step=".01"
required
/>
<div class="relative overflow-visible">
<button
@ -260,18 +283,33 @@ watch(walletAddress, (): void => {
>
</div>
</div>
<CustomButton
v-if="!walletAddress"
:text="'Conectar carteira'"
@buttonClicked="connectAccount()"
/>
<CustomButton
v-if="walletAddress"
:text="'Confirmar compra'"
:is-disabled="!enableConfirmButton"
@buttonClicked="emitConfirmButton()"
<div
class="flex flex-col w-full bg-white sm:px-10 px-6 py-4 rounded-lg border-y-10"
>
<input
type="text"
v-model="identification"
maxlength="14"
:pattern="'^\\d{11}$|^\\d{14}$'"
class="border-none outline-none sm:text-lg text-sm text-gray-900 w-full"
placeholder="Digite seu CPF ou CNPJ (somente números)"
required
/>
</div>
<!-- Action buttons -->
<CustomButton
v-if="walletAddress"
type="submit"
text="Confirmar Oferta"
/>
<CustomButton
v-else
text="Conectar carteira"
@buttonClicked="connectAccount()"
/>
</form>
</div>
</template>
@ -306,4 +344,10 @@ input[type="number"]::-webkit-inner-spin-button,
input[type="number"]::-webkit-outer-spin-button {
-webkit-appearance: none;
}
.custom-button {
@apply w-full py-3 px-6 rounded-lg font-semibold text-white bg-indigo-600
hover:bg-indigo-700 disabled:bg-gray-400 disabled:cursor-not-allowed
transition-colors duration-200;
}
</style>

View File

@ -9,6 +9,10 @@ import { getTokenImage } from "@/utils/imagesPath";
import { useOnboard } from "@web3-onboard/vue";
import ChevronDown from "@/assets/chevron.svg";
// Import the bank list
import bankList from "@/utils/files/isbpList.json";
import type { Participant } from "@/utils/bbPay";
// Define Bank interface
interface Bank {
ISPB: string;
@ -38,10 +42,6 @@ const bankSearchQuery = ref<string>("");
const showBankList = ref<boolean>(false);
const selectedBank = ref<Bank | null>(null);
// Import the bank list
import bankList from "@/utils/files/isbpList.json";
import { Participant } from "@/utils/bbPay";
const filteredBanks = computed(() => {
if (!bankSearchQuery.value) return [];
return bankList

View File

@ -1,6 +1,6 @@
import { NetworkEnum, TokenEnum } from "../model/NetworkEnum";
import type { ValidDeposit } from "@/model/ValidDeposit";
import { Participant } from "@/utils/bbPay";
import type { Participant } from "../utils/bbPay";
import { defineStore } from "pinia";
export const useEtherStore = defineStore("ether", {

View File

@ -15,9 +15,13 @@ export interface ParticipantWithID extends Participant {
export interface Offer {
amount: number;
sellerID: string;
lockId: string;
sellerId: string;
}
// Specs for BB Pay Sandbox
// https://apoio.developers.bb.com.br/sandbox/spec/665797498bb48200130fc32c
export const createParticipant = async (participant: Participant) => {
const response = await fetch(`${process.env.VUE_APP_API_URL}/participants`, {
method: "PUT",
@ -39,5 +43,15 @@ export const getSolicitation = async (id: string) => {
const response = await fetch(
`${process.env.VUE_APP_API_URL}/solicitation/${id}`
);
return response.json();
const obj: any = response.json();
return {
id: obj.numeroSolicitacao,
lockId: obj.codigoConciliacaoSolicitacao,
amount: obj.valorSolicitacao,
qrcode: obj.pix.textoQrCode,
status: obj.valorSomatorioPagamentosEfetivados >= obj.valorSolicitacao,
signature: obj.assinatura,
};
};

View File

@ -59,18 +59,15 @@ const confirmBuyClick = async (
}
};
const releaseTransaction = async (e2eId: string) => {
const releaseTransaction = async (lockId: string) => {
flowStep.value = Step.List;
showBuyAlert.value = true;
loadingRelease.value = true;
if (lockID.value && tokenAmount.value && pixTarget.value) {
const release = await releaseLock(
pixTarget.value,
tokenAmount.value,
e2eId,
lockID.value
);
const solicitation = await getSolicitation(lockId);
if (solicitation.confirmed) {
const release = await releaseLock(solicitation);
await release.wait();
await updateWalletStatus();

View File

@ -7,7 +7,7 @@ import { approveTokens, addDeposit } from "@/blockchain/sellerMethods";
import { ref } from "vue";
import { useEtherStore } from "@/store/ether";
import CustomAlert from "@/components/CustomAlert/CustomAlert.vue";
import { Participant } from "@/utils/bbPay";
import type { Participant } from "@/utils/bbPay";
enum Step {
Search,