docs(sdk): specs sdk_common, sdk_relay (WS), rust-silentpayments + pseudo-code & endpoints
This commit is contained in:
parent
f63bf086cf
commit
e13708d361
131
docs/SDK_USAGE_SPEC.md
Normal file
131
docs/SDK_USAGE_SPEC.md
Normal 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 d’un 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 d’un 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 d’un é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 d’accès aux privés.
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user