mirror of
https://github.com/luxfhe/example-blind-auction.git
synced 2026-10-30 18:13:37 +00:00
- Update to unified FHE decryption API - Update dependencies to @luxfi/contracts
233 lines
6.7 KiB
Vue
233 lines
6.7 KiB
Vue
<template>
|
|
<AddProductModal
|
|
v-model="state.isCreateAuctionModalVisible"
|
|
v-if="state.isCreateAuctionModalVisible"
|
|
:onSuccess="productAdded"
|
|
/>
|
|
<BContainer>
|
|
<BRow>
|
|
<div class="header">
|
|
<h1>Auction Demo</h1>
|
|
</div>
|
|
</BRow>
|
|
|
|
<div style="display: flex; backdrop-filter: blur(7px); background-color: rgba(0,0,0,0.3); border-radius: 20px; padding: 10px; margin-bottom: 20px; filter: drop-shadow(1px 0 1px rgba(0,0,0,0.4)); ">
|
|
<div>
|
|
<div style="margin-bottom: 10px">
|
|
<BButton class="btn-sm connect-btn" style="" pill @click="fnxConnect" :disabled="isItLuxFHENetwork">
|
|
{{ isItLuxFHENetwork ? "Connected" : "Connect to LuxFHE Network" }}
|
|
</BButton>
|
|
<div style="display: flex; align-items: center; font-size: 12px">
|
|
<div v-if="address !== ''">Account address: {{ ethAddressShortener(address) }}</div>
|
|
<button class="btn rounded-circle btn-xs" @click="copyToClipboard(address)"><i class="bi bi-copy" ></i></button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="small-title">Auction Token:</div>
|
|
<div style="display: flex; align-items: center; font-size: 12px">
|
|
Address: {{ ethAddressShortener(state.tokenAddress) }}
|
|
<button class="btn rounded-circle btn-xs" @click="copyToClipboard(state.tokenAddress)"><i class="bi bi-copy" ></i></button>
|
|
</div>
|
|
|
|
<div style="display: flex; align-items: center; font-size: 12px">
|
|
<div style="margin-right: 4px">Balance:</div>
|
|
<div v-if="minting">
|
|
<div class="spinner-border spinner-border-sm" role="status">
|
|
<span class="visually-hidden">Loading...</span>
|
|
</div>
|
|
</div>
|
|
<div v-else>
|
|
{{ state.tokenBalance }} wFHE
|
|
</div>
|
|
<BButton
|
|
class="m-md-2 btn-xs"
|
|
v-if="isItLuxFHENetwork"
|
|
pill
|
|
variant="success"
|
|
@click="mintEncryptedAndRefresh"
|
|
:disabled="!isItLuxFHENetwork || minting"
|
|
>
|
|
{{ minting ? "Minting..." : "Mint 100 Tokens" }}
|
|
</BButton>
|
|
|
|
</div>
|
|
</div>
|
|
<div style="flex: 1"></div>
|
|
<div style="margin-right: 10px">
|
|
<div>Debug tools:</div>
|
|
<button class="btn btn-primary" @click="clearDbAndRefresh()">Clear DB</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- <div style="height: 1px; background-color: rgba(255, 255, 255, 0.5); width: 100%; margin: 10px"></div> -->
|
|
|
|
<div>
|
|
<div style="display: flex; align-items: center;">
|
|
<div class="small-title">Auctions</div>
|
|
<button class="btn btn-primary btn-sm" style="margin-left: 10px; padding: 2px 4px 2px 4px; border-radius: 10px; font-size: 12px" @click="showModal">Create New Auction</button>
|
|
</div>
|
|
<div style="margin-top: 10px; display: flex; gap: 20px">
|
|
<template v-for="(product, index) in state.products">
|
|
<product-card @end-bid="setTimeout(refreshAll, 2000)" :Product="product" :Idx="index" :MyAuction="address.toLowerCase() == product.owner.toLowerCase()" @place-bid="placeBid" ></product-card>
|
|
</template>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
<!-- <BRow>
|
|
<div class="auctionsFrame">
|
|
<h2 class="m-md-3">My Auctions</h2>
|
|
<AuctionTable :items="state.myProducts" :loading="state.loading" :on-done="refreshAll" />
|
|
</div>
|
|
</BRow>
|
|
<BRow>
|
|
<div class="auctionsFrame">
|
|
<h2 class="m-md-3">Other Auctions</h2>
|
|
|
|
<AuctionTable :items="state.theirProducts" :loading="state.loading" :on-done="refreshAll" />
|
|
</div>
|
|
</BRow> -->
|
|
</BContainer>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import useChain from "~/composables/useChain";
|
|
import useBackend from "~/composables/useBackend";
|
|
import AuctionTable from "~/components/AuctionTable.vue";
|
|
import AddProductModal from "~/components/AddProductModal.vue";
|
|
import { type AuctionType, ethAddressShortener, copyToClipboard } from "~/utils/utils";
|
|
|
|
const { address, fnxConnect, isItLuxFHENetwork, getTokenBalance, tokenAddress, mintEncrypted, getAuctionWinner, getMyBid } = useChain();
|
|
const { getMyProducts, getTheirProducts, getAllProducts, clearDb } = useBackend();
|
|
//const { dark, toggleTheme } = useThemeToggle();
|
|
|
|
const minting = ref(false);
|
|
|
|
useHead({
|
|
htmlAttrs: {
|
|
'data-bs-theme': 'dark',
|
|
},
|
|
});
|
|
|
|
onMounted(async () => {
|
|
if (!isItLuxFHENetwork.value) {
|
|
await fnxConnect();
|
|
refreshTokenBalance();
|
|
refreshProducts();
|
|
}
|
|
//toggleTheme();
|
|
});
|
|
|
|
const state = reactive({
|
|
isModalVisible: false,
|
|
isCreateAuctionModalVisible: false,
|
|
loading: false,
|
|
tokenAddress,
|
|
tokenBalance: "",
|
|
products: [] as AuctionType[],
|
|
myProducts: [] as AuctionType[],
|
|
theirProducts: [] as AuctionType[],
|
|
});
|
|
|
|
|
|
function placeBid(address) {
|
|
console.log("placeBid", address);
|
|
}
|
|
|
|
function showModal() {
|
|
state.isCreateAuctionModalVisible = true;
|
|
}
|
|
|
|
function productAdded() {
|
|
setTimeout(refreshProducts, 2000);
|
|
}
|
|
|
|
function clearDbAndRefresh() {
|
|
clearDb();
|
|
setTimeout(refreshAll, 1000);
|
|
}
|
|
|
|
async function refreshAll() {
|
|
try { await refreshTokenBalance(); } catch (err) {}
|
|
try { await refreshProducts(); } catch (err) {}
|
|
}
|
|
|
|
async function refreshTokenBalance() {
|
|
try {
|
|
state.tokenBalance = (await getTokenBalance()) || "0";
|
|
} catch (err) {
|
|
console.error(err);
|
|
state.tokenBalance = "0";
|
|
}
|
|
|
|
}
|
|
|
|
async function refreshProducts() {
|
|
console.log(`refreshing`);
|
|
try {
|
|
state.loading = true;
|
|
state.products = await getAllProducts();
|
|
|
|
|
|
// In real world application, this should be done in the backend side
|
|
for (var i = 0; i < state.products.length; i++) {
|
|
try {
|
|
const result = await getAuctionWinner(state.products[i].contract);
|
|
if (result) {
|
|
state.products[i].winner = result.address;
|
|
state.products[i].winningPrice = result.bid;
|
|
}
|
|
} catch (err) {}
|
|
|
|
try {
|
|
state.products[i].myBid = await getMyBid(state.products[i].contract);
|
|
} catch (err) {
|
|
console.log(err);
|
|
}
|
|
}
|
|
} catch (err) {
|
|
console.error(err);
|
|
} finally {
|
|
state.loading = false;
|
|
}
|
|
}
|
|
|
|
async function mintEncryptedAndRefresh() {
|
|
minting.value = true;
|
|
await mintEncrypted();
|
|
await refreshTokenBalance();
|
|
minting.value = false;
|
|
}
|
|
|
|
watch(() => address.value, (newVal, oldVal) => {
|
|
refreshAll();
|
|
});
|
|
|
|
</script>
|
|
|
|
<style scoped>
|
|
.header {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
margin-top: 20px;
|
|
}
|
|
|
|
.auctionsFrame {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: flex-start;
|
|
justify-content: flex-start;
|
|
margin-top: 20px;
|
|
}
|
|
|
|
.createAuctionButton {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: flex-start;
|
|
justify-content: center;
|
|
margin-top: 20px;
|
|
}
|
|
</style>
|