Skip to content

Commit ea60b6c

Browse files
committed
improved UI
Signed-off-by: Alexander Diemand <[email protected]>
1 parent 001bd79 commit ea60b6c

File tree

2 files changed

+207
-15
lines changed

2 files changed

+207
-15
lines changed

bca-token-market/src/lib/contracts.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,21 @@ import abi_service_json from "$lib/bca_service-abi.json"
2121
export const serviceABI = abi_service_json["abi"];
2222
import abi_serviceinstance_json from "$lib/bca_serviceinstance-abi.json"
2323
export const serviceInstanceABI = abi_serviceinstance_json["abi"];
24+
25+
// token constants
26+
export const token_symbol: string = 'BCA1'
27+
export const token_decimals: number = 18
28+
29+
// calculations
30+
export function calculate_user_balance(deposit: number, startTime: number, dayPrice: number) {
31+
if (startTime <= 0) { return deposit }
32+
const now = new Date().getTime()
33+
const deltaMilsecs = now - startTime * 1000
34+
return Math.max(0, deposit - (dayPrice * deltaMilsecs / 24 / 3600 / 1000))
35+
}
36+
export function calculate_provider_balance(deposit: number, retracted: number, startTime: number, dayPrice: number) {
37+
if (startTime <= 0) { return deposit }
38+
const now = new Date().getTime()
39+
const deltaMilsecs = now - startTime * 1000
40+
return Math.max(0, Math.min(deposit, dayPrice * deltaMilsecs / 24 / 3600 / 1000) - retracted)
41+
}

bca-token-market/src/routes/serviceinstance/[addr]/+page.svelte

