Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions cold-wallet-app/lib/debug/debug_payloads.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class DebugPayloads {
'Reversible 8h': reversibleTransferWithDelay,
'Msig approve': multisigApproveTransfer,
'Msig propose': multisigProposeTransfer,
'Msig execute': multisigExecuteTransfer,
'Vote aye': governanceVoteAye,
};

Expand Down Expand Up @@ -82,6 +83,18 @@ class DebugPayloads {
);
}

/// A multisig execution carrying the call it dispatches — the same review as
/// the approval, labelled `You are executing`.
static Uint8List multisigExecuteTransfer() {
return withExtensions(
const multisig_pallet.Txs().execute(
multisigAddress: _debugMultisigAccount,
proposalId: 12,
call: _send(BigInt.from(900000000000)), // 0.9 tokens
),
);
}

/// An aye vote on a tech-collective referendum — the governance path a core dev
/// uses to enact a runtime upgrade. Moves no value, so the review screen must
/// name the call instead of showing an amount.
Expand Down
21 changes: 21 additions & 0 deletions cold-wallet-app/test/call_display_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,27 @@ void main() {
expect(find.textContaining('Multisig · approve → Balances · transfer_allow_death'), findsOneWidget);
});

testWidgets('a multisig execute reviews the call it dispatches', (tester) async {
final inner = const balances_pallet.Txs().transferAllowDeath(dest: account(bobId), value: oneToken);
await pumpSignScreen(
tester,
DebugPayloads.withExtensions(
const multisig_pallet.Txs().execute(multisigAddress: aliceId, proposalId: 12, call: inner),
),
);

expect(find.text('MULTISIG EXECUTE'), findsOneWidget);
expect(find.text('SEND'), findsOneWidget);
// The proposal contents are in the payload now, so the screen must not
// claim they are held on chain and unsigned.
expect(find.textContaining('not part of what you sign'), findsNothing);

await tester.ensureVisible(find.text('ADVANCED'));
await tester.tap(find.text('ADVANCED'));
await tester.pumpAndSettle();
expect(find.textContaining('Multisig · execute → Balances · transfer_allow_death'), findsOneWidget);
});

testWidgets('a reversible send names itself and shows its window', (tester) async {
await pumpSignScreen(
tester,
Expand Down
43 changes: 43 additions & 0 deletions cold-wallet-app/test/fixtures/qr/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Cold signing QR fixtures

Test payloads for the cold wallet and the Keystone firmware. Each case is a real signing
request: a call plus its signed extensions, wrapped in the `{"v":1,"signer":..,"payload":..}`
envelope and UR-encoded into QR frames. That is exactly what a cold wallet scans.

## Layout

```
reduced/
index.html pick a case, then show it to a camera or the simulator
manifest.json every case, what it is, and what a wallet must display
<case>/
index.html animated QR for this case (arrow keys change speed)
frames/frame-NNN.svg one SVG per UR frame
ur.txt the UR parts as text
payload.hex the signing payload
request.json the envelope before UR encoding
```

## Sets

- `reduced/` — the calls the Keystone firmware parses today. Small enough to scan on real
hardware. This is the set to run on the device.
- A full set covering every cold wallet call can be added later. It is not here yet because
large calls take a lot of QR frames (see below).

## Frame counts

The payload is hex encoded inside JSON, so the QR data is roughly twice the payload size.
UR splits it into 200 byte fragments. A simple transfer is 118 bytes and still needs 2
frames. A chain maximum 10 KiB call would need about 100 frames, which is not practical to
scan. Keep test calls small.

## Regenerating

```
cd ../quantus-cli
cargo run --example generate_qr_fixtures -- ../quantus-apps/cold-wallet-app/test/fixtures/qr
```

The generator encodes calls through the CLI's bundled chain metadata, so the bytes match
what the chain accepts. Regenerate after a runtime upgrade.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading