mirror of
https://gitlab.com/veilid/veilidchat.git
synced 2024-12-25 07:39:25 -05:00
better dht record class
This commit is contained in:
parent
90fc2e5f85
commit
bf813d7d0f
@ -1,3 +1,4 @@
|
||||
import 'package:fast_immutable_collections/fast_immutable_collections.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'package:veilid/veilid.dart';
|
||||
|
||||
@ -7,14 +8,15 @@ part 'identity.g.dart';
|
||||
// AccountOwnerInfo is the key and owner info for the account dht key that is
|
||||
// stored in the identity key
|
||||
@freezed
|
||||
class AccountOwnerInfo with _$AccountOwnerInfo {
|
||||
const factory AccountOwnerInfo({
|
||||
class AccountRecordInfo with _$AccountRecordInfo {
|
||||
const factory AccountRecordInfo({
|
||||
// Top level account keys and secrets
|
||||
required Map<String, TypedKeyPair> accountKeyPairs,
|
||||
}) = _AccountOwnerInfo;
|
||||
required TypedKey key,
|
||||
required KeyPair owner,
|
||||
}) = _AccountRecordInfo;
|
||||
|
||||
factory AccountOwnerInfo.fromJson(Map<String, dynamic> json) =>
|
||||
_$AccountOwnerInfoFromJson(json);
|
||||
factory AccountRecordInfo.fromJson(Map<String, dynamic> json) =>
|
||||
_$AccountRecordInfoFromJson(json);
|
||||
}
|
||||
|
||||
// Identity Key points to accounts associated with this identity
|
||||
@ -27,7 +29,7 @@ class AccountOwnerInfo with _$AccountOwnerInfo {
|
||||
class Identity with _$Identity {
|
||||
const factory Identity({
|
||||
// Top level account keys and secrets
|
||||
required Map<String, TypedKeyPair> accountKeyPairs,
|
||||
required IMap<String, ISet<AccountRecordInfo>> accountRecords,
|
||||
}) = _Identity;
|
||||
|
||||
factory Identity.fromJson(Map<String, dynamic> json) =>
|
||||
|
@ -14,35 +14,35 @@ T _$identity<T>(T value) => value;
|
||||
final _privateConstructorUsedError = UnsupportedError(
|
||||
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods');
|
||||
|
||||
AccountOwnerInfo _$AccountOwnerInfoFromJson(Map<String, dynamic> json) {
|
||||
return _AccountOwnerInfo.fromJson(json);
|
||||
AccountRecordInfo _$AccountRecordInfoFromJson(Map<String, dynamic> json) {
|
||||
return _AccountRecordInfo.fromJson(json);
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
mixin _$AccountOwnerInfo {
|
||||
mixin _$AccountRecordInfo {
|
||||
// Top level account keys and secrets
|
||||
Map<String, TypedKeyPair> get accountKeyPairs =>
|
||||
throw _privateConstructorUsedError;
|
||||
Typed<FixedEncodedString43> get key => throw _privateConstructorUsedError;
|
||||
KeyPair get owner => throw _privateConstructorUsedError;
|
||||
|
||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||
@JsonKey(ignore: true)
|
||||
$AccountOwnerInfoCopyWith<AccountOwnerInfo> get copyWith =>
|
||||
$AccountRecordInfoCopyWith<AccountRecordInfo> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $AccountOwnerInfoCopyWith<$Res> {
|
||||
factory $AccountOwnerInfoCopyWith(
|
||||
AccountOwnerInfo value, $Res Function(AccountOwnerInfo) then) =
|
||||
_$AccountOwnerInfoCopyWithImpl<$Res, AccountOwnerInfo>;
|
||||
abstract class $AccountRecordInfoCopyWith<$Res> {
|
||||
factory $AccountRecordInfoCopyWith(
|
||||
AccountRecordInfo value, $Res Function(AccountRecordInfo) then) =
|
||||
_$AccountRecordInfoCopyWithImpl<$Res, AccountRecordInfo>;
|
||||
@useResult
|
||||
$Res call({Map<String, TypedKeyPair> accountKeyPairs});
|
||||
$Res call({Typed<FixedEncodedString43> key, KeyPair owner});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$AccountOwnerInfoCopyWithImpl<$Res, $Val extends AccountOwnerInfo>
|
||||
implements $AccountOwnerInfoCopyWith<$Res> {
|
||||
_$AccountOwnerInfoCopyWithImpl(this._value, this._then);
|
||||
class _$AccountRecordInfoCopyWithImpl<$Res, $Val extends AccountRecordInfo>
|
||||
implements $AccountRecordInfoCopyWith<$Res> {
|
||||
_$AccountRecordInfoCopyWithImpl(this._value, this._then);
|
||||
|
||||
// ignore: unused_field
|
||||
final $Val _value;
|
||||
@ -52,116 +52,122 @@ class _$AccountOwnerInfoCopyWithImpl<$Res, $Val extends AccountOwnerInfo>
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? accountKeyPairs = null,
|
||||
Object? key = null,
|
||||
Object? owner = null,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
accountKeyPairs: null == accountKeyPairs
|
||||
? _value.accountKeyPairs
|
||||
: accountKeyPairs // ignore: cast_nullable_to_non_nullable
|
||||
as Map<String, TypedKeyPair>,
|
||||
key: null == key
|
||||
? _value.key
|
||||
: key // ignore: cast_nullable_to_non_nullable
|
||||
as Typed<FixedEncodedString43>,
|
||||
owner: null == owner
|
||||
? _value.owner
|
||||
: owner // ignore: cast_nullable_to_non_nullable
|
||||
as KeyPair,
|
||||
) as $Val);
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$_AccountOwnerInfoCopyWith<$Res>
|
||||
implements $AccountOwnerInfoCopyWith<$Res> {
|
||||
factory _$$_AccountOwnerInfoCopyWith(
|
||||
_$_AccountOwnerInfo value, $Res Function(_$_AccountOwnerInfo) then) =
|
||||
__$$_AccountOwnerInfoCopyWithImpl<$Res>;
|
||||
abstract class _$$_AccountRecordInfoCopyWith<$Res>
|
||||
implements $AccountRecordInfoCopyWith<$Res> {
|
||||
factory _$$_AccountRecordInfoCopyWith(_$_AccountRecordInfo value,
|
||||
$Res Function(_$_AccountRecordInfo) then) =
|
||||
__$$_AccountRecordInfoCopyWithImpl<$Res>;
|
||||
@override
|
||||
@useResult
|
||||
$Res call({Map<String, TypedKeyPair> accountKeyPairs});
|
||||
$Res call({Typed<FixedEncodedString43> key, KeyPair owner});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$_AccountOwnerInfoCopyWithImpl<$Res>
|
||||
extends _$AccountOwnerInfoCopyWithImpl<$Res, _$_AccountOwnerInfo>
|
||||
implements _$$_AccountOwnerInfoCopyWith<$Res> {
|
||||
__$$_AccountOwnerInfoCopyWithImpl(
|
||||
_$_AccountOwnerInfo _value, $Res Function(_$_AccountOwnerInfo) _then)
|
||||
class __$$_AccountRecordInfoCopyWithImpl<$Res>
|
||||
extends _$AccountRecordInfoCopyWithImpl<$Res, _$_AccountRecordInfo>
|
||||
implements _$$_AccountRecordInfoCopyWith<$Res> {
|
||||
__$$_AccountRecordInfoCopyWithImpl(
|
||||
_$_AccountRecordInfo _value, $Res Function(_$_AccountRecordInfo) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? accountKeyPairs = null,
|
||||
Object? key = null,
|
||||
Object? owner = null,
|
||||
}) {
|
||||
return _then(_$_AccountOwnerInfo(
|
||||
accountKeyPairs: null == accountKeyPairs
|
||||
? _value._accountKeyPairs
|
||||
: accountKeyPairs // ignore: cast_nullable_to_non_nullable
|
||||
as Map<String, TypedKeyPair>,
|
||||
return _then(_$_AccountRecordInfo(
|
||||
key: null == key
|
||||
? _value.key
|
||||
: key // ignore: cast_nullable_to_non_nullable
|
||||
as Typed<FixedEncodedString43>,
|
||||
owner: null == owner
|
||||
? _value.owner
|
||||
: owner // ignore: cast_nullable_to_non_nullable
|
||||
as KeyPair,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
class _$_AccountOwnerInfo implements _AccountOwnerInfo {
|
||||
const _$_AccountOwnerInfo(
|
||||
{required final Map<String, TypedKeyPair> accountKeyPairs})
|
||||
: _accountKeyPairs = accountKeyPairs;
|
||||
class _$_AccountRecordInfo implements _AccountRecordInfo {
|
||||
const _$_AccountRecordInfo({required this.key, required this.owner});
|
||||
|
||||
factory _$_AccountOwnerInfo.fromJson(Map<String, dynamic> json) =>
|
||||
_$$_AccountOwnerInfoFromJson(json);
|
||||
factory _$_AccountRecordInfo.fromJson(Map<String, dynamic> json) =>
|
||||
_$$_AccountRecordInfoFromJson(json);
|
||||
|
||||
// Top level account keys and secrets
|
||||
final Map<String, TypedKeyPair> _accountKeyPairs;
|
||||
// Top level account keys and secrets
|
||||
@override
|
||||
Map<String, TypedKeyPair> get accountKeyPairs {
|
||||
if (_accountKeyPairs is EqualUnmodifiableMapView) return _accountKeyPairs;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableMapView(_accountKeyPairs);
|
||||
}
|
||||
final Typed<FixedEncodedString43> key;
|
||||
@override
|
||||
final KeyPair owner;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'AccountOwnerInfo(accountKeyPairs: $accountKeyPairs)';
|
||||
return 'AccountRecordInfo(key: $key, owner: $owner)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(dynamic other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$_AccountOwnerInfo &&
|
||||
const DeepCollectionEquality()
|
||||
.equals(other._accountKeyPairs, _accountKeyPairs));
|
||||
other is _$_AccountRecordInfo &&
|
||||
(identical(other.key, key) || other.key == key) &&
|
||||
(identical(other.owner, owner) || other.owner == owner));
|
||||
}
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
int get hashCode => Object.hash(
|
||||
runtimeType, const DeepCollectionEquality().hash(_accountKeyPairs));
|
||||
int get hashCode => Object.hash(runtimeType, key, owner);
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$_AccountOwnerInfoCopyWith<_$_AccountOwnerInfo> get copyWith =>
|
||||
__$$_AccountOwnerInfoCopyWithImpl<_$_AccountOwnerInfo>(this, _$identity);
|
||||
_$$_AccountRecordInfoCopyWith<_$_AccountRecordInfo> get copyWith =>
|
||||
__$$_AccountRecordInfoCopyWithImpl<_$_AccountRecordInfo>(
|
||||
this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$$_AccountOwnerInfoToJson(
|
||||
return _$$_AccountRecordInfoToJson(
|
||||
this,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
abstract class _AccountOwnerInfo implements AccountOwnerInfo {
|
||||
const factory _AccountOwnerInfo(
|
||||
{required final Map<String, TypedKeyPair> accountKeyPairs}) =
|
||||
_$_AccountOwnerInfo;
|
||||
abstract class _AccountRecordInfo implements AccountRecordInfo {
|
||||
const factory _AccountRecordInfo(
|
||||
{required final Typed<FixedEncodedString43> key,
|
||||
required final KeyPair owner}) = _$_AccountRecordInfo;
|
||||
|
||||
factory _AccountOwnerInfo.fromJson(Map<String, dynamic> json) =
|
||||
_$_AccountOwnerInfo.fromJson;
|
||||
factory _AccountRecordInfo.fromJson(Map<String, dynamic> json) =
|
||||
_$_AccountRecordInfo.fromJson;
|
||||
|
||||
@override // Top level account keys and secrets
|
||||
Map<String, TypedKeyPair> get accountKeyPairs;
|
||||
Typed<FixedEncodedString43> get key;
|
||||
@override
|
||||
KeyPair get owner;
|
||||
@override
|
||||
@JsonKey(ignore: true)
|
||||
_$$_AccountOwnerInfoCopyWith<_$_AccountOwnerInfo> get copyWith =>
|
||||
_$$_AccountRecordInfoCopyWith<_$_AccountRecordInfo> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
@ -172,7 +178,7 @@ Identity _$IdentityFromJson(Map<String, dynamic> json) {
|
||||
/// @nodoc
|
||||
mixin _$Identity {
|
||||
// Top level account keys and secrets
|
||||
Map<String, TypedKeyPair> get accountKeyPairs =>
|
||||
IMap<String, ISet<AccountRecordInfo>> get accountRecords =>
|
||||
throw _privateConstructorUsedError;
|
||||
|
||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||
@ -186,7 +192,7 @@ abstract class $IdentityCopyWith<$Res> {
|
||||
factory $IdentityCopyWith(Identity value, $Res Function(Identity) then) =
|
||||
_$IdentityCopyWithImpl<$Res, Identity>;
|
||||
@useResult
|
||||
$Res call({Map<String, TypedKeyPair> accountKeyPairs});
|
||||
$Res call({IMap<String, ISet<AccountRecordInfo>> accountRecords});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@ -202,13 +208,13 @@ class _$IdentityCopyWithImpl<$Res, $Val extends Identity>
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? accountKeyPairs = null,
|
||||
Object? accountRecords = null,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
accountKeyPairs: null == accountKeyPairs
|
||||
? _value.accountKeyPairs
|
||||
: accountKeyPairs // ignore: cast_nullable_to_non_nullable
|
||||
as Map<String, TypedKeyPair>,
|
||||
accountRecords: null == accountRecords
|
||||
? _value.accountRecords
|
||||
: accountRecords // ignore: cast_nullable_to_non_nullable
|
||||
as IMap<String, ISet<AccountRecordInfo>>,
|
||||
) as $Val);
|
||||
}
|
||||
}
|
||||
@ -220,7 +226,7 @@ abstract class _$$_IdentityCopyWith<$Res> implements $IdentityCopyWith<$Res> {
|
||||
__$$_IdentityCopyWithImpl<$Res>;
|
||||
@override
|
||||
@useResult
|
||||
$Res call({Map<String, TypedKeyPair> accountKeyPairs});
|
||||
$Res call({IMap<String, ISet<AccountRecordInfo>> accountRecords});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@ -234,13 +240,13 @@ class __$$_IdentityCopyWithImpl<$Res>
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? accountKeyPairs = null,
|
||||
Object? accountRecords = null,
|
||||
}) {
|
||||
return _then(_$_Identity(
|
||||
accountKeyPairs: null == accountKeyPairs
|
||||
? _value._accountKeyPairs
|
||||
: accountKeyPairs // ignore: cast_nullable_to_non_nullable
|
||||
as Map<String, TypedKeyPair>,
|
||||
accountRecords: null == accountRecords
|
||||
? _value.accountRecords
|
||||
: accountRecords // ignore: cast_nullable_to_non_nullable
|
||||
as IMap<String, ISet<AccountRecordInfo>>,
|
||||
));
|
||||
}
|
||||
}
|
||||
@ -248,25 +254,18 @@ class __$$_IdentityCopyWithImpl<$Res>
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
class _$_Identity implements _Identity {
|
||||
const _$_Identity({required final Map<String, TypedKeyPair> accountKeyPairs})
|
||||
: _accountKeyPairs = accountKeyPairs;
|
||||
const _$_Identity({required this.accountRecords});
|
||||
|
||||
factory _$_Identity.fromJson(Map<String, dynamic> json) =>
|
||||
_$$_IdentityFromJson(json);
|
||||
|
||||
// Top level account keys and secrets
|
||||
final Map<String, TypedKeyPair> _accountKeyPairs;
|
||||
// Top level account keys and secrets
|
||||
@override
|
||||
Map<String, TypedKeyPair> get accountKeyPairs {
|
||||
if (_accountKeyPairs is EqualUnmodifiableMapView) return _accountKeyPairs;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableMapView(_accountKeyPairs);
|
||||
}
|
||||
final IMap<String, ISet<AccountRecordInfo>> accountRecords;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'Identity(accountKeyPairs: $accountKeyPairs)';
|
||||
return 'Identity(accountRecords: $accountRecords)';
|
||||
}
|
||||
|
||||
@override
|
||||
@ -274,14 +273,13 @@ class _$_Identity implements _Identity {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$_Identity &&
|
||||
const DeepCollectionEquality()
|
||||
.equals(other._accountKeyPairs, _accountKeyPairs));
|
||||
(identical(other.accountRecords, accountRecords) ||
|
||||
other.accountRecords == accountRecords));
|
||||
}
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
int get hashCode => Object.hash(
|
||||
runtimeType, const DeepCollectionEquality().hash(_accountKeyPairs));
|
||||
int get hashCode => Object.hash(runtimeType, accountRecords);
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
@ -299,12 +297,13 @@ class _$_Identity implements _Identity {
|
||||
|
||||
abstract class _Identity implements Identity {
|
||||
const factory _Identity(
|
||||
{required final Map<String, TypedKeyPair> accountKeyPairs}) = _$_Identity;
|
||||
{required final IMap<String, ISet<AccountRecordInfo>>
|
||||
accountRecords}) = _$_Identity;
|
||||
|
||||
factory _Identity.fromJson(Map<String, dynamic> json) = _$_Identity.fromJson;
|
||||
|
||||
@override // Top level account keys and secrets
|
||||
Map<String, TypedKeyPair> get accountKeyPairs;
|
||||
IMap<String, ISet<AccountRecordInfo>> get accountRecords;
|
||||
@override
|
||||
@JsonKey(ignore: true)
|
||||
_$$_IdentityCopyWith<_$_Identity> get copyWith =>
|
||||
|
@ -6,29 +6,37 @@ part of 'identity.dart';
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
_$_AccountOwnerInfo _$$_AccountOwnerInfoFromJson(Map<String, dynamic> json) =>
|
||||
_$_AccountOwnerInfo(
|
||||
accountKeyPairs: (json['account_key_pairs'] as Map<String, dynamic>).map(
|
||||
(k, e) => MapEntry(k, TypedKeyPair.fromJson(e)),
|
||||
),
|
||||
_$_AccountRecordInfo _$$_AccountRecordInfoFromJson(Map<String, dynamic> json) =>
|
||||
_$_AccountRecordInfo(
|
||||
key: Typed<FixedEncodedString43>.fromJson(json['key']),
|
||||
owner: KeyPair.fromJson(json['owner']),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$_AccountOwnerInfoToJson(_$_AccountOwnerInfo instance) =>
|
||||
Map<String, dynamic> _$$_AccountRecordInfoToJson(
|
||||
_$_AccountRecordInfo instance) =>
|
||||
<String, dynamic>{
|
||||
'account_key_pairs':
|
||||
instance.accountKeyPairs.map((k, e) => MapEntry(k, e.toJson())),
|
||||
'key': instance.key.toJson(),
|
||||
'owner': instance.owner.toJson(),
|
||||
};
|
||||
|
||||
_$_Identity _$$_IdentityFromJson(Map<String, dynamic> json) => _$_Identity(
|
||||
accountKeyPairs: (json['account_key_pairs'] as Map<String, dynamic>).map(
|
||||
(k, e) => MapEntry(k, TypedKeyPair.fromJson(e)),
|
||||
),
|
||||
accountRecords: IMap<String, ISet<AccountRecordInfo>>.fromJson(
|
||||
json['account_records'] as Map<String, dynamic>,
|
||||
(value) => value as String,
|
||||
(value) => ISet<AccountRecordInfo>.fromJson(
|
||||
value,
|
||||
(value) =>
|
||||
AccountRecordInfo.fromJson(value as Map<String, dynamic>))),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$_IdentityToJson(_$_Identity instance) =>
|
||||
<String, dynamic>{
|
||||
'account_key_pairs':
|
||||
instance.accountKeyPairs.map((k, e) => MapEntry(k, e.toJson())),
|
||||
'account_records': instance.accountRecords.toJson(
|
||||
(value) => value,
|
||||
(value) => value.toJson(
|
||||
(value) => value.toJson(),
|
||||
),
|
||||
),
|
||||
};
|
||||
|
||||
_$_IdentityMaster _$$_IdentityMasterFromJson(Map<String, dynamic> json) =>
|
||||
|
@ -102,23 +102,48 @@ class LocalAccountManager {
|
||||
}
|
||||
}
|
||||
|
||||
/// Adds a 'VeilidChat' account record to an identity key
|
||||
Future<void> updateIdentityKey(
|
||||
VeilidRoutingContext dhtctx,
|
||||
TypedKey identityRecordKey,
|
||||
TypedKey accountRecordKey,
|
||||
KeyPair accountRecordOwner) async {
|
||||
// Account record to add
|
||||
final accountRecordInfo =
|
||||
AccountRecordInfo(key: accountRecordKey, owner: accountRecordOwner);
|
||||
|
||||
// Eventually update identity key
|
||||
eventuallyConsistentUpdate(
|
||||
dhtctx,
|
||||
identityRecordKey,
|
||||
0,
|
||||
true,
|
||||
jsonUpdate(Identity.fromJson, (oldObj) async {
|
||||
final accountRecords = IMapOfSets.from(oldObj.accountRecords)
|
||||
.add("VeilidChat", accountRecordInfo)
|
||||
.asIMap();
|
||||
return oldObj.copyWith(accountRecords: accountRecords);
|
||||
}));
|
||||
|
||||
// Get existing identity key
|
||||
ValueData? identityValueData =
|
||||
await dhtctx.getDHTValue(identityRecordKey, 0, true);
|
||||
if (identityValueData == null) {
|
||||
throw const FormatException("Identity does not exist");
|
||||
}
|
||||
var identity = identityValueData.readJsonData(Identity.fromJson);
|
||||
xxx make back to bytes function and do update loop and maybe make that a tool function too (consistentUpdate)
|
||||
// Update identity key to include account
|
||||
const identity = Identity(accountKeyPairs: {});
|
||||
final identityBytes = Uint8List.fromList(utf8.encode(jsonEncode(identity)));
|
||||
await dhtctx.setDHTValue(identityRec.key, 0, identityBytes);
|
||||
do {
|
||||
if (identityValueData == null) {
|
||||
throw const FormatException("Identity does not exist");
|
||||
}
|
||||
|
||||
var identity = identityValueData.readJsonData(Identity.fromJson);
|
||||
// Update identity key to include account
|
||||
final accountRecords = IMapOfSets.from(identity.accountRecords)
|
||||
.add("VeilidChat", accountRecordInfo)
|
||||
.asIMap();
|
||||
identity = identity.copyWith(accountRecords: accountRecords);
|
||||
|
||||
final identityBytes = jsonEncodeBytes(identity);
|
||||
identityValueData =
|
||||
await dhtctx.setDHTValue(identityRecordKey, 0, identityBytes);
|
||||
} while (identityValueData != null);
|
||||
}
|
||||
|
||||
/// Creates a new account associated with master identity
|
||||
|
109
lib/tools/dht_record.dart
Normal file
109
lib/tools/dht_record.dart
Normal file
@ -0,0 +1,109 @@
|
||||
import 'package:veilid/veilid.dart';
|
||||
import 'dart:typed_data';
|
||||
import 'tools.dart';
|
||||
|
||||
class DHTRecord {
|
||||
final VeilidRoutingContext _dhtctx;
|
||||
final DHTRecordDescriptor _recordDescriptor;
|
||||
final int _defaultSubkey;
|
||||
|
||||
static Future<DHTRecord> create(VeilidRoutingContext dhtctx,
|
||||
{DHTSchema schema = const DHTSchema.dflt(oCnt: 1),
|
||||
int defaultSubkey = 0}) async {
|
||||
DHTRecordDescriptor recordDescriptor = await dhtctx.createDHTRecord(schema);
|
||||
return DHTRecord(
|
||||
dhtctx: dhtctx,
|
||||
recordDescriptor: recordDescriptor,
|
||||
defaultSubkey: defaultSubkey);
|
||||
}
|
||||
|
||||
static Future<DHTRecord> open(
|
||||
VeilidRoutingContext dhtctx, TypedKey recordKey, KeyPair? writer,
|
||||
{int defaultSubkey = 0}) async {
|
||||
DHTRecordDescriptor recordDescriptor =
|
||||
await dhtctx.openDHTRecord(recordKey, writer);
|
||||
return DHTRecord(
|
||||
dhtctx: dhtctx,
|
||||
recordDescriptor: recordDescriptor,
|
||||
defaultSubkey: defaultSubkey);
|
||||
}
|
||||
|
||||
DHTRecord(
|
||||
{required VeilidRoutingContext dhtctx,
|
||||
required DHTRecordDescriptor recordDescriptor,
|
||||
int defaultSubkey = 0})
|
||||
: _dhtctx = dhtctx,
|
||||
_recordDescriptor = recordDescriptor,
|
||||
_defaultSubkey = defaultSubkey;
|
||||
|
||||
int _subkey(int subkey) => (subkey == -1) ? _defaultSubkey : subkey;
|
||||
|
||||
Future<Uint8List?> get({int subkey = -1, bool forceRefresh = false}) async {
|
||||
ValueData? valueData = await _dhtctx.getDHTValue(
|
||||
_recordDescriptor.key, _subkey(subkey), false);
|
||||
if (valueData == null) {
|
||||
return null;
|
||||
}
|
||||
return valueData.data;
|
||||
}
|
||||
|
||||
Future<T?> getJson<T>(T Function(Map<String, dynamic>) fromJson,
|
||||
{int subkey = -1, bool forceRefresh = false}) async {
|
||||
ValueData? valueData = await _dhtctx.getDHTValue(
|
||||
_recordDescriptor.key, _subkey(subkey), false);
|
||||
if (valueData == null) {
|
||||
return null;
|
||||
}
|
||||
return valueData.readJsonData(fromJson);
|
||||
}
|
||||
|
||||
Future<void> eventualWriteBytes(Uint8List newValue, {int subkey = -1}) async {
|
||||
// Get existing identity key
|
||||
ValueData? valueData;
|
||||
do {
|
||||
// Ensure it exists already
|
||||
if (valueData == null) {
|
||||
throw const FormatException("value does not exist");
|
||||
}
|
||||
|
||||
// Set the new data
|
||||
valueData = await _dhtctx.setDHTValue(
|
||||
_recordDescriptor.key, _subkey(subkey), newValue);
|
||||
|
||||
// Repeat if newer data on the network was found
|
||||
} while (valueData != null);
|
||||
}
|
||||
|
||||
Future<void> eventualUpdateBytes(
|
||||
Future<Uint8List> Function(Uint8List oldValue) update,
|
||||
{int subkey = -1}) async {
|
||||
// Get existing identity key
|
||||
ValueData? valueData = await _dhtctx.getDHTValue(
|
||||
_recordDescriptor.key, _subkey(subkey), false);
|
||||
do {
|
||||
// Ensure it exists already
|
||||
if (valueData == null) {
|
||||
throw const FormatException("value does not exist");
|
||||
}
|
||||
|
||||
// Update the data
|
||||
final newData = await update(valueData.data);
|
||||
|
||||
// Set it back
|
||||
valueData = await _dhtctx.setDHTValue(
|
||||
_recordDescriptor.key, _subkey(subkey), newData);
|
||||
|
||||
// Repeat if newer data on the network was found
|
||||
} while (valueData != null);
|
||||
}
|
||||
|
||||
Future<void> eventualWriteJson<T>(T newValue, {int subkey = -1}) {
|
||||
return eventualWriteBytes(jsonEncodeBytes(newValue), subkey: subkey);
|
||||
}
|
||||
|
||||
Future<void> eventualUpdateJson<T>(
|
||||
T Function(Map<String, dynamic>) fromJson, Future<T> Function(T) update,
|
||||
{int subkey = -1}) {
|
||||
return eventualUpdateBytes(jsonUpdate(fromJson, update), subkey: subkey);
|
||||
}
|
||||
}
|
30
lib/tools/json_tools.dart
Normal file
30
lib/tools/json_tools.dart
Normal file
@ -0,0 +1,30 @@
|
||||
// import 'package:fast_immutable_collections/fast_immutable_collections.dart';
|
||||
import 'package:veilid/veilid.dart';
|
||||
import 'dart:typed_data';
|
||||
import 'dart:convert';
|
||||
|
||||
extension FromValueDataJsonExt on ValueData {
|
||||
T readJsonData<T>(T Function(Map<String, dynamic>) fromJson) {
|
||||
return fromJson(jsonDecode(utf8.decode(data)));
|
||||
}
|
||||
}
|
||||
|
||||
Uint8List jsonEncodeBytes(Object? object,
|
||||
{Object? Function(Object?)? toEncodable}) {
|
||||
return Uint8List.fromList(
|
||||
utf8.encode(jsonEncode(object, toEncodable: toEncodable)));
|
||||
}
|
||||
|
||||
Future<Uint8List> jsonUpdateBytes<T>(T Function(Map<String, dynamic>) fromJson,
|
||||
Uint8List oldBytes, Future<T> Function(T) update) async {
|
||||
T oldObj = fromJson(jsonDecode(utf8.decode(oldBytes)));
|
||||
T newObj = await update(oldObj);
|
||||
return jsonEncodeBytes(newObj);
|
||||
}
|
||||
|
||||
Future<Uint8List> Function(Uint8List) jsonUpdate<T>(
|
||||
T Function(Map<String, dynamic>) fromJson, Future<T> Function(T) update) {
|
||||
return (Uint8List oldBytes) {
|
||||
return jsonUpdateBytes(fromJson, oldBytes, update);
|
||||
};
|
||||
}
|
@ -1,9 +1,4 @@
|
||||
export 'external_stream_state.dart';
|
||||
import 'package:veilid/veilid.dart';
|
||||
import 'dart:convert';
|
||||
|
||||
extension FromValueDataJsonExt on ValueData {
|
||||
T readJsonData<T>(T Function(Map<String, dynamic>) fromJson) {
|
||||
return fromJson(jsonDecode(utf8.decode(data)));
|
||||
}
|
||||
}
|
||||
export 'dht_record.dart';
|
||||
export 'json_tools.dart';
|
||||
export 'phono_byte.dart';
|
||||
|
Loading…
Reference in New Issue
Block a user