tane/apps/app_seeds/test/services/social_service_test.dart
vjrj 70905a0578 feat(block2): wire the social identity into app_seeds (DI, no UI)
Third slice: bridge Block 1's root seed to the Block 2 transport foundation.

- SocialService: derives the secp256k1 Nostr identity from the SAME root seed
  the recovery QR backs up (no extra backup), exposes npub/pubkey, and opens a
  SocialSession = one shared connection carrying all three transports.
- injector.dart: registers SocialService in get_it. Local-first — derivation is
  cheap + offline; no relay is contacted at startup. Replaces the old
  "nodeId slice of the seed is the social pubkey" placeholder; keeps the CRDT
  author id distinct (unifying it would rewrite authorship — a later decision).
- Test: deterministic identity from the seed hex, matches commons_core, rejects
  malformed hex. 5 tests green; app_seeds analyzes clean (0 errors).
2026-07-10 02:44:37 +02:00

48 lines
1.8 KiB
Dart

import 'package:commons_core/commons_core.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:tane/services/social_service.dart';
/// Wiring test: the app derives its social identity from the SAME root seed the
/// recovery QR backs up, deterministically and without any network.
void main() {
// A fixed 32-byte seed (64 hex chars).
const seedHex =
'000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f';
test('derives a stable Nostr identity from the root-seed hex', () async {
final service = await SocialService.fromRootSeedHex(seedHex);
expect(service.npub, startsWith('npub1'));
expect(service.publicKeyHex, matches(RegExp(r'^[0-9a-f]{64}$')));
});
test('is deterministic: same seed → same public identity', () async {
final a = await SocialService.fromRootSeedHex(seedHex);
final b = await SocialService.fromRootSeedHex(seedHex);
expect(a.publicKeyHex, b.publicKeyHex);
expect(a.npub, b.npub);
});
test('matches commons_core derivation on the same bytes', () async {
final service = await SocialService.fromRootSeedHex(seedHex);
final direct = await NostrKeyDerivation.deriveFromSeed([
for (var i = 0; i < seedHex.length; i += 2)
int.parse(seedHex.substring(i, i + 2), radix: 16),
]);
expect(service.publicKeyHex, direct.publicKeyHex);
});
test('a different seed yields a different identity', () async {
final a = await SocialService.fromRootSeedHex(seedHex);
final b = await SocialService.fromRootSeedHex(
'ff${seedHex.substring(2)}',
);
expect(a.publicKeyHex, isNot(b.publicKeyHex));
});
test('rejects a malformed (odd-length) seed hex', () async {
await expectLater(
SocialService.fromRootSeedHex('abc'),
throwsA(isA<ArgumentError>()),
);
});
}