Skip to content

Commit

Permalink
improved UI
Browse files Browse the repository at this point in the history
Signed-off-by: Alexander Diemand <codieplusplus@apax.net>
  • Loading branch information
CodiePP committed Nov 21, 2024
1 parent 001bd79 commit ea60b6c
Show file tree
Hide file tree
Showing 2 changed files with 207 additions and 15 deletions.
18 changes: 18 additions & 0 deletions bca-token-market/src/lib/contracts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,21 @@ import abi_service_json from "$lib/bca_service-abi.json"
export const serviceABI = abi_service_json["abi"];
import abi_serviceinstance_json from "$lib/bca_serviceinstance-abi.json"
export const serviceInstanceABI = abi_serviceinstance_json["abi"];

// token constants
export const token_symbol: string = 'BCA1'
export const token_decimals: number = 18

// calculations
export function calculate_user_balance(deposit: number, startTime: number, dayPrice: number) {
if (startTime <= 0) { return deposit }
const now = new Date().getTime()
const deltaMilsecs = now - startTime * 1000
return Math.max(0, deposit - (dayPrice * deltaMilsecs / 24 / 3600 / 1000))
}
export function calculate_provider_balance(deposit: number, retracted: number, startTime: number, dayPrice: number) {
if (startTime <= 0) { return deposit }
const now = new Date().getTime()
const deltaMilsecs = now - startTime * 1000
return Math.max(0, Math.min(deposit, dayPrice * deltaMilsecs / 24 / 3600 / 1000) - retracted)
}
204 changes: 189 additions & 15 deletions bca-token-market/src/routes/serviceinstance/[addr]/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import { onMount } from 'svelte'
import { createForm } from "svelte-forms-lib";
import { Contract, Web3 } from 'web3'
import { serviceInstanceABI, tokenContractABI } from "$lib/contracts.js"
import { serviceInstanceABI, tokenContractABI, token_symbol, token_decimals, calculate_user_balance, calculate_provider_balance } from "$lib/contracts.js"
import { WalletInformation, reset_warning, get_wallet_addr, wallet_logout } from '$lib/wallet'
import { number } from "zod";
Expand All @@ -14,11 +14,14 @@
onMount ( async () => {
if (window.ethereum) {
window.web3 = new Web3(window.ethereum);
local_get_wallet_addr({target: undefined})
} else {
wallet.warning = "no web3 wallet attached!"
}
})
$: has_wallet = !!wallet.walletaddr
const is_provider = $page.data.session?.user?.role == "Provider"
async function local_get_wallet_addr(ev) {
Expand All @@ -31,6 +34,18 @@
reset_warning(wallet);
}
const locale = 'en' // better get this from the browser
const options: Intl.DateTimeFormatOptions = {
weekday: undefined,
year: 'numeric',
month: 'numeric',
day: 'numeric',
hour: '2-digit',
minute: '2-digit',
second: '2-digit'
}
const date_formatter = new Intl.DateTimeFormat(locale, options)
let details: { dayPrice: number; deposit: number; retracted: number; startTime: number; endTime: number; userAddress: string; providerAddress: string; tokenAddress: string } | undefined = undefined
async function read_contract(contractAddress: string) {
if (window.web3 && wallet.walletaddr && contractAddress) {
Expand All @@ -55,12 +70,43 @@
return this.toString();
};
let contractevents = undefined //: { event: string, blockNumber: string, blockHash: string, transactionHash: string, address: string, returnValues: Record<string,string>, topics: string[] }[] | undefined = undefined
async function list_events() {
if (window.web3 && wallet.walletaddr !== undefined && data !== undefined && data.addr) {
let contract: Contract<typeof serviceInstanceABI> = new window.web3.eth.Contract(serviceInstanceABI, data.addr)
contract.getPastEvents('ALLEVENTS', { fromBlock: 0, toBlock: 'latest'}).then(function (events) {
if (events.length) {
contractevents = events
// console.log(JSON.stringify(events,null,2))
}
})
} else {
contractevents = undefined
}
}
async function get_transaction(txhash: string) {
if (window.web3 && txhash) {
window.web3.eth.getTransaction(txhash).then((tx) => console.log(JSON.stringify(tx,null,2)))
}
}
async function get_block_time(blockHash: string): Promise<bigint> {
if (window.web3 && blockHash) {
// console.log(`get_block_time ${blockHash}`)
const bdata = await window.web3.eth.getBlock(blockHash, false)
if (bdata && bdata.timestamp) {
// console.log(`block data: ${JSON.stringify(bdata,null,2)}`)
return BigInt(bdata.timestamp)
}
return 0n
}
return 0n
}
async function withdraw_user(amount: number, useGas: number) {
if (window.web3 && wallet.walletaddr !== undefined && data !== undefined && data.addr) {
const contract = new window.web3.eth.Contract(serviceInstanceABI, data.addr);
contract.setConfig({ "defaultNetworkId": wallet.walletnetwork });
try {
const one_token: number = 10**18;
const one_token: number = 10**(token_decimals);
const gasPrice = await window.web3.eth.getGasPrice();
let estimatedGas = useGas;
if (wallet.walletnetwork === "0x89") { // Polygon
Expand All @@ -87,7 +133,7 @@
const contract = new window.web3.eth.Contract(serviceInstanceABI, data.addr);
contract.setConfig({ "defaultNetworkId": wallet.walletnetwork });
try {
const one_token: number = 10**18;
const one_token: number = 10**(token_decimals);
const gasPrice = await window.web3.eth.getGasPrice();
let estimatedGas = useGas;
if (wallet.walletnetwork === "0x89") { // Polygon
Expand Down Expand Up @@ -187,39 +233,89 @@
<div class="w3-container w3-padding-32">

{#if $page.data.session}
<span id="details"></span>
<p>&nbsp;</p>

<h2 class="{is_provider ? 'w3-green' : 'w3-gray'}">Service Instance</h2>

<h3>Details</h3>

<h2 class="{is_provider ? 'w3-green' : 'w3-gray'}">Service Instance - {data.addr}</h2>
<div class="w3-bar w3-theme">
<a href="#details" class="w3-bar-item w3-button w3-hover-white">Details</a>
<a href="#contract" class="w3-bar-item w3-button {has_wallet ? "w3-hover-white" : 'w3-disabled'}">Contract</a>
<a href="#events" class="w3-bar-item w3-button {has_wallet ? "w3-hover-white" : 'w3-disabled'}">Events</a>
<a href="#transactions" class="w3-bar-item w3-button {has_wallet ? "w3-hover-white" : 'w3-disabled'}">Transactions</a>
</div>

<section class="addr-section">
<ul>
<li>Contract address: {data.addr}</li>
{#if wallet.walletnetwork === "0x89"}
<li>PolygonScan: <a href={"https://polygonscan.com/address/"+data.addr}>view</a></li>
{:else if wallet.walletnetwork === "0x80002"}
<li>PolygonScan: <a href={"https://polygonscan.com/address/"+data.addr}>view</a></li>
{/if}
</ul>
</section>

<section class="login-section">
{#if wallet.walletaddr == undefined}
{#if !has_wallet}
<p><button type="button" class="login-btn" on:click={ (ev) => local_get_wallet_addr(ev) }>🔓 Log in with Web3</button></p>
<span class="instruction">
Ensure to have an Ethereum based wallet installed i.e MetaMask. Change the network and account in the wallet and
click the button again to update the app's state.
</span>
{:else}
<p><button type="button" class="logout-btn" on:click={ () => local_wallet_logout() }>🔐 Log out</button></p>
<p>connected:
<span> network: {wallet.walletnetwork} </span>
<span> address: {wallet.walletaddr} </span>
<button type="button" class="logout-btn" on:click={ () => local_wallet_logout() }>🔐 Log out</button></p>
{/if}
</section>

<p><br/></p>
<p><br/></p>
<p><br/></p>
<p><br/></p>
<p><br/></p>
<p><br/></p>
<p><br/></p>
<p><br/></p>
<span id="contract"></span>
<p>&nbsp;</p>

<h2 class="{is_provider ? 'w3-green' : 'w3-gray'}">Service Instance</h2>

<h3>Contract</h3>

<button type="button" on:click={() => read_contract(data.addr)}>show</button>
<div class="w3-bar w3-theme">
<a href="#details" class="w3-bar-item w3-button w3-hover-white">Details</a>
<a href="#contract" class="w3-bar-item w3-button {has_wallet ? "w3-hover-white" : 'w3-disabled'}">Contract</a>
<a href="#events" class="w3-bar-item w3-button {has_wallet ? "w3-hover-white" : 'w3-disabled'}">Events</a>
<a href="#transactions" class="w3-bar-item w3-button {has_wallet ? "w3-hover-white" : 'w3-disabled'}">Transactions</a>
</div>

<div>
<p><button type="button" class="{has_wallet ? "w3-theme" : 'w3-disabled'}" on:click={() => has_wallet && read_contract(data.addr)}><i class="fa fa-refresh"></i></button></p>

{#if details !== undefined && wallet.walletaddr !== undefined}
<p>daily price: {details.dayPrice / 10**18}</p>
<p>user deposit: {details.deposit / 10**18}</p>
<p>retracted: {details.retracted / 10**18}</p>
<p>start time: {details.startTime}</p>
<p>end time: {details.endTime}</p>
<p>provider address: {details.providerAddress}</p>
<p>user address: {details.userAddress}</p>
<ul>
<li>daily price: {details.dayPrice / 10**(token_decimals)} {token_symbol}</li>
<li>user deposit: {details.deposit / 10**(token_decimals)} {token_symbol}</li>
<li>retracted: {details.retracted / 10**(token_decimals)} {token_symbol}</li>
<li>start time: { details.startTime > 0 ? date_formatter.format(details.startTime * 1000) : '' }</li>
<li>end time: {details.endTime > 0 ? date_formatter.format(details.endTime * 1000) : (details.startTime > 0 ? "(" + date_formatter.format(details.startTime * 1000 + (details.deposit * 1000 * 24 * 3600 / details.dayPrice)) + ") estimated" : '') }</li>
<li>provider address: {details.providerAddress}</li>
<li>user address: {details.userAddress}</li>
<li>estimated user balance: { calculate_user_balance(details.deposit, details.startTime, details.dayPrice) / 10**(token_decimals)} {token_symbol}</li>
<li>estimated provider balance: { calculate_provider_balance(details.deposit, details.retracted, details.startTime, details.dayPrice) / 10**(token_decimals)} {token_symbol}</li>
</ul>
{/if}

<section class="withdrawal">
<h3>Withdrawal from contract</h3>
<form on:submit={w_handleSubmit}>
<label for="amount">amount:</label>
<label for="amount">amount {token_symbol}:</label>
<input
id="amount"
name="amount"
Expand Down Expand Up @@ -262,6 +358,84 @@
</form>
</section>
{/if}
</div>

<p><br/></p>
<p><br/></p>
<p><br/></p>
<p><br/></p>
<p><br/></p>
<p><br/></p>
<p><br/></p>
<p><br/></p>
<span id="events"></span>
<p>&nbsp;</p>

<h2 class="{is_provider ? 'w3-green' : 'w3-gray'}">Service Instance</h2>
<h3>Events</h3>

<div class="w3-bar w3-theme">
<a href="#details" class="w3-bar-item w3-button w3-hover-white">Details</a>
<a href="#contract" class="w3-bar-item w3-button {has_wallet ? "w3-hover-white" : 'w3-disabled'}">Contract</a>
<a href="#events" class="w3-bar-item w3-button {has_wallet ? "w3-hover-white" : 'w3-disabled'}">Events</a>
<a href="#transactions" class="w3-bar-item w3-button {has_wallet ? "w3-hover-white" : 'w3-disabled'}">Transactions</a>
</div>

<div>
<p><button type="button" class="{has_wallet ? "w3-theme" : 'w3-disabled'}" on:click={() => has_wallet && list_events()}><i class="fa fa-refresh"></i></button></p>

{#if contractevents && contractevents.length}
{#each contractevents as cev}
<h4>{cev.event ? cev.event : "some event"}</h4>
<table class="w3-table w3-bordered">
<tr><td>Timestamp:</td><td>
{#await get_block_time(cev.blockHash) then timestamp}
{date_formatter.format(Number(timestamp * 1000n))}
{:catch}
<i class="fa fa-thumbs-down"></i> error
{/await}
</td></tr>
<tr><td>Block:</td><td>#{cev.blockNumber ? cev.blockNumber : "#?"} {cev.blockHash ? cev.blockHash : "0x.."}</td></tr>
<tr><td>Transaction:</td><td>
{#if cev.transactionHash}
<button type="button" class="w3-btn" on:click={() => has_wallet && get_transaction(cev.transactionHash)}>{cev.transactionHash}</button>
{:else}
"no transaction info"
{/if}
</td></tr>
<tr><td>Address:</td><td>{cev.address ? cev.address : "0x.."}</td></tr>
<tr><td>Topics:</td><td>{cev.topics ? JSON.stringify(cev.topics,null,2) : "[ ]"}</td></tr>
<tr><td>Values:</td><td>{cev.returnValues ? JSON.stringify(cev.returnValues,null,2) : "{ }"}</td></tr>
</table>
{/each}
{/if} </div>

<p><br/></p>
<p><br/></p>
<p><br/></p>
<p><br/></p>
<p><br/></p>
<p><br/></p>
<p><br/></p>
<p><br/></p>
<span id="transactions"></span>
<p>&nbsp;</p>

<h2 class="{is_provider ? 'w3-green' : 'w3-gray'}">Service Instance</h2>
<h3>Transactions</h3>

<div class="w3-bar w3-theme">
<a href="#details" class="w3-bar-item w3-button w3-hover-white">Details</a>
<a href="#contract" class="w3-bar-item w3-button {has_wallet ? "w3-hover-white" : 'w3-disabled'}">Contract</a>
<a href="#events" class="w3-bar-item w3-button {has_wallet ? "w3-hover-white" : 'w3-disabled'}">Events</a>
<a href="#transactions" class="w3-bar-item w3-button {has_wallet ? "w3-hover-white" : 'w3-disabled'}">Transactions</a>
</div>

<div>
<p><br/></p>
<p><br/></p>
<p><br/></p>
</div>

{/if}
</div>
Expand Down

0 comments on commit ea60b6c

Please sign in to comment.