Skip to content

Commit 0652f29

Browse files
j-muellerJann Müller
andauthored
Demo fixes (#75)
* Use address instead of account * Rename accounts. Copy address from WST table * More fixes * Enable connected wallet again * Fix link to transaction * Add screenshot * Fix link to transactio in wallet * Linter warning * Fix mint endpoint * Add override to submit failing tx to network * Fix UI build * Start updating balance * Show ada balance * Fix table; add override to transfer * Override field is mandatory * More progress on submitting invalid transaction * Finish 'force submit' failing transaction * Update schema --------- Co-authored-by: Jann Müller <[email protected]>
1 parent 960b08a commit 0652f29

File tree

22 files changed

+262
-137
lines changed

22 files changed

+262
-137
lines changed

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# Regulated stablecoin POC
22

3-
This is a proof-of-concept for a regulated stablecoin. It is NOT a finished product.
3+
This is a proof-of-concept for a regulated token with freeze and seize capabilities.
4+
5+
![Screenshot of the UI showing the minting authority.](image.png)
46

57
# Overview
68

@@ -20,6 +22,7 @@ This repository contains
2022
* A user interface that implements the use cases using browser-based wallets. Based on next.js and lucid.
2123
* An OCI container image with the on-chain code, the off-chain code and the UI
2224

25+
2326
With the container image it is possible to run the complete system locally with just a single command.
2427
There is no need to install the build toolchain or to operate a cardano node or related infrastructure.
2528
The image can even be used to interact with existing deployments of the POC.

cabal.project

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,8 @@ source-repository-package
4141

4242
source-repository-package
4343
type: git
44-
-- location: https://github.com/j-mueller/sc-tools
45-
location: https://github.com/amirmrad/sc-tools
46-
tag: 6c63efe07015e87719d77fa3fabfe07f959c7227
44+
location: https://github.com/j-mueller/sc-tools
45+
tag: a3662e093f40082dd6fa525bb0640a10caa1bd70
4746
subdir:
4847
src/devnet
4948
src/blockfrost

frontend/src/app/[username]/index.tsx

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import React, { useEffect, useState } from 'react';
66
import axios from 'axios';
77

88
//Mui imports
9-
import { Box, Typography } from '@mui/material';
9+
import { Box, Checkbox, FormControlLabel, Typography } from '@mui/material';
1010

1111
//Local components
1212
import useStore from '../store/store';
@@ -19,6 +19,7 @@ import CopyTextField from '../components/CopyTextField';
1919
export default function Profile() {
2020
const { lucid, currentUser, mintAccount, changeAlertInfo, changeWalletAccountDetails } = useStore();
2121
const accounts = useStore((state) => state.accounts);
22+
const [overrideTx, setOverrideTx] = useState<boolean>(false);
2223

2324
useEffect(() => {
2425
useStore.getState();
@@ -27,8 +28,8 @@ export default function Profile() {
2728

2829
const getUserAccountDetails = () => {
2930
switch (currentUser) {
30-
case "User A": return accounts.userA;
31-
case "User B": return accounts.userB;
31+
case "Alice": return accounts.alice;
32+
case "Bob": return accounts.bob;
3233
case "Connected Wallet": return accounts.walletUser;
3334
};
3435
};
@@ -38,10 +39,10 @@ export default function Profile() {
3839
const [sendRecipientAddress, setsendRecipientAddress] = useState('address');
3940

4041
const onSend = async () => {
41-
if (getUserAccountDetails()?.status === 'Frozen') {
42+
if (getUserAccountDetails()?.status === 'Frozen' && !overrideTx) {
4243
changeAlertInfo({
4344
severity: 'error',
44-
message: 'Cannot send WST with frozen account.',
45+
message: 'Cannot send WST with frozen address.',
4546
open: true,
4647
link: ''
4748
});
@@ -51,7 +52,7 @@ export default function Profile() {
5152
changeAlertInfo({severity: 'info', message: 'Transaction processing', open: true, link: ''});
5253
const accountInfo = getUserAccountDetails();
5354
if (!accountInfo) {
54-
console.error("No valid send account found! Cannot send.");
55+
console.error("No valid send address found! Cannot send.");
5556
return;
5657
}
5758
lucid.selectWallet.fromSeed(accountInfo.mnemonic);
@@ -61,6 +62,7 @@ export default function Profile() {
6162
quantity: sendTokenAmount,
6263
recipient: sendRecipientAddress,
6364
sender: accountInfo.address,
65+
submit_failing_tx: overrideTx
6466
};
6567
try {
6668
const response = await axios.post(
@@ -77,7 +79,7 @@ export default function Profile() {
7779
const txId = await signAndSentTx(lucid, tx);
7880
await updateAccountBalance(sendRecipientAddress);
7981
await updateAccountBalance(accountInfo.address);
80-
changeAlertInfo({severity: 'success', message: 'Transaction sent successfully!', open: true, link: `https://preview.cardanoscan.io/transaction/${txId.inputs[0].transaction_id}`});
82+
changeAlertInfo({severity: 'success', message: 'Transaction sent successfully!', open: true, link: `https://preview.cexplorer.io/tx/${txId}`});
8183
} catch (error) {
8284
console.error('Send failed:', error);
8385
}
@@ -111,6 +113,12 @@ export default function Profile() {
111113
label="Recipient’s Address"
112114
fullWidth={true}
113115
/>
116+
<FormControlLabel
117+
control={<Checkbox size="small" checked={overrideTx} onChange={x => setOverrideTx(x.target.checked)} />}
118+
label="⚠️ Force send failing transaction"
119+
sx={{ mb: 2 }}
120+
/>
121+
114122
</Box>;
115123

116124
const receiveContent = <Box>
@@ -125,8 +133,9 @@ export default function Profile() {
125133
<div className="page">
126134
<Box sx={{display: 'flex', justifyContent: 'space-between', alignItems: 'end', marginBottom: '16px'}}>
127135
<Box>
128-
<Typography variant='h4'>Account Balance</Typography>
129-
<Typography variant='h1'>{getUserAccountDetails()?.balance} WST</Typography>
136+
<Typography variant='h4'>Address Balance</Typography>
137+
<Typography variant='h1'>{getUserAccountDetails()?.balance.wst} WST</Typography>
138+
<Typography variant='h5'>{getUserAccountDetails()?.balance.ada} Ada</Typography>
130139
</Box>
131140
<Typography variant='h5'>{getUserAccountDetails()?.address.slice(0,15)}</Typography>
132141
</Box>

frontend/src/app/[username]/page.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ import Profile from '.';
22

33
export async function generateStaticParams() {
44
return [
5-
{ username: 'user-a' },
6-
{ username: 'user-b' },
5+
{ username: 'alice' },
6+
{ username: 'bob' },
77
{ username: 'connected-wallet' } // connected wallet
88
]
99
}

frontend/src/app/clientLayout.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,13 @@ export default function ClientLayout({ children }: { children: React.ReactNode }
2222
try {
2323
// retrieve wallet info
2424
const mintAuthorityWallet = await getWalletFromSeed(mintAccount.mnemonic);
25-
const walletA = await getWalletFromSeed(accounts.userA.mnemonic);
26-
const walletB = await getWalletFromSeed(accounts.userB.mnemonic);
25+
const walletA = await getWalletFromSeed(accounts.alice.mnemonic);
26+
const walletB = await getWalletFromSeed(accounts.bob.mnemonic);
2727

2828
// Update Zustand store with the initialized wallet information
2929
changeMintAccountDetails({ ...mintAccount, address: mintAuthorityWallet.address});
30-
changeWalletAccountDetails('userA', { ...accounts.userA, address: walletA.address},);
31-
changeWalletAccountDetails('userB', { ...accounts.userB, address: walletB.address});
30+
changeWalletAccountDetails('alice', { ...accounts.alice, address: walletA.address},);
31+
changeWalletAccountDetails('bob', { ...accounts.bob, address: walletB.address});
3232

3333
const initialLucid = await makeLucid();
3434
setLucidInstance(initialLucid);
@@ -41,7 +41,7 @@ export default function ClientLayout({ children }: { children: React.ReactNode }
4141
fetchUserWallets();
4242
},[]);
4343

44-
if(accounts.userB.address === '') {
44+
if(accounts.bob.address === '') {
4545
return <div className="mainLoadingContainer">
4646
<div className="mainLoader" />
4747
</div>;

frontend/src/app/components/NavDrawer.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ const drawerWidth = 200;
2121

2222
const iconMapping = {
2323
'Mint Actions': <ImportExportIcon />,
24-
'Accounts': <FormatListBulletedIcon />,
24+
'Addresses': <FormatListBulletedIcon />,
2525
'Wallet': <AccountBalanceWalletIcon />
2626
};
2727

@@ -30,7 +30,7 @@ export default function NavDrawer() {
3030

3131
// Define list items based on the current user
3232
const listItems: MenuTab[] = currentUser === 'Mint Authority' ?
33-
['Mint Actions', 'Accounts'] :
33+
['Mint Actions', 'Addresses'] :
3434
['Wallet'];
3535

3636
const handleListItemClick = (item: MenuTab) => {

frontend/src/app/components/ProfileSwitcher.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,8 @@ export default function ProfileSwitcher() {
8686
onClose={handleClose}
8787
>
8888
<MenuItem onClick={() => handleSelect('Mint Authority')}>Mint Authority</MenuItem>
89-
<MenuItem onClick={() => handleSelect('User A')}>User A</MenuItem>
90-
<MenuItem onClick={() => handleSelect('User B')}>User B</MenuItem>
89+
<MenuItem onClick={() => handleSelect('Alice')}>Alice</MenuItem>
90+
<MenuItem onClick={() => handleSelect('Bob')}>Bob</MenuItem>
9191
<MenuItem onClick={() => handleWalletConnect('Connected Wallet')}>Lace</MenuItem>
9292
</Menu>
9393
</>

frontend/src/app/components/WSTTable.tsx

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,12 @@ import TableCell from "@mui/material/TableCell";
1212
import TableHead from "@mui/material/TableHead";
1313
import TableRow from "@mui/material/TableRow";
1414
import Paper from "@mui/material/Paper";
15+
import ContentCopyIcon from '@mui/icons-material/ContentCopy';
1516

1617
//Local Imports
1718
import useStore from '../store/store';
1819
import { useEffect } from "react";
20+
import IconButton from './WSTIconButton';
1921

2022
const progLogicBase : LucidCredential = {
2123
type: "Script",
@@ -43,6 +45,9 @@ export default function WSTTable() {
4345
getAccounts();
4446
}, []);
4547

48+
const copyToClipboard = (str: string) => {
49+
navigator.clipboard.writeText(str);
50+
}
4651

4752
return (
4853
<Box className="tableContainerBox">
@@ -51,8 +56,8 @@ export default function WSTTable() {
5156
<TableHead>
5257
<TableRow>
5358
<TableCell>Address</TableCell>
54-
<TableCell>Account Status</TableCell>
55-
<TableCell align="right">Account Balance</TableCell>
59+
<TableCell>Address Status</TableCell>
60+
<TableCell align="right">Address Balance</TableCell>
5661
</TableRow>
5762
</TableHead>
5863
<TableBody>
@@ -61,12 +66,13 @@ export default function WSTTable() {
6166
<TableRow key={i}>
6267
<TableCell>
6368
{`${acct?.address.slice(0,15)}...${acct?.address.slice(104,108)}`}
69+
<IconButton onClick={() => copyToClipboard(acct.address)} icon={<ContentCopyIcon />}/>
6470
</TableCell>
6571
<TableCell sx={{color: acct.status === 'Frozen' ? 'error.main' : 'success.main', fontWeight: '500'}}>
6672
{acct.status}
6773
</TableCell>
6874
<TableCell align="right">
69-
{`${acct?.balance} WST`}
75+
{`${acct?.balance.wst} WST`}
7076
</TableCell>
7177
</TableRow>
7278
))

0 commit comments

Comments
 (0)