Merge branch 'develop' of https://github.com/liftlearning/P2Pix-Front-End into faq
This commit is contained in:
commit
80e3296131
@ -1 +1,3 @@
|
|||||||
VITE_API_URL=http://localhost:8000/
|
VITE_API_URL=http://localhost:8000/
|
||||||
|
VITE_GOERLI_API_URL={GOERLI_API_URL_ALCHEMY}
|
||||||
|
VITE_MUMBAI_API_URL={MUMBAI_API_URL_ALCHEMY}
|
29
README.md
29
README.md
@ -6,9 +6,30 @@
|
|||||||
This application aims to create a democratic and secure solution for the purchase and sale of ERC20 tokens, through the PIX, integrating the functionalities of smart contracts (smart contracts) of the blockchain with a receipt by digital signature. Allowing the integration of national financial system transactions to public blockchains, dispensing with custody through intermediaries.
|
This application aims to create a democratic and secure solution for the purchase and sale of ERC20 tokens, through the PIX, integrating the functionalities of smart contracts (smart contracts) of the blockchain with a receipt by digital signature. Allowing the integration of national financial system transactions to public blockchains, dispensing with custody through intermediaries.
|
||||||
|
|
||||||
# Table of Contents
|
# Table of Contents
|
||||||
|
* [Metamask Tutorial](#metamask-tutorial)
|
||||||
* [Recommended IDE Setup](#recommended-ide-setup)
|
* [Recommended IDE Setup](#recommended-ide-setup)
|
||||||
* [Dependencies](#dependencies)
|
* [Dependencies](#dependencies)
|
||||||
* [Build Setup](#build-setup)
|
* [Build Setup](#build-setup)
|
||||||
|
## Metamask Tutorial
|
||||||
|
### Installation
|
||||||
|
|
||||||
|
Install the Metamask extension at https://metamask.io/download/
|
||||||
|
|
||||||
|
### Enable Testnets on Metamask
|
||||||
|
|
||||||
|
Go to Settings -> Advanced -> Show Testnets
|
||||||
|
|
||||||
|
Now you can select the Goerli testnet.
|
||||||
|
|
||||||
|
### Add Polygon Mumbai to your Metamask
|
||||||
|
|
||||||
|
To add the Mumbai network, follow the instructions at:
|
||||||
|
https://www.youtube.com/watch?v=Jegmru0Q0j4
|
||||||
|
|
||||||
|
### Import the MBRL token
|
||||||
|
|
||||||
|
Go to Import Tokens and paste the following address: `0x294003F602c321627152c6b7DED3EAb5bEa853Ee`
|
||||||
|
|
||||||
## Recommended IDE Setup
|
## Recommended IDE Setup
|
||||||
|
|
||||||
[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin).
|
[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin).
|
||||||
@ -31,12 +52,14 @@ See [Vite Configuration Reference](https://vitejs.dev/config/).
|
|||||||
|
|
||||||
## Dependencies
|
## Dependencies
|
||||||
|
|
||||||
### Smart Contract
|
|
||||||
It is necessary to be running the smart contract locally to have access to all the functionalities of the application. The smart contract repository and instructions on how to run it can be found at [https://github.com/doiim/p2pix-smart-contracts](https://github.com/doiim/p2pix-smart-contracts)
|
|
||||||
|
|
||||||
### API
|
### API
|
||||||
For full operation of the application, it is necessary to correctly configure the variable that points to the api in the .env file, in the repository there is an .env.example file, just rename it to just .env and modify the variable `VITE_API_URL`. The api can be run locally see [https://github.com/liftlearning/Pix-Explorer-Back-End](https://github.com/liftlearning/Pix-Explorer-Back-End), or it can be pointed to just her staging address: [https://p2pix-block-explorer-api-staging.vercel.app/](https://p2pix-block-explorer-api-staging.vercel.app/)
|
For full operation of the application, it is necessary to correctly configure the variable that points to the api in the .env file, in the repository there is an .env.example file, just rename it to just .env and modify the variable `VITE_API_URL`. The api can be run locally see [https://github.com/liftlearning/Pix-Explorer-Back-End](https://github.com/liftlearning/Pix-Explorer-Back-End), or it can be pointed to just her staging address: [https://p2pix-block-explorer-api-staging.vercel.app/](https://p2pix-block-explorer-api-staging.vercel.app/)
|
||||||
|
|
||||||
|
### Alchemy Keys
|
||||||
|
In the .env file, set `VITE_GOERLI_API_URL=https://eth-goerli.g.alchemy.com/v2/Zu9m4b2U_EzVU_zd-vgZDOleY8OF1DNP` and `VITE_MUMBAI_API_URL=https://polygon-mumbai.g.alchemy.com/v2/ZANeCqfj6VsXGpOH6gWAP6SIVIgD9Pwv`
|
||||||
|
|
||||||
|
You can also replace it with your own Alchemy Keys if you have one.
|
||||||
|
|
||||||
## Build Setup
|
## Build Setup
|
||||||
|
|
||||||
The application can be tested by its trial version [https://p2pix-staging.vercel.app/](https://p2pix-staging.vercel.app/), the only requirement is to be running the smart contract of local way. To run the application locally, there are two different ways:
|
The application can be tested by its trial version [https://p2pix-staging.vercel.app/](https://p2pix-staging.vercel.app/), the only requirement is to be running the smart contract of local way. To run the application locally, there are two different ways:
|
||||||
|
10686
package-lock.json
generated
10686
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -14,6 +14,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@headlessui/vue": "^1.7.3",
|
"@headlessui/vue": "^1.7.3",
|
||||||
"@heroicons/vue": "^2.0.12",
|
"@heroicons/vue": "^2.0.12",
|
||||||
|
"alchemy-sdk": "^2.3.0",
|
||||||
"axios": "^1.2.1",
|
"axios": "^1.2.1",
|
||||||
"crc": "^3.8.0",
|
"crc": "^3.8.0",
|
||||||
"marked": "^4.2.12",
|
"marked": "^4.2.12",
|
||||||
|
64
src/blockchain/addresses.ts
Normal file
64
src/blockchain/addresses.ts
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
import { useEtherStore } from "@/store/ether";
|
||||||
|
import { NetworkEnum } from "@/model/NetworkEnum";
|
||||||
|
|
||||||
|
const getTokenAddress = (): string => {
|
||||||
|
const etherStore = useEtherStore();
|
||||||
|
|
||||||
|
const possibleTokenAddresses: { [key: string]: string } = {
|
||||||
|
Ethereum: "0x294003F602c321627152c6b7DED3EAb5bEa853Ee",
|
||||||
|
Polygon: "0x294003F602c321627152c6b7DED3EAb5bEa853Ee",
|
||||||
|
};
|
||||||
|
|
||||||
|
return possibleTokenAddresses[etherStore.networkName];
|
||||||
|
};
|
||||||
|
|
||||||
|
const getP2PixAddress = (): string => {
|
||||||
|
const etherStore = useEtherStore();
|
||||||
|
|
||||||
|
const possibleP2PixAddresses: { [key: string]: string } = {
|
||||||
|
Ethereum: "0x5f3EFA9A90532914545CEf527C530658af87e196",
|
||||||
|
Polygon: "0x5f3EFA9A90532914545CEf527C530658af87e196",
|
||||||
|
};
|
||||||
|
|
||||||
|
return possibleP2PixAddresses[etherStore.networkName];
|
||||||
|
};
|
||||||
|
|
||||||
|
const getProviderUrl = (): string => {
|
||||||
|
const etherStore = useEtherStore();
|
||||||
|
|
||||||
|
const possibleProvidersUrls: { [key: string]: string } = {
|
||||||
|
Ethereum: import.meta.env.VITE_GOERLI_API_URL,
|
||||||
|
Polygon: import.meta.env.VITE_MUMBAI_API_URL,
|
||||||
|
};
|
||||||
|
|
||||||
|
return possibleProvidersUrls[etherStore.networkName];
|
||||||
|
};
|
||||||
|
|
||||||
|
const possibleChains: { [key: string]: NetworkEnum } = {
|
||||||
|
"0x5": NetworkEnum.ethereum,
|
||||||
|
"5": NetworkEnum.ethereum,
|
||||||
|
"0x13881": NetworkEnum.polygon,
|
||||||
|
"80001": NetworkEnum.polygon,
|
||||||
|
};
|
||||||
|
|
||||||
|
const network2Chain: { [key: string]: string } = {
|
||||||
|
Ethereum: "0x5",
|
||||||
|
Polygon: "0x13881",
|
||||||
|
Localhost: "0x7a69",
|
||||||
|
};
|
||||||
|
|
||||||
|
const isPossibleNetwork = (networkChain: string): boolean => {
|
||||||
|
if (Object.keys(possibleChains).includes(networkChain)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
export {
|
||||||
|
getTokenAddress,
|
||||||
|
getProviderUrl,
|
||||||
|
possibleChains,
|
||||||
|
network2Chain,
|
||||||
|
isPossibleNetwork,
|
||||||
|
getP2PixAddress,
|
||||||
|
};
|
94
src/blockchain/buyerMethods.ts
Normal file
94
src/blockchain/buyerMethods.ts
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
import { useEtherStore } from "@/store/ether";
|
||||||
|
|
||||||
|
import { getContract, getProvider } from "./provider";
|
||||||
|
import { getP2PixAddress } from "./addresses";
|
||||||
|
|
||||||
|
import p2pix from "../utils/smart_contract_files/P2PIX.json";
|
||||||
|
|
||||||
|
import { BigNumber, ethers } from "ethers";
|
||||||
|
import { parseEther } from "ethers/lib/utils";
|
||||||
|
|
||||||
|
const addLock = async (
|
||||||
|
depositId: BigNumber,
|
||||||
|
amount: number
|
||||||
|
): Promise<string> => {
|
||||||
|
const etherStore = useEtherStore();
|
||||||
|
|
||||||
|
const p2pContract = getContract();
|
||||||
|
|
||||||
|
const lock = await p2pContract.lock(
|
||||||
|
depositId, // BigNumber
|
||||||
|
etherStore.walletAddress, // String "0x70997970C51812dc3A010C7d01b50e0d17dc79C8" (Example)
|
||||||
|
ethers.constants.AddressZero, // String "0x0000000000000000000000000000000000000000"
|
||||||
|
0,
|
||||||
|
parseEther(String(amount)), // BigNumber
|
||||||
|
[],
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
|
||||||
|
const lock_rec = await lock.wait();
|
||||||
|
const [t] = lock_rec.events;
|
||||||
|
|
||||||
|
return t.args.lockID;
|
||||||
|
};
|
||||||
|
|
||||||
|
const releaseLock = async (
|
||||||
|
pixKey: string,
|
||||||
|
amount: number,
|
||||||
|
e2eId: string,
|
||||||
|
lockId: string
|
||||||
|
): Promise<any> => {
|
||||||
|
const mockBacenSigner = new ethers.Wallet(
|
||||||
|
"0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"
|
||||||
|
);
|
||||||
|
|
||||||
|
const messageToSign = ethers.utils.solidityKeccak256(
|
||||||
|
["string", "uint256", "bytes32"],
|
||||||
|
[
|
||||||
|
pixKey,
|
||||||
|
parseEther(String(amount)),
|
||||||
|
ethers.utils.formatBytes32String(e2eId),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
const messageHashBytes = ethers.utils.arrayify(messageToSign);
|
||||||
|
const flatSig = await mockBacenSigner.signMessage(messageHashBytes);
|
||||||
|
const provider = getProvider();
|
||||||
|
|
||||||
|
const sig = ethers.utils.splitSignature(flatSig);
|
||||||
|
|
||||||
|
const signer = provider.getSigner();
|
||||||
|
const p2pContract = new ethers.Contract(getP2PixAddress(), p2pix.abi, signer);
|
||||||
|
|
||||||
|
const release = await p2pContract.release(
|
||||||
|
lockId,
|
||||||
|
ethers.constants.AddressZero,
|
||||||
|
ethers.utils.formatBytes32String(e2eId),
|
||||||
|
sig.r,
|
||||||
|
sig.s,
|
||||||
|
sig.v
|
||||||
|
);
|
||||||
|
await release.wait();
|
||||||
|
|
||||||
|
return release;
|
||||||
|
};
|
||||||
|
|
||||||
|
const cancelDeposit = async (depositId: BigNumber): Promise<any> => {
|
||||||
|
const contract = getContract();
|
||||||
|
|
||||||
|
const cancel = await contract.cancelDeposit(depositId);
|
||||||
|
await cancel.wait();
|
||||||
|
|
||||||
|
return cancel;
|
||||||
|
};
|
||||||
|
|
||||||
|
const withdrawDeposit = async (depositId: BigNumber): Promise<any> => {
|
||||||
|
const contract = getContract();
|
||||||
|
|
||||||
|
const withdraw = await contract.withdraw(depositId, []);
|
||||||
|
await withdraw.wait();
|
||||||
|
|
||||||
|
return withdraw;
|
||||||
|
};
|
||||||
|
|
||||||
|
export { cancelDeposit, withdrawDeposit, addLock, releaseLock };
|
84
src/blockchain/events.ts
Normal file
84
src/blockchain/events.ts
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
import { useEtherStore } from "@/store/ether";
|
||||||
|
import { Contract, ethers } from "ethers";
|
||||||
|
|
||||||
|
import p2pix from "../utils/smart_contract_files/P2PIX.json";
|
||||||
|
import { formatEther } from "ethers/lib/utils";
|
||||||
|
import { getContract } from "./provider";
|
||||||
|
import type { ValidDeposit } from "@/model/ValidDeposit";
|
||||||
|
|
||||||
|
const getNetworksLiquidity = async (): Promise<void> => {
|
||||||
|
const etherStore = useEtherStore();
|
||||||
|
console.log("Loading events");
|
||||||
|
|
||||||
|
const goerliProvider = new ethers.providers.JsonRpcProvider(
|
||||||
|
import.meta.env.VITE_GOERLI_API_URL,
|
||||||
|
5
|
||||||
|
); // goerli provider
|
||||||
|
const mumbaiProvider = new ethers.providers.JsonRpcProvider(
|
||||||
|
import.meta.env.VITE_MUMBAI_API_URL,
|
||||||
|
80001
|
||||||
|
); // mumbai provider
|
||||||
|
|
||||||
|
const p2pContractGoerli = new ethers.Contract(
|
||||||
|
"0x5f3EFA9A90532914545CEf527C530658af87e196",
|
||||||
|
p2pix.abi,
|
||||||
|
goerliProvider
|
||||||
|
);
|
||||||
|
const p2pContractMumbai = new ethers.Contract(
|
||||||
|
"0x5f3EFA9A90532914545CEf527C530658af87e196",
|
||||||
|
p2pix.abi,
|
||||||
|
mumbaiProvider
|
||||||
|
);
|
||||||
|
|
||||||
|
const depositListGoerli = await getValidDeposits(p2pContractGoerli);
|
||||||
|
|
||||||
|
const depositListMumbai = await getValidDeposits(p2pContractMumbai);
|
||||||
|
|
||||||
|
etherStore.setDepositsValidListGoerli(depositListGoerli);
|
||||||
|
console.log(depositListGoerli);
|
||||||
|
|
||||||
|
etherStore.setDepositsValidListMumbai(depositListMumbai);
|
||||||
|
console.log(depositListMumbai);
|
||||||
|
};
|
||||||
|
|
||||||
|
const getValidDeposits = async (
|
||||||
|
contract?: Contract
|
||||||
|
): Promise<ValidDeposit[]> => {
|
||||||
|
let p2pContract: Contract;
|
||||||
|
|
||||||
|
if (contract) {
|
||||||
|
p2pContract = contract;
|
||||||
|
} else {
|
||||||
|
p2pContract = getContract(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
const filterDeposits = p2pContract.filters.DepositAdded(null);
|
||||||
|
const eventsDeposits = await p2pContract.queryFilter(filterDeposits);
|
||||||
|
|
||||||
|
p2pContract = getContract(); // get metamask provider contract
|
||||||
|
|
||||||
|
const depositList = await Promise.all(
|
||||||
|
eventsDeposits.map(async (deposit) => {
|
||||||
|
const mappedDeposit = await p2pContract.mapDeposits(
|
||||||
|
deposit.args?.depositID
|
||||||
|
);
|
||||||
|
let validDeposit: ValidDeposit | null = null;
|
||||||
|
|
||||||
|
if (mappedDeposit.valid) {
|
||||||
|
validDeposit = {
|
||||||
|
blockNumber: deposit.blockNumber,
|
||||||
|
depositID: deposit.args?.depositID,
|
||||||
|
remaining: Number(formatEther(mappedDeposit.remaining)),
|
||||||
|
seller: mappedDeposit.seller,
|
||||||
|
pixKey: mappedDeposit.pixTarget,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return validDeposit;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
return depositList.filter((deposit) => deposit) as ValidDeposit[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export { getValidDeposits, getNetworksLiquidity };
|
95
src/blockchain/provider.ts
Normal file
95
src/blockchain/provider.ts
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
import { useEtherStore } from "@/store/ether";
|
||||||
|
|
||||||
|
import p2pix from "../utils/smart_contract_files/P2PIX.json";
|
||||||
|
|
||||||
|
import { updateWalletStatus } from "./wallet";
|
||||||
|
import {
|
||||||
|
getProviderUrl,
|
||||||
|
isPossibleNetwork,
|
||||||
|
possibleChains,
|
||||||
|
network2Chain,
|
||||||
|
getP2PixAddress,
|
||||||
|
} from "./addresses";
|
||||||
|
|
||||||
|
import { ethers } from "ethers";
|
||||||
|
|
||||||
|
const getProvider = (
|
||||||
|
onlyAlchemyProvider: boolean = false
|
||||||
|
): ethers.providers.Web3Provider | ethers.providers.JsonRpcProvider => {
|
||||||
|
const window_ = window as any;
|
||||||
|
const connection = window_.ethereum;
|
||||||
|
|
||||||
|
if (!connection || onlyAlchemyProvider)
|
||||||
|
return new ethers.providers.JsonRpcProvider(getProviderUrl()); // alchemy provider
|
||||||
|
|
||||||
|
return new ethers.providers.Web3Provider(connection); // metamask provider
|
||||||
|
};
|
||||||
|
|
||||||
|
const getContract = (onlyAlchemyProvider: boolean = false) => {
|
||||||
|
const provider = getProvider(onlyAlchemyProvider);
|
||||||
|
const signer = provider.getSigner();
|
||||||
|
return new ethers.Contract(getP2PixAddress(), p2pix.abi, signer);
|
||||||
|
};
|
||||||
|
|
||||||
|
const connectProvider = async (): Promise<void> => {
|
||||||
|
const window_ = window as any;
|
||||||
|
const connection = window_.ethereum;
|
||||||
|
const provider = getProvider();
|
||||||
|
|
||||||
|
if (!(provider instanceof ethers.providers.Web3Provider)) {
|
||||||
|
window.alert("Please, connect to metamask extension");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await updateWalletStatus();
|
||||||
|
|
||||||
|
listenToNetworkChange(connection);
|
||||||
|
listenToWalletChange(connection);
|
||||||
|
};
|
||||||
|
|
||||||
|
const listenToWalletChange = (connection: any): void => {
|
||||||
|
connection.on("accountsChanged", async () => {
|
||||||
|
console.log("Changed account!");
|
||||||
|
updateWalletStatus();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const listenToNetworkChange = (connection: any) => {
|
||||||
|
const etherStore = useEtherStore();
|
||||||
|
|
||||||
|
connection.on("chainChanged", (networkChain: string) => {
|
||||||
|
console.log("Changed network!");
|
||||||
|
|
||||||
|
if (isPossibleNetwork(networkChain)) {
|
||||||
|
etherStore.setNetworkName(possibleChains[networkChain]);
|
||||||
|
updateWalletStatus();
|
||||||
|
} else {
|
||||||
|
window.alert("Invalid chain!");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const requestNetworkChange = async (network: string): Promise<boolean> => {
|
||||||
|
const etherStore = useEtherStore();
|
||||||
|
if (!etherStore.walletAddress) return true;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const window_ = window as any;
|
||||||
|
await window_.ethereum.request({
|
||||||
|
method: "wallet_switchEthereumChain",
|
||||||
|
params: [{ chainId: network2Chain[network] }], // chainId must be in hexadecimal numbers
|
||||||
|
});
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
export {
|
||||||
|
getProvider,
|
||||||
|
getContract,
|
||||||
|
connectProvider,
|
||||||
|
listenToNetworkChange,
|
||||||
|
requestNetworkChange,
|
||||||
|
};
|
44
src/blockchain/sellerMethods.ts
Normal file
44
src/blockchain/sellerMethods.ts
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
import { getContract, getProvider } from "./provider";
|
||||||
|
import { getTokenAddress, getP2PixAddress } from "./addresses";
|
||||||
|
import { parseEther } from "ethers/lib/utils";
|
||||||
|
|
||||||
|
import { ethers } from "ethers";
|
||||||
|
|
||||||
|
import mockToken from "../utils/smart_contract_files/MockToken.json";
|
||||||
|
|
||||||
|
const approveTokens = async (tokenQty: string): Promise<any> => {
|
||||||
|
const provider = getProvider();
|
||||||
|
const signer = provider.getSigner();
|
||||||
|
|
||||||
|
const tokenContract = new ethers.Contract(
|
||||||
|
getTokenAddress(),
|
||||||
|
mockToken.abi,
|
||||||
|
signer
|
||||||
|
);
|
||||||
|
|
||||||
|
const apprv = await tokenContract.approve(
|
||||||
|
getP2PixAddress(),
|
||||||
|
parseEther(tokenQty)
|
||||||
|
);
|
||||||
|
|
||||||
|
await apprv.wait();
|
||||||
|
console.log(apprv);
|
||||||
|
return apprv;
|
||||||
|
};
|
||||||
|
|
||||||
|
const addDeposit = async (tokenQty: string, pixKey: string): Promise<any> => {
|
||||||
|
const p2pContract = getContract();
|
||||||
|
|
||||||
|
const deposit = await p2pContract.deposit(
|
||||||
|
getTokenAddress(),
|
||||||
|
parseEther(tokenQty),
|
||||||
|
pixKey,
|
||||||
|
ethers.utils.formatBytes32String("")
|
||||||
|
);
|
||||||
|
|
||||||
|
await deposit.wait();
|
||||||
|
|
||||||
|
return deposit;
|
||||||
|
};
|
||||||
|
|
||||||
|
export { approveTokens, addDeposit };
|
95
src/blockchain/wallet.ts
Normal file
95
src/blockchain/wallet.ts
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
import { useEtherStore } from "@/store/ether";
|
||||||
|
|
||||||
|
import { getContract, getProvider } from "./provider";
|
||||||
|
import { getTokenAddress, possibleChains } from "./addresses";
|
||||||
|
|
||||||
|
import mockToken from "../utils/smart_contract_files/MockToken.json";
|
||||||
|
|
||||||
|
import { ethers, type Event } from "ethers";
|
||||||
|
import { formatEther } from "ethers/lib/utils";
|
||||||
|
import { getValidDeposits } from "./events";
|
||||||
|
import type { ValidDeposit } from "@/model/ValidDeposit";
|
||||||
|
|
||||||
|
const updateWalletStatus = async (): Promise<void> => {
|
||||||
|
const etherStore = useEtherStore();
|
||||||
|
|
||||||
|
const provider = getProvider();
|
||||||
|
const signer = provider.getSigner();
|
||||||
|
|
||||||
|
const { chainId } = await provider.getNetwork();
|
||||||
|
etherStore.setNetworkName(possibleChains[chainId]);
|
||||||
|
|
||||||
|
const mockTokenContract = new ethers.Contract(
|
||||||
|
getTokenAddress(),
|
||||||
|
mockToken.abi,
|
||||||
|
signer
|
||||||
|
);
|
||||||
|
|
||||||
|
const walletAddress = await provider.send("eth_requestAccounts", []);
|
||||||
|
const balance = await mockTokenContract.balanceOf(walletAddress[0]);
|
||||||
|
|
||||||
|
etherStore.setBalance(formatEther(balance));
|
||||||
|
etherStore.setWalletAddress(ethers.utils.getAddress(walletAddress[0]));
|
||||||
|
};
|
||||||
|
|
||||||
|
const listValidDepositTransactionsByWalletAddress = async (
|
||||||
|
walletAddress: string
|
||||||
|
): Promise<ValidDeposit[]> => {
|
||||||
|
const walletDeposits = await getValidDeposits();
|
||||||
|
|
||||||
|
if (walletDeposits) {
|
||||||
|
return walletDeposits
|
||||||
|
.filter((deposit) => deposit.seller == walletAddress)
|
||||||
|
.sort((a, b) => {
|
||||||
|
return b.blockNumber - a.blockNumber;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return [];
|
||||||
|
};
|
||||||
|
|
||||||
|
const listAllTransactionByWalletAddress = async (
|
||||||
|
walletAddress: string
|
||||||
|
): Promise<Event[]> => {
|
||||||
|
const p2pContract = getContract();
|
||||||
|
|
||||||
|
const filterDeposits = p2pContract.filters.DepositAdded([walletAddress]);
|
||||||
|
const eventsDeposits = await p2pContract.queryFilter(filterDeposits);
|
||||||
|
|
||||||
|
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 release transactions
|
||||||
|
const listReleaseTransactionByWalletAddress = async (
|
||||||
|
walletAddress: string
|
||||||
|
): Promise<Event[]> => {
|
||||||
|
const p2pContract = getContract();
|
||||||
|
|
||||||
|
const filterReleasedLocks = p2pContract.filters.LockReleased([walletAddress]);
|
||||||
|
const eventsReleasedLocks = await p2pContract.queryFilter(
|
||||||
|
filterReleasedLocks
|
||||||
|
);
|
||||||
|
|
||||||
|
return eventsReleasedLocks.sort((a, b) => {
|
||||||
|
return b.blockNumber - a.blockNumber;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export {
|
||||||
|
updateWalletStatus,
|
||||||
|
listValidDepositTransactionsByWalletAddress,
|
||||||
|
listAllTransactionByWalletAddress,
|
||||||
|
listReleaseTransactionByWalletAddress,
|
||||||
|
};
|
@ -1,11 +1,12 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import CustomButton from "@/components/CustomButton.vue";
|
import CustomButton from "@/components/CustomButton.vue";
|
||||||
import ListingComponent from "@/components/ListingComponent.vue";
|
import ListingComponent from "@/components/ListingComponent.vue";
|
||||||
|
import type { Event } from "ethers";
|
||||||
|
|
||||||
// props
|
// props
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
lastWalletReleaseTransactions: any[];
|
lastWalletReleaseTransactions: Event[];
|
||||||
tokenAmount: Number | undefined;
|
tokenAmount: number | undefined;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
// Emits
|
// Emits
|
||||||
|
@ -1,42 +1,62 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import blockchain from "@/utils/blockchain";
|
import { NetworkEnum } from "@/model/NetworkEnum";
|
||||||
|
import type { ValidDeposit } from "@/model/ValidDeposit";
|
||||||
|
import { useEtherStore } from "@/store/ether";
|
||||||
|
import { formatEther } from "@ethersproject/units";
|
||||||
|
import type { Event } from "ethers";
|
||||||
import { ref, watch } from "vue";
|
import { ref, watch } from "vue";
|
||||||
|
|
||||||
// props
|
// props
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
walletTransactions: any[];
|
walletTransactions: (Event | ValidDeposit)[];
|
||||||
isManageMode: boolean;
|
isManageMode: boolean;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const itemsToShow = ref<any[]>([]);
|
const etherStore = useEtherStore();
|
||||||
|
|
||||||
|
const itemsToShow = ref<(Event | ValidDeposit)[]>([]);
|
||||||
|
|
||||||
// Methods
|
// Methods
|
||||||
const showInitialItems = () => {
|
const isValidDeposit = (
|
||||||
|
deposit: Event | ValidDeposit
|
||||||
|
): deposit is ValidDeposit => {
|
||||||
|
return (deposit as ValidDeposit).depositID !== undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
const showInitialItems = (): void => {
|
||||||
itemsToShow.value = props.walletTransactions.slice(0, 3);
|
itemsToShow.value = props.walletTransactions.slice(0, 3);
|
||||||
};
|
};
|
||||||
|
|
||||||
const formatEventsAmount = (amount: any) => {
|
const openEtherscanUrl = (transactionHash: string): void => {
|
||||||
try {
|
const networkUrl =
|
||||||
const formated = blockchain.formatBigNumber(amount);
|
etherStore.networkName == NetworkEnum.ethereum
|
||||||
return formated;
|
? "goerli.etherscan.io"
|
||||||
} catch {
|
: "mumbai.polygonscan.com";
|
||||||
return "";
|
const url = `https://${networkUrl}/tx/${transactionHash}`;
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const openEtherscanUrl = (url: string) => {
|
|
||||||
window.open(url, "_blank");
|
window.open(url, "_blank");
|
||||||
};
|
};
|
||||||
|
|
||||||
const loadMore = () => {
|
const loadMore = (): void => {
|
||||||
const itemsShowing = itemsToShow.value.length;
|
const itemsShowing = itemsToShow.value.length;
|
||||||
itemsToShow.value?.push(
|
itemsToShow.value?.push(
|
||||||
...props.walletTransactions.slice(itemsShowing, itemsShowing + 3)
|
...props.walletTransactions.slice(itemsShowing, itemsShowing + 3)
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getEventName = (event: string | undefined): string => {
|
||||||
|
if (!event) return "Desconhecido";
|
||||||
|
|
||||||
|
const possibleEventName: { [key: string]: string } = {
|
||||||
|
DepositAdded: "Oferta",
|
||||||
|
LockAdded: "Compra",
|
||||||
|
LockReleased: "Reserva",
|
||||||
|
};
|
||||||
|
|
||||||
|
return possibleEventName[event];
|
||||||
|
};
|
||||||
|
|
||||||
// watch props changes
|
// watch props changes
|
||||||
watch(props, async () => {
|
watch(props, async (): Promise<void> => {
|
||||||
const itemsToShowQty = itemsToShow.value.length;
|
const itemsToShowQty = itemsToShow.value.length;
|
||||||
if (itemsToShowQty == 0) showInitialItems();
|
if (itemsToShowQty == 0) showInitialItems();
|
||||||
else
|
else
|
||||||
@ -75,11 +95,11 @@ showInitialItems();
|
|||||||
<div
|
<div
|
||||||
class="grid grid-cols-4 grid-flow-row w-full bg-white px-6 py-4 rounded-lg"
|
class="grid grid-cols-4 grid-flow-row w-full bg-white px-6 py-4 rounded-lg"
|
||||||
v-for="(item, index) in itemsToShow"
|
v-for="(item, index) in itemsToShow"
|
||||||
:key="item.depositID"
|
:key="item.blockNumber"
|
||||||
>
|
>
|
||||||
<span class="last-release-info">
|
<span class="last-release-info">
|
||||||
{{
|
{{
|
||||||
item?.args ? formatEventsAmount(item?.args.amount) : item?.remaining
|
isValidDeposit(item) ? item.remaining : formatEther(item.args?.amount)
|
||||||
}}
|
}}
|
||||||
BRZ
|
BRZ
|
||||||
</span>
|
</span>
|
||||||
@ -87,55 +107,38 @@ showInitialItems();
|
|||||||
<!-- TODO: change this hardcoded date -->
|
<!-- TODO: change this hardcoded date -->
|
||||||
<span class="last-release-info"> 20 out 2022 </span>
|
<span class="last-release-info"> 20 out 2022 </span>
|
||||||
|
|
||||||
|
<span class="last-release-info" v-if="!props.isManageMode">
|
||||||
|
{{ getEventName((item as Event).event) }}
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-if="!props.isManageMode"
|
||||||
|
class="flex gap-2 cursor-pointer items-center justify-self-center"
|
||||||
|
@click="openEtherscanUrl((item as Event)?.transactionHash)"
|
||||||
|
>
|
||||||
|
<span class="last-release-info">Etherscan</span>
|
||||||
|
<img alt="Redirect image" src="@/assets/redirect.svg" />
|
||||||
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
v-if="props.isManageMode"
|
v-if="props.isManageMode"
|
||||||
class="flex gap-2 cursor-pointer items-center justify-self-center"
|
class="flex gap-2 cursor-pointer items-center justify-self-center"
|
||||||
@click="emit('cancelDeposit', item.depositID, index)"
|
@click="emit('cancelDeposit', (item as ValidDeposit).depositID, index)"
|
||||||
>
|
>
|
||||||
<span class="last-release-info">Cancelar</span>
|
<span class="last-release-info">Cancelar</span>
|
||||||
<img alt="Cancel image" src="@/assets/cancel.svg" />
|
<img alt="Cancel image" src="@/assets/cancel.svg" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span
|
|
||||||
class="last-release-info"
|
|
||||||
v-if="item.event == 'DepositAdded' && !props.isManageMode"
|
|
||||||
>
|
|
||||||
{{ "Oferta" }}
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<span
|
|
||||||
class="last-release-info"
|
|
||||||
v-if="item.event == 'LockAdded' && !props.isManageMode"
|
|
||||||
>
|
|
||||||
{{ "Reserva" }}
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<span
|
|
||||||
class="last-release-info"
|
|
||||||
v-if="item.event == 'LockReleased' && !props.isManageMode"
|
|
||||||
>
|
|
||||||
{{ "Compra" }}
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<div
|
<div
|
||||||
v-if="props.isManageMode"
|
v-if="props.isManageMode"
|
||||||
class="flex gap-2 cursor-pointer items-center justify-self-center"
|
class="flex gap-2 cursor-pointer items-center justify-self-center"
|
||||||
@click="emit('withdrawDeposit', item.depositID, index)"
|
@click="
|
||||||
|
emit('withdrawDeposit', (item as ValidDeposit).depositID, index)
|
||||||
|
"
|
||||||
>
|
>
|
||||||
<span class="last-release-info">Retirar</span>
|
<span class="last-release-info">Retirar</span>
|
||||||
<img alt="Cancel image" src="@/assets/withdraw.svg" />
|
<img alt="Cancel image" src="@/assets/withdraw.svg" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
|
||||||
v-if="!props.isManageMode"
|
|
||||||
class="flex gap-2 cursor-pointer items-center justify-self-center"
|
|
||||||
@click="
|
|
||||||
openEtherscanUrl(`https://etherscan.io/tx/${item?.transactionHash}`)
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<span class="last-release-info">Etherscan</span>
|
|
||||||
<img alt="Redirect image" src="@/assets/redirect.svg" />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="flex flex-col justify-center items-center w-full mt-2 gap-2"
|
class="flex flex-col justify-center items-center w-full mt-2 gap-2"
|
||||||
|
@ -24,19 +24,20 @@ const pixQrCode = pix({
|
|||||||
pixKey: props.pixTarget ?? "",
|
pixKey: props.pixTarget ?? "",
|
||||||
value: props.tokenValue,
|
value: props.tokenValue,
|
||||||
});
|
});
|
||||||
|
|
||||||
pixQrCode.base64QrCode().then((code: string) => {
|
pixQrCode.base64QrCode().then((code: string) => {
|
||||||
qrCode.value = code;
|
qrCode.value = code;
|
||||||
});
|
});
|
||||||
|
|
||||||
qrCodePayload.value = pixQrCode.payload();
|
qrCodePayload.value = pixQrCode.payload();
|
||||||
|
|
||||||
const handleInputEvent = (event: any) => {
|
const handleInputEvent = async (event: any): Promise<void> => {
|
||||||
const { value } = event.target;
|
const { value } = event.target;
|
||||||
e2eId.value = value;
|
e2eId.value = value;
|
||||||
validatePix();
|
await validatePix();
|
||||||
};
|
};
|
||||||
|
|
||||||
const validatePix = async () => {
|
const validatePix = async (): Promise<void> => {
|
||||||
if (e2eId.value == "") {
|
if (e2eId.value == "") {
|
||||||
isPixValid.value = false;
|
isPixValid.value = false;
|
||||||
isCodeInputEmpty.value = true;
|
isCodeInputEmpty.value = true;
|
||||||
@ -146,7 +147,7 @@ const validatePix = async () => {
|
|||||||
<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 })"
|
@button-clicked="emit('pixValidated', e2eId)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,41 +1,61 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from "vue";
|
import { ref, watch } from "vue";
|
||||||
import CustomButton from "../components/CustomButton.vue";
|
import CustomButton from "../components/CustomButton.vue";
|
||||||
import { debounce } from "@/utils/debounce";
|
import { debounce } from "@/utils/debounce";
|
||||||
import { useEtherStore } from "@/store/ether";
|
import { useEtherStore } from "@/store/ether";
|
||||||
import { storeToRefs } from "pinia";
|
import { storeToRefs } from "pinia";
|
||||||
import blockchain from "../utils/blockchain";
|
import { connectProvider } from "@/blockchain/provider";
|
||||||
|
import { verifyNetworkLiquidity } from "@/utils/networkLiquidity";
|
||||||
|
import { NetworkEnum } from "@/model/NetworkEnum";
|
||||||
|
import type { ValidDeposit } from "@/model/ValidDeposit";
|
||||||
|
import { decimalCount } from "@/utils/decimalCount";
|
||||||
|
|
||||||
// Store reference
|
// Store reference
|
||||||
const etherStore = useEtherStore();
|
const etherStore = useEtherStore();
|
||||||
|
|
||||||
const { walletAddress, depositsValidList } = storeToRefs(etherStore);
|
const {
|
||||||
|
walletAddress,
|
||||||
|
networkName,
|
||||||
|
depositsValidListGoerli,
|
||||||
|
depositsValidListMumbai,
|
||||||
|
} = storeToRefs(etherStore);
|
||||||
|
|
||||||
// Reactive state
|
// Reactive state
|
||||||
const tokenValue = ref(0);
|
const tokenValue = ref<number>(0);
|
||||||
const enableSelectButton = ref(false);
|
const enableConfirmButton = ref<boolean>(false);
|
||||||
const hasLiquidity = ref(true);
|
const enableWalletButton = ref<boolean>(false);
|
||||||
const validDecimals = ref(true);
|
const hasLiquidity = ref<boolean>(true);
|
||||||
const selectedDeposit = ref();
|
const validDecimals = ref<boolean>(true);
|
||||||
|
const selectedGoerliDeposit = ref<ValidDeposit>();
|
||||||
|
const selectedMumbaiDeposit = ref<ValidDeposit>();
|
||||||
|
|
||||||
// Emits
|
// Emits
|
||||||
const emit = defineEmits(["tokenBuy"]);
|
const emit = defineEmits(["tokenBuy"]);
|
||||||
|
|
||||||
// Blockchain methods
|
// Blockchain methods
|
||||||
const connectAccount = async () => {
|
const connectAccount = async (): Promise<void> => {
|
||||||
await blockchain.connectProvider();
|
await connectProvider();
|
||||||
verifyLiquidity();
|
|
||||||
|
enableOrDisableConfirmButton();
|
||||||
|
};
|
||||||
|
|
||||||
|
const emitConfirmButton = (): void => {
|
||||||
|
const selectedDeposit =
|
||||||
|
networkName.value == NetworkEnum.ethereum
|
||||||
|
? selectedGoerliDeposit.value
|
||||||
|
: selectedMumbaiDeposit.value;
|
||||||
|
emit("tokenBuy", selectedDeposit, tokenValue.value);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Debounce methods
|
// Debounce methods
|
||||||
const handleInputEvent = (event: any) => {
|
const handleInputEvent = (event: any): void => {
|
||||||
const { value } = event.target;
|
const { value } = event.target;
|
||||||
|
|
||||||
tokenValue.value = Number(value);
|
tokenValue.value = Number(value);
|
||||||
|
|
||||||
if (decimalCount(tokenValue.value) > 2) {
|
if (decimalCount(String(tokenValue.value)) > 2) {
|
||||||
validDecimals.value = false;
|
validDecimals.value = false;
|
||||||
enableSelectButton.value = false;
|
enableConfirmButton.value = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
validDecimals.value = true;
|
validDecimals.value = true;
|
||||||
@ -43,41 +63,52 @@ const handleInputEvent = (event: any) => {
|
|||||||
verifyLiquidity();
|
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
|
// Verify if there is a valid deposit to buy
|
||||||
const verifyLiquidity = () => {
|
const verifyLiquidity = (): void => {
|
||||||
enableSelectButton.value = false;
|
enableConfirmButton.value = false;
|
||||||
selectedDeposit.value = null;
|
selectedGoerliDeposit.value = undefined;
|
||||||
if (!walletAddress.value || tokenValue.value <= 0) return;
|
selectedMumbaiDeposit.value = undefined;
|
||||||
|
|
||||||
depositsValidList.value.find((element) => {
|
if (tokenValue.value <= 0) {
|
||||||
const remaining = element.remaining;
|
enableWalletButton.value = false;
|
||||||
if (
|
return;
|
||||||
tokenValue.value!! <= remaining &&
|
|
||||||
tokenValue.value!! != 0 &&
|
|
||||||
element.seller !== walletAddress.value
|
|
||||||
) {
|
|
||||||
enableSelectButton.value = true;
|
|
||||||
hasLiquidity.value = true;
|
|
||||||
selectedDeposit.value = element;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!enableSelectButton.value) {
|
selectedGoerliDeposit.value = verifyNetworkLiquidity(
|
||||||
|
tokenValue.value,
|
||||||
|
walletAddress.value,
|
||||||
|
depositsValidListGoerli.value
|
||||||
|
);
|
||||||
|
selectedMumbaiDeposit.value = verifyNetworkLiquidity(
|
||||||
|
tokenValue.value,
|
||||||
|
walletAddress.value,
|
||||||
|
depositsValidListMumbai.value
|
||||||
|
);
|
||||||
|
|
||||||
|
enableOrDisableConfirmButton();
|
||||||
|
if (selectedGoerliDeposit.value || selectedMumbaiDeposit.value) {
|
||||||
|
hasLiquidity.value = true;
|
||||||
|
enableWalletButton.value = true;
|
||||||
|
} else {
|
||||||
hasLiquidity.value = false;
|
hasLiquidity.value = false;
|
||||||
|
enableWalletButton.value = true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const enableOrDisableConfirmButton = (): void => {
|
||||||
|
if (selectedGoerliDeposit.value && networkName.value == NetworkEnum.ethereum)
|
||||||
|
enableConfirmButton.value = true;
|
||||||
|
else if (
|
||||||
|
selectedMumbaiDeposit.value &&
|
||||||
|
networkName.value == NetworkEnum.polygon
|
||||||
|
)
|
||||||
|
enableConfirmButton.value = true;
|
||||||
|
else enableConfirmButton.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
watch(networkName, (): void => {
|
||||||
|
enableOrDisableConfirmButton();
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -126,12 +157,14 @@ const verifyLiquidity = () => {
|
|||||||
src="@/assets/polygon.svg"
|
src="@/assets/polygon.svg"
|
||||||
width="24"
|
width="24"
|
||||||
height="24"
|
height="24"
|
||||||
|
v-if="selectedMumbaiDeposit"
|
||||||
/>
|
/>
|
||||||
<img
|
<img
|
||||||
alt="Ethereum image"
|
alt="Ethereum image"
|
||||||
src="@/assets/ethereum.svg"
|
src="@/assets/ethereum.svg"
|
||||||
width="24"
|
width="24"
|
||||||
height="24"
|
height="24"
|
||||||
|
v-if="selectedGoerliDeposit"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -149,13 +182,14 @@ const verifyLiquidity = () => {
|
|||||||
<CustomButton
|
<CustomButton
|
||||||
v-if="!walletAddress"
|
v-if="!walletAddress"
|
||||||
:text="'Conectar carteira'"
|
:text="'Conectar carteira'"
|
||||||
|
:is-disabled="!enableWalletButton"
|
||||||
@buttonClicked="connectAccount()"
|
@buttonClicked="connectAccount()"
|
||||||
/>
|
/>
|
||||||
<CustomButton
|
<CustomButton
|
||||||
v-if="walletAddress"
|
v-if="walletAddress"
|
||||||
:text="'Confirmar compra'"
|
:text="'Confirmar compra'"
|
||||||
:is-disabled="!enableSelectButton"
|
:is-disabled="!enableConfirmButton"
|
||||||
@buttonClicked="emit('tokenBuy', { selectedDeposit, tokenValue })"
|
@buttonClicked="emitConfirmButton()"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -2,39 +2,30 @@
|
|||||||
import { ref } from "vue";
|
import { ref } from "vue";
|
||||||
import CustomButton from "../../components/CustomButton.vue";
|
import CustomButton from "../../components/CustomButton.vue";
|
||||||
import { debounce } from "@/utils/debounce";
|
import { debounce } from "@/utils/debounce";
|
||||||
|
import { decimalCount } from "@/utils/decimalCount";
|
||||||
|
|
||||||
// Reactive state
|
// Reactive state
|
||||||
const tokenValue = ref(0);
|
const tokenValue = ref<number>(0);
|
||||||
const enableSelectButton = ref(false);
|
const enableSelectButton = ref<boolean>(false);
|
||||||
const hasLiquidity = ref(true);
|
const hasLiquidity = ref<boolean>(true);
|
||||||
const validDecimals = ref(true);
|
const validDecimals = ref<boolean>(true);
|
||||||
|
|
||||||
// Emits
|
// Emits
|
||||||
const emit = defineEmits(["tokenBuy"]);
|
const emit = defineEmits(["tokenBuy"]);
|
||||||
|
|
||||||
// Debounce methods
|
// Debounce methods
|
||||||
const handleInputEvent = (event: any) => {
|
const handleInputEvent = (event: any): void => {
|
||||||
const { value } = event.target;
|
const { value } = event.target;
|
||||||
|
|
||||||
tokenValue.value = Number(value);
|
tokenValue.value = Number(value);
|
||||||
|
|
||||||
if (decimalCount(tokenValue.value) > 2) {
|
if (decimalCount(String(tokenValue.value)) > 2) {
|
||||||
validDecimals.value = false;
|
validDecimals.value = false;
|
||||||
enableSelectButton.value = false;
|
enableSelectButton.value = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
validDecimals.value = true;
|
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>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -2,23 +2,30 @@
|
|||||||
import { ref } from "vue";
|
import { ref } from "vue";
|
||||||
import CustomButton from "../CustomButton.vue";
|
import CustomButton from "../CustomButton.vue";
|
||||||
import { debounce } from "@/utils/debounce";
|
import { debounce } from "@/utils/debounce";
|
||||||
|
import { decimalCount } from "@/utils/decimalCount";
|
||||||
|
import { useEtherStore } from "@/store/ether";
|
||||||
|
import { storeToRefs } from "pinia";
|
||||||
|
import { connectProvider } from "@/blockchain/provider";
|
||||||
|
|
||||||
// Reactive state
|
// Reactive state
|
||||||
const offer = ref<string | number>("");
|
const etherStore = useEtherStore();
|
||||||
|
const { walletAddress } = storeToRefs(etherStore);
|
||||||
|
|
||||||
|
const offer = ref<string>("");
|
||||||
const pixKey = ref<string>("");
|
const pixKey = ref<string>("");
|
||||||
|
|
||||||
const enableSelectButton = ref(false);
|
const enableSelectButton = ref<boolean>(false);
|
||||||
const hasLiquidity = ref(true);
|
const hasLiquidity = ref<boolean>(true);
|
||||||
const validDecimals = ref(true);
|
const validDecimals = ref<boolean>(true);
|
||||||
|
|
||||||
// Emits
|
// Emits
|
||||||
const emit = defineEmits(["approveTokens"]);
|
const emit = defineEmits(["approveTokens"]);
|
||||||
|
|
||||||
// Debounce methods
|
// Debounce methods
|
||||||
const handleInputEvent = (event: any) => {
|
const handleInputEvent = (event: any): void => {
|
||||||
const { value } = event.target;
|
const { value } = event.target;
|
||||||
|
|
||||||
offer.value = Number(value);
|
offer.value = value;
|
||||||
|
|
||||||
if (decimalCount(offer.value) > 2) {
|
if (decimalCount(offer.value) > 2) {
|
||||||
validDecimals.value = false;
|
validDecimals.value = false;
|
||||||
@ -28,14 +35,12 @@ const handleInputEvent = (event: any) => {
|
|||||||
validDecimals.value = true;
|
validDecimals.value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Enable button methods
|
const handleButtonClick = async (
|
||||||
// Check if has more than 2 decimal places
|
offer: string,
|
||||||
const decimalCount = (num: Number) => {
|
pixKey: string
|
||||||
const numStr = String(num);
|
): Promise<void> => {
|
||||||
if (numStr.includes(".")) {
|
if (walletAddress.value) emit("approveTokens", { offer, pixKey });
|
||||||
return numStr.split(".")[1].length;
|
else await connectProvider();
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -99,8 +104,8 @@ const decimalCount = (num: Number) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<CustomButton
|
<CustomButton
|
||||||
:text="'Aprovar tokens'"
|
:text="walletAddress ? 'Aprovar tokens' : 'Conectar Carteira'"
|
||||||
@buttonClicked="emit('approveTokens', { offer, pixKey })"
|
@buttonClicked="handleButtonClick(offer, pixKey)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -2,12 +2,15 @@
|
|||||||
import { storeToRefs } from "pinia";
|
import { storeToRefs } from "pinia";
|
||||||
import { useEtherStore } from "../store/ether";
|
import { useEtherStore } from "../store/ether";
|
||||||
import { ref } from "vue";
|
import { ref } from "vue";
|
||||||
import blockchain from "../utils/blockchain";
|
import { NetworkEnum } from "@/model/NetworkEnum";
|
||||||
|
import { connectProvider, requestNetworkChange } from "../blockchain/provider";
|
||||||
|
import ethereumImage from "../assets/ethereum.svg";
|
||||||
|
import polygonImage from "../assets/polygon.svg";
|
||||||
|
|
||||||
// Store reference
|
// Store reference
|
||||||
const etherStore = useEtherStore();
|
const etherStore = useEtherStore();
|
||||||
|
|
||||||
const { walletAddress, balance, sellerView } = storeToRefs(etherStore);
|
const { walletAddress, sellerView } = storeToRefs(etherStore);
|
||||||
|
|
||||||
const menuOpenToggle = ref<boolean>(false);
|
const menuOpenToggle = ref<boolean>(false);
|
||||||
const menuHoverToggle = ref<boolean>(false);
|
const menuHoverToggle = ref<boolean>(false);
|
||||||
@ -16,8 +19,8 @@ const currencyMenuOpenToggle = ref<boolean>(false);
|
|||||||
const currencyMenuHoverToggle = ref<boolean>(false);
|
const currencyMenuHoverToggle = ref<boolean>(false);
|
||||||
|
|
||||||
//Methods
|
//Methods
|
||||||
const connectMetaMask = () => {
|
const connectMetaMask = async (): Promise<void> => {
|
||||||
blockchain.connectProvider();
|
await connectProvider();
|
||||||
};
|
};
|
||||||
|
|
||||||
const formatWalletAddress = (): string => {
|
const formatWalletAddress = (): string => {
|
||||||
@ -30,20 +33,31 @@ const formatWalletAddress = (): string => {
|
|||||||
return `${initialText}...${finalText}`;
|
return `${initialText}...${finalText}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
const formatWalletBalance = (): String => {
|
const disconnectUser = (): void => {
|
||||||
const fixed = Number(balance.value);
|
|
||||||
return fixed.toFixed(2);
|
|
||||||
};
|
|
||||||
|
|
||||||
const disconnectUser = () => {
|
|
||||||
etherStore.setWalletAddress("");
|
etherStore.setWalletAddress("");
|
||||||
closeMenu();
|
closeMenu();
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
};
|
};
|
||||||
|
|
||||||
const closeMenu = () => {
|
const closeMenu = (): void => {
|
||||||
menuOpenToggle.value = false;
|
menuOpenToggle.value = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const networkChange = async (network: NetworkEnum): Promise<void> => {
|
||||||
|
currencyMenuOpenToggle.value = false;
|
||||||
|
const change = await requestNetworkChange(network);
|
||||||
|
if (change) etherStore.setNetworkName(network);
|
||||||
|
};
|
||||||
|
|
||||||
|
const getNetworkImage = (networkName: NetworkEnum): string => {
|
||||||
|
let validImages = {
|
||||||
|
Ethereum: ethereumImage,
|
||||||
|
Polygon: polygonImage,
|
||||||
|
Localhost: ethereumImage,
|
||||||
|
};
|
||||||
|
|
||||||
|
return validImages[networkName];
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -63,16 +77,7 @@ const closeMenu = () => {
|
|||||||
<RouterLink :to="sellerView ? '/' : '/seller'" class="default-button">
|
<RouterLink :to="sellerView ? '/' : '/seller'" class="default-button">
|
||||||
{{ sellerView ? "Quero comprar" : "Quero vender" }}
|
{{ sellerView ? "Quero comprar" : "Quero vender" }}
|
||||||
</RouterLink>
|
</RouterLink>
|
||||||
<button
|
<div class="flex flex-col" v-if="walletAddress">
|
||||||
type="button"
|
|
||||||
v-if="!walletAddress"
|
|
||||||
class="border-amber-500 border-2 rounded default-button"
|
|
||||||
@click="connectMetaMask()"
|
|
||||||
>
|
|
||||||
Conectar carteira
|
|
||||||
</button>
|
|
||||||
<div v-if="walletAddress" class="account-info">
|
|
||||||
<div class="flex flex-col">
|
|
||||||
<div
|
<div
|
||||||
class="group top-bar-info cursor-pointer hover:bg-white"
|
class="group top-bar-info cursor-pointer hover:bg-white"
|
||||||
@click="
|
@click="
|
||||||
@ -91,7 +96,10 @@ const closeMenu = () => {
|
|||||||
: 'transparent',
|
: 'transparent',
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<img alt="Ethereum image" src="@/assets/ethereum.svg" />
|
<img
|
||||||
|
alt="Choosed network image"
|
||||||
|
:src="getNetworkImage(etherStore.networkName)"
|
||||||
|
/>
|
||||||
<span
|
<span
|
||||||
class="default-text group-hover:text-gray-900"
|
class="default-text group-hover:text-gray-900"
|
||||||
:style="{
|
:style="{
|
||||||
@ -102,7 +110,7 @@ const closeMenu = () => {
|
|||||||
: 'rgb(249 250 251)',
|
: 'rgb(249 250 251)',
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
Ethereum
|
{{ etherStore.networkName }}
|
||||||
</span>
|
</span>
|
||||||
<img
|
<img
|
||||||
class="text-gray-900"
|
class="text-gray-900"
|
||||||
@ -127,40 +135,53 @@ const closeMenu = () => {
|
|||||||
>
|
>
|
||||||
<div class="mt-2">
|
<div class="mt-2">
|
||||||
<div class="bg-white rounded-md z-10">
|
<div class="bg-white rounded-md z-10">
|
||||||
<div class="menu-button gap-2 px-4 rounded-md cursor-pointer">
|
<div
|
||||||
|
class="menu-button gap-2 px-4 rounded-md cursor-pointer"
|
||||||
|
@click="networkChange(NetworkEnum.ethereum)"
|
||||||
|
>
|
||||||
<img
|
<img
|
||||||
alt="Ethereum image"
|
alt="Ethereum image"
|
||||||
width="20"
|
width="20"
|
||||||
height="20"
|
height="20"
|
||||||
src="@/assets/ethereum.svg"
|
src="@/assets/ethereum.svg"
|
||||||
/>
|
/>
|
||||||
<span
|
<span class="text-gray-900 py-4 text-end font-semibold text-sm">
|
||||||
class="text-gray-900 py-4 text-end font-semibold text-sm"
|
|
||||||
>
|
|
||||||
Ethereum
|
Ethereum
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-full flex justify-center">
|
<div class="w-full flex justify-center">
|
||||||
<hr class="w-4/5" />
|
<hr class="w-4/5" />
|
||||||
</div>
|
</div>
|
||||||
<div class="menu-button gap-2 px-4 rounded-md cursor-pointer">
|
<div
|
||||||
|
class="menu-button gap-2 px-4 rounded-md cursor-pointer"
|
||||||
|
@click="networkChange(NetworkEnum.polygon)"
|
||||||
|
>
|
||||||
<img
|
<img
|
||||||
alt="Polygon image"
|
alt="Polygon image"
|
||||||
width="20"
|
width="20"
|
||||||
height="20"
|
height="20"
|
||||||
src="@/assets/polygon.svg"
|
src="@/assets/polygon.svg"
|
||||||
/>
|
/>
|
||||||
<span
|
<span class="text-gray-900 py-4 text-end font-semibold text-sm">
|
||||||
class="text-gray-900 py-4 text-end font-semibold text-sm"
|
|
||||||
>
|
|
||||||
Polygon
|
Polygon
|
||||||
</span>
|
</span>
|
||||||
<hr />
|
</div>
|
||||||
|
<div class="w-full flex justify-center">
|
||||||
|
<hr class="w-4/5" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
v-if="!walletAddress"
|
||||||
|
class="border-amber-500 border-2 rounded default-button"
|
||||||
|
@click="connectMetaMask()"
|
||||||
|
>
|
||||||
|
Conectar carteira
|
||||||
|
</button>
|
||||||
|
<div v-if="walletAddress" class="account-info">
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<div
|
<div
|
||||||
class="top-bar-info cursor-pointer"
|
class="top-bar-info cursor-pointer"
|
||||||
@ -241,12 +262,6 @@ const closeMenu = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="top-bar-info">
|
|
||||||
<span class="default-text text-sm">
|
|
||||||
MBRZ: {{ formatWalletBalance() }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<!-- Temporary div, just to show a wallet's balance -->
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
4
src/model/NetworkEnum.ts
Normal file
4
src/model/NetworkEnum.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
export enum NetworkEnum {
|
||||||
|
ethereum = "Ethereum",
|
||||||
|
polygon = "Polygon",
|
||||||
|
}
|
10
src/model/ValidDeposit.ts
Normal file
10
src/model/ValidDeposit.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import type { BigNumber } from "ethers";
|
||||||
|
|
||||||
|
export type ValidDeposit = {
|
||||||
|
depositID: BigNumber;
|
||||||
|
blockNumber: number;
|
||||||
|
remaining: number;
|
||||||
|
seller: string;
|
||||||
|
pixKey: string;
|
||||||
|
pixTarget?: string;
|
||||||
|
};
|
@ -1,6 +1,5 @@
|
|||||||
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 TransactionHistoryView from "../views/TransactionHistoryView.vue";
|
import TransactionHistoryView from "../views/TransactionHistoryView.vue";
|
||||||
import FaqView from "../views/FaqView.vue";
|
import FaqView from "../views/FaqView.vue";
|
||||||
import ManageBidsView from "../views/ManageBidsView.vue";
|
import ManageBidsView from "../views/ManageBidsView.vue";
|
||||||
@ -19,11 +18,6 @@ const router = createRouter({
|
|||||||
name: "seller",
|
name: "seller",
|
||||||
component: SellerView,
|
component: SellerView,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
path: "/mock",
|
|
||||||
name: "mock",
|
|
||||||
component: MockView,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
path: "/transaction_history",
|
path: "/transaction_history",
|
||||||
name: "transaction history",
|
name: "transaction history",
|
||||||
|
@ -1,23 +1,18 @@
|
|||||||
|
import { NetworkEnum } from "@/model/NetworkEnum";
|
||||||
|
import type { ValidDeposit } from "@/model/ValidDeposit";
|
||||||
import { defineStore } from "pinia";
|
import { defineStore } from "pinia";
|
||||||
|
|
||||||
export const useEtherStore = defineStore("ether", {
|
export const useEtherStore = defineStore("ether", {
|
||||||
state: () => ({
|
state: () => ({
|
||||||
walletAddress: "",
|
walletAddress: "",
|
||||||
balance: "",
|
balance: "",
|
||||||
|
networkName: NetworkEnum.ethereum,
|
||||||
loadingLock: false,
|
loadingLock: false,
|
||||||
sellerView: false,
|
sellerView: false,
|
||||||
// Depósitos válidos para compra
|
// Depósitos válidos para compra GOERLI
|
||||||
depositsValidList: [] as any[],
|
depositsValidListGoerli: [] as ValidDeposit[],
|
||||||
// Depósitos adicionados na blockchain
|
// Depósitos válidos para compra MUMBAI
|
||||||
depositsAddedList: [] as any[],
|
depositsValidListMumbai: [] as ValidDeposit[],
|
||||||
// Depósitos expirados na blockchain
|
|
||||||
depositsExpiredList: [] as any[],
|
|
||||||
// Locks adicionados na blockchain
|
|
||||||
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) {
|
||||||
@ -26,35 +21,27 @@ export const useEtherStore = defineStore("ether", {
|
|||||||
setBalance(balance: string) {
|
setBalance(balance: string) {
|
||||||
this.balance = balance;
|
this.balance = balance;
|
||||||
},
|
},
|
||||||
|
setNetworkName(networkName: NetworkEnum) {
|
||||||
|
this.networkName = networkName;
|
||||||
|
},
|
||||||
setLoadingLock(isLoadingLock: boolean) {
|
setLoadingLock(isLoadingLock: boolean) {
|
||||||
this.loadingLock = isLoadingLock;
|
this.loadingLock = isLoadingLock;
|
||||||
},
|
},
|
||||||
setSellerView(sellerView: boolean) {
|
setSellerView(sellerView: boolean) {
|
||||||
this.sellerView = sellerView;
|
this.sellerView = sellerView;
|
||||||
},
|
},
|
||||||
setDepositsValidList(depositsValidList: any[]) {
|
setDepositsValidListGoerli(depositsValidList: ValidDeposit[]) {
|
||||||
this.depositsValidList = depositsValidList;
|
this.depositsValidListGoerli = depositsValidList;
|
||||||
},
|
},
|
||||||
setDepositsAddedList(depositsAddedList: any[]) {
|
setDepositsValidListMumbai(depositsValidList: ValidDeposit[]) {
|
||||||
this.depositsAddedList = depositsAddedList;
|
this.depositsValidListMumbai = depositsValidList;
|
||||||
},
|
|
||||||
setDepositsExpiredList(depositsExpiredList: any[]) {
|
|
||||||
this.depositsExpiredList = depositsExpiredList;
|
|
||||||
},
|
|
||||||
setLocksAddedList(locksAddedList: any[]) {
|
|
||||||
this.locksAddedList = locksAddedList;
|
|
||||||
},
|
|
||||||
setLocksReleasedList(locksReleasedList: any[]) {
|
|
||||||
this.locksReleasedList = locksReleasedList;
|
|
||||||
},
|
|
||||||
setLocksExpiredList(locksExpiredList: any[]) {
|
|
||||||
this.locksExpiredList = locksExpiredList;
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
// Alterar para integrar com mumbai
|
||||||
getters: {
|
getters: {
|
||||||
getValidDepositByWalletAddress: (state) => {
|
getValidDepositByWalletAddress: (state) => {
|
||||||
return (walletAddress: string) =>
|
return (walletAddress: string) =>
|
||||||
state.depositsValidList
|
state.depositsValidListGoerli
|
||||||
.filter((deposit) => deposit.seller == walletAddress)
|
.filter((deposit) => deposit.seller == walletAddress)
|
||||||
.sort((a, b) => {
|
.sort((a, b) => {
|
||||||
return b.blockNumber - a.blockNumber;
|
return b.blockNumber - a.blockNumber;
|
||||||
|
@ -1,531 +0,0 @@
|
|||||||
import { useEtherStore } from "@/store/ether";
|
|
||||||
import { BigNumber, ethers } from "ethers";
|
|
||||||
|
|
||||||
// Smart contract imports
|
|
||||||
import mockToken from "./smart_contract_files/MockToken.json";
|
|
||||||
import p2pix from "./smart_contract_files/P2PIX.json";
|
|
||||||
import addresses from "./smart_contract_files/localhost.json";
|
|
||||||
// Mock wallets import
|
|
||||||
import { wallets } from "./smart_contract_files/wallets.json";
|
|
||||||
|
|
||||||
// Wallet methods
|
|
||||||
// Update wallet state (balance and address)
|
|
||||||
const updateWalletStatus = async () => {
|
|
||||||
const etherStore = useEtherStore();
|
|
||||||
const provider = getProvider();
|
|
||||||
|
|
||||||
if (!provider) return;
|
|
||||||
|
|
||||||
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]));
|
|
||||||
};
|
|
||||||
|
|
||||||
const updateWalletBalance = async () => {
|
|
||||||
const etherStore = useEtherStore();
|
|
||||||
const provider = getProvider();
|
|
||||||
|
|
||||||
if (!provider) return;
|
|
||||||
|
|
||||||
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));
|
|
||||||
};
|
|
||||||
|
|
||||||
// Split tokens between wallets in wallets.json
|
|
||||||
const splitTokens = async () => {
|
|
||||||
const provider = getProvider();
|
|
||||||
if (!provider) return;
|
|
||||||
|
|
||||||
const signer = provider.getSigner();
|
|
||||||
const tokenContract = new ethers.Contract(
|
|
||||||
addresses.token,
|
|
||||||
mockToken.abi,
|
|
||||||
signer
|
|
||||||
);
|
|
||||||
|
|
||||||
for (let i = 0; i < wallets.length; i++) {
|
|
||||||
const tx = await tokenContract.transfer(
|
|
||||||
wallets[i],
|
|
||||||
ethers.utils.parseEther("4000000.0")
|
|
||||||
);
|
|
||||||
await tx.wait();
|
|
||||||
updateWalletStatus();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// get all wallet transactions
|
|
||||||
const listAllTransactionByWalletAddress = 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);
|
|
||||||
|
|
||||||
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[]> => {
|
|
||||||
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 deposit transactions
|
|
||||||
const listValidDepositTransactionsByWalletAddress = async (
|
|
||||||
walletAddress: string
|
|
||||||
): Promise<any[]> => {
|
|
||||||
const walletDeposits = await getValidDeposits();
|
|
||||||
if (walletDeposits) {
|
|
||||||
return walletDeposits
|
|
||||||
.filter((deposit) => deposit.seller == walletAddress)
|
|
||||||
.sort((a, b) => {
|
|
||||||
return b.blockNumber - a.blockNumber;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return [];
|
|
||||||
};
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
//get valid deposits
|
|
||||||
const getValidDeposits = async (): Promise<any[] | undefined> => {
|
|
||||||
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: any[] = await Promise.all(
|
|
||||||
eventsDeposits
|
|
||||||
.map(async (deposit) => {
|
|
||||||
const mappedDeposit = await mapDeposits(deposit.args?.depositID);
|
|
||||||
let validDeposit = {};
|
|
||||||
|
|
||||||
if (mappedDeposit.valid) {
|
|
||||||
validDeposit = {
|
|
||||||
blockNumber: deposit.blockNumber,
|
|
||||||
depositID: deposit.args?.depositID,
|
|
||||||
remaining: formatBigNumber(mappedDeposit.remaining),
|
|
||||||
seller: mappedDeposit.seller,
|
|
||||||
pixKey: mappedDeposit.pixTarget,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return validDeposit;
|
|
||||||
})
|
|
||||||
.filter((deposit) => deposit)
|
|
||||||
);
|
|
||||||
|
|
||||||
return depositList;
|
|
||||||
};
|
|
||||||
// Update events at store methods
|
|
||||||
const updateValidDeposits = async () => {
|
|
||||||
const etherStore = useEtherStore();
|
|
||||||
const deposits = await getValidDeposits();
|
|
||||||
if (deposits) etherStore.setDepositsValidList(deposits);
|
|
||||||
};
|
|
||||||
|
|
||||||
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);
|
|
||||||
console.log("DEPOSITS", eventsDeposits);
|
|
||||||
};
|
|
||||||
|
|
||||||
const updateLockAddedEvents = 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 filterLocks = p2pContract.filters.LockAdded(null);
|
|
||||||
const eventsLocks = await p2pContract.queryFilter(filterLocks);
|
|
||||||
etherStore.setLocksAddedList(eventsLocks);
|
|
||||||
console.log("LOCKS", eventsLocks);
|
|
||||||
};
|
|
||||||
|
|
||||||
const updateLockReleasedEvents = 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 filterReleases = p2pContract.filters.LockReleased(null);
|
|
||||||
const eventsReleases = await p2pContract.queryFilter(filterReleases);
|
|
||||||
etherStore.setLocksReleasedList(eventsReleases);
|
|
||||||
console.log("RELEASES", eventsReleases);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Provider methods
|
|
||||||
const connectProvider = async () => {
|
|
||||||
const window_ = window as any;
|
|
||||||
const connection = window_.ethereum;
|
|
||||||
|
|
||||||
await updateWalletStatus();
|
|
||||||
await updateValidDeposits();
|
|
||||||
await updateDepositAddedEvents();
|
|
||||||
await updateLockAddedEvents();
|
|
||||||
await updateLockReleasedEvents();
|
|
||||||
|
|
||||||
connection.on("accountsChanged", async () => {
|
|
||||||
await updateWalletStatus();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const getProvider = (): ethers.providers.Web3Provider | null => {
|
|
||||||
const window_ = window as any;
|
|
||||||
const connection = window_.ethereum;
|
|
||||||
|
|
||||||
if (!connection) return null;
|
|
||||||
|
|
||||||
return new ethers.providers.Web3Provider(connection);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Deposit methods
|
|
||||||
const approveTokens = async (tokenQty: Number) => {
|
|
||||||
const provider = getProvider();
|
|
||||||
if (!provider) return;
|
|
||||||
|
|
||||||
const signer = provider.getSigner();
|
|
||||||
|
|
||||||
const tokenContract = new ethers.Contract(
|
|
||||||
addresses.token,
|
|
||||||
mockToken.abi,
|
|
||||||
signer
|
|
||||||
);
|
|
||||||
|
|
||||||
const apprv = await tokenContract.approve(
|
|
||||||
addresses.p2pix,
|
|
||||||
formatEther(String(tokenQty))
|
|
||||||
);
|
|
||||||
await apprv.wait();
|
|
||||||
return apprv;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Gets value and pix key from user's form to create a deposit in the blockchain
|
|
||||||
const addDeposit = async (tokenQty: Number, pixKey: String) => {
|
|
||||||
const provider = getProvider();
|
|
||||||
if (!provider) return;
|
|
||||||
|
|
||||||
const signer = provider.getSigner();
|
|
||||||
const p2pContract = new ethers.Contract(addresses.p2pix, p2pix.abi, signer);
|
|
||||||
|
|
||||||
const deposit = await p2pContract.deposit(
|
|
||||||
addresses.token,
|
|
||||||
formatEther(String(tokenQty)),
|
|
||||||
pixKey,
|
|
||||||
ethers.utils.formatBytes32String("")
|
|
||||||
);
|
|
||||||
await deposit.wait();
|
|
||||||
|
|
||||||
await updateWalletStatus();
|
|
||||||
await updateDepositAddedEvents();
|
|
||||||
await updateValidDeposits();
|
|
||||||
};
|
|
||||||
|
|
||||||
const mockDeposit = async (tokenQty: Number, pixKey: String) => {
|
|
||||||
const provider = getProvider();
|
|
||||||
if (!provider) return;
|
|
||||||
|
|
||||||
const signer = provider.getSigner();
|
|
||||||
|
|
||||||
const tokenContract = new ethers.Contract(
|
|
||||||
addresses.token,
|
|
||||||
mockToken.abi,
|
|
||||||
signer
|
|
||||||
);
|
|
||||||
|
|
||||||
const apprv = await tokenContract.approve(
|
|
||||||
addresses.p2pix,
|
|
||||||
formatEther(String(tokenQty))
|
|
||||||
);
|
|
||||||
await apprv.wait();
|
|
||||||
|
|
||||||
const p2pContract = new ethers.Contract(addresses.p2pix, p2pix.abi, signer);
|
|
||||||
|
|
||||||
const deposit = await p2pContract.deposit(
|
|
||||||
addresses.token,
|
|
||||||
formatEther(String(tokenQty)),
|
|
||||||
pixKey,
|
|
||||||
ethers.utils.formatBytes32String("")
|
|
||||||
);
|
|
||||||
await deposit.wait();
|
|
||||||
|
|
||||||
await updateWalletStatus();
|
|
||||||
await updateValidDeposits();
|
|
||||||
await updateDepositAddedEvents();
|
|
||||||
};
|
|
||||||
|
|
||||||
// cancel a deposit by its Id
|
|
||||||
const cancelDeposit = async (depositId: BigNumber): Promise<Boolean> => {
|
|
||||||
const provider = getProvider();
|
|
||||||
|
|
||||||
if (!provider) return false;
|
|
||||||
|
|
||||||
const signer = provider.getSigner();
|
|
||||||
const contract = new ethers.Contract(addresses.p2pix, p2pix.abi, signer);
|
|
||||||
await contract.cancelDeposit(depositId);
|
|
||||||
|
|
||||||
await updateWalletBalance();
|
|
||||||
await updateValidDeposits();
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
// withdraw a deposit by its Id
|
|
||||||
const withdrawDeposit = async (depositId: BigNumber): Promise<Boolean> => {
|
|
||||||
const provider = getProvider();
|
|
||||||
|
|
||||||
if (!provider) return false;
|
|
||||||
|
|
||||||
const signer = provider.getSigner();
|
|
||||||
const contract = new ethers.Contract(addresses.p2pix, p2pix.abi, signer);
|
|
||||||
await contract.withdraw(depositId, []);
|
|
||||||
|
|
||||||
await updateWalletBalance();
|
|
||||||
await updateValidDeposits();
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Get specific deposit data by its ID
|
|
||||||
const mapDeposits = async (depositId: BigNumber): Promise<any> => {
|
|
||||||
const provider = getProvider();
|
|
||||||
|
|
||||||
if (!provider) return;
|
|
||||||
|
|
||||||
const signer = provider.getSigner();
|
|
||||||
const contract = new ethers.Contract(addresses.p2pix, p2pix.abi, signer);
|
|
||||||
const deposit = await contract.mapDeposits(depositId);
|
|
||||||
|
|
||||||
return deposit;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Lock methods
|
|
||||||
// Gets value from user's form to create a lock in the blockchain
|
|
||||||
const addLock = async (depositId: BigNumber, amount: Number) => {
|
|
||||||
const etherStore = useEtherStore();
|
|
||||||
const provider = getProvider();
|
|
||||||
|
|
||||||
if (!provider) return;
|
|
||||||
const signer = provider.getSigner();
|
|
||||||
const p2pContract = new ethers.Contract(addresses.p2pix, p2pix.abi, signer);
|
|
||||||
|
|
||||||
// Make lock
|
|
||||||
const oldEventsLen = etherStore.locksAddedList.length;
|
|
||||||
const lock = await p2pContract.lock(
|
|
||||||
depositId, // BigNumber
|
|
||||||
etherStore.walletAddress, // String "0x70997970C51812dc3A010C7d01b50e0d17dc79C8" (Example)
|
|
||||||
ethers.constants.AddressZero, // String "0x0000000000000000000000000000000000000000"
|
|
||||||
0,
|
|
||||||
formatEther(String(amount)), // BigNumber
|
|
||||||
[],
|
|
||||||
[]
|
|
||||||
);
|
|
||||||
lock.wait();
|
|
||||||
|
|
||||||
while (etherStore.locksAddedList.length === oldEventsLen) {
|
|
||||||
await updateLockAddedEvents();
|
|
||||||
await updateValidDeposits();
|
|
||||||
}
|
|
||||||
|
|
||||||
return lock;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Get specific lock data by its ID
|
|
||||||
const mapLocks = async (lockId: string) => {
|
|
||||||
const provider = getProvider();
|
|
||||||
|
|
||||||
if (!provider) return;
|
|
||||||
|
|
||||||
const signer = provider.getSigner();
|
|
||||||
const contract = new ethers.Contract(addresses.p2pix, p2pix.abi, signer);
|
|
||||||
const lock = await contract.mapLocks(lockId);
|
|
||||||
|
|
||||||
return lock;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Releases lock by specific ID and other additional data
|
|
||||||
const releaseLock = async (
|
|
||||||
pixKey: string,
|
|
||||||
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", "bytes32"],
|
|
||||||
[
|
|
||||||
pixKey,
|
|
||||||
formatEther(String(amount)),
|
|
||||||
ethers.utils.formatBytes32String(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,
|
|
||||||
ethers.constants.AddressZero,
|
|
||||||
ethers.utils.formatBytes32String(e2eId),
|
|
||||||
sig.r,
|
|
||||||
sig.s,
|
|
||||||
sig.v
|
|
||||||
);
|
|
||||||
release.wait();
|
|
||||||
await updateLockReleasedEvents();
|
|
||||||
await updateValidDeposits();
|
|
||||||
|
|
||||||
return release;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Formatting methods
|
|
||||||
const formatEther = (num: string) => {
|
|
||||||
const formattedNum = ethers.utils.parseEther(num);
|
|
||||||
return formattedNum;
|
|
||||||
};
|
|
||||||
|
|
||||||
const formatBigNumber = (num: BigNumber) => {
|
|
||||||
const formattedNum = ethers.utils.formatEther(num);
|
|
||||||
return formattedNum;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default {
|
|
||||||
connectProvider,
|
|
||||||
formatEther,
|
|
||||||
updateWalletStatus,
|
|
||||||
splitTokens,
|
|
||||||
listValidDepositTransactionsByWalletAddress,
|
|
||||||
listAllTransactionByWalletAddress,
|
|
||||||
listReleaseTransactionByWalletAddress,
|
|
||||||
listDepositTransactionByWalletAddress,
|
|
||||||
listLockTransactionByWalletAddress,
|
|
||||||
approveTokens,
|
|
||||||
addDeposit,
|
|
||||||
cancelDeposit,
|
|
||||||
withdrawDeposit,
|
|
||||||
mockDeposit,
|
|
||||||
mapDeposits,
|
|
||||||
formatBigNumber,
|
|
||||||
addLock,
|
|
||||||
mapLocks,
|
|
||||||
releaseLock,
|
|
||||||
updateLockAddedEvents,
|
|
||||||
updateValidDeposits,
|
|
||||||
getValidDeposits,
|
|
||||||
};
|
|
6
src/utils/decimalCount.ts
Normal file
6
src/utils/decimalCount.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
export const decimalCount = (numStr: string): number => {
|
||||||
|
if (numStr.includes(".")) {
|
||||||
|
return numStr.split(".")[1].length;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
};
|
23
src/utils/networkLiquidity.ts
Normal file
23
src/utils/networkLiquidity.ts
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import type { ValidDeposit } from "@/model/ValidDeposit";
|
||||||
|
|
||||||
|
const verifyNetworkLiquidity = (
|
||||||
|
tokenValue: number,
|
||||||
|
walletAddress: string,
|
||||||
|
validDepositList: ValidDeposit[]
|
||||||
|
): ValidDeposit | undefined => {
|
||||||
|
const element = validDepositList.find((element) => {
|
||||||
|
const remaining = element.remaining;
|
||||||
|
if (
|
||||||
|
tokenValue!! <= remaining &&
|
||||||
|
tokenValue!! != 0 &&
|
||||||
|
element.seller !== walletAddress
|
||||||
|
) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
return element;
|
||||||
|
};
|
||||||
|
|
||||||
|
export { verifyNetworkLiquidity };
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
8
src/utils/smart_contract_files/goerli.json
Normal file
8
src/utils/smart_contract_files/goerli.json
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"signers": [
|
||||||
|
"0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
|
||||||
|
"0x70997970C51812dc3A010C7d01b50e0d17dc79C8"
|
||||||
|
],
|
||||||
|
"p2pix": "0x5f3EFA9A90532914545CEf527C530658af87e196",
|
||||||
|
"token": "0x294003F602c321627152c6b7DED3EAb5bEa853Ee"
|
||||||
|
}
|
8
src/utils/smart_contract_files/polygon-mumbai.json
Normal file
8
src/utils/smart_contract_files/polygon-mumbai.json
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"signers": [
|
||||||
|
"0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
|
||||||
|
"0x70997970C51812dc3A010C7d01b50e0d17dc79C8"
|
||||||
|
],
|
||||||
|
"p2pix": "0x5f3EFA9A90532914545CEf527C530658af87e196",
|
||||||
|
"token": "0x294003F602c321627152c6b7DED3EAb5bEa853Ee"
|
||||||
|
}
|
@ -2,12 +2,17 @@
|
|||||||
import SearchComponent from "../components/SearchComponent.vue";
|
import SearchComponent from "../components/SearchComponent.vue";
|
||||||
import ValidationComponent from "../components/LoadingComponent.vue";
|
import ValidationComponent from "../components/LoadingComponent.vue";
|
||||||
import BuyConfirmedComponent from "@/components/BuyConfirmedComponent.vue";
|
import BuyConfirmedComponent from "@/components/BuyConfirmedComponent.vue";
|
||||||
import blockchain from "../utils/blockchain";
|
import { ref, onMounted } from "vue";
|
||||||
import { ref } from "vue";
|
|
||||||
|
|
||||||
import { useEtherStore } from "@/store/ether";
|
import { useEtherStore } from "@/store/ether";
|
||||||
import QrCodeComponent from "../components/QrCodeComponent.vue";
|
import QrCodeComponent from "../components/QrCodeComponent.vue";
|
||||||
import { storeToRefs } from "pinia";
|
import { storeToRefs } from "pinia";
|
||||||
|
import { addLock, releaseLock } from "@/blockchain/buyerMethods";
|
||||||
|
import { updateWalletStatus } from "@/blockchain/wallet";
|
||||||
|
import { getNetworksLiquidity } from "@/blockchain/events";
|
||||||
|
import { listReleaseTransactionByWalletAddress } from "@/blockchain/wallet";
|
||||||
|
import type { Event } from "ethers";
|
||||||
|
import type { ValidDeposit } from "@/model/ValidDeposit";
|
||||||
|
|
||||||
enum Step {
|
enum Step {
|
||||||
Search,
|
Search,
|
||||||
@ -19,33 +24,33 @@ const etherStore = useEtherStore();
|
|||||||
etherStore.setSellerView(false);
|
etherStore.setSellerView(false);
|
||||||
|
|
||||||
// States
|
// States
|
||||||
const { loadingLock, walletAddress, locksAddedList } = storeToRefs(etherStore);
|
const { loadingLock, walletAddress } = storeToRefs(etherStore);
|
||||||
const flowStep = ref<Step>(Step.Search);
|
const flowStep = ref<Step>(Step.Search);
|
||||||
const pixTarget = ref<string>("");
|
const pixTarget = ref<string>("");
|
||||||
const tokenAmount = ref<number>();
|
const tokenAmount = ref<number>();
|
||||||
const lockTransactionHash = ref<string>("");
|
const _lockID = ref<string>("");
|
||||||
const lockId = ref<string>("");
|
const loadingRelease = ref<boolean>(false);
|
||||||
const loadingRelease = ref<Boolean>(false);
|
const lastWalletReleaseTransactions = ref<Event[]>([]);
|
||||||
const lastWalletReleaseTransactions = ref<any[]>([]);
|
|
||||||
|
|
||||||
const confirmBuyClick = async ({ selectedDeposit, tokenValue }: any) => {
|
const confirmBuyClick = async (
|
||||||
|
selectedDeposit: ValidDeposit,
|
||||||
|
tokenValue: number
|
||||||
|
) => {
|
||||||
// finish buy screen
|
// finish buy screen
|
||||||
const depositDetail = selectedDeposit;
|
|
||||||
const depositId = selectedDeposit.depositID;
|
|
||||||
pixTarget.value = selectedDeposit.pixKey;
|
pixTarget.value = selectedDeposit.pixKey;
|
||||||
tokenAmount.value = tokenValue;
|
tokenAmount.value = tokenValue;
|
||||||
|
|
||||||
// Makes lock with deposit ID and the Amount
|
// Makes lock with deposit ID and the Amount
|
||||||
if (depositDetail) {
|
if (selectedDeposit) {
|
||||||
flowStep.value = Step.Buy;
|
flowStep.value = Step.Buy;
|
||||||
etherStore.setLoadingLock(true);
|
etherStore.setLoadingLock(true);
|
||||||
|
|
||||||
await blockchain
|
await addLock(selectedDeposit.depositID, tokenValue)
|
||||||
.addLock(depositId, tokenValue)
|
.then((lockID) => {
|
||||||
.then((lock) => {
|
_lockID.value = lockID;
|
||||||
lockTransactionHash.value = lock.hash;
|
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch((err) => {
|
||||||
|
console.log(err);
|
||||||
flowStep.value = Step.Search;
|
flowStep.value = Step.Search;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -53,38 +58,34 @@ const confirmBuyClick = async ({ selectedDeposit, tokenValue }: any) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const releaseTransaction = async ({ e2eId }: any) => {
|
const releaseTransaction = async (e2eId: string) => {
|
||||||
flowStep.value = Step.List;
|
flowStep.value = Step.List;
|
||||||
loadingRelease.value = true;
|
loadingRelease.value = true;
|
||||||
|
|
||||||
const findLock = locksAddedList.value.find((element) => {
|
if (_lockID.value && tokenAmount.value) {
|
||||||
if (element.transactionHash === lockTransactionHash.value) {
|
const release = await releaseLock(
|
||||||
lockId.value = element.args.lockID;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (findLock && tokenAmount.value) {
|
|
||||||
const release = await blockchain.releaseLock(
|
|
||||||
pixTarget.value,
|
pixTarget.value,
|
||||||
tokenAmount.value,
|
tokenAmount.value,
|
||||||
e2eId,
|
e2eId,
|
||||||
lockId.value
|
_lockID.value
|
||||||
);
|
);
|
||||||
release.wait();
|
release.wait();
|
||||||
|
|
||||||
await blockchain
|
await listReleaseTransactionByWalletAddress(
|
||||||
.listReleaseTransactionByWalletAddress(walletAddress.value.toLowerCase())
|
walletAddress.value.toLowerCase()
|
||||||
.then((releaseTransactions) => {
|
).then((releaseTransactions) => {
|
||||||
if (releaseTransactions)
|
if (releaseTransactions)
|
||||||
lastWalletReleaseTransactions.value = releaseTransactions;
|
lastWalletReleaseTransactions.value = releaseTransactions;
|
||||||
});
|
});
|
||||||
|
|
||||||
await blockchain.updateWalletStatus();
|
await updateWalletStatus();
|
||||||
loadingRelease.value = false;
|
loadingRelease.value = false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
await getNetworksLiquidity();
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -1,28 +1,31 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useEtherStore } from "@/store/ether";
|
import { useEtherStore } from "@/store/ether";
|
||||||
import { storeToRefs } from "pinia";
|
import { storeToRefs } from "pinia";
|
||||||
import blockchain from "../utils/blockchain";
|
|
||||||
import ListingComponent from "@/components/ListingComponent.vue";
|
import ListingComponent from "@/components/ListingComponent.vue";
|
||||||
import type { BigNumber } from "ethers";
|
import type { BigNumber } from "ethers";
|
||||||
import { ref, watch } from "vue";
|
import { ref, watch, onMounted } from "vue";
|
||||||
|
import { cancelDeposit, withdrawDeposit } from "@/blockchain/buyerMethods";
|
||||||
|
import { listValidDepositTransactionsByWalletAddress } from "@/blockchain/wallet";
|
||||||
|
import type { ValidDeposit } from "@/model/ValidDeposit";
|
||||||
|
|
||||||
const etherStore = useEtherStore();
|
const etherStore = useEtherStore();
|
||||||
|
|
||||||
const { walletAddress } = storeToRefs(etherStore);
|
const { walletAddress, networkName } = storeToRefs(etherStore);
|
||||||
const depositList = ref<any[]>([]);
|
const depositList = ref<ValidDeposit[]>([]);
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
if (walletAddress.value) {
|
if (walletAddress.value) {
|
||||||
const walletDeposits =
|
const walletDeposits = await listValidDepositTransactionsByWalletAddress(
|
||||||
await blockchain.listValidDepositTransactionsByWalletAddress(
|
|
||||||
walletAddress.value
|
walletAddress.value
|
||||||
);
|
);
|
||||||
if (walletDeposits) {
|
if (walletDeposits) {
|
||||||
depositList.value = walletDeposits;
|
depositList.value = walletDeposits;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const handleCancelDeposit = async (depositID: BigNumber, index: number) => {
|
const handleCancelDeposit = async (depositID: BigNumber, index: number) => {
|
||||||
const response = await blockchain.cancelDeposit(depositID);
|
const response = await cancelDeposit(depositID);
|
||||||
if (response == true) {
|
if (response == true) {
|
||||||
console.log("Depósito cancelado com sucesso.");
|
console.log("Depósito cancelado com sucesso.");
|
||||||
depositList.value.splice(index, 1);
|
depositList.value.splice(index, 1);
|
||||||
@ -30,7 +33,7 @@ const handleCancelDeposit = async (depositID: BigNumber, index: number) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleWithDrawDeposit = async (depositID: BigNumber, index: number) => {
|
const handleWithDrawDeposit = async (depositID: BigNumber, index: number) => {
|
||||||
const response = await blockchain.withdrawDeposit(depositID);
|
const response = await withdrawDeposit(depositID);
|
||||||
if (response == true) {
|
if (response == true) {
|
||||||
console.log("Token retirado com sucesso.");
|
console.log("Token retirado com sucesso.");
|
||||||
depositList.value.splice(index, 1);
|
depositList.value.splice(index, 1);
|
||||||
@ -38,13 +41,23 @@ const handleWithDrawDeposit = async (depositID: BigNumber, index: number) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
watch(walletAddress, async () => {
|
watch(walletAddress, async () => {
|
||||||
const walletDeposits =
|
await listValidDepositTransactionsByWalletAddress(walletAddress.value)
|
||||||
await blockchain.listValidDepositTransactionsByWalletAddress(
|
.then((res) => {
|
||||||
walletAddress.value
|
if (res) depositList.value = res;
|
||||||
);
|
})
|
||||||
if (walletDeposits) {
|
.catch(() => {
|
||||||
depositList.value = walletDeposits;
|
depositList.value = [];
|
||||||
}
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(networkName, async () => {
|
||||||
|
await listValidDepositTransactionsByWalletAddress(walletAddress.value)
|
||||||
|
.then((res) => {
|
||||||
|
if (res) depositList.value = res;
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
depositList.value = [];
|
||||||
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -1,142 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import type { BigNumber } from "ethers";
|
|
||||||
import { storeToRefs } from "pinia";
|
|
||||||
import { ref } from "vue";
|
|
||||||
import { useEtherStore } from "../store/ether";
|
|
||||||
import blockchain from "../utils/blockchain";
|
|
||||||
|
|
||||||
// Blockchain Data
|
|
||||||
const etherStore = useEtherStore();
|
|
||||||
const { depositsValidList } = storeToRefs(etherStore);
|
|
||||||
const { depositsAddedList } = storeToRefs(etherStore);
|
|
||||||
const { locksAddedList } = storeToRefs(etherStore);
|
|
||||||
|
|
||||||
// Buyer's flow Data
|
|
||||||
const depositValue = ref<Number>();
|
|
||||||
const depositPixKey = ref<string>("");
|
|
||||||
|
|
||||||
// Split tokens between wallets in wallets.json
|
|
||||||
const splitTokens = async () => {
|
|
||||||
blockchain.splitTokens();
|
|
||||||
};
|
|
||||||
|
|
||||||
// Formatting methods
|
|
||||||
// Formats wallet address in 0x000...0000 format
|
|
||||||
const formatWalletAddress = (wallet: string): string => {
|
|
||||||
const walletAddressLength = wallet.length;
|
|
||||||
const initialText = wallet.substring(0, 5);
|
|
||||||
const finalText = wallet.substring(
|
|
||||||
walletAddressLength - 4,
|
|
||||||
walletAddressLength
|
|
||||||
);
|
|
||||||
return `${initialText}...${finalText}`;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Deposit methods
|
|
||||||
// Gets value and pix key from user's form to create a deposit in the blockchain
|
|
||||||
const mockDeposit = () => {
|
|
||||||
if (!depositValue.value || !depositPixKey.value) return;
|
|
||||||
blockchain.mockDeposit(depositValue.value, depositPixKey.value);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Get specific deposit data by its ID
|
|
||||||
const mapDeposit = (depositId: BigNumber) => {
|
|
||||||
const deposit = blockchain.mapDeposits(depositId);
|
|
||||||
return deposit;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Lock methods
|
|
||||||
// Get specific lock data by its ID
|
|
||||||
const mapLock = (lockId: string) => {
|
|
||||||
const lock = blockchain.mapLocks(lockId);
|
|
||||||
return lock;
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div class="page">
|
|
||||||
<div class="flex flex-col gap-4 justify-start items-start w-2/3">
|
|
||||||
<div class="flex gap-4 w-full justify-between">
|
|
||||||
<input
|
|
||||||
type="number"
|
|
||||||
class="default-input"
|
|
||||||
placeholder="Quantidade de tokens"
|
|
||||||
v-model="depositValue"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
class="default-input"
|
|
||||||
placeholder="Chave pix"
|
|
||||||
v-model="depositPixKey"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<button type="button" class="default-button" @click="mockDeposit()">
|
|
||||||
Mockar depósitos
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<button type="button" class="default-button" @click="splitTokens()">
|
|
||||||
Dividir tokens
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<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="deposit in depositsAddedList"
|
|
||||||
:key="deposit.blockNumber"
|
|
||||||
@click="mapDeposit(deposit.args.depositID)"
|
|
||||||
>
|
|
||||||
Seller:<br />{{ formatWalletAddress(deposit.args.seller) }}<br />
|
|
||||||
MRBZ: {{ blockchain.formatBigNumber(deposit.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="lock in locksAddedList"
|
|
||||||
:key="lock.blockNumber"
|
|
||||||
@click="mapLock(lock.args.lockID)"
|
|
||||||
>
|
|
||||||
Buyer:<br />{{ formatWalletAddress(lock.args.buyer) }}<br />
|
|
||||||
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>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
header {
|
|
||||||
@apply flex flex-row justify-between w-full items-center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.default-button {
|
|
||||||
@apply p-2 rounded border-2 border-amber-400 text-gray-50 font-extrabold text-base w-full;
|
|
||||||
}
|
|
||||||
|
|
||||||
.default-input {
|
|
||||||
@apply border-none outline-none text-lg text-gray-900 w-64 p-2 rounded-lg;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page {
|
|
||||||
@apply flex gap-8 mt-24;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 1024px) {
|
|
||||||
.page {
|
|
||||||
@apply flex-wrap;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -2,7 +2,7 @@
|
|||||||
import WantSellComponent from "../components/SellerSteps/WantSellComponent.vue";
|
import WantSellComponent from "../components/SellerSteps/WantSellComponent.vue";
|
||||||
import SendNetwork from "../components/SellerSteps/SendNetwork.vue";
|
import SendNetwork from "../components/SellerSteps/SendNetwork.vue";
|
||||||
import ValidationComponent from "../components/LoadingComponent.vue";
|
import ValidationComponent from "../components/LoadingComponent.vue";
|
||||||
import blockchain from "../utils/blockchain";
|
import { approveTokens, addDeposit } from "../blockchain/sellerMethods";
|
||||||
|
|
||||||
import { ref } from "vue";
|
import { ref } from "vue";
|
||||||
import { useEtherStore } from "@/store/ether";
|
import { useEtherStore } from "@/store/ether";
|
||||||
@ -19,19 +19,20 @@ etherStore.setSellerView(true);
|
|||||||
const flowStep = ref<Step>(Step.Sell);
|
const flowStep = ref<Step>(Step.Sell);
|
||||||
const loading = ref<boolean>(false);
|
const loading = ref<boolean>(false);
|
||||||
|
|
||||||
const offerValue = ref<number>();
|
const offerValue = ref<string>("");
|
||||||
const pixKeyBuyer = ref<string>("");
|
const pixKeyBuyer = ref<string>("");
|
||||||
|
|
||||||
// Verificar tipagem
|
// Verificar tipagem
|
||||||
const approveOffer = async ({ offer, pixKey }: any) => {
|
const approveOffer = async (args: { offer: string; pixKey: string }) => {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
try {
|
try {
|
||||||
offerValue.value = offer;
|
offerValue.value = args.offer;
|
||||||
pixKeyBuyer.value = pixKey;
|
pixKeyBuyer.value = args.pixKey;
|
||||||
await blockchain.approveTokens(Number(offerValue.value));
|
await approveTokens(args.offer);
|
||||||
flowStep.value = Step.Network;
|
flowStep.value = Step.Network;
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
} catch {
|
} catch (err) {
|
||||||
|
console.log(err);
|
||||||
flowStep.value = Step.Sell;
|
flowStep.value = Step.Sell;
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
}
|
}
|
||||||
@ -41,7 +42,7 @@ const sendNetwork = async () => {
|
|||||||
loading.value = true;
|
loading.value = true;
|
||||||
try {
|
try {
|
||||||
if (offerValue.value && pixKeyBuyer.value) {
|
if (offerValue.value && pixKeyBuyer.value) {
|
||||||
await blockchain.addDeposit(offerValue.value, pixKeyBuyer.value);
|
await addDeposit(String(offerValue.value), pixKeyBuyer.value);
|
||||||
flowStep.value = Step.Sell;
|
flowStep.value = Step.Sell;
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
}
|
}
|
||||||
|
@ -1,34 +1,42 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useEtherStore } from "@/store/ether";
|
import { useEtherStore } from "@/store/ether";
|
||||||
import { storeToRefs } from "pinia";
|
import { storeToRefs } from "pinia";
|
||||||
import { ref, watch } from "vue";
|
import { ref, watch, onMounted } from "vue";
|
||||||
import ListingComponent from "@/components/ListingComponent.vue";
|
import ListingComponent from "@/components/ListingComponent.vue";
|
||||||
import blockchain from "../utils/blockchain";
|
import { listAllTransactionByWalletAddress } from "@/blockchain/wallet";
|
||||||
|
import type { Event } from "ethers";
|
||||||
|
import type { ValidDeposit } from "@/model/ValidDeposit";
|
||||||
|
|
||||||
const etherStore = useEtherStore();
|
const etherStore = useEtherStore();
|
||||||
const { walletAddress } = storeToRefs(etherStore);
|
const { walletAddress, networkName } = storeToRefs(etherStore);
|
||||||
const allUserTransactions = ref<any[]>([]);
|
const allUserTransactions = ref<(Event | ValidDeposit)[]>([]);
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
if (walletAddress.value) {
|
if (walletAddress.value) {
|
||||||
await blockchain
|
await listAllTransactionByWalletAddress(walletAddress.value).then((res) => {
|
||||||
.listAllTransactionByWalletAddress(walletAddress.value)
|
|
||||||
.then((res) => {
|
|
||||||
if (res) allUserTransactions.value = res;
|
if (res) allUserTransactions.value = res;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
watch(walletAddress, async (newValue) => {
|
watch(walletAddress, async (newValue) => {
|
||||||
await blockchain.listAllTransactionByWalletAddress(newValue).then((res) => {
|
await listAllTransactionByWalletAddress(newValue)
|
||||||
|
.then((res) => {
|
||||||
if (res) allUserTransactions.value = res;
|
if (res) allUserTransactions.value = res;
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
allUserTransactions.value = [];
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
watch(walletAddress, async (newValue) => {
|
watch(networkName, async () => {
|
||||||
console.log(newValue);
|
await listAllTransactionByWalletAddress(walletAddress.value)
|
||||||
|
.then((res) => {
|
||||||
|
if (res) allUserTransactions.value = res;
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
allUserTransactions.value = [];
|
||||||
});
|
});
|
||||||
|
|
||||||
watch(allUserTransactions, (newValue) => {
|
|
||||||
console.log(newValue);
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user