Skip to content

Commit

Permalink
TSDK-775 Track minting tx (#6)
Browse files Browse the repository at this point in the history
* TSDK-775 Show LVL status

* TSDK-775 Auto-init bridge

* TSDK-775 First implementation/missing WS

* TSDK-775 Fix integration tests

* TSDK-775 Fix integration tests

* TSDK-775 Fix integration tests (add log)

* TSDK-775 Fix integration tests (add log)

* TSDK-775 Use latest version

* TSDK-775 Remove logs

* TSDK-775 First more or less working version

* TSDK-775 First version completed

* TSDK-775 Add extra information to session

* TSDK-775 Fix UI build
  • Loading branch information
mundacho committed Apr 8, 2024
1 parent a56818f commit 2ad0c11
Show file tree
Hide file tree
Showing 32 changed files with 2,320 additions and 661 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/sbt_checkPR.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ jobs:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Push images to registries
run: sbt "toplBtcBridge / Docker / publish"
run: sbt "buildClient; toplBtcBridge / Docker / publish"
env:
DOCKER_PUBLISH: true
integration-test:
Expand All @@ -54,7 +54,7 @@ jobs:
# Label used to access the service container
bifrost:
# Docker Hub image
image: docker.io/toplprotocol/bifrost-node:2.0.0-alpha10
image: docker.io/toplprotocol/bifrost-node:2.0.0-beta3
#
ports:
- 9084:9084
Expand Down Expand Up @@ -176,7 +176,7 @@ jobs:
password: ${{ secrets.DOCKERHUB_TOKEN }}
- if: github.event.release
name: Push images to registries
run: sbt "toplBtcBridge / Docker / publish"
run: sbt "buildClient; toplBtcBridge / Docker / publish"
env:
DOCKER_PUBLISH: true
RELEASE_PUBLISH: true
Expand Down
73 changes: 72 additions & 1 deletion bridge-ui/src/Frame.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,81 @@
import { useEffect, useState } from 'react';
import { Link, Outlet } from 'react-router-dom';
import { PeginUIState, mintedBTC, setupSession } from './controllers/PeginController';
import { deleteCookie } from './cookie-typescript-utils';
import { ErrorResponse, SessionInformation } from './views/StartSession';

export type SessionCtx = {
session: SessionInformation;
setSession: React.Dispatch<React.SetStateAction<SessionInformation>>;
}


interface MintingStatusRequest {
sessionID: string;
}

interface MintingStatusResponse {
mintingStatus: string;
address: string;
bridgePKey: string;
redeemTemplate: string;
}

async function checkMintingStatus(mintingStatusRequest: MintingStatusRequest): Promise<MintingStatusResponse | ErrorResponse> {
const response = await fetch('/api/topl-minting-status',
{
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(mintingStatusRequest)
});
if (response.status == 200) {
const data = await response.json();
return data;
} else {
return { error: "Error" };
}
}


function Frame() {


const [session, setSession] = useState<SessionInformation>({ isSet: false, sessionID: "", escrowAddress: "", currentState: PeginUIState.InitialState, redeemAddress: "", toplBridgePKey: "", redeemTemplate: "" });
useEffect(() => setupSession(session, setSession), []);
const updateStatus = async (sessionId: string) => {
if ((session.currentState === PeginUIState.MintingTBTC) ||
(session.currentState === PeginUIState.WaitingForMint)) {
const currentStatus = await checkMintingStatus({ sessionID: sessionId });
if (typeof currentStatus === 'object' && ("mintingStatus" in currentStatus)) {
console.log(currentStatus.mintingStatus);
if (currentStatus.mintingStatus !== "MintingBTCStateMinted") {
// if (currentStatus.mintingStatus === "MintingBTCStateMinting") {
// mintingBTC(setSession, session);
// }
// if (currentStatus.mintingStatus === "MintingBTCStateWaiting") {
// waitingForTBTC(setSession, session);
// }
setTimeout(() => {
updateStatus(sessionId);
}, 5000);
} else {
mintedBTC(setSession, session, currentStatus.address, currentStatus.bridgePKey, currentStatus.redeemTemplate);
}
}
} else {
setTimeout(() => {
updateStatus(sessionId);
}, 5000);
}
}

useEffect(() => {
updateStatus(session.sessionID);
}, [session.currentState]);


function handleLogout() {
deleteCookie("sessionID");
deleteCookie("escrowAddress");
Expand Down Expand Up @@ -39,7 +110,7 @@ function Frame() {
</ul>
</nav>
<div className='container'>
<Outlet />
<Outlet context={{ session, setSession } satisfies SessionCtx} />
</div>
</div>
</>
Expand Down
81 changes: 81 additions & 0 deletions bridge-ui/src/controllers/PeginController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@

import { getCookie, setCookie } from '../cookie-typescript-utils';
import { SessionInformation, StartSessionResponse } from '../views/StartSession';

export enum PeginUIState {
InitialState,
SessionStarted,
WaitingForBTC,
MintingTBTC,
WaitingForMint,
MintedTBTC
}

function stringToPeginUIState(state: string): PeginUIState {
switch (state) {
case "InitialState":
return PeginUIState.InitialState;
case "SessionStarted":
return PeginUIState.SessionStarted;
case "WaitingForBTC":
return PeginUIState.WaitingForBTC;
case "MintingTBTC":
return PeginUIState.MintingTBTC;
case "WaitingForMint":
return PeginUIState.WaitingForMint;
case "MintedTBTC":
return PeginUIState.MintedTBTC;
default:
return PeginUIState.InitialState;
}
}

export function setupSession(session: SessionInformation, setSession: React.Dispatch<React.SetStateAction<SessionInformation>>) {
if (!session.isSet) {
const sessionId = getCookie("sessionID");
const escrowAddress = getCookie("escrowAddress");
const currentState = getCookie("currentState");
const redeemAddress = getCookie("redeemAddress");
const toplBridgePKey = getCookie("toplBridgePKey");
const redeemTemplate = getCookie("redeemTemplate");

if (sessionId !== undefined && escrowAddress !== undefined && currentState !== undefined && redeemAddress !== undefined && toplBridgePKey !== undefined && redeemTemplate !== undefined) {
console.log("Session exists in cookie")
setSession({ isSet: true, sessionID: sessionId, escrowAddress: escrowAddress, currentState: stringToPeginUIState(currentState), redeemAddress: redeemAddress, toplBridgePKey: toplBridgePKey, redeemTemplate: redeemTemplate });
}
}
}

export function sessionStarted(setSession: React.Dispatch<React.SetStateAction<SessionInformation>>, response: StartSessionResponse) {
setCookie("sessionID", response.sessionID);
setCookie("escrowAddress", response.escrowAddress);
setCookie("currentState", "SessionStarted");
setSession({ isSet: true, sessionID: response.sessionID, escrowAddress: response.escrowAddress, currentState: PeginUIState.SessionStarted, redeemAddress: "", toplBridgePKey: "", redeemTemplate: "" });
}

export function btcSent(setSession: React.Dispatch<React.SetStateAction<SessionInformation>>, session: SessionInformation) {
setCookie("currentState", "WaitingForBTC");
setSession({ isSet: true, sessionID: session.sessionID, escrowAddress: session.escrowAddress, currentState: PeginUIState.WaitingForBTC, redeemAddress: "", toplBridgePKey: "", redeemTemplate: "" });
}
export function btcArrived(setSession: React.Dispatch<React.SetStateAction<SessionInformation>>, session: SessionInformation) {
setCookie("currentState", "MintingTBTC");
setSession({ isSet: true, sessionID: session.sessionID, escrowAddress: session.escrowAddress, currentState: PeginUIState.MintingTBTC, redeemAddress: "", toplBridgePKey: "", redeemTemplate: "" });
}

export function mintingBTC(setSession: React.Dispatch<React.SetStateAction<SessionInformation>>, session: SessionInformation) {
setCookie("currentState", "MintingTBTC");
setSession({ isSet: true, sessionID: session.sessionID, escrowAddress: session.escrowAddress, currentState: PeginUIState.MintingTBTC, redeemAddress: "", toplBridgePKey: "", redeemTemplate: "" });
}

export function waitingForTBTC(setSession: React.Dispatch<React.SetStateAction<SessionInformation>>, session: SessionInformation) {
setCookie("currentState", "WaitingForMint");
setSession({ isSet: true, sessionID: session.sessionID, escrowAddress: session.escrowAddress, currentState: PeginUIState.WaitingForMint, redeemAddress: "", toplBridgePKey: "", redeemTemplate: "" });
}

export function mintedBTC(setSession: React.Dispatch<React.SetStateAction<SessionInformation>>, session: SessionInformation, address: string, toplBridgePKey: string, redeemTemplate: string) {
setCookie("currentState", "MintedTBTC");
setCookie("redeemAddress", address);
setCookie("toplBridgePKey", toplBridgePKey);
setCookie("redeemTemplate", redeemTemplate);
setSession({ isSet: true, sessionID: session.sessionID, escrowAddress: session.escrowAddress, currentState: PeginUIState.MintedTBTC, redeemAddress: address, toplBridgePKey: toplBridgePKey, redeemTemplate: redeemTemplate });
}
13 changes: 4 additions & 9 deletions bridge-ui/src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,20 @@ import {
} from "react-router-dom"
import Frame from './Frame.tsx'
import './index.css'
import StartSession from './views/StartSession.tsx'
import WaitingForBTC from './views/WaitingForBTC.tsx'
import PeginView from './views/PeginView.tsx'

const router = createBrowserRouter([
{
path: "/",
element: <Frame />,
children: [
{
path: "/pegin/startSession",
element: <StartSession />,
},
{
path: "/pegin/waitingForFunds",
element: <WaitingForBTC />,
path: "/pegin",
element: <PeginView />,
},
{
path: "/",
element: <Navigate to="/pegin/startSession" replace={true} />,
element: <Navigate to="/pegin" replace={true} />,
},
]
},
Expand Down
50 changes: 50 additions & 0 deletions bridge-ui/src/views/PeginView.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { useOutletContext } from "react-router-dom";
import { PeginUIState } from "../controllers/PeginController";
import StartSession, { SessionInformation } from "./StartSession";
import WaitingForBTC from "./WaitingForBTC";
import WaitingForMint from "./WaitingForMint";
import { SessionCtx } from "../Frame";

const currentView = (session: SessionInformation, setSession: React.Dispatch<React.SetStateAction<SessionInformation>>) => {
switch (session.currentState) {
case PeginUIState.InitialState:
return StartSession(session, setSession)
case PeginUIState.SessionStarted:
return StartSession(session, setSession)
case PeginUIState.WaitingForBTC:
return WaitingForBTC(session, setSession)
case PeginUIState.WaitingForMint:
return WaitingForMint(session)
case PeginUIState.MintingTBTC:
return WaitingForMint(session)
case PeginUIState.MintedTBTC:
return WaitingForMint(session)
default:
return StartSession(session, setSession)
}
}


function PeginView() {

const sessionCtx = useOutletContext<SessionCtx>();

return (
<>
<h1 className="mt-4">Peg-in</h1>
<div className='row g-3'>
<div className="col"></div>
<div className="col">
<div className="card">
<div className="card-header">
Peg-in
</div>
{currentView(sessionCtx.session, sessionCtx.setSession)}
</div></div>
<div className="col"></div>
</div>
</>)

}

export default PeginView;

0 comments on commit 2ad0c11

Please sign in to comment.