docs(sdk): specs sdk_common, sdk_relay (WS), rust-silentpayments + pseudo-code & endpoints

This commit is contained in:
LeCoffre Deployment 2025-10-05 12:24:55 +00:00
parent f63bf086cf
commit e13708d361

131
docs/SDK_USAGE_SPEC.md Normal file
View File

@ -0,0 +1,131 @@
### Spécifications d'utilisation: sdk_common, sdk_relay, rust-silentpayments
Ce document décrit comment utiliser les briques 4NK côté client pour: (1) les types/utilitaires communs, (2) l'intégration au relay (WebSocket), et (3) l'usage de la librairie Rust « silent payments » exposée via wasm (`pkg/sdk_client.js`).
### 1) sdk_common (contrats et conventions)
- Rôle: référentiel de types/constantes (MessageType, enveloppe de messages, erreurs), helpers purs. Dans ce projet, il n'est pas modifié par les specs chat; l'hôte/iframe se basent sur `MessageType` existants et un `CHANNEL_MESSAGE` côté IHM.
- Enveloppes: `{ type, messageId, correlationId?, payload, ts?, version? }`
- Erreurs: `ERROR { code, reason, details?, refMessageId? }`
- Bonnes pratiques: versionner la sémantique applicative via `version` dans `payload` si nécessaire (ex: `chat/1.0`).
### 2) sdk_relay (intégration relay via WebSocket)
- Transport: WebSocket vers `VITE_BOOTSTRAPURL` (fallback `wss://${BASEURL}/ws/`).
- Fichier de référence: `4NK_modules/ihm_client/src/websockets.ts` et `src/services/service.ts`.
- Canaux applicatifs (flags): `NewTx`, `Commit`, `Cipher`, `Faucet` (utilisés par `Services.send*Message`).
Interfaces (côté host/IHM)
```ts
// Initialisation de la connexion
await initWebsocket('wss://<relay>/ws/');
// Envoi générique (wrappé par Services)
sendMessage(flag: 'NewTx'|'Commit'|'Cipher'|'Faucet', message: string): void
// Événements
ws.onopen: flush de la file; onmessage: routage vers Services (parse, handleApiReturn)
```
Handshake et messages relay
- `Services.connectAllRelays()` ouvre les WS et attend au moins un « handshake » (`waitForHandshakeMessage`).
- Sur message `handshake`: `handleHandshakeMsg(url, parsed)` met à jour:
- `relayAddresses[wsurl] -> sp_address`
- `membersList` (peers)
- `processesCache` (via `batchSaveProcessesToDb` ou merge par state)
- déclenche `checkConnections` et `request_data` si des clés manquent
Séquences typiques (texte)
1) Démarrage: `connectAllRelays``waitForHandshakeMessage``membersList`/`processes` prêts.
2) Parse de nouveaux TX: `parse_new_tx``handleApiReturn` → envoi `NewTx` et MAJ device.
3) Partage de secrets/données: `request_data(processId, stateIds, roles, members)``handleApiReturn` alimente secrets/IndexedDB.
### 3) rust-silentpayments (wasm sdk_client)
- Exposé via `4NK_modules/ihm_client/pkg/sdk_client.js`.
- Fonctions principales utilisées:
- Device: `create_new_device`, `restore_device`, `dump_device`, `dump_neutered_device`, `get_available_amount`, `get_address`, `scan_blocks`, `reset_device`.
- Process: `create_new_process`, `update_process`, `process_commit_new_state`.
- Cryptographie: `encode_json`, `encode_binary`, `decode_value`, `decrypt_data`, `hash_value`.
- Réseau/process sync: `create_transaction` (connexion membres), `create_update_message`, `create_response_prd`, `validate_state`, `refuse_state`, `parse_cipher`, `parse_new_tx`, `request_data`, `sign_transaction`.
Interfaces (signatures conceptuelles)
```ts
// Création d'un device et restauration
create_new_device(birthday: number, network: 'signet'|'testnet'|'mainnet'): string // retourne sp_address
restore_device(device: Device): void
dump_device(): Device
get_pairing_process_id(): string
// Encodage/chiffrement
encode_json(obj: Record<string, any>): Record<string, number[]>
encode_binary(files: Record<string, { type: string; data: Uint8Array }>): Record<string, number[]>
decode_value(encoded: number[]): any
decrypt_data(key: Uint8Array, cipher: Uint8Array): number[] // puis decode_value(clear)
// Process
create_new_process(encodedPrivate, roles, encodedPublic, relayAddress, feeRate, members): ApiReturn
update_process(process, encodedPrivate, rolesOrNull, encodedPublic, members): ApiReturn
validate_state(process, stateId, members): ApiReturn
create_update_message(process, stateId, members): ApiReturn
create_response_prd(process, stateId, members): ApiReturn
refuse_state(process, stateId): ApiReturn
// Réseau/sync
create_transaction(addresses: string[], feeRate: number): ApiReturn
request_data(processId: string, stateIds: string[], roles: RoleDefinition[], members): ApiReturn
parse_cipher(message: string, members, processes): ApiReturn
parse_new_tx(newTxMsg: string, _: number, members): ApiReturn
sign_transaction(partial): { new_tx_to_send: NewTxMessage }
```
### Pseudocode réaliste
Création dun process
```ts
const { jsonCompatibleData, binaryData } = splitData(privateData);
const encodedPrivate = { ...sdk.encode_json(jsonCompatibleData), ...sdk.encode_binary(binaryData) };
const encodedPublic = { ...sdk.encode_json(publicData) };
const members = services.getAllMembers();
const res = sdk.create_new_process(encodedPrivate, roles, encodedPublic, relayAddr, 1, members);
await services.handleApiReturn(res); // stocke process, blobs, secrets, diffs
await services.checkConnections(res.updated_process.current_process);
```
Mise à jour dun process
```ts
const { privateDelta, publicDelta, rolesDelta } = computeDelta(...);
const encPriv = encode(privateDelta);
const encPub = encode(publicDelta);
const res = sdk.update_process(process, encPriv, rolesDelta ?? services.getRoles(process), encPub, services.getAllMembers());
await services.handleApiReturn(res);
```
Récupération des données privées dun état
```ts
// hôte → iframe via postMessage: RETRIEVE_DATA
postMessage({ type: 'RETRIEVE_DATA', processId, stateId, accessToken });
// iframe (router) → Services
const process = await services.getProcess(processId);
await services.checkConnections(process, stateId);
const clear = await services.decryptAttribute(processId, state, 'attributeName');
// réponse: DATA_RETRIEVED
```
Connexion aux membres (pour obtenir des clés)
```ts
await services.ensureSufficientAmount();
const api = sdk.create_transaction(addresses, 1);
await services.handleApiReturn(api); // secrets dans IndexedDB puis set_shared_secrets() via restoreSecretsFromDB
```
### Endpoints / Interfaces réseau
- WebSocket relay (exemples):
- URL: `wss://<BASEURL>/ws/`
- Messages sortants (JSON): `{ flag: 'NewTx'|'Commit'|'Cipher'|'Faucet', payload: string }`
- Messages entrants: `handshake` (contient `sp_address`, `chain_tip`, `peers_list`, `processes_list`), `new_tx`, `cipher`, réponses aux commits/requests.
### Bonnes pratiques
- Toujours attendre au moins un handshake relay avant de tenter `request_data`.
- Utiliser `handleApiReturn` pour appliquer systématiquement les effets (stockage blobs/diffs/process, envoi tx, secrets).
- Vérifier rôles et pairing avant toute tentative daccès aux privés.