Merge pull request #9 from liftlearning/list-tokens
List tokens screen and steps integration (Search, Buy and List)
This commit is contained in:
commit
fbf14ee86f
10
.github/workflows/cd.yml
vendored
10
.github/workflows/cd.yml
vendored
@ -11,10 +11,15 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID_STAGING }}
|
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID_STAGING }}
|
||||||
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID_STAGING }}
|
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID_STAGING }}
|
||||||
|
ENV_VARIABLE: ${{ secrets.ENV_STAGING }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: 🏗 Setup repo
|
- name: 🏗 Setup repo
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: 🏗 Config .env
|
||||||
|
run: echo "$ENV_VARIABLE" > .env
|
||||||
|
|
||||||
- name: 🏗 Install Vercel CLI
|
- name: 🏗 Install Vercel CLI
|
||||||
run: npm install --global vercel@latest
|
run: npm install --global vercel@latest
|
||||||
|
|
||||||
@ -33,10 +38,15 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
|
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
|
||||||
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
|
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
|
||||||
|
ENV_VARIABLE: ${{ secrets.ENV_PROD }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: 🏗 Setup repo
|
- name: 🏗 Setup repo
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: 🏗 Config .env
|
||||||
|
run: echo "$ENV_VARIABLE" > .env
|
||||||
|
|
||||||
- name: 🏗 Install Vercel CLI
|
- name: 🏗 Install Vercel CLI
|
||||||
run: npm install --global vercel@latest
|
run: npm install --global vercel@latest
|
||||||
|
|
||||||
|
19
.github/workflows/ci.yml
vendored
19
.github/workflows/ci.yml
vendored
@ -23,19 +23,18 @@ jobs:
|
|||||||
|
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID_STAGING }}
|
||||||
|
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID_STAGING }}
|
||||||
steps:
|
steps:
|
||||||
- name: 🏗 Setup repo
|
- name: 🏗 Setup repo
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: 📦 Build docker image
|
- name: 🏗 Install Vercel CLI
|
||||||
run: |
|
run: npm install --global vercel@latest
|
||||||
docker build -t p2pix:$GITHUB_SHA .
|
|
||||||
docker save -o image_$GITHUB_SHA p2pix:$GITHUB_SHA
|
|
||||||
|
|
||||||
- name: 📦 Put docker image in cache
|
- name: 🏗 Pull staging app from vercel environment
|
||||||
uses: actions/cache@v3
|
run: vercel pull --yes --token=${{ secrets.VERCEL_AUTH_TOKEN }}
|
||||||
with:
|
|
||||||
key: p2pix
|
|
||||||
path: image_${{ github.sha }}
|
|
||||||
|
|
||||||
# test job
|
- name: 📦 Build staging app artifacts
|
||||||
|
run: vercel build --token=${{ secrets.VERCEL_AUTH_TOKEN }}
|
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 3.9 MiB After Width: | Height: | Size: 744 KiB |
3
src/assets/redirect.svg
Normal file
3
src/assets/redirect.svg
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M9.97059 0.888889C9.97059 0.397969 10.3686 0 10.8595 0H15.1111C15.602 0 16 0.397969 16 0.888889V5.23654C16 5.72746 15.602 6.12543 15.1111 6.12543C14.6202 6.12543 14.2222 5.72746 14.2222 5.23654V3.06921L8.66058 8.75646C8.31735 9.10744 7.75457 9.11373 7.40358 8.77049C7.05259 8.42726 7.04631 7.86448 7.38954 7.51349L12.9986 1.77778H10.8595C10.3686 1.77778 9.97059 1.37981 9.97059 0.888889ZM2.74997 2.67823C2.11751 2.67823 1.77778 3.11618 1.77778 3.45456V13.4459C1.77778 13.7843 2.11751 14.2222 2.74997 14.2222H12.0554C12.6878 14.2222 13.0275 13.7843 13.0275 13.4459V9.98736C13.0275 9.49644 13.4255 9.09847 13.9164 9.09847C14.4073 9.09847 14.8053 9.49644 14.8053 9.98736V13.4459C14.8053 14.9469 13.4786 16 12.0554 16H2.74997C1.32673 16 0 14.9469 0 13.4459V3.45456C0 1.9536 1.32673 0.900455 2.74997 0.900455H5.89948C6.3904 0.900455 6.78837 1.29842 6.78837 1.78934C6.78837 2.28026 6.3904 2.67823 5.89948 2.67823H2.74997Z" fill="#111827"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
151
src/components/ListComponent.vue
Normal file
151
src/components/ListComponent.vue
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import CustomButton from "@/components/CustomButton.vue";
|
||||||
|
import blockchain from "../utils/blockchain";
|
||||||
|
|
||||||
|
// props
|
||||||
|
const props = defineProps<{
|
||||||
|
lastWalletReleaseTransactions: any[] | undefined;
|
||||||
|
tokenAmount: Number | undefined;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
// Emits
|
||||||
|
const emit = defineEmits(["makeAnotherTransaction"]);
|
||||||
|
|
||||||
|
const formatEventsAmount = (amount: any) => {
|
||||||
|
try {
|
||||||
|
const formated = blockchain.formatBigNumber(amount);
|
||||||
|
return formated;
|
||||||
|
} catch {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const openEtherscanUrl = (url: string) => {
|
||||||
|
window.open(url, "_blank");
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="page">
|
||||||
|
<div class="text-container">
|
||||||
|
<span class="text font-extrabold text-5xl max-w-[50rem]"
|
||||||
|
>Os tokens já foram transferidos <br />
|
||||||
|
para a sua carteira!
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="blur-container">
|
||||||
|
<div
|
||||||
|
class="flex flex-col w-full bg-white px-10 py-5 rounded-lg border-y-10"
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<p>Tokens recebidos</p>
|
||||||
|
<p class="text-2xl text-gray-900">{{ props.tokenAmount }} BRZ</p>
|
||||||
|
</div>
|
||||||
|
<div class="my-5">
|
||||||
|
<p>
|
||||||
|
<b>Não encontrou os tokens? </b>Clique no botão abaixo para <br />
|
||||||
|
cadastrar o BRZ em sua carteira.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<CustomButton
|
||||||
|
:text="'Cadastrar token na carteira'"
|
||||||
|
@buttonClicked="() => {}"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="border-amber-500 border-2 rounded default-button text-white p-2 px-50 min-w-[198px]"
|
||||||
|
@click="emit('makeAnotherTransaction')"
|
||||||
|
>
|
||||||
|
Fazer nova transação
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="text-container mt-16">
|
||||||
|
<span class="text font-extrabold text-3xl max-w-[50rem]"
|
||||||
|
>Últimas transações
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="blur-container min-w-[80%] gap-8">
|
||||||
|
<div class="flex flex-row justify-between w-full px-8">
|
||||||
|
<span class="text-xs text-gray-50 font-medium">Valor</span>
|
||||||
|
<span class="text-xs text-gray-50 font-medium">Tipo de transação</span>
|
||||||
|
<span class="text-xs text-gray-50 font-medium">Checar transação</span>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="flex flex-row justify-between w-full bg-white px-6 py-4 rounded-lg"
|
||||||
|
v-for="release in lastWalletReleaseTransactions"
|
||||||
|
:key="release?.blockNumber"
|
||||||
|
>
|
||||||
|
<span class="last-release-info">
|
||||||
|
{{ formatEventsAmount(release?.args.amount) }} BRZ
|
||||||
|
</span>
|
||||||
|
<span class="last-release-info">
|
||||||
|
{{ "Compra" }}
|
||||||
|
</span>
|
||||||
|
<div
|
||||||
|
class="flex gap-2 cursor-pointer items-center"
|
||||||
|
@click="
|
||||||
|
openEtherscanUrl(
|
||||||
|
`https://etherscan.io/tx/${release?.transactionHash}`
|
||||||
|
)
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<span class="last-release-info">Etherscan</span>
|
||||||
|
<img alt="Redirect image" src="@/assets/redirect.svg" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex justify-center w-full right-6 mt-2">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="text-white"
|
||||||
|
@click="() => {}"
|
||||||
|
v-if="lastWalletReleaseTransactions?.length != 0"
|
||||||
|
>
|
||||||
|
Carregar mais
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="font-bold" v-if="lastWalletReleaseTransactions?.length == 0">
|
||||||
|
Não há nenhuma transação anterior
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.page {
|
||||||
|
@apply flex flex-col items-center justify-center w-full mt-16;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
@apply text-gray-900;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-container {
|
||||||
|
@apply flex flex-col items-center justify-center gap-4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text {
|
||||||
|
@apply text-gray-800 text-center;
|
||||||
|
}
|
||||||
|
.blur-container-row {
|
||||||
|
@apply flex flex-row justify-center items-center px-8 py-6 gap-2 rounded-lg shadow-md shadow-gray-600 backdrop-blur-md mt-8 w-1/3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.blur-container {
|
||||||
|
@apply flex flex-col justify-center items-center px-8 py-6 gap-4 rounded-lg shadow-md shadow-gray-600 backdrop-blur-md mt-10 w-auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.last-release-info {
|
||||||
|
@apply font-medium text-base text-gray-900;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="number"] {
|
||||||
|
-moz-appearance: textfield;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="number"]::-webkit-inner-spin-button,
|
||||||
|
input[type="number"]::-webkit-outer-spin-button {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
}
|
||||||
|
</style>
|
@ -1,10 +1,17 @@
|
|||||||
<script setup lang="ts"></script>
|
<script setup lang="ts">
|
||||||
|
// prop
|
||||||
|
const props = defineProps({
|
||||||
|
title: String,
|
||||||
|
message: String,
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="page">
|
<div class="page">
|
||||||
<div class="text-container">
|
<div class="text-container">
|
||||||
<span class="text font-bold text-3xl max-w-[29rem]"
|
<span class="text font-bold text-3xl max-w-[29rem]">{{
|
||||||
>Confirme em sua carteira</span
|
props.title ? props.title : "Confirme em sua carteira"
|
||||||
>
|
}}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="blur-container w-[26rem]">
|
<div class="blur-container w-[26rem]">
|
||||||
<div
|
<div
|
||||||
@ -20,7 +27,7 @@
|
|||||||
height="48"
|
height="48"
|
||||||
/>
|
/>
|
||||||
<span class="text-black font-medium text-sm px-12 mt-4">
|
<span class="text-black font-medium text-sm px-12 mt-4">
|
||||||
A transação está sendo enviada para a rede
|
{{ $props.message }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
@ -5,6 +5,7 @@ import { debounce } from "@/utils/debounce";
|
|||||||
import CustomButton from "./CustomButton.vue";
|
import CustomButton from "./CustomButton.vue";
|
||||||
import api from "../services/index";
|
import api from "../services/index";
|
||||||
|
|
||||||
|
// props and store references
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
pixTarget: String,
|
pixTarget: String,
|
||||||
tokenValue: Number,
|
tokenValue: Number,
|
||||||
@ -12,13 +13,17 @@ const props = defineProps({
|
|||||||
|
|
||||||
const qrCode = ref<string>("");
|
const qrCode = ref<string>("");
|
||||||
const qrCodePayload = ref<string>("");
|
const qrCodePayload = ref<string>("");
|
||||||
|
const isPixValid = ref<boolean>(false);
|
||||||
|
const isCodeInputEmpty = ref<boolean>(true);
|
||||||
|
const e2eId = ref<string>("");
|
||||||
|
|
||||||
|
// Emits
|
||||||
|
const emit = defineEmits(["pixValidated"]);
|
||||||
|
|
||||||
const pixQrCode = pix({
|
const pixQrCode = pix({
|
||||||
pixKey: props.pixTarget ?? "",
|
pixKey: props.pixTarget ?? "",
|
||||||
value: props.tokenValue,
|
value: props.tokenValue,
|
||||||
});
|
});
|
||||||
const isPixValid = ref<boolean>(false);
|
|
||||||
const isCodeInputEmpty = ref<boolean>(true);
|
|
||||||
|
|
||||||
pixQrCode.base64QrCode().then((code: string) => {
|
pixQrCode.base64QrCode().then((code: string) => {
|
||||||
qrCode.value = code;
|
qrCode.value = code;
|
||||||
});
|
});
|
||||||
@ -27,12 +32,12 @@ qrCodePayload.value = pixQrCode.payload();
|
|||||||
|
|
||||||
const handleInputEvent = (event: any) => {
|
const handleInputEvent = (event: any) => {
|
||||||
const { value } = event.target;
|
const { value } = event.target;
|
||||||
|
e2eId.value = value;
|
||||||
validatePix(value);
|
validatePix();
|
||||||
};
|
};
|
||||||
|
|
||||||
const validatePix = async (e2eid: any) => {
|
const validatePix = async () => {
|
||||||
if (e2eid == "") {
|
if (e2eId.value == "") {
|
||||||
isPixValid.value = false;
|
isPixValid.value = false;
|
||||||
isCodeInputEmpty.value = true;
|
isCodeInputEmpty.value = true;
|
||||||
return;
|
return;
|
||||||
@ -42,7 +47,7 @@ const validatePix = async (e2eid: any) => {
|
|||||||
|
|
||||||
if (sellerPixKey && transactionValue) {
|
if (sellerPixKey && transactionValue) {
|
||||||
var body_req = {
|
var body_req = {
|
||||||
e2e_id: e2eid,
|
e2e_id: e2eId.value,
|
||||||
pix_key: sellerPixKey,
|
pix_key: sellerPixKey,
|
||||||
pix_value: transactionValue,
|
pix_value: transactionValue,
|
||||||
};
|
};
|
||||||
@ -141,6 +146,7 @@ const validatePix = async (e2eid: any) => {
|
|||||||
<CustomButton
|
<CustomButton
|
||||||
:is-disabled="isPixValid == false"
|
:is-disabled="isPixValid == false"
|
||||||
:text="'Enviar para a rede'"
|
:text="'Enviar para a rede'"
|
||||||
|
@button-clicked="emit('pixValidated', { e2eId })"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -9,7 +9,7 @@ import blockchain from "../utils/blockchain";
|
|||||||
// Store reference
|
// Store reference
|
||||||
const etherStore = useEtherStore();
|
const etherStore = useEtherStore();
|
||||||
|
|
||||||
const { walletAddress, depositsAddedList } = storeToRefs(etherStore);
|
const { walletAddress, depositsValidList } = storeToRefs(etherStore);
|
||||||
|
|
||||||
// Reactive state
|
// Reactive state
|
||||||
const tokenValue = ref(0);
|
const tokenValue = ref(0);
|
||||||
@ -52,18 +52,20 @@ const decimalCount = (num: Number) => {
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Verify if there is a valid deposit to buy
|
// Verify if there is a valid deposit to buy
|
||||||
const verifyLiquidity = () => {
|
const verifyLiquidity = () => {
|
||||||
enableSelectButton.value = false;
|
enableSelectButton.value = false;
|
||||||
selectedDeposit.value = null;
|
selectedDeposit.value = null;
|
||||||
if (!walletAddress.value || tokenValue.value <= 0) return;
|
if (!walletAddress.value || tokenValue.value <= 0) return;
|
||||||
|
|
||||||
depositsAddedList.value.find((element) => {
|
depositsValidList.value.find((element) => {
|
||||||
const p2pixTokenValue = blockchain.formatBigNumber(element.args.amount);
|
const remaining = element.remaining;
|
||||||
if (
|
if (
|
||||||
tokenValue.value!! <= Number(p2pixTokenValue) &&
|
element.valid == true &&
|
||||||
|
tokenValue.value!! <= remaining &&
|
||||||
tokenValue.value!! != 0 &&
|
tokenValue.value!! != 0 &&
|
||||||
element.args.seller !== walletAddress.value
|
element.seller !== walletAddress.value
|
||||||
) {
|
) {
|
||||||
enableSelectButton.value = true;
|
enableSelectButton.value = true;
|
||||||
hasLiquidity.value = true;
|
hasLiquidity.value = true;
|
||||||
|
188
src/components/SellerSteps/SellerSearchComponent.vue
Normal file
188
src/components/SellerSteps/SellerSearchComponent.vue
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from "vue";
|
||||||
|
import CustomButton from "../../components/CustomButton.vue";
|
||||||
|
import { debounce } from "@/utils/debounce";
|
||||||
|
import { useEtherStore } from "@/store/ether";
|
||||||
|
import { storeToRefs } from "pinia";
|
||||||
|
|
||||||
|
// Store reference
|
||||||
|
const etherStore = useEtherStore();
|
||||||
|
|
||||||
|
const { walletAddress, depositsAddedList } = storeToRefs(etherStore);
|
||||||
|
|
||||||
|
// Reactive state
|
||||||
|
const tokenValue = ref(0);
|
||||||
|
const enableSelectButton = ref(false);
|
||||||
|
const hasLiquidity = ref(true);
|
||||||
|
const validDecimals = ref(true);
|
||||||
|
const selectedDeposit = ref();
|
||||||
|
|
||||||
|
// Emits
|
||||||
|
const emit = defineEmits(["tokenBuy"]);
|
||||||
|
|
||||||
|
// Blockchain methods
|
||||||
|
const connectAccount = async () => {};
|
||||||
|
|
||||||
|
// Debounce methods
|
||||||
|
const handleInputEvent = (event: any) => {
|
||||||
|
const { value } = event.target;
|
||||||
|
|
||||||
|
tokenValue.value = Number(value);
|
||||||
|
|
||||||
|
if (decimalCount(tokenValue.value) > 2) {
|
||||||
|
validDecimals.value = false;
|
||||||
|
enableSelectButton.value = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
validDecimals.value = true;
|
||||||
|
|
||||||
|
// verifyLiquidity();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Enable button methods
|
||||||
|
// Check if has more than 2 decimal places
|
||||||
|
const decimalCount = (num: Number) => {
|
||||||
|
const numStr = String(num);
|
||||||
|
if (numStr.includes(".")) {
|
||||||
|
return numStr.split(".")[1].length;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Verify if there is a valid deposit to buy
|
||||||
|
// const verifyLiquidity = () => {
|
||||||
|
// enableSelectButton.value = false;
|
||||||
|
// selectedDeposit.value = null;
|
||||||
|
// if (!walletAddress.value || tokenValue.value <= 0) return;
|
||||||
|
|
||||||
|
// depositsAddedList.value.find((element) => {
|
||||||
|
// const p2pixTokenValue = blockchain.formatBigNumber(element.args.amount);
|
||||||
|
// if (
|
||||||
|
// tokenValue.value!! <= Number(p2pixTokenValue) &&
|
||||||
|
// tokenValue.value!! != 0 &&
|
||||||
|
// element.args.seller !== walletAddress.value
|
||||||
|
// ) {
|
||||||
|
// enableSelectButton.value = true;
|
||||||
|
// hasLiquidity.value = true;
|
||||||
|
// selectedDeposit.value = element;
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
// return false;
|
||||||
|
// });
|
||||||
|
|
||||||
|
// if (!enableSelectButton.value) {
|
||||||
|
// hasLiquidity.value = false;
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="page">
|
||||||
|
<div class="text-container">
|
||||||
|
<span class="text font-extrabold text-5xl max-w-[29rem]"
|
||||||
|
>Adquira cripto com apenas um Pix</span
|
||||||
|
>
|
||||||
|
<span class="text font-medium text-base max-w-[28rem]"
|
||||||
|
>Digite um valor, confira a oferta, conecte sua carteira e receba os
|
||||||
|
tokens após realizar o Pix</span
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<div class="blur-container">
|
||||||
|
<div
|
||||||
|
class="flex flex-col w-full bg-white px-10 py-5 rounded-lg border-y-10"
|
||||||
|
>
|
||||||
|
<div class="flex justify-between w-full items-center">
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
class="border-none outline-none text-lg text-gray-900 w-fit"
|
||||||
|
v-bind:class="{
|
||||||
|
'font-semibold': tokenValue != undefined,
|
||||||
|
'text-xl': tokenValue != undefined,
|
||||||
|
}"
|
||||||
|
@input="debounce(handleInputEvent, 500)($event)"
|
||||||
|
placeholder="0 "
|
||||||
|
step=".01"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
class="flex flex-row p-2 px-3 bg-gray-300 rounded-3xl min-w-fit gap-1"
|
||||||
|
>
|
||||||
|
<img alt="Token image" class="w-fit" src="@/assets/brz.svg" />
|
||||||
|
<span class="text-gray-900 text-lg w-fit" id="brz">BRZ</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="custom-divide py-2"></div>
|
||||||
|
<div class="flex justify-between pt-2" v-if="hasLiquidity">
|
||||||
|
<p class="text-gray-500 font-normal text-sm w-auto">
|
||||||
|
~ R$ {{ tokenValue.toFixed(2) }}
|
||||||
|
</p>
|
||||||
|
<div class="flex gap-2">
|
||||||
|
<img
|
||||||
|
alt="Polygon image"
|
||||||
|
src="@/assets/polygon.svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
/>
|
||||||
|
<img
|
||||||
|
alt="Ethereum image"
|
||||||
|
src="@/assets/ethereum.svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex pt-2 justify-center" v-if="!validDecimals">
|
||||||
|
<span class="text-red-500 font-normal text-sm"
|
||||||
|
>Por favor utilize no máximo 2 casas decimais</span
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<div class="flex pt-2 justify-center" v-else-if="!hasLiquidity">
|
||||||
|
<span class="text-red-500 font-normal text-sm"
|
||||||
|
>Atualmente não há liquidez nas redes para sua demanda</span
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<CustomButton
|
||||||
|
:text="'Conectar carteira'"
|
||||||
|
@buttonClicked="emit('tokenBuy')"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.custom-divide {
|
||||||
|
width: 100%;
|
||||||
|
border-bottom: 1px solid #d1d5db;
|
||||||
|
}
|
||||||
|
.bottom-position {
|
||||||
|
top: -20px;
|
||||||
|
right: 50%;
|
||||||
|
transform: translateX(50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.page {
|
||||||
|
@apply flex flex-col items-center justify-center w-full mt-16;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-container {
|
||||||
|
@apply flex flex-col items-center justify-center gap-4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text {
|
||||||
|
@apply text-gray-800 text-center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.blur-container {
|
||||||
|
@apply flex flex-col justify-center items-center px-8 py-6 gap-2 rounded-lg shadow-md shadow-gray-600 backdrop-blur-md mt-10;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="number"] {
|
||||||
|
-moz-appearance: textfield;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="number"]::-webkit-inner-spin-button,
|
||||||
|
input[type="number"]::-webkit-outer-spin-button {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
}
|
||||||
|
</style>
|
90
src/components/SellerSteps/SendNetwork.vue
Normal file
90
src/components/SellerSteps/SendNetwork.vue
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import CustomButton from "@/components/CustomButton.vue";
|
||||||
|
|
||||||
|
// Emits
|
||||||
|
const emit = defineEmits(["sendNetwork"]);
|
||||||
|
|
||||||
|
const sendNetworkHandle = () => {
|
||||||
|
emit("sendNetwork");
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="page">
|
||||||
|
<div class="text-container">
|
||||||
|
<span class="text font-extrabold text-5xl max-w-[50rem]"
|
||||||
|
>Envie sua oferta para a rede
|
||||||
|
</span>
|
||||||
|
<span class="text text-xl font-medium text-base max-w-[30rem]"
|
||||||
|
>Após a confirmação sua oferta estará disponível para outros usuários.
|
||||||
|
Caso deseje retirar a oferta, será necessário aguardar 24h para receber
|
||||||
|
os tokens de volta.</span
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<div class="blur-container">
|
||||||
|
<div
|
||||||
|
class="flex flex-col w-full bg-white px-10 py-5 rounded-lg border-y-10"
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<p>Tokens ofertados</p>
|
||||||
|
<p class="text-2xl text-gray-900">100 BRZ</p>
|
||||||
|
</div>
|
||||||
|
<div class="my-3">
|
||||||
|
<p>Chave Pix</p>
|
||||||
|
<p class="text-xl text-gray-900 break-words">
|
||||||
|
c02942far7047f6shri5ifh371908973
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="mb-5">
|
||||||
|
<p>
|
||||||
|
<b>Atenção! </b> Os tokens ofertados ficam registrados no smart
|
||||||
|
contract e serão transferidos automaticamente para o comprador assim
|
||||||
|
que o Pix for detectado e confirmado.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<CustomButton
|
||||||
|
:text="'Enviar para a rede'"
|
||||||
|
@buttonClicked="sendNetworkHandle()"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.page {
|
||||||
|
@apply flex flex-col items-center justify-center w-full mt-16;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
@apply text-gray-900;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-container {
|
||||||
|
@apply flex flex-col items-center justify-center gap-4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text {
|
||||||
|
@apply text-gray-800 text-center;
|
||||||
|
}
|
||||||
|
.blur-container-row {
|
||||||
|
@apply flex flex-row justify-center items-center px-8 py-6 gap-2 rounded-lg shadow-md shadow-gray-600 backdrop-blur-md mt-8 w-1/3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.blur-container {
|
||||||
|
@apply flex flex-col justify-center items-center px-8 py-6 gap-2 rounded-lg shadow-md shadow-gray-600 backdrop-blur-md mt-8 w-1/3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.last-deposit-info {
|
||||||
|
@apply font-medium text-base;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="number"] {
|
||||||
|
-moz-appearance: textfield;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="number"]::-webkit-inner-spin-button,
|
||||||
|
input[type="number"]::-webkit-outer-spin-button {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
}
|
||||||
|
</style>
|
150
src/components/SellerSteps/WantSellComponent.vue
Normal file
150
src/components/SellerSteps/WantSellComponent.vue
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from "vue";
|
||||||
|
import CustomButton from "../CustomButton.vue";
|
||||||
|
import { debounce } from "@/utils/debounce";
|
||||||
|
|
||||||
|
// Reactive state
|
||||||
|
const offer = ref<string | number>("");
|
||||||
|
const pixKey = ref<string>("");
|
||||||
|
|
||||||
|
const enableSelectButton = ref(false);
|
||||||
|
const hasLiquidity = ref(true);
|
||||||
|
const validDecimals = ref(true);
|
||||||
|
|
||||||
|
// Emits
|
||||||
|
const emit = defineEmits(["approveTokens"]);
|
||||||
|
|
||||||
|
// Blockchain methods
|
||||||
|
const approveTokensHandle = async () => {
|
||||||
|
console.log(offer.value, pixKey.value);
|
||||||
|
emit("approveTokens");
|
||||||
|
};
|
||||||
|
|
||||||
|
// Debounce methods
|
||||||
|
const handleInputEvent = (event: any) => {
|
||||||
|
const { value } = event.target;
|
||||||
|
|
||||||
|
offer.value = Number(value);
|
||||||
|
|
||||||
|
if (decimalCount(offer.value) > 2) {
|
||||||
|
validDecimals.value = false;
|
||||||
|
enableSelectButton.value = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
validDecimals.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Enable button methods
|
||||||
|
// Check if has more than 2 decimal places
|
||||||
|
const decimalCount = (num: Number) => {
|
||||||
|
const numStr = String(num);
|
||||||
|
if (numStr.includes(".")) {
|
||||||
|
return numStr.split(".")[1].length;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="page">
|
||||||
|
<div class="text-container">
|
||||||
|
<span class="text font-extrabold text-5xl max-w-[29rem]"
|
||||||
|
>Venda cripto e receba em Pix</span
|
||||||
|
>
|
||||||
|
<span class="text font-medium text-base max-w-[28rem]"
|
||||||
|
>Digite sua oferta, informe a chave Pix, selecione a rede, aprove o
|
||||||
|
envio da transação e confirme sua oferta.</span
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<div class="blur-container">
|
||||||
|
<div
|
||||||
|
class="flex flex-col w-full bg-white px-10 py-5 rounded-lg border-y-10"
|
||||||
|
>
|
||||||
|
<div class="flex justify-between w-full items-center">
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
v-model="offer"
|
||||||
|
class="border-none outline-none text-lg text-gray-900 w-fit"
|
||||||
|
v-bind:class="{
|
||||||
|
'font-semibold': offer != undefined,
|
||||||
|
'text-xl': offer != undefined,
|
||||||
|
}"
|
||||||
|
@input="debounce(handleInputEvent, 500)($event)"
|
||||||
|
placeholder="Digite sua oferta"
|
||||||
|
step=".01"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
class="flex flex-row p-2 px-3 bg-gray-300 rounded-3xl min-w-fit gap-1"
|
||||||
|
>
|
||||||
|
<img alt="Token image" class="w-fit" src="@/assets/brz.svg" />
|
||||||
|
<span class="text-gray-900 text-lg w-fit" id="brz">BRZ</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex pt-2 justify-center" v-if="!validDecimals">
|
||||||
|
<span class="text-red-500 font-normal text-sm"
|
||||||
|
>Por favor utilize no máximo 2 casas decimais</span
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<div class="flex pt-2 justify-center" v-else-if="!hasLiquidity">
|
||||||
|
<span class="text-red-500 font-normal text-sm"
|
||||||
|
>Atualmente não há liquidez nas redes para sua demanda</span
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="flex flex-col w-full bg-white px-10 py-8 rounded-lg border-y-10"
|
||||||
|
>
|
||||||
|
<div class="flex justify-between w-full items-center">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
v-model="pixKey"
|
||||||
|
class="border-none outline-none text-lg text-gray-900 w-fit"
|
||||||
|
placeholder="Digite a chave Pix"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<CustomButton
|
||||||
|
:text="'Aprovar tokens'"
|
||||||
|
@buttonClicked="approveTokensHandle()"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.custom-divide {
|
||||||
|
width: 100%;
|
||||||
|
border-bottom: 1px solid #d1d5db;
|
||||||
|
}
|
||||||
|
.bottom-position {
|
||||||
|
top: -20px;
|
||||||
|
right: 50%;
|
||||||
|
transform: translateX(50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.page {
|
||||||
|
@apply flex flex-col items-center justify-center w-full mt-16;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-container {
|
||||||
|
@apply flex flex-col items-center justify-center gap-4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text {
|
||||||
|
@apply text-gray-800 text-center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.blur-container {
|
||||||
|
@apply flex flex-col justify-center items-center px-8 py-6 gap-2 rounded-lg shadow-md shadow-gray-600 backdrop-blur-md mt-10;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="number"] {
|
||||||
|
-moz-appearance: textfield;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="number"]::-webkit-inner-spin-button,
|
||||||
|
input[type="number"]::-webkit-outer-spin-button {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
}
|
||||||
|
</style>
|
@ -1,4 +1,5 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import router from "@/router";
|
||||||
import { storeToRefs } from "pinia";
|
import { storeToRefs } from "pinia";
|
||||||
import { useEtherStore } from "../store/ether";
|
import { useEtherStore } from "../store/ether";
|
||||||
import blockchain from "../utils/blockchain";
|
import blockchain from "../utils/blockchain";
|
||||||
@ -23,11 +24,9 @@ const formatWalletAddress = (): string => {
|
|||||||
return `${initialText}...${finalText}`;
|
return `${initialText}...${finalText}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
const formatWalletBalance = (): string => {
|
const formatWalletBalance = (): String => {
|
||||||
const formattedBalance = blockchain.formatEther(balance.value);
|
const fixed = Number(balance.value);
|
||||||
const fixed = formattedBalance.substring(0, 8);
|
return fixed.toFixed(2);
|
||||||
|
|
||||||
return fixed;
|
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -41,7 +40,13 @@ const formatWalletBalance = (): string => {
|
|||||||
height="75"
|
height="75"
|
||||||
/>
|
/>
|
||||||
<div class="flex gap-4 items-center">
|
<div class="flex gap-4 items-center">
|
||||||
<button type="button" class="default-button">Quero vender</button>
|
<button
|
||||||
|
type="button"
|
||||||
|
class="default-button"
|
||||||
|
v-on:click="router.push('/seller')"
|
||||||
|
>
|
||||||
|
Quero vender
|
||||||
|
</button>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
v-if="!walletAddress"
|
v-if="!walletAddress"
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { createRouter, createWebHistory } from "vue-router";
|
import { createRouter, createWebHistory } from "vue-router";
|
||||||
import HomeView from "../views/HomeView.vue";
|
import HomeView from "../views/HomeView.vue";
|
||||||
import MockView from "../views/MockView.vue";
|
import MockView from "../views/MockView.vue";
|
||||||
|
import SellerView from "@/views/SellerView.vue";
|
||||||
|
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
history: createWebHistory(import.meta.env.BASE_URL),
|
history: createWebHistory(import.meta.env.BASE_URL),
|
||||||
@ -10,6 +11,11 @@ const router = createRouter({
|
|||||||
name: "home",
|
name: "home",
|
||||||
component: HomeView,
|
component: HomeView,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "/seller",
|
||||||
|
name: "seller",
|
||||||
|
component: SellerView,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: "/mock",
|
path: "/mock",
|
||||||
name: "mock",
|
name: "mock",
|
||||||
|
@ -13,6 +13,10 @@ export const useEtherStore = defineStore("ether", {
|
|||||||
depositsExpiredList: [] as any[],
|
depositsExpiredList: [] as any[],
|
||||||
// Locks adicionados na blockchain
|
// Locks adicionados na blockchain
|
||||||
locksAddedList: [] as any[],
|
locksAddedList: [] as any[],
|
||||||
|
// Locks 'released' na blockchain
|
||||||
|
locksReleasedList: [] as any[],
|
||||||
|
// Locks expirados na blockchain
|
||||||
|
locksExpiredList: [] as any[],
|
||||||
}),
|
}),
|
||||||
actions: {
|
actions: {
|
||||||
setWalletAddress(walletAddress: string) {
|
setWalletAddress(walletAddress: string) {
|
||||||
@ -36,5 +40,11 @@ export const useEtherStore = defineStore("ether", {
|
|||||||
setLocksAddedList(locksAddedList: any[]) {
|
setLocksAddedList(locksAddedList: any[]) {
|
||||||
this.locksAddedList = locksAddedList;
|
this.locksAddedList = locksAddedList;
|
||||||
},
|
},
|
||||||
|
setLocksReleasedList(locksReleasedList: any[]) {
|
||||||
|
this.locksReleasedList = locksReleasedList;
|
||||||
|
},
|
||||||
|
setLocksExpiredList(locksExpiredList: any[]) {
|
||||||
|
this.locksExpiredList = locksExpiredList;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -8,15 +8,28 @@ import addresses from "./smart_contract_files/localhost.json";
|
|||||||
// Mock wallets import
|
// Mock wallets import
|
||||||
import { wallets } from "./smart_contract_files/wallets.json";
|
import { wallets } from "./smart_contract_files/wallets.json";
|
||||||
|
|
||||||
// Provider methods
|
// Wallet methods
|
||||||
const connectProvider = async () => {
|
// Update wallet state (balance and address)
|
||||||
|
const updateWalletStatus = async () => {
|
||||||
const etherStore = useEtherStore();
|
const etherStore = useEtherStore();
|
||||||
const window_ = window as any;
|
const provider = getProvider();
|
||||||
const connection = window_.ethereum;
|
if (!provider) return;
|
||||||
let provider: ethers.providers.Web3Provider | null = null;
|
|
||||||
|
const signer = provider.getSigner();
|
||||||
|
const contract = new ethers.Contract(addresses.token, mockToken.abi, signer);
|
||||||
|
|
||||||
|
const walletAddress = await provider.send("eth_requestAccounts", []);
|
||||||
|
|
||||||
|
const balance = await contract.balanceOf(walletAddress[0]);
|
||||||
|
etherStore.setBalance(formatBigNumber(balance));
|
||||||
|
etherStore.setWalletAddress(ethers.utils.getAddress(walletAddress[0]));
|
||||||
|
};
|
||||||
|
|
||||||
|
// Split tokens between wallets in wallets.json
|
||||||
|
const splitTokens = async () => {
|
||||||
|
const provider = getProvider();
|
||||||
|
if (!provider) return;
|
||||||
|
|
||||||
if (!connection) return;
|
|
||||||
provider = new ethers.providers.Web3Provider(connection);
|
|
||||||
const signer = provider.getSigner();
|
const signer = provider.getSigner();
|
||||||
const tokenContract = new ethers.Contract(
|
const tokenContract = new ethers.Contract(
|
||||||
addresses.token,
|
addresses.token,
|
||||||
@ -24,33 +37,197 @@ const connectProvider = async () => {
|
|||||||
signer
|
signer
|
||||||
);
|
);
|
||||||
|
|
||||||
const walletAddress = await provider.send("eth_requestAccounts", []);
|
for (let i = 0; i < wallets.length; i++) {
|
||||||
const balance = await tokenContract.balanceOf(walletAddress[0]);
|
const tx = await tokenContract.transfer(
|
||||||
|
wallets[i],
|
||||||
|
ethers.utils.parseEther("4000000.0")
|
||||||
|
);
|
||||||
|
await tx.wait();
|
||||||
|
updateWalletStatus();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
etherStore.setWalletAddress(ethers.utils.getAddress(walletAddress[0]));
|
// get all wallet transactions
|
||||||
etherStore.setBalance(String(balance));
|
const listAllTransactionByWalletAddress = async (
|
||||||
|
walletAddress: string
|
||||||
|
): Promise<any[] | undefined> => {
|
||||||
|
const provider = getProvider();
|
||||||
|
if (!provider) return;
|
||||||
|
|
||||||
const p2pEvents = new ethers.Contract(addresses.p2pix, p2pix.abi, signer);
|
const signer = provider.getSigner();
|
||||||
|
const p2pContract = new ethers.Contract(addresses.p2pix, p2pix.abi, signer);
|
||||||
|
|
||||||
const filterDeposits = p2pEvents.filters.DepositAdded(null);
|
const filterDeposits = p2pContract.filters.DepositAdded([walletAddress]);
|
||||||
const eventsDeposits = await p2pEvents.queryFilter(filterDeposits);
|
const eventsDeposits = await p2pContract.queryFilter(filterDeposits);
|
||||||
console.log("Deposits Added: ", eventsDeposits);
|
|
||||||
|
const filterAddedLocks = p2pContract.filters.LockAdded([walletAddress]);
|
||||||
|
const eventsAddedLocks = await p2pContract.queryFilter(filterAddedLocks);
|
||||||
|
|
||||||
|
const filterReleasedLocks = p2pContract.filters.LockReleased([walletAddress]);
|
||||||
|
const eventsReleasedLocks = await p2pContract.queryFilter(
|
||||||
|
filterReleasedLocks
|
||||||
|
);
|
||||||
|
|
||||||
|
return [...eventsDeposits, ...eventsAddedLocks, ...eventsReleasedLocks].sort(
|
||||||
|
(a, b) => {
|
||||||
|
return b.blockNumber - a.blockNumber;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
// get wallet's deposit transactions
|
||||||
|
const listDepositTransactionByWalletAddress = async (
|
||||||
|
walletAddress: string
|
||||||
|
): Promise<any[] | undefined> => {
|
||||||
|
const provider = getProvider();
|
||||||
|
if (!provider) return;
|
||||||
|
|
||||||
|
const signer = provider.getSigner();
|
||||||
|
const p2pContract = new ethers.Contract(addresses.p2pix, p2pix.abi, signer);
|
||||||
|
|
||||||
|
const filterDeposits = p2pContract.filters.DepositAdded([walletAddress]);
|
||||||
|
const eventsDeposits = await p2pContract.queryFilter(filterDeposits);
|
||||||
|
|
||||||
|
return eventsDeposits.sort((a, b) => {
|
||||||
|
return b.blockNumber - a.blockNumber;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// get wallet's lock transactions
|
||||||
|
const listLockTransactionByWalletAddress = async (
|
||||||
|
walletAddress: string
|
||||||
|
): Promise<any[] | undefined> => {
|
||||||
|
const provider = getProvider();
|
||||||
|
if (!provider) return;
|
||||||
|
|
||||||
|
const signer = provider.getSigner();
|
||||||
|
const p2pContract = new ethers.Contract(addresses.p2pix, p2pix.abi, signer);
|
||||||
|
|
||||||
|
const filterAddedLocks = p2pContract.filters.LockAdded([walletAddress]);
|
||||||
|
const eventsAddedLocks = await p2pContract.queryFilter(filterAddedLocks);
|
||||||
|
|
||||||
|
return eventsAddedLocks.sort((a, b) => {
|
||||||
|
return b.blockNumber - a.blockNumber;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// get wallet's release transactions
|
||||||
|
const listReleaseTransactionByWalletAddress = async (
|
||||||
|
walletAddress: string
|
||||||
|
): Promise<any[] | undefined> => {
|
||||||
|
const provider = getProvider();
|
||||||
|
if (!provider) return;
|
||||||
|
|
||||||
|
const signer = provider.getSigner();
|
||||||
|
const p2pContract = new ethers.Contract(addresses.p2pix, p2pix.abi, signer);
|
||||||
|
|
||||||
|
const filterReleasedLocks = p2pContract.filters.LockReleased([walletAddress]);
|
||||||
|
const eventsReleasedLocks = await p2pContract.queryFilter(
|
||||||
|
filterReleasedLocks
|
||||||
|
);
|
||||||
|
|
||||||
|
return eventsReleasedLocks.sort((a, b) => {
|
||||||
|
return b.blockNumber - a.blockNumber;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Update events at store methods
|
||||||
|
const updateValidDeposits = async () => {
|
||||||
|
const etherStore = useEtherStore();
|
||||||
|
const window_ = window as any;
|
||||||
|
const connection = window_.ethereum;
|
||||||
|
let provider: ethers.providers.Web3Provider | null = null;
|
||||||
|
if (!connection) return;
|
||||||
|
provider = new ethers.providers.Web3Provider(connection);
|
||||||
|
const signer = provider.getSigner();
|
||||||
|
const p2pContract = new ethers.Contract(addresses.p2pix, p2pix.abi, signer);
|
||||||
|
|
||||||
|
const filterDeposits = p2pContract.filters.DepositAdded(null);
|
||||||
|
const eventsDeposits = await p2pContract.queryFilter(filterDeposits);
|
||||||
|
|
||||||
|
const depositList = [] as any[];
|
||||||
|
|
||||||
|
eventsDeposits.forEach(async (deposit) => {
|
||||||
|
const mappedDeposit = await mapDeposits(deposit.args?.depositID);
|
||||||
|
|
||||||
|
const validDeposit = {
|
||||||
|
depositID: deposit.args?.depositID,
|
||||||
|
remaining: formatBigNumber(mappedDeposit.remaining),
|
||||||
|
seller: mappedDeposit.seller,
|
||||||
|
pixKey: mappedDeposit.pixTarget,
|
||||||
|
valid: mappedDeposit.valid,
|
||||||
|
};
|
||||||
|
|
||||||
|
depositList.push(validDeposit);
|
||||||
|
});
|
||||||
|
|
||||||
|
etherStore.setDepositsValidList(depositList);
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateDepositAddedEvents = async () => {
|
||||||
|
const etherStore = useEtherStore();
|
||||||
|
const window_ = window as any;
|
||||||
|
const connection = window_.ethereum;
|
||||||
|
let provider: ethers.providers.Web3Provider | null = null;
|
||||||
|
|
||||||
|
if (!connection) return;
|
||||||
|
provider = new ethers.providers.Web3Provider(connection);
|
||||||
|
|
||||||
|
const signer = provider.getSigner();
|
||||||
|
const p2pContract = new ethers.Contract(addresses.p2pix, p2pix.abi, signer);
|
||||||
|
|
||||||
|
const filterDeposits = p2pContract.filters.DepositAdded(null);
|
||||||
|
const eventsDeposits = await p2pContract.queryFilter(filterDeposits);
|
||||||
etherStore.setDepositsAddedList(eventsDeposits);
|
etherStore.setDepositsAddedList(eventsDeposits);
|
||||||
|
};
|
||||||
|
|
||||||
const filterLocks = p2pEvents.filters.LockAdded(null);
|
const updateLockAddedEvents = async () => {
|
||||||
const eventsLocks = await p2pEvents.queryFilter(filterLocks);
|
const etherStore = useEtherStore();
|
||||||
console.log("Locks Added: ", eventsLocks);
|
const window_ = window as any;
|
||||||
|
const connection = window_.ethereum;
|
||||||
|
let provider: ethers.providers.Web3Provider | null = null;
|
||||||
|
|
||||||
|
if (!connection) return;
|
||||||
|
provider = new ethers.providers.Web3Provider(connection);
|
||||||
|
|
||||||
|
const signer = provider.getSigner();
|
||||||
|
const p2pContract = new ethers.Contract(addresses.p2pix, p2pix.abi, signer);
|
||||||
|
|
||||||
|
const filterLocks = p2pContract.filters.LockAdded(null);
|
||||||
|
const eventsLocks = await p2pContract.queryFilter(filterLocks);
|
||||||
etherStore.setLocksAddedList(eventsLocks);
|
etherStore.setLocksAddedList(eventsLocks);
|
||||||
|
};
|
||||||
|
|
||||||
const filterExpiredLocks = p2pEvents.filters.LockReturned(null);
|
const updateLockReleasedEvents = async () => {
|
||||||
const eventsExpiredLocks = await p2pEvents.queryFilter(filterExpiredLocks);
|
const etherStore = useEtherStore();
|
||||||
console.log("Expired Locks: ", eventsExpiredLocks);
|
const window_ = window as any;
|
||||||
etherStore.setDepositsExpiredList(eventsExpiredLocks);
|
const connection = window_.ethereum;
|
||||||
|
let provider: ethers.providers.Web3Provider | null = null;
|
||||||
|
|
||||||
// (TO DO) Filter valid deposits
|
if (!connection) return;
|
||||||
|
provider = new ethers.providers.Web3Provider(connection);
|
||||||
|
|
||||||
connection.on("accountsChanged", (accounts: string[]) => {
|
const signer = provider.getSigner();
|
||||||
updateWalletStatus(accounts[0]);
|
const p2pContract = new ethers.Contract(addresses.p2pix, p2pix.abi, signer);
|
||||||
|
|
||||||
|
const filterLocks = p2pContract.filters.LockReleased(null);
|
||||||
|
const eventsLocks = await p2pContract.queryFilter(filterLocks);
|
||||||
|
etherStore.setLocksReleasedList(eventsLocks);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Provider methods
|
||||||
|
const connectProvider = async () => {
|
||||||
|
const window_ = window as any;
|
||||||
|
const connection = window_.ethereum;
|
||||||
|
|
||||||
|
await updateWalletStatus();
|
||||||
|
await updateDepositAddedEvents();
|
||||||
|
await updateLockAddedEvents();
|
||||||
|
await updateLockReleasedEvents();
|
||||||
|
await updateValidDeposits();
|
||||||
|
|
||||||
|
connection.on("accountsChanged", async () => {
|
||||||
|
await updateWalletStatus();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -63,49 +240,14 @@ const getProvider = (): ethers.providers.Web3Provider | null => {
|
|||||||
return new ethers.providers.Web3Provider(connection);
|
return new ethers.providers.Web3Provider(connection);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Wallet methods
|
|
||||||
// Update wallet state (balance and address)
|
|
||||||
const updateWalletStatus = async (walletAddress: string) => {
|
|
||||||
const etherStore = useEtherStore();
|
|
||||||
const provider = getProvider();
|
|
||||||
if (!provider) return;
|
|
||||||
|
|
||||||
const signer = provider.getSigner();
|
|
||||||
const contract = new ethers.Contract(addresses.token, mockToken.abi, signer);
|
|
||||||
|
|
||||||
const balance = await contract.balanceOf(walletAddress);
|
|
||||||
|
|
||||||
etherStore.setBalance(String(balance));
|
|
||||||
etherStore.setWalletAddress(ethers.utils.getAddress(walletAddress));
|
|
||||||
};
|
|
||||||
|
|
||||||
// Split tokens between wallets in wallets.json
|
|
||||||
const splitTokens = async () => {
|
|
||||||
const etherStore = useEtherStore();
|
|
||||||
const provider = getProvider();
|
|
||||||
if (!provider) return;
|
|
||||||
|
|
||||||
const signer = provider.getSigner();
|
|
||||||
const contract = new ethers.Contract(addresses.token, mockToken.abi, signer);
|
|
||||||
|
|
||||||
for (let i = 0; i < wallets.length; i++) {
|
|
||||||
const tx = await contract.transfer(
|
|
||||||
wallets[i],
|
|
||||||
ethers.utils.parseEther("4000000.0")
|
|
||||||
);
|
|
||||||
await tx.wait();
|
|
||||||
updateWalletStatus(etherStore.walletAddress);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Deposit methods
|
// Deposit methods
|
||||||
// Gets value and pix key from user's form to create a deposit in the blockchain
|
// Gets value and pix key from user's form to create a deposit in the blockchain
|
||||||
const addDeposit = async (tokenQty = "1000.0", pixKey = "00011122233") => {
|
const addDeposit = async (tokenQty: Number, pixKey: string) => {
|
||||||
const etherStore = useEtherStore();
|
|
||||||
const provider = getProvider();
|
const provider = getProvider();
|
||||||
|
|
||||||
if (!provider) return;
|
if (!provider) return;
|
||||||
|
|
||||||
const signer = provider.getSigner();
|
const signer = provider.getSigner();
|
||||||
|
|
||||||
const tokenContract = new ethers.Contract(
|
const tokenContract = new ethers.Contract(
|
||||||
addresses.token,
|
addresses.token,
|
||||||
mockToken.abi,
|
mockToken.abi,
|
||||||
@ -116,44 +258,39 @@ const addDeposit = async (tokenQty = "1000.0", pixKey = "00011122233") => {
|
|||||||
// First get the approval
|
// First get the approval
|
||||||
const apprv = await tokenContract.approve(
|
const apprv = await tokenContract.approve(
|
||||||
addresses.p2pix,
|
addresses.p2pix,
|
||||||
ethers.utils.parseEther(tokenQty)
|
formatEther(String(tokenQty))
|
||||||
);
|
);
|
||||||
await apprv.wait();
|
await apprv.wait();
|
||||||
|
|
||||||
// Now we make the deposit
|
// Now we make the deposit
|
||||||
const deposit = await p2pContract.deposit(
|
const deposit = await p2pContract.deposit(
|
||||||
addresses.token,
|
addresses.token,
|
||||||
ethers.utils.parseEther(tokenQty),
|
formatEther(String(tokenQty)),
|
||||||
pixKey
|
pixKey
|
||||||
);
|
);
|
||||||
await deposit.wait();
|
await deposit.wait();
|
||||||
|
|
||||||
updateWalletStatus(etherStore.walletAddress);
|
await updateWalletStatus();
|
||||||
|
await updateDepositAddedEvents();
|
||||||
const p2pEvents = new ethers.Contract(addresses.p2pix, p2pix.abi, signer);
|
await updateValidDeposits();
|
||||||
const filter = p2pEvents.filters.DepositAdded(null);
|
|
||||||
const events = await p2pEvents.queryFilter(filter);
|
|
||||||
|
|
||||||
etherStore.setDepositsAddedList(events);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get specific deposit data by its ID
|
// Get specific deposit data by its ID
|
||||||
const mapDeposits = async (depositId: BigNumber) => {
|
const mapDeposits = async (depositId: BigNumber): Promise<any> => {
|
||||||
const provider = getProvider();
|
const provider = getProvider();
|
||||||
|
|
||||||
if (!provider) return;
|
if (!provider) return;
|
||||||
|
|
||||||
const signer = provider.getSigner();
|
const signer = provider.getSigner();
|
||||||
const contract = new ethers.Contract(addresses.p2pix, p2pix.abi, signer);
|
const contract = new ethers.Contract(addresses.p2pix, p2pix.abi, signer);
|
||||||
const deposit = await contract.mapDeposits(depositId.toNumber());
|
const deposit = await contract.mapDeposits(depositId);
|
||||||
|
|
||||||
console.log(deposit);
|
|
||||||
return deposit;
|
return deposit;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Lock methods
|
// Lock methods
|
||||||
// Gets value from user's form to create a lock in the blockchain
|
// Gets value from user's form to create a lock in the blockchain
|
||||||
const addLock = async (depositId: Number, amount: Number) => {
|
const addLock = async (depositId: BigNumber, amount: Number) => {
|
||||||
const etherStore = useEtherStore();
|
const etherStore = useEtherStore();
|
||||||
const provider = getProvider();
|
const provider = getProvider();
|
||||||
|
|
||||||
@ -162,18 +299,23 @@ const addLock = async (depositId: Number, amount: Number) => {
|
|||||||
const p2pContract = new ethers.Contract(addresses.p2pix, p2pix.abi, signer);
|
const p2pContract = new ethers.Contract(addresses.p2pix, p2pix.abi, signer);
|
||||||
|
|
||||||
// Make lock
|
// Make lock
|
||||||
await p2pContract.lock(
|
const oldEventsLen = etherStore.locksAddedList.length;
|
||||||
depositId,
|
const lock = await p2pContract.lock(
|
||||||
etherStore.walletAddress,
|
depositId, // BigNumber
|
||||||
ethers.constants.AddressZero,
|
etherStore.walletAddress, // String "0x70997970C51812dc3A010C7d01b50e0d17dc79C8" (Example)
|
||||||
|
ethers.constants.AddressZero, // String "0x0000000000000000000000000000000000000000"
|
||||||
0,
|
0,
|
||||||
ethers.utils.parseEther(amount.toString()),
|
formatEther(String(amount)), // BigNumber
|
||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
|
lock.wait();
|
||||||
|
|
||||||
const filterLocks = p2pContract.filters.LockAdded(null);
|
while (etherStore.locksAddedList.length === oldEventsLen) {
|
||||||
const eventsLocks = await p2pContract.queryFilter(filterLocks);
|
await updateLockAddedEvents();
|
||||||
etherStore.setLocksAddedList(eventsLocks);
|
await updateValidDeposits();
|
||||||
|
}
|
||||||
|
|
||||||
|
return lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get specific lock data by its ID
|
// Get specific lock data by its ID
|
||||||
@ -186,20 +328,53 @@ const mapLocks = async (lockId: string) => {
|
|||||||
const contract = new ethers.Contract(addresses.p2pix, p2pix.abi, signer);
|
const contract = new ethers.Contract(addresses.p2pix, p2pix.abi, signer);
|
||||||
const lock = await contract.mapLocks(lockId);
|
const lock = await contract.mapLocks(lockId);
|
||||||
|
|
||||||
console.log(lock);
|
|
||||||
return lock;
|
return lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Releases lock by specific ID and other additional data
|
// Releases lock by specific ID and other additional data
|
||||||
// (TO DO)
|
const releaseLock = async (
|
||||||
const releaseLock = async () => {
|
pixKey: string,
|
||||||
return;
|
amount: Number,
|
||||||
|
e2eId: string,
|
||||||
|
lockId: string
|
||||||
|
) => {
|
||||||
|
const provider = getProvider();
|
||||||
|
if (!provider) return;
|
||||||
|
|
||||||
|
const mockBacenSigner = new ethers.Wallet(
|
||||||
|
"0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"
|
||||||
|
);
|
||||||
|
|
||||||
|
const messageToSign = ethers.utils.solidityKeccak256(
|
||||||
|
["string", "uint256", "uint256"],
|
||||||
|
[pixKey, formatEther(String(amount)), formatEther(e2eId)]
|
||||||
|
);
|
||||||
|
|
||||||
|
const messageHashBytes = ethers.utils.arrayify(messageToSign);
|
||||||
|
const flatSig = await mockBacenSigner.signMessage(messageHashBytes);
|
||||||
|
const sig = ethers.utils.splitSignature(flatSig);
|
||||||
|
|
||||||
|
const signer = provider.getSigner();
|
||||||
|
const p2pContract = new ethers.Contract(addresses.p2pix, p2pix.abi, signer);
|
||||||
|
|
||||||
|
const release = await p2pContract.release(
|
||||||
|
lockId,
|
||||||
|
formatEther(e2eId),
|
||||||
|
sig.r,
|
||||||
|
sig.s,
|
||||||
|
sig.v
|
||||||
|
);
|
||||||
|
release.wait();
|
||||||
|
await updateLockReleasedEvents();
|
||||||
|
await updateValidDeposits();
|
||||||
|
|
||||||
|
return release;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Formatting methods
|
// Formatting methods
|
||||||
const formatEther = (balance: string) => {
|
const formatEther = (num: string) => {
|
||||||
const formatted = ethers.utils.formatEther(balance);
|
const formattedNum = ethers.utils.parseEther(num);
|
||||||
return formatted;
|
return formattedNum;
|
||||||
};
|
};
|
||||||
|
|
||||||
const formatBigNumber = (num: BigNumber) => {
|
const formatBigNumber = (num: BigNumber) => {
|
||||||
@ -210,11 +385,18 @@ const formatBigNumber = (num: BigNumber) => {
|
|||||||
export default {
|
export default {
|
||||||
connectProvider,
|
connectProvider,
|
||||||
formatEther,
|
formatEther,
|
||||||
|
updateWalletStatus,
|
||||||
splitTokens,
|
splitTokens,
|
||||||
|
listAllTransactionByWalletAddress,
|
||||||
|
listReleaseTransactionByWalletAddress,
|
||||||
|
listDepositTransactionByWalletAddress,
|
||||||
|
listLockTransactionByWalletAddress,
|
||||||
addDeposit,
|
addDeposit,
|
||||||
mapDeposits,
|
mapDeposits,
|
||||||
formatBigNumber,
|
formatBigNumber,
|
||||||
addLock,
|
addLock,
|
||||||
mapLocks,
|
mapLocks,
|
||||||
releaseLock,
|
releaseLock,
|
||||||
|
updateLockAddedEvents,
|
||||||
|
updateValidDeposits,
|
||||||
};
|
};
|
||||||
|
@ -270,6 +270,25 @@
|
|||||||
"stateMutability": "pure",
|
"stateMutability": "pure",
|
||||||
"type": "function"
|
"type": "function"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "_addr",
|
||||||
|
"type": "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "_castAddrToKey",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "_key",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "pure",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"inputs": [
|
"inputs": [
|
||||||
{
|
{
|
||||||
|
@ -1,65 +1,88 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import SearchComponent from "../components/SearchComponent.vue";
|
import SearchComponent from "../components/SearchComponent.vue";
|
||||||
import ValidationComponent from "../components/ValidationComponent.vue";
|
import ValidationComponent from "../components/LoadingComponent.vue";
|
||||||
|
import ListComponent from "@/components/ListComponent.vue";
|
||||||
import blockchain from "../utils/blockchain";
|
import blockchain from "../utils/blockchain";
|
||||||
import { ref } from "vue";
|
import { ref } from "vue";
|
||||||
|
|
||||||
// (TO DO) Tirar isso tudo daqui
|
|
||||||
import p2pix from "../utils/smart_contract_files/P2PIX.json";
|
|
||||||
import addresses from "../utils/smart_contract_files/localhost.json";
|
|
||||||
import { useEtherStore } from "@/store/ether";
|
import { useEtherStore } from "@/store/ether";
|
||||||
import { ethers } from "ethers";
|
|
||||||
import QrCodeComponent from "../components/QrCodeComponent.vue";
|
import QrCodeComponent from "../components/QrCodeComponent.vue";
|
||||||
import { storeToRefs } from "pinia";
|
import { storeToRefs } from "pinia";
|
||||||
|
|
||||||
enum Step {
|
enum Step {
|
||||||
Search,
|
Search,
|
||||||
Buy,
|
Buy,
|
||||||
|
List,
|
||||||
}
|
}
|
||||||
|
|
||||||
// States
|
// States
|
||||||
const etherStore = useEtherStore();
|
const etherStore = useEtherStore();
|
||||||
const { loadingLock } = storeToRefs(etherStore);
|
const { loadingLock, walletAddress, locksAddedList } = storeToRefs(etherStore);
|
||||||
const flowStep = ref<Step>(Step.Search);
|
const flowStep = ref<Step>(Step.Search);
|
||||||
const pixTarget = ref<string>("");
|
const pixTarget = ref<string>("");
|
||||||
const tokens = ref<number>();
|
const tokenAmount = ref<number>();
|
||||||
|
const lockTransactionHash = ref<string>("");
|
||||||
|
const lockId = ref<string>("");
|
||||||
|
const loadingRelease = ref<Boolean>(false);
|
||||||
|
const lastWalletReleaseTransactions = ref<any[] | undefined>([]);
|
||||||
|
|
||||||
const confirmBuyClick = async ({ selectedDeposit, tokenValue }: any) => {
|
const confirmBuyClick = async ({ selectedDeposit, tokenValue }: any) => {
|
||||||
// finish buy screen
|
// finish buy screen
|
||||||
console.log(selectedDeposit);
|
const depositDetail = selectedDeposit;
|
||||||
let depositDetail;
|
const depositId = selectedDeposit.depositID;
|
||||||
const depositId = selectedDeposit["args"]["depositID"];
|
pixTarget.value = selectedDeposit.pixKey;
|
||||||
await blockchain
|
tokenAmount.value = tokenValue;
|
||||||
.mapDeposits(depositId)
|
// depositId is BigNumber type object
|
||||||
.then((deposit) => (depositDetail = deposit));
|
tokenAmount.value = tokenValue;
|
||||||
tokens.value = tokenValue;
|
|
||||||
pixTarget.value = depositDetail?.pixTarget;
|
pixTarget.value = String(depositDetail?.pixTarget);
|
||||||
|
|
||||||
// Makes lock with deposit ID and the Amount
|
// Makes lock with deposit ID and the Amount
|
||||||
if (depositDetail) {
|
if (depositDetail) {
|
||||||
flowStep.value = Step.Buy;
|
flowStep.value = Step.Buy;
|
||||||
etherStore.setLoadingLock(true);
|
etherStore.setLoadingLock(true);
|
||||||
|
|
||||||
await blockchain.addLock(depositId, tokenValue).catch(() => {
|
await blockchain
|
||||||
flowStep.value = Step.Search;
|
.addLock(depositId, tokenValue)
|
||||||
});
|
.then((lock) => {
|
||||||
|
lockTransactionHash.value = lock.hash;
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
flowStep.value = Step.Search;
|
||||||
|
});
|
||||||
|
|
||||||
// (TO DO) Tirar isso daqui
|
|
||||||
const window_ = window as any;
|
|
||||||
const connection = window_.ethereum;
|
|
||||||
let provider: ethers.providers.Web3Provider | null = null;
|
|
||||||
if (!connection) return;
|
|
||||||
provider = new ethers.providers.Web3Provider(connection);
|
|
||||||
const signer = provider.getSigner();
|
|
||||||
const p2pContract = new ethers.Contract(addresses.p2pix, p2pix.abi, signer);
|
|
||||||
const filterLocks = p2pContract.filters.LockAdded(null);
|
|
||||||
const eventsLocks = await p2pContract.queryFilter(filterLocks);
|
|
||||||
etherStore.setLocksAddedList(eventsLocks);
|
|
||||||
etherStore.setLoadingLock(false);
|
etherStore.setLoadingLock(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Data to QRCode
|
const releaseTransaction = async ({ e2eId }: any) => {
|
||||||
// Chave Pix = depositDetail.pixTarget
|
flowStep.value = Step.List;
|
||||||
// Valor = tokenValue
|
loadingRelease.value = true;
|
||||||
|
|
||||||
|
const findLock = locksAddedList.value.find((element) => {
|
||||||
|
if (element.transactionHash === lockTransactionHash.value) {
|
||||||
|
lockId.value = element.args.lockID;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (findLock && tokenAmount.value) {
|
||||||
|
const release = await blockchain.releaseLock(
|
||||||
|
pixTarget.value,
|
||||||
|
tokenAmount.value,
|
||||||
|
e2eId,
|
||||||
|
lockId.value
|
||||||
|
);
|
||||||
|
release.wait();
|
||||||
|
|
||||||
|
lastWalletReleaseTransactions.value =
|
||||||
|
await blockchain.listReleaseTransactionByWalletAddress(
|
||||||
|
walletAddress.value.toLowerCase()
|
||||||
|
);
|
||||||
|
|
||||||
|
await blockchain.updateWalletStatus();
|
||||||
|
loadingRelease.value = false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
@ -72,10 +95,26 @@ const confirmBuyClick = async ({ selectedDeposit, tokenValue }: any) => {
|
|||||||
<div v-if="flowStep == Step.Buy">
|
<div v-if="flowStep == Step.Buy">
|
||||||
<QrCodeComponent
|
<QrCodeComponent
|
||||||
:pixTarget="pixTarget"
|
:pixTarget="pixTarget"
|
||||||
:tokenValue="tokens"
|
:tokenValue="tokenAmount"
|
||||||
|
@pix-validated="releaseTransaction"
|
||||||
v-if="!loadingLock"
|
v-if="!loadingLock"
|
||||||
/>
|
/>
|
||||||
<ValidationComponent v-if="loadingLock" />
|
<ValidationComponent
|
||||||
|
v-if="loadingLock"
|
||||||
|
:message="'A transação está sendo enviada para a rede'"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div v-if="flowStep == Step.List">
|
||||||
|
<ListComponent
|
||||||
|
v-if="!loadingRelease"
|
||||||
|
:last-wallet-release-transactions="lastWalletReleaseTransactions"
|
||||||
|
:tokenAmount="tokenAmount"
|
||||||
|
@make-another-transaction="flowStep = Step.Search"
|
||||||
|
/>
|
||||||
|
<ValidationComponent
|
||||||
|
v-if="loadingRelease"
|
||||||
|
:message="'A transação está sendo enviada para a rede. Em breve os tokens serão depositados em sua carteira.'"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
98
src/views/ListView.vue
Normal file
98
src/views/ListView.vue
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import CustomButton from "@/components/CustomButton.vue";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="page">
|
||||||
|
<div class="text-container">
|
||||||
|
<span class="text font-extrabold text-5xl max-w-[50rem]"
|
||||||
|
>Os tokens já foram transferidos <br />
|
||||||
|
para a sua carteira!
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="blur-container">
|
||||||
|
<div
|
||||||
|
class="flex flex-col w-full bg-white px-10 py-5 rounded-lg border-y-10"
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<p>Tokens recebidos</p>
|
||||||
|
<p class="text-2xl text-gray-900">100 BRZ</p>
|
||||||
|
</div>
|
||||||
|
<div class="my-5">
|
||||||
|
<p>
|
||||||
|
<b>Não encontrou os tokens? </b>Clique no botão abaixo para <br />
|
||||||
|
cadastrar o BRZ em sua carteira.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<CustomButton
|
||||||
|
:text="'Cadastrar token na carteira'"
|
||||||
|
@buttonClicked="() => {}"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="blur-container-row">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="border-amber-500 border-2 rounded default-button text-white p-2 px-50 w-full"
|
||||||
|
@click="() => {}"
|
||||||
|
>
|
||||||
|
Fazer nova transação
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="border-amber-500 border-2 rounded default-button text-white p-2"
|
||||||
|
@click="() => {}"
|
||||||
|
>
|
||||||
|
Desconectar
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="text-container mt-10">
|
||||||
|
<span class="text font-extrabold text-3xl max-w-[50rem]"
|
||||||
|
>Últimas transações
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="blur-container">
|
||||||
|
<div class="flex flex-row justify-between w-full bg-white p-5 rounded-lg">
|
||||||
|
<p>100 BRZ</p>
|
||||||
|
<p>20 out 2022</p>
|
||||||
|
<p>Etherscan</p>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-row justify-between w-full bg-white p-5 rounded-lg">
|
||||||
|
<p>100 BRZ</p>
|
||||||
|
<p>20 out 2022</p>
|
||||||
|
<p>Etherscan</p>
|
||||||
|
</div>
|
||||||
|
<p class="text-white mt-2 cursor-pointer">Carregar mais</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.page {
|
||||||
|
@apply flex flex-col items-center justify-center w-full mt-16;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-container {
|
||||||
|
@apply flex flex-col items-center justify-center gap-4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text {
|
||||||
|
@apply text-gray-800 text-center;
|
||||||
|
}
|
||||||
|
.blur-container-row {
|
||||||
|
@apply flex flex-row justify-center items-center px-8 py-6 gap-2 rounded-lg shadow-md shadow-gray-600 backdrop-blur-md mt-8 w-1/3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.blur-container {
|
||||||
|
@apply flex flex-col justify-center items-center px-8 py-6 gap-2 rounded-lg shadow-md shadow-gray-600 backdrop-blur-md mt-8 w-1/3;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="number"] {
|
||||||
|
-moz-appearance: textfield;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="number"]::-webkit-inner-spin-button,
|
||||||
|
input[type="number"]::-webkit-outer-spin-button {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
}
|
||||||
|
</style>
|
@ -7,6 +7,7 @@ import blockchain from "../utils/blockchain";
|
|||||||
|
|
||||||
// Blockchain Data
|
// Blockchain Data
|
||||||
const etherStore = useEtherStore();
|
const etherStore = useEtherStore();
|
||||||
|
const { depositsValidList } = storeToRefs(etherStore);
|
||||||
const { depositsAddedList } = storeToRefs(etherStore);
|
const { depositsAddedList } = storeToRefs(etherStore);
|
||||||
const { locksAddedList } = storeToRefs(etherStore);
|
const { locksAddedList } = storeToRefs(etherStore);
|
||||||
|
|
||||||
@ -15,7 +16,7 @@ const depositValue = ref<Number>();
|
|||||||
const depositPixKey = ref<string>("");
|
const depositPixKey = ref<string>("");
|
||||||
|
|
||||||
// Split tokens between wallets in wallets.json
|
// Split tokens between wallets in wallets.json
|
||||||
const splitTokens = () => {
|
const splitTokens = async () => {
|
||||||
blockchain.splitTokens();
|
blockchain.splitTokens();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -35,23 +36,20 @@ const formatWalletAddress = (wallet: string): string => {
|
|||||||
// Gets value and pix key from user's form to create a deposit in the blockchain
|
// Gets value and pix key from user's form to create a deposit in the blockchain
|
||||||
const mockDeposit = () => {
|
const mockDeposit = () => {
|
||||||
if (!depositValue.value || !depositPixKey.value) return;
|
if (!depositValue.value || !depositPixKey.value) return;
|
||||||
blockchain.addDeposit(depositValue.value.toString(), depositPixKey.value);
|
blockchain.addDeposit(depositValue.value, depositPixKey.value);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get specific deposit data by its ID
|
// Get specific deposit data by its ID
|
||||||
const mapDeposit = (depositId: BigNumber) => {
|
const mapDeposit = (depositId: BigNumber) => {
|
||||||
blockchain.mapDeposits(depositId);
|
const deposit = blockchain.mapDeposits(depositId);
|
||||||
|
return deposit;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Lock methods
|
// Lock methods
|
||||||
// (TO DO) Releases lock by specific ID and other additional data
|
|
||||||
const releaseLock = () => {
|
|
||||||
blockchain.releaseLock();
|
|
||||||
};
|
|
||||||
|
|
||||||
// Get specific lock data by its ID
|
// Get specific lock data by its ID
|
||||||
const mapLock = (lockId: string) => {
|
const mapLock = (lockId: string) => {
|
||||||
blockchain.mapLocks(lockId);
|
const lock = blockchain.mapLocks(lockId);
|
||||||
|
return lock;
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -81,10 +79,6 @@ const mapLock = (lockId: string) => {
|
|||||||
<button type="button" class="default-button" @click="splitTokens()">
|
<button type="button" class="default-button" @click="splitTokens()">
|
||||||
Dividir tokens
|
Dividir tokens
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button type="button" class="default-button" @click="releaseLock()">
|
|
||||||
Release Lock
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ul class="flex flex-col justify-center items-center gap-4">
|
<ul class="flex flex-col justify-center items-center gap-4">
|
||||||
@ -95,7 +89,7 @@ const mapLock = (lockId: string) => {
|
|||||||
@click="mapDeposit(deposit.args.depositID)"
|
@click="mapDeposit(deposit.args.depositID)"
|
||||||
>
|
>
|
||||||
Seller:<br />{{ formatWalletAddress(deposit.args.seller) }}<br />
|
Seller:<br />{{ formatWalletAddress(deposit.args.seller) }}<br />
|
||||||
MRBZ: {{ blockchain.formatEther(deposit.args.amount) }}
|
MRBZ: {{ blockchain.formatBigNumber(deposit.args.amount) }}
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<ul class="flex flex-col justify-center items-center gap-4">
|
<ul class="flex flex-col justify-center items-center gap-4">
|
||||||
@ -106,7 +100,18 @@ const mapLock = (lockId: string) => {
|
|||||||
@click="mapLock(lock.args.lockID)"
|
@click="mapLock(lock.args.lockID)"
|
||||||
>
|
>
|
||||||
Buyer:<br />{{ formatWalletAddress(lock.args.buyer) }}<br />
|
Buyer:<br />{{ formatWalletAddress(lock.args.buyer) }}<br />
|
||||||
MRBZ: {{ blockchain.formatEther(lock.args.amount) }}
|
MRBZ: {{ blockchain.formatBigNumber(lock.args.amount) }}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<ul class="flex flex-col justify-center items-center gap-4">
|
||||||
|
<li
|
||||||
|
class="text-gray-900 font-semibold text-lg cursor-pointer border-2 border-amber-400 p-2 rounded-md bg-amber-200"
|
||||||
|
v-for="valid in depositsValidList"
|
||||||
|
:key="valid.depositID"
|
||||||
|
@click="mapDeposit(valid.depositID)"
|
||||||
|
>
|
||||||
|
Buyer:<br />{{ formatWalletAddress(valid.seller) }}<br />
|
||||||
|
MRBZ: {{ valid.remaining }}
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
60
src/views/SellerView.vue
Normal file
60
src/views/SellerView.vue
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import WantSellComponent from "../components/SellerSteps/WantSellComponent.vue";
|
||||||
|
import SendNetwork from "../components/SellerSteps/SendNetwork.vue";
|
||||||
|
import ValidationComponent from "../components/LoadingComponent.vue";
|
||||||
|
|
||||||
|
import { ref } from "vue";
|
||||||
|
import router from "@/router";
|
||||||
|
|
||||||
|
enum Step {
|
||||||
|
Search,
|
||||||
|
Sell,
|
||||||
|
Network,
|
||||||
|
}
|
||||||
|
|
||||||
|
const flowStep = ref<Step>(Step.Sell);
|
||||||
|
const loading = ref<boolean>(false);
|
||||||
|
|
||||||
|
const walletConnect = async () => {
|
||||||
|
flowStep.value = Step.Sell;
|
||||||
|
};
|
||||||
|
|
||||||
|
const approveTokens = async () => {
|
||||||
|
loading.value = true;
|
||||||
|
setTimeout(() => {
|
||||||
|
loading.value = false;
|
||||||
|
flowStep.value = Step.Network;
|
||||||
|
}, 2000);
|
||||||
|
};
|
||||||
|
|
||||||
|
const sendNetwork = async () => {
|
||||||
|
loading.value = true;
|
||||||
|
setTimeout(() => {
|
||||||
|
loading.value = false;
|
||||||
|
router.push("/");
|
||||||
|
}, 2000);
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<!-- <SellerSearchComponent
|
||||||
|
v-if="flowStep == Step.Search"
|
||||||
|
@token-buy="walletConnect"
|
||||||
|
/> -->
|
||||||
|
<div v-if="flowStep == Step.Sell">
|
||||||
|
<WantSellComponent v-if="!loading" @approve-tokens="approveTokens" />
|
||||||
|
<ValidationComponent
|
||||||
|
v-if="loading"
|
||||||
|
:message="'A transação está sendo enviada para a rede.'"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div v-if="flowStep == Step.Network">
|
||||||
|
<SendNetwork v-if="!loading" @send-network="sendNetwork" />
|
||||||
|
<ValidationComponent
|
||||||
|
v-if="loading"
|
||||||
|
:message="'A transação está sendo enviada para a rede.'"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped></style>
|
Loading…
x
Reference in New Issue
Block a user