Lines changed: 189 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import { onMount } from 'svelte'
44
import { createForm } from "svelte-forms-lib";
55
import { Contract, Web3 } from 'web3'
6-
import { serviceInstanceABI, tokenContractABI } from "$lib/contracts.js"
6+
import { serviceInstanceABI, tokenContractABI, token_symbol, token_decimals, calculate_user_balance, calculate_provider_balance } from "$lib/contracts.js"
77
import { WalletInformation, reset_warning, get_wallet_addr, wallet_logout } from '$lib/wallet'
88
import { number } from "zod";
99
@@ -14,11 +14,14 @@
1414
onMount ( async () => {
1515
if (window.ethereum) {
1616
window.web3 = new Web3(window.ethereum);
17+
local_get_wallet_addr({target: undefined})
1718
} else {
1819
wallet.warning = "no web3 wallet attached!"
1920
}
2021
})
2122
23+
$: has_wallet = !!wallet.walletaddr
24+
2225
const is_provider = $page.data.session?.user?.role == "Provider"
2326
2427
async function local_get_wallet_addr(ev) {
@@ -31,6 +34,18 @@
3134
reset_warning(wallet);
3235
}
3336
37+
const locale = 'en' // better get this from the browser
38+
const options: Intl.DateTimeFormatOptions = {
39+
weekday: undefined,
40+
year: 'numeric',
41+
month: 'numeric',
42+
day: 'numeric',
43+
hour: '2-digit',
44+
minute: '2-digit',
45+
second: '2-digit'
46+
}
47+
const date_formatter = new Intl.DateTimeFormat(locale, options)
48+
3449
let details: { dayPrice: number; deposit: number; retracted: number; startTime: number; endTime: number; userAddress: string; providerAddress: string; tokenAddress: string } | undefined = undefined
3550
async function read_contract(contractAddress: string) {
3651
if (window.web3 && wallet.walletaddr && contractAddress) {
@@ -55,12 +70,43 @@
5570
return this.toString();
5671
};
5772
73+
let contractevents = undefined //: { event: string, blockNumber: string, blockHash: string, transactionHash: string, address: string, returnValues: Record<string,string>, topics: string[] }[] | undefined = undefined
74+
async function list_events() {
75+
if (window.web3 && wallet.walletaddr !== undefined && data !== undefined && data.addr) {
76+
let contract: Contract<typeof serviceInstanceABI> = new window.web3.eth.Contract(serviceInstanceABI, data.addr)
77+
contract.getPastEvents('ALLEVENTS', { fromBlock: 0, toBlock: 'latest'}).then(function (events) {
78+
if (events.length) {
79+
contractevents = events
80+
// console.log(JSON.stringify(events,null,2))
81+
}
82+
})
83+
} else {
84+
contractevents = undefined
85+
}
86+
}
87+
async function get_transaction(txhash: string) {
88+
if (window.web3 && txhash) {
89+
window.web3.eth.getTransaction(txhash).then((tx) => console.log(JSON.stringify(tx,null,2)))
90+
}
91+
}
92+
async function get_block_time(blockHash: string): Promise<bigint> {
93+
if (window.web3 && blockHash) {
94+
// console.log(`get_block_time ${blockHash}`)
95+
const bdata = await window.web3.eth.getBlock(blockHash, false)
96+
if (bdata && bdata.timestamp) {
97+
// console.log(`block data: ${JSON.stringify(bdata,null,2)}`)
98+
return BigInt(bdata.timestamp)
99+
}
100+
return 0n
101+
}
102+
return 0n
103+
}
58104
async function withdraw_user(amount: number, useGas: number) {
59105
if (window.web3 && wallet.walletaddr !== undefined && data !== undefined && data.addr) {
60106
const contract = new window.web3.eth.Contract(serviceInstanceABI, data.addr);
61107
contract.setConfig({ "defaultNetworkId": wallet.walletnetwork });
62108
try {
63-
const one_token: number = 10**18;
109+
const one_token: number = 10**(token_decimals);
64110
const gasPrice = await window.web3.eth.getGasPrice();
65111
let estimatedGas = useGas;
66112
if (wallet.walletnetwork === "0x89") { // Polygon
@@ -87,7 +133,7 @@
87133
const contract = new window.web3.eth.Contract(serviceInstanceABI, data.addr);
88134
contract.setConfig({ "defaultNetworkId": wallet.walletnetwork });
89135
try {
90-
const one_token: number = 10**18;
136+
const one_token: number = 10**(token_decimals);
91137
const gasPrice = await window.web3.eth.getGasPrice();
92138
let estimatedGas = useGas;
93139
if (wallet.walletnetwork === "0x89") { // Polygon
@@ -187,39 +233,89 @@
187233
<div class="w3-container w3-padding-32">
188234

189235
{#if $page.data.session}
236+
<span id="details"></span>
237+
<p>&nbsp;</p>
238+
239+
<h2 class="{is_provider ? 'w3-green' : 'w3-gray'}">Service Instance</h2>
240+
241+
<h3>Details</h3>
190242

191-
<h2 class="{is_provider ? 'w3-green' : 'w3-gray'}">Service Instance - {data.addr}</h2>
243+
<div class="w3-bar w3-theme">
244+
<a href="#details" class="w3-bar-item w3-button w3-hover-white">Details</a>
245+
<a href="#contract" class="w3-bar-item w3-button {has_wallet ? "w3-hover-white" : 'w3-disabled'}">Contract</a>
246+
<a href="#events" class="w3-bar-item w3-button {has_wallet ? "w3-hover-white" : 'w3-disabled'}">Events</a>
247+
<a href="#transactions" class="w3-bar-item w3-button {has_wallet ? "w3-hover-white" : 'w3-disabled'}">Transactions</a>
248+
</div>
249+
250+
<section class="addr-section">
251+
<ul>
252+
<li>Contract address: {data.addr}</li>
253+
{#if wallet.walletnetwork === "0x89"}
254+
<li>PolygonScan: <a href={"https://polygonscan.com/address/"+data.addr}>view</a></li>
255+
{:else if wallet.walletnetwork === "0x80002"}
256+
<li>PolygonScan: <a href={"https://polygonscan.com/address/"+data.addr}>view</a></li>
257+
{/if}
258+
</ul>
259+
</section>
192260

193261
<section class="login-section">
194-
{#if wallet.walletaddr == undefined}
262+
{#if !has_wallet}
195263
<p><button type="button" class="login-btn" on:click={ (ev) => local_get_wallet_addr(ev) }>🔓 Log in with Web3</button></p>
196264
<span class="instruction">
197265
Ensure to have an Ethereum based wallet installed i.e MetaMask. Change the network and account in the wallet and
198266
click the button again to update the app's state.
199267
</span>
200268
{:else}
201-
<p><button type="button" class="logout-btn" on:click={ () => local_wallet_logout() }>🔐 Log out</button></p>
269+
<p>connected:
202270
<span> network: {wallet.walletnetwork} </span>
203271
<span> address: {wallet.walletaddr} </span>
272+
<button type="button" class="logout-btn" on:click={ () => local_wallet_logout() }>🔐 Log out</button></p>
204273
{/if}
205274
</section>
275+
276+
<p><br/></p>
277+
<p><br/></p>
278+
<p><br/></p>
279+
<p><br/></p>
280+
<p><br/></p>
281+
<p><br/></p>
282+
<p><br/></p>
283+
<p><br/></p>
284+
<span id="contract"></span>
285+
<p>&nbsp;</p>
286+
287+
<h2 class="{is_provider ? 'w3-green' : 'w3-gray'}">Service Instance</h2>
288+
289+
<h3>Contract</h3>
206290

207-
<button type="button" on:click={() => read_contract(data.addr)}>show</button>
291+
<div class="w3-bar w3-theme">
292+
<a href="#details" class="w3-bar-item w3-button w3-hover-white">Details</a>
293+
<a href="#contract" class="w3-bar-item w3-button {has_wallet ? "w3-hover-white" : 'w3-disabled'}">Contract</a>
294+
<a href="#events" class="w3-bar-item w3-button {has_wallet ? "w3-hover-white" : 'w3-disabled'}">Events</a>
295+
<a href="#transactions" class="w3-bar-item w3-button {has_wallet ? "w3-hover-white" : 'w3-disabled'}">Transactions</a>
296+
</div>
297+
298+
<div>
299+
<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>
208300

209301
{#if details !== undefined && wallet.walletaddr !== undefined}
210-
<p>daily price: {details.dayPrice / 10**18}</p>
211-
<p>user deposit: {details.deposit / 10**18}</p>
212-
<p>retracted: {details.retracted / 10**18}</p>
213-
<p>start time: {details.startTime}</p>
214-
<p>end time: {details.endTime}</p>
215-
<p>provider address: {details.providerAddress}</p>
216-
<p>user address: {details.userAddress}</p>
302+
<ul>
303+
<li>daily price: {details.dayPrice / 10**(token_decimals)} {token_symbol}</li>
304+
<li>user deposit: {details.deposit / 10**(token_decimals)} {token_symbol}</li>
305+
<li>retracted: {details.retracted / 10**(token_decimals)} {token_symbol}</li>
306+
<li>start time: { details.startTime > 0 ? date_formatter.format(details.startTime * 1000) : '' }</li>
307+
<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>
308+
<li>provider address: {details.providerAddress}</li>
309+
<li>user address: {details.userAddress}</li>
310+
<li>estimated user balance: { calculate_user_balance(details.deposit, details.startTime, details.dayPrice) / 10**(token_decimals)} {token_symbol}</li>
311+
<li>estimated provider balance: { calculate_provider_balance(details.deposit, details.retracted, details.startTime, details.dayPrice) / 10**(token_decimals)} {token_symbol}</li>
312+
</ul>
217313
{/if}
218314

219315
<section class="withdrawal">
220316
<h3>Withdrawal from contract</h3>
221317
<form on:submit={w_handleSubmit}>
222-
<label for="amount">amount:</label>
318+
<label for="amount">amount {token_symbol}:</label>
223319
<input
224320
id="amount"
225321
name="amount"
@@ -262,6 +358,84 @@
262358
</form>
263359
</section>
264360
{/if}
361+
</div>
362+
363+
<p><br/></p>
364+
<p><br/></p>
365+
<p><br/></p>
366+
<p><br/></p>
367+
<p><br/></p>
368+
<p><br/></p>
369+
<p><br/></p>
370+
<p><br/></p>
371+
<span id="events"></span>
372+
<p>&nbsp;</p>
373+
374+
<h2 class="{is_provider ? 'w3-green' : 'w3-gray'}">Service Instance</h2>
375+
<h3>Events</h3>
376+
377+
<div class="w3-bar w3-theme">
378+
<a href="#details" class="w3-bar-item w3-button w3-hover-white">Details</a>
379+
<a href="#contract" class="w3-bar-item w3-button {has_wallet ? "w3-hover-white" : 'w3-disabled'}">Contract</a>
380+
<a href="#events" class="w3-bar-item w3-button {has_wallet ? "w3-hover-white" : 'w3-disabled'}">Events</a>
381+
<a href="#transactions" class="w3-bar-item w3-button {has_wallet ? "w3-hover-white" : 'w3-disabled'}">Transactions</a>
382+
</div>
383+
384+
<div>
385+
<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>
386+
387+
{#if contractevents && contractevents.length}
388+
{#each contractevents as cev}
389+
<h4>{cev.event ? cev.event : "some event"}</h4>
390+
<table class="w3-table w3-bordered">
391+
<tr><td>Timestamp:</td><td>
392+
{#await get_block_time(cev.blockHash) then timestamp}
393+
{date_formatter.format(Number(timestamp * 1000n))}
394+
{:catch}
395+
<i class="fa fa-thumbs-down"></i> error
396+
{/await}
397+
</td></tr>
398+
<tr><td>Block:</td><td>#{cev.blockNumber ? cev.blockNumber : "#?"} {cev.blockHash ? cev.blockHash : "0x.."}</td></tr>
399+
<tr><td>Transaction:</td><td>
400+
{#if cev.transactionHash}
401+
<button type="button" class="w3-btn" on:click={() => has_wallet && get_transaction(cev.transactionHash)}>{cev.transactionHash}</button>
402+
{:else}
403+
"no transaction info"
404+
{/if}
405+
</td></tr>
406+
<tr><td>Address:</td><td>{cev.address ? cev.address : "0x.."}</td></tr>
407+
<tr><td>Topics:</td><td>{cev.topics ? JSON.stringify(cev.topics,null,2) : "[ ]"}</td></tr>
408+
<tr><td>Values:</td><td>{cev.returnValues ? JSON.stringify(cev.returnValues,null,2) : "{ }"}</td></tr>
409+
</table>
410+
{/each}
411+
{/if} </div>
412+
413+
<p><br/></p>
414+
<p><br/></p>
415+
<p><br/></p>
416+
<p><br/></p>
417+
<p><br/></p>
418+
<p><br/></p>
419+
<p><br/></p>
420+
<p><br/></p>
421+
<span id="transactions"></span>
422+
<p>&nbsp;</p>
423+
424+
<h2 class="{is_provider ? 'w3-green' : 'w3-gray'}">Service Instance</h2>
425+
<h3>Transactions</h3>
426+
427+
<div class="w3-bar w3-theme">
428+
<a href="#details" class="w3-bar-item w3-button w3-hover-white">Details</a>
429+
<a href="#contract" class="w3-bar-item w3-button {has_wallet ? "w3-hover-white" : 'w3-disabled'}">Contract</a>
430+
<a href="#events" class="w3-bar-item w3-button {has_wallet ? "w3-hover-white" : 'w3-disabled'}">Events</a>
431+
<a href="#transactions" class="w3-bar-item w3-button {has_wallet ? "w3-hover-white" : 'w3-disabled'}">Transactions</a>
432+
</div>
433+
434+
<div>
435+
<p><br/></p>
436+
<p><br/></p>
437+
<p><br/></p>
438+
</div>
265439

266440
{/if}
267441
</div>

0 commit comments

Comments
 (0)