v3 : vote par la chaîne, corrections de la relecture de 74f96be (interface)
- rien n'est parti (nœud muet avant la signature, refus, fenêtre fermée avant) : la page lâche le bulletin ; signé, ou montré en code Ğecko, il est gardé et le serveur le confirme sans la page ; le refus de la chaîne se dit (« chain ») ; - le reçu : téléchargeable depuis la fenêtre de vote, et la page « Tes bulletins » (/bulletins) qui garde l'historique et vérifie un reçu dans le navigateur, sans le serveur (lib/receipt.ts, mêmes vecteurs que le moteur) ; - le panier ne dit plus « Tes votes comptent dès l'envoi » quand le vote est fermé ; - @noble/hashes déclaré (utilisé par e2e/chain-mock.mjs et le reçu) ; - chaîne simulée : finalité, pages, filtres, nœud qui tombe ; contrôles C32, C33. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+16
-3
@@ -9,6 +9,7 @@ export const VOTE_ACCOUNT = 'g1L5EYvvSBaYuQCPW78bHxYcvHfmWAqHYe3Gsrp9SV4kWZaEM';
|
||||
export const ALICE = { address: 'g1Pn1geRZnHcVdWdKkoYwQrAARDTXK1D7H3zuXj7GNayT1thu', name: 'Alice' };
|
||||
export const BOB = { address: 'g1NCrQaFReZcbUW8pKsazfWFCKNSdrTomnDraUMybJc4DFF5g', name: 'Bob' };
|
||||
export const CHARLIE = { address: 'g1NFWUkPTyZWE77YUrfBKfAhV9W81qmgdD17v1NGhb1EjYFqi', name: 'Charlie' };
|
||||
export const EVE = { address: 'g1QBoGEqZuxL77pF4rMa25f1cH6HAxwgBq66zZu76JPqsaVgj', name: 'Eve' };
|
||||
|
||||
export async function signIn(page: Page, name: string, admin = false) {
|
||||
const r = await page.request.post('/api/auth/dev', {
|
||||
@@ -28,12 +29,19 @@ export async function person(browser: Browser, name: string, admin = false): Pro
|
||||
/**
|
||||
* A fake wallet extension, as duniter-connect offers itself to pages
|
||||
* (`window.injectedWeb3`): it lists `accounts` and signs whatever it is given,
|
||||
* recording it in `window.__ldSigned`; `window.__ldRefuse = true` makes it refuse.
|
||||
* recording it in `window.__ldSigned`; `window.__ldRefuse = true` makes it refuse;
|
||||
* `window.__ldHold = true` makes it wait, as a person who has not answered yet,
|
||||
* until `window.__ldAnswer(true | false)` (sign, or refuse).
|
||||
* It signs nothing real: the page, in test mode, sends to the simulated node.
|
||||
*/
|
||||
export async function wallet(page: Page, accounts: { address: string; name: string }[]) {
|
||||
await page.addInitScript((list) => {
|
||||
const w = window as unknown as Record<string, unknown> & { __ldSigned: unknown[]; __ldRefuse?: boolean };
|
||||
const w = window as unknown as Record<string, unknown> & {
|
||||
__ldSigned: unknown[];
|
||||
__ldRefuse?: boolean;
|
||||
__ldHold?: boolean;
|
||||
__ldAnswer?: (yes: boolean) => void;
|
||||
};
|
||||
w.__ldSigned = [];
|
||||
w.injectedWeb3 = {
|
||||
'duniter-connect': {
|
||||
@@ -42,6 +50,10 @@ export async function wallet(page: Page, accounts: { address: string; name: stri
|
||||
accounts: { get: async () => list, subscribe: () => () => undefined },
|
||||
signer: {
|
||||
signPayload: async (payload: Record<string, unknown>) => {
|
||||
if (w.__ldHold) {
|
||||
const yes = await new Promise<boolean>((resolve) => (w.__ldAnswer = resolve));
|
||||
if (!yes) throw new Error('Cancelled');
|
||||
}
|
||||
if (w.__ldRefuse) throw new Error('Cancelled');
|
||||
w.__ldSigned.push(payload);
|
||||
return { id: w.__ldSigned.length, signature: `0x${'01'.repeat(64)}` };
|
||||
@@ -79,6 +91,7 @@ export async function chain(page: Page, docPath = DOC) {
|
||||
return {
|
||||
doc: d as { doc: { id: string }; units: { code: string; inForce: { id: string } | null; proposals: { id: string }[] }[] },
|
||||
node,
|
||||
control: async (what: 'hide' | 'show' | 'release' | 'state' | 'silent') => (await page.request.post(`${base}/control/${what}`)).json(),
|
||||
control: async (what: 'hide' | 'show' | 'release' | 'state' | 'silent' | 'node?down=1' | 'node?down=0') =>
|
||||
(await page.request.post(`${base}/control/${what}`)).json(),
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user