Merge pull request #49 from input-output-hk/DAC-290
DAC-290 [FE]Result of the broadcasting
DAC-290 [FE]Result of the broadcasting
REACT_APP_BASE_URL="https://testing.dapps.iog.io/"
\ No newline at end of file
REACT_APP_BASE_URL="https://testing.dapps.iog.io/"
REACT_APP_WALLET_NETWORK="1"
\ No newline at end of file
section > svg.spinner {
top: 100px;
left: 50%;
}
#contentWrapper {
margin: 0 auto;
padding: 40px;
color: #2d333a;
@media (max-width: 768px) {
& {
padding: 0;
}
}
}
#globalBanners {
padding: 10px 40px;
}
\ No newline at end of file
import React, { lazy, Suspense } from "react";
import React, { lazy, memo, Suspense } from "react";
import { Routes, Route, Outlet } from "react-router-dom";
import { BASE_URL } from "constants/route";
import Alert from '@mui/material/Alert';
import "./App.scss";
import Header from "components/Header/Header";
import PrivateRoutes from "components/PrivateRoutes/PrivateRoutes";
import NotFound from "components/NotFound/NotFound";
import Loader from "components/Loader/Loader";
import { useAppSelector } from "store/store";
const Certification = lazy(() => import("../pages/certification/Certification"));
const MaintenancePage = lazy(() => import("../pages/maintenance/Maintenance"));
const PageLayout = () => {
const { network } = useAppSelector((state) => state.auth);
// const networkNames:{[x:string]:string} = {
// '0': 'Testnet',
// '1': 'Mainnet'
// }
const Banner = memo(() => {
const networkEnvVar: any = process.env.REACT_APP_WALLET_NETWORK
return (<>
{network !== null && network !== 1 ?
// always show Info if not in Mainnet
<Alert severity="info" style={{marginBottom: '10px'}}>Your connected wallet is not in Mainnet.</Alert> : null}
{/* if not in Mainnet and app-wallet not Mainnet (i.e. in Testnet), show Warning to connect to Preprod. */}
{network !== null && network !== 1 && networkEnvVar !== '1' ?
<Alert severity="warning">Being in a test network, please make sure you are connected to wallet in <strong>Preprod</strong> to avail services without any issues.</Alert> : null}
</>)
})
return (
<>
<Header />
<section id="globalBanners">
<Banner />
</section>
{/* Load page content here */}
<section data-testid="contentWrapper" id="contentWrapper">
<Suspense fallback={<Loader />}>
span {
padding: 2px 16px;
}
}
.error {
color: red;
}
\ No newline at end of file
import React, { useEffect, useState, useCallback } from "react";
import { Address } from "@emurgo/cardano-serialization-lib-browser";
import { useAppDispatch } from "store/store";
import { getProfileDetails } from "store/slices/auth.slice";
import { getProfileDetails, setNetwork } from "store/slices/auth.slice";
import Modal from "components/Modal/Modal";
import Button from "components/Button/Button";
import Loader from "components/Loader/Loader";
import Toast from "components/Toast/Toast";
import './ConnectWallet.scss';
const [walletName, setWalletName] = useState("")
const [address, setAddress] = useState("")
const [isOpen, setIsOpen] = useState(false)
const [errorToast, setErrorToast] = useState<{display: boolean; statusText?: string; message?: string;}>({display: false});
const [walletLoading, setWalletLoading] = useState(false)
const openConnectWalletModal = useCallback(() => setIsOpen(true),[])
try {
setWalletLoading(true)
const enabledWallet = await CardanoNS[walletName].enable();
setWallet(enabledWallet)
setWalletName(walletName)
if (enabledWallet) {
const response = await enabledWallet.getChangeAddress()
setAddress(Address.from_bytes(Buffer.from(response, "hex")).to_bech32())
}
enabledWallet.getNetworkId().then(async (data: number) => {
dispatch(setNetwork(data))
setWallet(enabledWallet)
setWalletName(walletName)
if (enabledWallet) {
const response = await enabledWallet.getChangeAddress()
setAddress(Address.from_bytes(Buffer.from(response, "hex")).to_bech32())
}
})
} catch (e) { handleError(e); }
}
const handleError = (err: any) => {
console.log(err)
const handleError = (error: any) => {
if (error.info) {
setErrorToast({display: true, message: error.info})
} else if (error.response) {
setErrorToast({display: true, statusText: error.response.statusText, message: error.response.data || undefined})
} else {
setErrorToast({display: true})
}
setTimeout(() => { setErrorToast({display: false}) }, 3000)
}
useEffect(() => {
})
}
{ walletLoading ? <Loader /> : null}
{
(errorToast && errorToast.display) ? (<span className="error">{errorToast.message}</span>): null
}
</div>
</Modal>
{/* {(errorToast && errorToast.display) ? (
((errorToast.message && errorToast.statusText) ?
<Toast message={errorToast.message} title={errorToast.statusText}/> :
<Toast />))
: null} */}
</>
)
}
import { useNavigate, Link } from "react-router-dom";
import { Address } from "@emurgo/cardano-serialization-lib-browser";
import { useAppDispatch, useAppSelector } from "store/store";
import { logout, getProfileDetails } from "store/slices/auth.slice";
import { logout, getProfileDetails, setNetwork } from "store/slices/auth.slice";
import "./Header.scss";
import AvatarDropDown from "components/AvatarDropdown/AvatarDropdown";
import ConnectWallet from "components/ConnectWallet/ConnectWallet";
import { useDelayedApi } from "hooks/useDelayedApi";
const Header = () => {
const { isLoggedIn, address, wallet } = useAppSelector((state) => state.auth);
const { isLoggedIn, address, wallet, network } = useAppSelector((state) => state.auth);
const dispatch = useAppDispatch();
const [isActive, setIsActive] = useState(false);
const [pollForAddress, setPollForAddress] = useState(false);
const [pollForNetwork, setPollForNetwork] = useState(false);
const navigate = useNavigate();
useEffect(() => {
try {
const enabledWallet = await window.cardano[walletNameCache].enable()
dispatch(getProfileDetails({"address": addressCache, "wallet": enabledWallet, "walletName": walletNameCache}))
enabledWallet.getNetworkId().then(async (data: number) => { console.log('new network -', data)
dispatch(setNetwork(data))
})
} catch(e) {
console.log(e)
}
useEffect(() => {
setPollForAddress(wallet && address && isLoggedIn);
}, [wallet, address, isLoggedIn]);
setPollForNetwork(wallet && address && isLoggedIn && network !== null)
}, [wallet, address, isLoggedIn, network]);
const forceUserLogout = () => {
// account/network has been changed. Force logout the user
setPollForAddress(false);
setPollForNetwork(false)
dispatch(logout());
}
useDelayedApi(
async () => {
newAddress = Address.from_bytes(Buffer.from(response, "hex")).to_bech32()
}
if (newAddress && address !== newAddress) {
// account has been changed. Force logout the user
dispatch(logout());
setPollForAddress(false);
forceUserLogout()
} else {
setPollForAddress(true);
}
},
3 * 1000,
1 * 1000,
pollForAddress
);
useDelayedApi(
async() => {
setPollForNetwork(false)
wallet.getNetworkId().then((id: number) => {
// Preview/Preprod/Testnet are all 0. Switching among them cannot be distinguished.
// But, switching to-and-fro Mainnet is triggered
if (id !== network) {
forceUserLogout();
} else {
setPollForNetwork(true)
}
})
},
1 * 1000,
pollForNetwork
)
const hasCachedAddress = () => {
return (!localStorage.getItem('address')?.length || !localStorage.getItem('walletName')?.length)
}
// position: relative;
}
#contentWrapper {
margin: 0 auto;
padding: 40px;
color: #2d333a;
@media (max-width: 768px) {
& {
padding: 0;
}
}
}
input {
font-family: monospace, -apple-system, BlinkMacSystemFont, "Segoe UI",
"Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans",
}
#resultContainer {
button.back-btn {
background: transparent;
cursor: pointer;
border: none;
img {
width: "30px";
padding: "10px";
}
}
header {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
gap: 15px;
.back-btn {
background: transparent;
cursor: pointer;
border: none;
}
&>div {
display: flex;
flex-wrap: wrap;
{formSubmitted && (
<>
<div id="resultContainer">
{runStatus !== "finished" ? (
<button
className="back-btn"
onClick={(e) => {
resetStates();
}}
>
{" "}
<img
src="images/back.png"
alt="back_btn"
/>
</button>
) : null}
<header>
{runStatus === "finished" ? (
<button
className="back-btn"
onClick={(e) => {
resetStates();
}}
>
{" "}
<img
src="images/back.png"
alt="back_btn"
style={{ width: "30px", padding: "10px" }}
/>
</button>
) : (
""
)}
<h2
id="breadcrumb"
style={{alignSelf:"center"}}
wallet: any;
userDetails: IUserProfile;
loading: boolean;
network: number | null;
}
// Define the initial state using that type
address: '',
wallet: null,
userDetails: {dapp: null},
loading: false
loading: false,
network: null
};
const clearLSCache = () => {
localStorage.removeItem('address')
localStorage.removeItem('walletName')
}
export const getProfileDetails: any = createAsyncThunk("getProfileDetails", async (data: any, { }) => {
localStorage.setItem('address', data.address)
const response = await fetchData.get("/profile/current", data)
// FOR MOCK - const response = await fetchData.get(data.url || 'static/data/current-profile.json', data)
return response.data
export const getProfileDetails: any = createAsyncThunk("getProfileDetails", async (data: any, { rejectWithValue }) => {
localStorage.setItem('address', data.address)
const response = await fetchData.get("/profile/current", data)
// FOR MOCK - const response = await fetchData.get(data.url || 'static/data/current-profile.json', data)
return response.data
})
export const authSlice = createSlice({
clearLSCache();
},
logout: (state) => {
clearLSCache()
clearLSCache();
state.loading = false;
return initialState
},
setNetwork: (state, actions) => {
state.network = actions.payload
}
},
extraReducers: (builder) => {
builder.addCase(getProfileDetails.pending, (state) => {state.loading = true;})
});
export const { logout, clearCache } = authSlice.actions;
export const { logout, clearCache, setNetwork } = authSlice.actions;
export default authSlice.reducer;
A flaky test run was discovering this and we seemingly had forgotten to add this schema when introducing the IgnoredInitTx constructor.
Fixes #348
Fixes #347
Fixes #412
Fixes #347
Fixes #348
Fixes #347
From https://github.com/input-output-hk/ouroboros-network at ff2331f0d254944f7c375078e6a3eb8e4f8770db
From https://github.com/input-output-hk/ouroboros-network at ff2331f0d254944f7c375078e6a3eb8e4f8770db
Fixes #347
Fixes #347
Fixes #347