Skip to content

Commit cd74a20

Browse files
authored
Merge pull request #12 from AztecProtocol/gj/iframe
iframe wallet test
2 parents cb9b048 + 7eaec28 commit cd74a20

File tree

13 files changed

+2036
-1235
lines changed

13 files changed

+2036
-1235
lines changed

.github/workflows/deploy.yml

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ on:
1212

1313
env:
1414
PASSWORD: ${{ secrets.PASSWORD }}
15+
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
16+
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
1517

1618
permissions:
1719
contents: read
@@ -67,13 +69,17 @@ jobs:
6769
- name: Pull Vercel Environment Information
6870
run: vercel pull --yes --environment=production --token=${{ secrets.VERCEL_TOKEN }}
6971

70-
- name: Deploy to Vercel
72+
- name: Build and deploy to Vercel
7173
id: deploy
74+
env:
75+
VITE_WEB_WALLET_URL: ${{ vars.VITE_WEB_WALLET_URL }}
7276
run: |
7377
if [ "${{ github.event_name }}" == "push" ] && [ "${{ github.ref }}" == "refs/heads/main" ]; then
74-
DEPLOY_URL=$(vercel deploy --prod --token=${{ secrets.VERCEL_TOKEN }} --archive=tgz --yes)
78+
vercel build --prod --token=${{ secrets.VERCEL_TOKEN }}
79+
DEPLOY_URL=$(vercel deploy --prebuilt --prod --token=${{ secrets.VERCEL_TOKEN }} --archive=tgz --yes)
7580
else
76-
DEPLOY_URL=$(vercel deploy --token=${{ secrets.VERCEL_TOKEN }} --archive=tgz --yes)
81+
vercel build --token=${{ secrets.VERCEL_TOKEN }}
82+
DEPLOY_URL=$(vercel deploy --prebuilt --token=${{ secrets.VERCEL_TOKEN }} --archive=tgz --yes)
7783
fi
7884
echo "url=$DEPLOY_URL" >> $GITHUB_OUTPUT
7985

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ VERSION=4.0.0-nightly.20260205 bash -i <(curl -sL https://install.aztec.network/
3333

3434
### 3. Set Aztec Version
3535

36-
The project uses Aztec version `v4.0.0-devnet.1-patch.0`. Set it using:
36+
The project uses Aztec version `v4.0.0-devnet.2-patch.3`. Set it using:
3737

3838
```bash
3939
aztec-up install 4.0.0-nightly.20260205

contracts/proof_of_password/Nargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ type = "contract"
44
authors = [""]
55

66
[dependencies]
7-
aztec = { git = "https://github.com/AztecProtocol/aztec-packages/", tag = "v4.0.0-devnet.2-patch.1", directory = "noir-projects/aztec-nr/aztec" }
8-
token = { git = "https://github.com/AztecProtocol/aztec-packages/", tag = "v4.0.0-devnet.2-patch.1", directory = "noir-projects/noir-contracts/contracts/app/token_contract" }
7+
aztec = { git = "https://github.com/AztecProtocol/aztec-packages/", tag = "v4.0.0-devnet.2-patch.3", directory = "noir-projects/aztec-nr/aztec" }
8+
token = { git = "https://github.com/AztecProtocol/aztec-packages/", tag = "v4.0.0-devnet.2-patch.3", directory = "noir-projects/noir-contracts/contracts/app/token_contract" }
99
poseidon = { tag = "v0.1.1", git = "https://github.com/noir-lang/poseidon" }
10-
compressed_string = { git = "https://github.com/AztecProtocol/aztec-packages/", tag = "v4.0.0-devnet.2-patch.1", directory = "noir-projects/aztec-nr/compressed-string" }
10+
compressed_string = { git = "https://github.com/AztecProtocol/aztec-packages/", tag = "v4.0.0-devnet.2-patch.3", directory = "noir-projects/aztec-nr/compressed-string" }

package.json

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"serve": "vite",
1010
"build": "tsc -b && vite build",
1111
"lint": "eslint .",
12-
"copy:dependencies": "cd contracts && nargo check && WORKDIR=$(pwd) && cd $HOME/nargo/github.com/AztecProtocol/aztec-packages/v4.0.0-devnet.2-patch.1/noir-projects/noir-contracts && aztec compile --package token_contract && mkdir -p $WORKDIR/target && cp $HOME/nargo/github.com/AztecProtocol/aztec-packages/v4.0.0-devnet.2-patch.1/noir-projects/noir-contracts/target/token_contract-Token.json $WORKDIR/target/token_contract-Token.json",
12+
"copy:dependencies": "cd contracts && nargo check && WORKDIR=$(pwd) && cd $HOME/nargo/github.com/AztecProtocol/aztec-packages/v4.0.0-devnet.2-patch.3/noir-projects/noir-contracts && aztec compile --package token_contract && mkdir -p $WORKDIR/target && cp $HOME/nargo/github.com/AztecProtocol/aztec-packages/v4.0.0-devnet.2-patch.3/noir-projects/noir-contracts/target/token_contract-Token.json $WORKDIR/target/token_contract-Token.json",
1313
"compile:contracts": "cd contracts && aztec compile --package proof_of_password && aztec codegen ./target/proof_of_password-ProofOfPassword.json",
1414
"test": "cd contracts && aztec test",
1515
"preview": "vite preview",
@@ -23,16 +23,16 @@
2323
"local-aztec:status": "node scripts/toggle-local-aztec.js status"
2424
},
2525
"dependencies": {
26-
"@aztec/accounts": "v4.0.0-devnet.2-patch.1",
27-
"@aztec/aztec.js": "v4.0.0-devnet.2-patch.1",
28-
"@aztec/constants": "v4.0.0-devnet.2-patch.1",
29-
"@aztec/entrypoints": "v4.0.0-devnet.2-patch.1",
30-
"@aztec/foundation": "v4.0.0-devnet.2-patch.1",
31-
"@aztec/noir-contracts.js": "v4.0.0-devnet.2-patch.1",
32-
"@aztec/protocol-contracts": "v4.0.0-devnet.2-patch.1",
33-
"@aztec/pxe": "v4.0.0-devnet.2-patch.1",
34-
"@aztec/stdlib": "v4.0.0-devnet.2-patch.1",
35-
"@aztec/wallet-sdk": "v4.0.0-devnet.2-patch.1",
26+
"@aztec/accounts": "v4.0.0-devnet.2-patch.3",
27+
"@aztec/aztec.js": "v4.0.0-devnet.2-patch.3",
28+
"@aztec/constants": "v4.0.0-devnet.2-patch.3",
29+
"@aztec/entrypoints": "v4.0.0-devnet.2-patch.3",
30+
"@aztec/foundation": "v4.0.0-devnet.2-patch.3",
31+
"@aztec/noir-contracts.js": "v4.0.0-devnet.2-patch.3",
32+
"@aztec/protocol-contracts": "v4.0.0-devnet.2-patch.3",
33+
"@aztec/pxe": "v4.0.0-devnet.2-patch.3",
34+
"@aztec/stdlib": "v4.0.0-devnet.2-patch.3",
35+
"@aztec/wallet-sdk": "v4.0.0-devnet.2-patch.3",
3636
"@emotion/react": "^11.14.0",
3737
"@emotion/styled": "^11.14.0",
3838
"@mui/icons-material": "^6.3.1",
@@ -45,7 +45,7 @@
4545
"zod": "^3.23.8"
4646
},
4747
"devDependencies": {
48-
"@aztec/wallets": "v4.0.0-devnet.2-patch.1",
48+
"@aztec/wallets": "v4.0.0-devnet.2-patch.3",
4949
"@eslint/js": "^9.18.0",
5050
"@playwright/test": "1.49.0",
5151
"@types/buffer-json": "^2",

src/components/TxNotificationCenter.tsx

Lines changed: 103 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,24 @@ import UnfoldLessIcon from '@mui/icons-material/UnfoldLess';
2626
import UnfoldMoreIcon from '@mui/icons-material/UnfoldMore';
2727
import { txProgress, type TxProgressEvent, type PhaseTiming } from '../tx-progress';
2828

29+
// ─── Live phase support ───────────────────────────────────────────────────────
30+
31+
interface LivePhaseTiming extends PhaseTiming {
32+
isLive?: boolean;
33+
}
34+
35+
const ACTIVE_PHASE_COLORS: Record<string, string> = {
36+
simulating: '#ce93d8',
37+
proving: '#f48fb1',
38+
sending: '#2196f3',
39+
mining: '#4caf50',
40+
};
41+
42+
const shimmer = keyframes`
43+
0% { background-position: -400px 0; }
44+
100% { background-position: 400px 0; }
45+
`;
46+
2947
// ─── Helpers ─────────────────────────────────────────────────────────────────
3048

3149
const formatDuration = (ms: number): string => {
@@ -60,22 +78,29 @@ const pulse = keyframes`
6078

6179
// ─── PhaseTimeline (inline, simplified from demo-wallet) ─────────────────────
6280

63-
function PhaseTimelineBar({ phases }: { phases: PhaseTiming[] }) {
64-
const totalDuration = useMemo(() => phases.reduce((sum, p) => sum + p.duration, 0), [phases]);
81+
function PhaseTimelineBar({ phases }: { phases: LivePhaseTiming[] }) {
82+
const completedPhases = useMemo(() => phases.filter(p => !p.isLive), [phases]);
83+
const livePhase = useMemo(() => phases.find(p => p.isLive), [phases]);
84+
85+
const completedDuration = useMemo(() => completedPhases.reduce((sum, p) => sum + p.duration, 0), [completedPhases]);
86+
const liveDuration = livePhase?.duration ?? 0;
87+
const totalDuration = completedDuration + liveDuration;
88+
6589
const miningDuration = useMemo(
66-
() => phases.filter(p => p.name === 'Mining').reduce((sum, p) => sum + p.duration, 0),
67-
[phases],
90+
() => completedPhases.filter(p => p.name === 'Mining').reduce((sum, p) => sum + p.duration, 0),
91+
[completedPhases],
6892
);
6993

7094
if (phases.length === 0 || totalDuration === 0) return null;
7195

7296
const preparingDuration = totalDuration - miningDuration;
7397
const hasMining = miningDuration > 0;
98+
const hasLive = !!livePhase;
7499

75100
return (
76101
<Box sx={{ width: '100%', mt: 1.5 }}>
77102
{/* Summary chips */}
78-
<Box sx={{ display: 'flex', gap: 0.5, mb: 0.5, flexWrap: 'wrap' }}>
103+
<Box sx={{ display: 'flex', gap: 0.5, mb: 0.5, flexWrap: 'wrap', alignItems: 'center' }}>
79104
{hasMining ? (
80105
<>
81106
<Chip
@@ -96,7 +121,7 @@ function PhaseTimelineBar({ phases }: { phases: PhaseTiming[] }) {
96121
</>
97122
) : (
98123
<Chip
99-
label={`Total: ${formatDuration(totalDuration)}`}
124+
label={hasLive ? `Elapsed: ${formatDuration(totalDuration)}` : `Total: ${formatDuration(totalDuration)}`}
100125
size="small"
101126
sx={{ height: 18, fontSize: '0.6rem', fontWeight: 600 }}
102127
/>
@@ -114,7 +139,8 @@ function PhaseTimelineBar({ phases }: { phases: PhaseTiming[] }) {
114139
bgcolor: 'action.hover',
115140
}}
116141
>
117-
{phases.map((phase, index) => {
142+
{/* Completed segments (proportional width based on total) */}
143+
{completedPhases.map((phase, index) => {
118144
const percentage = (phase.duration / totalDuration) * 100;
119145
return (
120146
<Tooltip
@@ -165,7 +191,7 @@ function PhaseTimelineBar({ phases }: { phases: PhaseTiming[] }) {
165191
minWidth: percentage > 0 ? 2 : 0,
166192
height: '100%',
167193
bgcolor: phase.color,
168-
borderRight: index < phases.length - 1 ? '1px solid rgba(255,255,255,0.3)' : undefined,
194+
borderRight: (index < completedPhases.length - 1 || hasLive) ? '1px solid rgba(255,255,255,0.3)' : undefined,
169195
transition: 'filter 0.2s ease',
170196
cursor: 'pointer',
171197
'&:hover': { filter: 'brightness(1.2)' },
@@ -174,15 +200,43 @@ function PhaseTimelineBar({ phases }: { phases: PhaseTiming[] }) {
174200
</Tooltip>
175201
);
176202
})}
203+
204+
{/* Live (shimmer) segment — flex: 1 to fill remaining space */}
205+
{livePhase && (
206+
<Tooltip
207+
title={
208+
<Box sx={{ p: 0.5 }}>
209+
<Typography variant="subtitle2" sx={{ fontWeight: 600 }}>
210+
{livePhase.name}
211+
</Typography>
212+
<Typography variant="body2">{formatDurationLong(livePhase.duration)} (in progress)</Typography>
213+
</Box>
214+
}
215+
arrow
216+
placement="top"
217+
>
218+
<Box
219+
sx={{
220+
flex: 1,
221+
minWidth: 40,
222+
height: '100%',
223+
background: `linear-gradient(90deg, ${livePhase.color}88 0%, ${livePhase.color} 50%, ${livePhase.color}88 100%)`,
224+
backgroundSize: '400px 100%',
225+
animation: `${shimmer} 1.5s infinite linear`,
226+
cursor: 'pointer',
227+
}}
228+
/>
229+
</Tooltip>
230+
)}
177231
</Box>
178232

179233
{/* Legend */}
180234
<Box sx={{ display: 'flex', gap: 1, mt: 0.5, flexWrap: 'wrap' }}>
181235
{phases.map(phase => (
182236
<Box key={phase.name} sx={{ display: 'flex', alignItems: 'center', gap: 0.3 }}>
183-
<Box sx={{ width: 6, height: 6, borderRadius: '50%', bgcolor: phase.color }} />
237+
<Box sx={{ width: 6, height: 6, borderRadius: '50%', bgcolor: phase.color, ...(phase.isLive && { animation: `${pulse} 1.2s ease-in-out infinite` }) }} />
184238
<Typography variant="caption" color="text.secondary" sx={{ fontSize: '0.6rem' }}>
185-
{phase.name}
239+
{phase.name}{phase.isLive ? ' ●' : ''}
186240
</Typography>
187241
</Box>
188242
))}
@@ -201,14 +255,16 @@ interface TxToastProps {
201255
function TxToast({ event, onDismiss }: TxToastProps) {
202256
const isActive = event.phase !== 'complete' && event.phase !== 'error';
203257

204-
// For completed events, compute total from recorded phase timings (stable across refreshes)
258+
// For completed events, compute total from recorded phases (stable across refreshes)
205259
const computeFinalElapsed = () => {
206-
const t = event.phaseTimings;
207-
const fromTimings = (t.simulation ?? 0) + (t.proving ?? 0) + (t.sending ?? 0) + (t.mining ?? 0);
208-
return fromTimings > 0 ? fromTimings : Date.now() - event.startTime;
260+
const fromPhases = event.phases.reduce((sum, p) => sum + p.duration, 0);
261+
return fromPhases > 0 ? fromPhases : Date.now() - event.startTime;
209262
};
210263

264+
// Total wall-clock elapsed since tx start (for header display)
211265
const [elapsed, setElapsed] = useState(() => isActive ? Date.now() - event.startTime : computeFinalElapsed());
266+
// Live elapsed within the *current* phase (resets when phase changes)
267+
const [phaseElapsed, setPhaseElapsed] = useState(() => isActive ? Date.now() - event.phaseStartTime : 0);
212268
const [expanded, setExpanded] = useState(true);
213269
const frozen = useRef(!isActive);
214270

@@ -218,17 +274,44 @@ function TxToast({ event, onDismiss }: TxToastProps) {
218274
if (!frozen.current) {
219275
frozen.current = true;
220276
setElapsed(computeFinalElapsed());
277+
setPhaseElapsed(0);
221278
}
222279
return;
223280
}
224281
frozen.current = false;
225-
const interval = setInterval(() => setElapsed(Date.now() - event.startTime), 200);
282+
const interval = setInterval(() => {
283+
setElapsed(Date.now() - event.startTime);
284+
setPhaseElapsed(Date.now() - event.phaseStartTime);
285+
}, 200);
226286
return () => clearInterval(interval);
227-
}, [isActive, event.startTime]);
287+
}, [isActive, event.startTime, event.phaseStartTime]);
288+
289+
// Re-initialize elapsed when txId changes (new transaction)
290+
const prevTxIdRef = useRef(event.txId);
291+
useEffect(() => {
292+
if (event.txId !== prevTxIdRef.current) {
293+
prevTxIdRef.current = event.txId;
294+
setElapsed(isActive ? Date.now() - event.startTime : computeFinalElapsed());
295+
setPhaseElapsed(isActive ? Date.now() - event.phaseStartTime : 0);
296+
frozen.current = !isActive;
297+
}
298+
}, [event.txId]);
228299

229300
const isComplete = event.phase === 'complete';
230301
const isError = event.phase === 'error';
231302

303+
// Build display phases: completed phases + live shimmer phase when active
304+
const displayPhases: LivePhaseTiming[] = useMemo(() => {
305+
if (!isActive) return event.phases;
306+
if (phaseElapsed <= 0 && event.phases.length === 0) return [];
307+
const liveColor = ACTIVE_PHASE_COLORS[event.phase] ?? '#90caf9';
308+
const liveName = PHASE_LABELS[event.phase] ?? event.phase;
309+
return [
310+
...event.phases,
311+
{ name: liveName, duration: phaseElapsed > 0 ? phaseElapsed : 100, color: liveColor, isLive: true },
312+
];
313+
}, [isActive, event.phases, event.phase, phaseElapsed]);
314+
232315
return (
233316
<Paper
234317
elevation={8}
@@ -304,7 +387,7 @@ function TxToast({ event, onDismiss }: TxToastProps) {
304387
</Typography>
305388

306389
{/* Expand/collapse */}
307-
{isComplete && event.phases.length > 0 && (
390+
{displayPhases.length > 0 && (
308391
<IconButton size="small" onClick={() => setExpanded(prev => !prev)} sx={{ p: 0.25 }}>
309392
{expanded ? <ExpandLessIcon sx={{ fontSize: 16 }} /> : <ExpandMoreIcon sx={{ fontSize: 16 }} />}
310393
</IconButton>
@@ -316,10 +399,10 @@ function TxToast({ event, onDismiss }: TxToastProps) {
316399
</IconButton>
317400
</Box>
318401

319-
{/* Phase timeline breakdown (shown when complete) */}
320-
<Collapse in={isComplete && expanded && event.phases.length > 0}>
402+
{/* Phase timeline breakdown (shown during execution and when complete) */}
403+
<Collapse in={expanded && displayPhases.length > 0}>
321404
<Box sx={{ px: 1.5, pb: 1.5 }}>
322-
<PhaseTimelineBar phases={event.phases} />
405+
<PhaseTimelineBar phases={displayPhases} />
323406
</Box>
324407
</Collapse>
325408

0 commit comments

Comments
 (0)