feat(useragent): add SDK clients table screen

This commit is contained in:
hdbg
2026-03-22 13:07:14 +01:00
parent 4ebe7b6fc4
commit d9b3694cab
26 changed files with 1977 additions and 1402 deletions

View File

@@ -4,14 +4,8 @@ import 'package:arbiter/proto/user_agent.pb.dart';
import 'package:fixnum/fixnum.dart';
import 'package:protobuf/well_known_types/google/protobuf/timestamp.pb.dart';
Future<List<GrantEntry>> listEvmGrants(
Connection connection, {
int? walletId,
}) async {
Future<List<GrantEntry>> listEvmGrants(Connection connection) async {
final request = EvmGrantListRequest();
if (walletId != null) {
request.walletId = walletId;
}
final response = await connection.request(
UserAgentRequest(evmGrantList: request),
@@ -45,38 +39,7 @@ Future<int> createEvmGrant(
TransactionRateLimit? rateLimit,
required SpecificGrant specific,
}) async {
final response = await connection.request(
UserAgentRequest(
evmGrantCreate: EvmGrantCreateRequest(
clientId: clientId,
shared: SharedSettings(
walletId: walletId,
chainId: chainId,
validFrom: validFrom == null ? null : _toTimestamp(validFrom),
validUntil: validUntil == null ? null : _toTimestamp(validUntil),
maxGasFeePerGas: maxGasFeePerGas,
maxPriorityFeePerGas: maxPriorityFeePerGas,
rateLimit: rateLimit,
),
specific: specific,
),
),
);
if (!response.hasEvmGrantCreate()) {
throw Exception(
'Expected EVM grant create response, got ${response.whichPayload()}',
);
}
final result = response.evmGrantCreate;
switch (result.whichResult()) {
case EvmGrantCreateResponse_Result.grantId:
return result.grantId;
case EvmGrantCreateResponse_Result.error:
throw Exception(_describeGrantError(result.error));
case EvmGrantCreateResponse_Result.notSet:
throw Exception('Grant creation returned no result.');
}
throw UnimplementedError('EVM grant creation is not yet implemented.');
}
Future<void> deleteEvmGrant(Connection connection, int grantId) async {

View File

@@ -22,12 +22,91 @@ export 'package:protobuf/protobuf.dart' show GeneratedMessageGenericExtensions;
export 'client.pbenum.dart';
class ClientInfo extends $pb.GeneratedMessage {
factory ClientInfo({
$core.String? name,
$core.String? description,
$core.String? version,
}) {
final result = create();
if (name != null) result.name = name;
if (description != null) result.description = description;
if (version != null) result.version = version;
return result;
}
ClientInfo._();
factory ClientInfo.fromBuffer($core.List<$core.int> data,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromBuffer(data, registry);
factory ClientInfo.fromJson($core.String json,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromJson(json, registry);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
_omitMessageNames ? '' : 'ClientInfo',
package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.client'),
createEmptyInstance: create)
..aOS(1, _omitFieldNames ? '' : 'name')
..aOS(2, _omitFieldNames ? '' : 'description')
..aOS(3, _omitFieldNames ? '' : 'version')
..hasRequiredFields = false;
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
ClientInfo clone() => deepCopy();
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
ClientInfo copyWith(void Function(ClientInfo) updates) =>
super.copyWith((message) => updates(message as ClientInfo)) as ClientInfo;
@$core.override
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static ClientInfo create() => ClientInfo._();
@$core.override
ClientInfo createEmptyInstance() => create();
@$core.pragma('dart2js:noInline')
static ClientInfo getDefault() => _defaultInstance ??=
$pb.GeneratedMessage.$_defaultFor<ClientInfo>(create);
static ClientInfo? _defaultInstance;
@$pb.TagNumber(1)
$core.String get name => $_getSZ(0);
@$pb.TagNumber(1)
set name($core.String value) => $_setString(0, value);
@$pb.TagNumber(1)
$core.bool hasName() => $_has(0);
@$pb.TagNumber(1)
void clearName() => $_clearField(1);
@$pb.TagNumber(2)
$core.String get description => $_getSZ(1);
@$pb.TagNumber(2)
set description($core.String value) => $_setString(1, value);
@$pb.TagNumber(2)
$core.bool hasDescription() => $_has(1);
@$pb.TagNumber(2)
void clearDescription() => $_clearField(2);
@$pb.TagNumber(3)
$core.String get version => $_getSZ(2);
@$pb.TagNumber(3)
set version($core.String value) => $_setString(2, value);
@$pb.TagNumber(3)
$core.bool hasVersion() => $_has(2);
@$pb.TagNumber(3)
void clearVersion() => $_clearField(3);
}
class AuthChallengeRequest extends $pb.GeneratedMessage {
factory AuthChallengeRequest({
$core.List<$core.int>? pubkey,
ClientInfo? clientInfo,
}) {
final result = create();
if (pubkey != null) result.pubkey = pubkey;
if (clientInfo != null) result.clientInfo = clientInfo;
return result;
}
@@ -46,6 +125,8 @@ class AuthChallengeRequest extends $pb.GeneratedMessage {
createEmptyInstance: create)
..a<$core.List<$core.int>>(
1, _omitFieldNames ? '' : 'pubkey', $pb.PbFieldType.OY)
..aOM<ClientInfo>(2, _omitFieldNames ? '' : 'clientInfo',
subBuilder: ClientInfo.create)
..hasRequiredFields = false;
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
@@ -75,6 +156,17 @@ class AuthChallengeRequest extends $pb.GeneratedMessage {
$core.bool hasPubkey() => $_has(0);
@$pb.TagNumber(1)
void clearPubkey() => $_clearField(1);
@$pb.TagNumber(2)
ClientInfo get clientInfo => $_getN(1);
@$pb.TagNumber(2)
set clientInfo(ClientInfo value) => $_setField(2, value);
@$pb.TagNumber(2)
$core.bool hasClientInfo() => $_has(1);
@$pb.TagNumber(2)
void clearClientInfo() => $_clearField(2);
@$pb.TagNumber(2)
ClientInfo ensureClientInfo() => $_ensure(1);
}
class AuthChallenge extends $pb.GeneratedMessage {

View File

@@ -55,18 +55,62 @@ final $typed_data.Uint8List vaultStateDescriptor = $convert.base64Decode(
'VfVU5CT09UU1RSQVBQRUQQARIWChJWQVVMVF9TVEFURV9TRUFMRUQQAhIYChRWQVVMVF9TVEFU'
'RV9VTlNFQUxFRBADEhUKEVZBVUxUX1NUQVRFX0VSUk9SEAQ=');
@$core.Deprecated('Use clientInfoDescriptor instead')
const ClientInfo$json = {
'1': 'ClientInfo',
'2': [
{'1': 'name', '3': 1, '4': 1, '5': 9, '10': 'name'},
{
'1': 'description',
'3': 2,
'4': 1,
'5': 9,
'9': 0,
'10': 'description',
'17': true
},
{
'1': 'version',
'3': 3,
'4': 1,
'5': 9,
'9': 1,
'10': 'version',
'17': true
},
],
'8': [
{'1': '_description'},
{'1': '_version'},
],
};
/// Descriptor for `ClientInfo`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List clientInfoDescriptor = $convert.base64Decode(
'CgpDbGllbnRJbmZvEhIKBG5hbWUYASABKAlSBG5hbWUSJQoLZGVzY3JpcHRpb24YAiABKAlIAF'
'ILZGVzY3JpcHRpb26IAQESHQoHdmVyc2lvbhgDIAEoCUgBUgd2ZXJzaW9uiAEBQg4KDF9kZXNj'
'cmlwdGlvbkIKCghfdmVyc2lvbg==');
@$core.Deprecated('Use authChallengeRequestDescriptor instead')
const AuthChallengeRequest$json = {
'1': 'AuthChallengeRequest',
'2': [
{'1': 'pubkey', '3': 1, '4': 1, '5': 12, '10': 'pubkey'},
{
'1': 'client_info',
'3': 2,
'4': 1,
'5': 11,
'6': '.arbiter.client.ClientInfo',
'10': 'clientInfo'
},
],
};
/// Descriptor for `AuthChallengeRequest`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List authChallengeRequestDescriptor =
$convert.base64Decode(
'ChRBdXRoQ2hhbGxlbmdlUmVxdWVzdBIWCgZwdWJrZXkYASABKAxSBnB1YmtleQ==');
final $typed_data.Uint8List authChallengeRequestDescriptor = $convert.base64Decode(
'ChRBdXRoQ2hhbGxlbmdlUmVxdWVzdBIWCgZwdWJrZXkYASABKAxSBnB1YmtleRI7CgtjbGllbn'
'RfaW5mbxgCIAEoCzIaLmFyYml0ZXIuY2xpZW50LkNsaWVudEluZm9SCmNsaWVudEluZm8=');
@$core.Deprecated('Use authChallengeDescriptor instead')
const AuthChallenge$json = {

View File

@@ -436,7 +436,7 @@ class VolumeRateLimit extends $pb.GeneratedMessage {
class SharedSettings extends $pb.GeneratedMessage {
factory SharedSettings({
$core.int? walletId,
$core.int? walletAccessId,
$fixnum.Int64? chainId,
$0.Timestamp? validFrom,
$0.Timestamp? validUntil,
@@ -445,7 +445,7 @@ class SharedSettings extends $pb.GeneratedMessage {
TransactionRateLimit? rateLimit,
}) {
final result = create();
if (walletId != null) result.walletId = walletId;
if (walletAccessId != null) result.walletAccessId = walletAccessId;
if (chainId != null) result.chainId = chainId;
if (validFrom != null) result.validFrom = validFrom;
if (validUntil != null) result.validUntil = validUntil;
@@ -469,7 +469,7 @@ class SharedSettings extends $pb.GeneratedMessage {
_omitMessageNames ? '' : 'SharedSettings',
package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.evm'),
createEmptyInstance: create)
..aI(1, _omitFieldNames ? '' : 'walletId')
..aI(1, _omitFieldNames ? '' : 'walletAccessId')
..a<$fixnum.Int64>(2, _omitFieldNames ? '' : 'chainId', $pb.PbFieldType.OU6,
defaultOrMaker: $fixnum.Int64.ZERO)
..aOM<$0.Timestamp>(3, _omitFieldNames ? '' : 'validFrom',
@@ -504,13 +504,13 @@ class SharedSettings extends $pb.GeneratedMessage {
static SharedSettings? _defaultInstance;
@$pb.TagNumber(1)
$core.int get walletId => $_getIZ(0);
$core.int get walletAccessId => $_getIZ(0);
@$pb.TagNumber(1)
set walletId($core.int value) => $_setSignedInt32(0, value);
set walletAccessId($core.int value) => $_setSignedInt32(0, value);
@$pb.TagNumber(1)
$core.bool hasWalletId() => $_has(0);
$core.bool hasWalletAccessId() => $_has(0);
@$pb.TagNumber(1)
void clearWalletId() => $_clearField(1);
void clearWalletAccessId() => $_clearField(1);
@$pb.TagNumber(2)
$fixnum.Int64 get chainId => $_getI64(1);
@@ -1625,12 +1625,10 @@ class TransactionEvalError extends $pb.GeneratedMessage {
/// --- UserAgent grant management ---
class EvmGrantCreateRequest extends $pb.GeneratedMessage {
factory EvmGrantCreateRequest({
$core.int? clientId,
SharedSettings? shared,
SpecificGrant? specific,
}) {
final result = create();
if (clientId != null) result.clientId = clientId;
if (shared != null) result.shared = shared;
if (specific != null) result.specific = specific;
return result;
@@ -1649,10 +1647,9 @@ class EvmGrantCreateRequest extends $pb.GeneratedMessage {
_omitMessageNames ? '' : 'EvmGrantCreateRequest',
package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.evm'),
createEmptyInstance: create)
..aI(1, _omitFieldNames ? '' : 'clientId')
..aOM<SharedSettings>(2, _omitFieldNames ? '' : 'shared',
..aOM<SharedSettings>(1, _omitFieldNames ? '' : 'shared',
subBuilder: SharedSettings.create)
..aOM<SpecificGrant>(3, _omitFieldNames ? '' : 'specific',
..aOM<SpecificGrant>(2, _omitFieldNames ? '' : 'specific',
subBuilder: SpecificGrant.create)
..hasRequiredFields = false;
@@ -1677,35 +1674,26 @@ class EvmGrantCreateRequest extends $pb.GeneratedMessage {
static EvmGrantCreateRequest? _defaultInstance;
@$pb.TagNumber(1)
$core.int get clientId => $_getIZ(0);
SharedSettings get shared => $_getN(0);
@$pb.TagNumber(1)
set clientId($core.int value) => $_setSignedInt32(0, value);
set shared(SharedSettings value) => $_setField(1, value);
@$pb.TagNumber(1)
$core.bool hasClientId() => $_has(0);
$core.bool hasShared() => $_has(0);
@$pb.TagNumber(1)
void clearClientId() => $_clearField(1);
void clearShared() => $_clearField(1);
@$pb.TagNumber(1)
SharedSettings ensureShared() => $_ensure(0);
@$pb.TagNumber(2)
SharedSettings get shared => $_getN(1);
SpecificGrant get specific => $_getN(1);
@$pb.TagNumber(2)
set shared(SharedSettings value) => $_setField(2, value);
set specific(SpecificGrant value) => $_setField(2, value);
@$pb.TagNumber(2)
$core.bool hasShared() => $_has(1);
$core.bool hasSpecific() => $_has(1);
@$pb.TagNumber(2)
void clearShared() => $_clearField(2);
void clearSpecific() => $_clearField(2);
@$pb.TagNumber(2)
SharedSettings ensureShared() => $_ensure(1);
@$pb.TagNumber(3)
SpecificGrant get specific => $_getN(2);
@$pb.TagNumber(3)
set specific(SpecificGrant value) => $_setField(3, value);
@$pb.TagNumber(3)
$core.bool hasSpecific() => $_has(2);
@$pb.TagNumber(3)
void clearSpecific() => $_clearField(3);
@$pb.TagNumber(3)
SpecificGrant ensureSpecific() => $_ensure(2);
SpecificGrant ensureSpecific() => $_ensure(1);
}
enum EvmGrantCreateResponse_Result { grantId, error, notSet }
@@ -1939,13 +1927,13 @@ class EvmGrantDeleteResponse extends $pb.GeneratedMessage {
class GrantEntry extends $pb.GeneratedMessage {
factory GrantEntry({
$core.int? id,
$core.int? clientId,
$core.int? walletAccessId,
SharedSettings? shared,
SpecificGrant? specific,
}) {
final result = create();
if (id != null) result.id = id;
if (clientId != null) result.clientId = clientId;
if (walletAccessId != null) result.walletAccessId = walletAccessId;
if (shared != null) result.shared = shared;
if (specific != null) result.specific = specific;
return result;
@@ -1965,7 +1953,7 @@ class GrantEntry extends $pb.GeneratedMessage {
package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.evm'),
createEmptyInstance: create)
..aI(1, _omitFieldNames ? '' : 'id')
..aI(2, _omitFieldNames ? '' : 'clientId')
..aI(2, _omitFieldNames ? '' : 'walletAccessId')
..aOM<SharedSettings>(3, _omitFieldNames ? '' : 'shared',
subBuilder: SharedSettings.create)
..aOM<SpecificGrant>(4, _omitFieldNames ? '' : 'specific',
@@ -2000,13 +1988,13 @@ class GrantEntry extends $pb.GeneratedMessage {
void clearId() => $_clearField(1);
@$pb.TagNumber(2)
$core.int get clientId => $_getIZ(1);
$core.int get walletAccessId => $_getIZ(1);
@$pb.TagNumber(2)
set clientId($core.int value) => $_setSignedInt32(1, value);
set walletAccessId($core.int value) => $_setSignedInt32(1, value);
@$pb.TagNumber(2)
$core.bool hasClientId() => $_has(1);
$core.bool hasWalletAccessId() => $_has(1);
@$pb.TagNumber(2)
void clearClientId() => $_clearField(2);
void clearWalletAccessId() => $_clearField(2);
@$pb.TagNumber(3)
SharedSettings get shared => $_getN(2);
@@ -2033,10 +2021,10 @@ class GrantEntry extends $pb.GeneratedMessage {
class EvmGrantListRequest extends $pb.GeneratedMessage {
factory EvmGrantListRequest({
$core.int? walletId,
$core.int? walletAccessId,
}) {
final result = create();
if (walletId != null) result.walletId = walletId;
if (walletAccessId != null) result.walletAccessId = walletAccessId;
return result;
}
@@ -2053,7 +2041,7 @@ class EvmGrantListRequest extends $pb.GeneratedMessage {
_omitMessageNames ? '' : 'EvmGrantListRequest',
package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.evm'),
createEmptyInstance: create)
..aI(1, _omitFieldNames ? '' : 'walletId')
..aI(1, _omitFieldNames ? '' : 'walletAccessId')
..hasRequiredFields = false;
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
@@ -2076,13 +2064,13 @@ class EvmGrantListRequest extends $pb.GeneratedMessage {
static EvmGrantListRequest? _defaultInstance;
@$pb.TagNumber(1)
$core.int get walletId => $_getIZ(0);
$core.int get walletAccessId => $_getIZ(0);
@$pb.TagNumber(1)
set walletId($core.int value) => $_setSignedInt32(0, value);
set walletAccessId($core.int value) => $_setSignedInt32(0, value);
@$pb.TagNumber(1)
$core.bool hasWalletId() => $_has(0);
$core.bool hasWalletAccessId() => $_has(0);
@$pb.TagNumber(1)
void clearWalletId() => $_clearField(1);
void clearWalletAccessId() => $_clearField(1);
}
enum EvmGrantListResponse_Result { grants, error, notSet }

View File

@@ -162,7 +162,7 @@ final $typed_data.Uint8List volumeRateLimitDescriptor = $convert.base64Decode(
const SharedSettings$json = {
'1': 'SharedSettings',
'2': [
{'1': 'wallet_id', '3': 1, '4': 1, '5': 5, '10': 'walletId'},
{'1': 'wallet_access_id', '3': 1, '4': 1, '5': 5, '10': 'walletAccessId'},
{'1': 'chain_id', '3': 2, '4': 1, '5': 4, '10': 'chainId'},
{
'1': 'valid_from',
@@ -224,15 +224,15 @@ const SharedSettings$json = {
/// Descriptor for `SharedSettings`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List sharedSettingsDescriptor = $convert.base64Decode(
'Cg5TaGFyZWRTZXR0aW5ncxIbCgl3YWxsZXRfaWQYASABKAVSCHdhbGxldElkEhkKCGNoYWluX2'
'lkGAIgASgEUgdjaGFpbklkEj4KCnZhbGlkX2Zyb20YAyABKAsyGi5nb29nbGUucHJvdG9idWYu'
'VGltZXN0YW1wSABSCXZhbGlkRnJvbYgBARJACgt2YWxpZF91bnRpbBgEIAEoCzIaLmdvb2dsZS'
'5wcm90b2J1Zi5UaW1lc3RhbXBIAVIKdmFsaWRVbnRpbIgBARIxChNtYXhfZ2FzX2ZlZV9wZXJf'
'Z2FzGAUgASgMSAJSD21heEdhc0ZlZVBlckdhc4gBARI7ChhtYXhfcHJpb3JpdHlfZmVlX3Blcl'
'9nYXMYBiABKAxIA1IUbWF4UHJpb3JpdHlGZWVQZXJHYXOIAQESRQoKcmF0ZV9saW1pdBgHIAEo'
'CzIhLmFyYml0ZXIuZXZtLlRyYW5zYWN0aW9uUmF0ZUxpbWl0SARSCXJhdGVMaW1pdIgBAUINCg'
'tfdmFsaWRfZnJvbUIOCgxfdmFsaWRfdW50aWxCFgoUX21heF9nYXNfZmVlX3Blcl9nYXNCGwoZ'
'X21heF9wcmlvcml0eV9mZWVfcGVyX2dhc0INCgtfcmF0ZV9saW1pdA==');
'Cg5TaGFyZWRTZXR0aW5ncxIoChB3YWxsZXRfYWNjZXNzX2lkGAEgASgFUg53YWxsZXRBY2Nlc3'
'NJZBIZCghjaGFpbl9pZBgCIAEoBFIHY2hhaW5JZBI+Cgp2YWxpZF9mcm9tGAMgASgLMhouZ29v'
'Z2xlLnByb3RvYnVmLlRpbWVzdGFtcEgAUgl2YWxpZEZyb22IAQESQAoLdmFsaWRfdW50aWwYBC'
'ABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wSAFSCnZhbGlkVW50aWyIAQESMQoTbWF4'
'X2dhc19mZWVfcGVyX2dhcxgFIAEoDEgCUg9tYXhHYXNGZWVQZXJHYXOIAQESOwoYbWF4X3ByaW'
'9yaXR5X2ZlZV9wZXJfZ2FzGAYgASgMSANSFG1heFByaW9yaXR5RmVlUGVyR2FziAEBEkUKCnJh'
'dGVfbGltaXQYByABKAsyIS5hcmJpdGVyLmV2bS5UcmFuc2FjdGlvblJhdGVMaW1pdEgEUglyYX'
'RlTGltaXSIAQFCDQoLX3ZhbGlkX2Zyb21CDgoMX3ZhbGlkX3VudGlsQhYKFF9tYXhfZ2FzX2Zl'
'ZV9wZXJfZ2FzQhsKGV9tYXhfcHJpb3JpdHlfZmVlX3Blcl9nYXNCDQoLX3JhdGVfbGltaXQ=');
@$core.Deprecated('Use etherTransferSettingsDescriptor instead')
const EtherTransferSettings$json = {
@@ -631,10 +631,9 @@ final $typed_data.Uint8List transactionEvalErrorDescriptor = $convert.base64Deco
const EvmGrantCreateRequest$json = {
'1': 'EvmGrantCreateRequest',
'2': [
{'1': 'client_id', '3': 1, '4': 1, '5': 5, '10': 'clientId'},
{
'1': 'shared',
'3': 2,
'3': 1,
'4': 1,
'5': 11,
'6': '.arbiter.evm.SharedSettings',
@@ -642,7 +641,7 @@ const EvmGrantCreateRequest$json = {
},
{
'1': 'specific',
'3': 3,
'3': 2,
'4': 1,
'5': 11,
'6': '.arbiter.evm.SpecificGrant',
@@ -653,9 +652,9 @@ const EvmGrantCreateRequest$json = {
/// Descriptor for `EvmGrantCreateRequest`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List evmGrantCreateRequestDescriptor = $convert.base64Decode(
'ChVFdm1HcmFudENyZWF0ZVJlcXVlc3QSGwoJY2xpZW50X2lkGAEgASgFUghjbGllbnRJZBIzCg'
'ZzaGFyZWQYAiABKAsyGy5hcmJpdGVyLmV2bS5TaGFyZWRTZXR0aW5nc1IGc2hhcmVkEjYKCHNw'
'ZWNpZmljGAMgASgLMhouYXJiaXRlci5ldm0uU3BlY2lmaWNHcmFudFIIc3BlY2lmaWM=');
'ChVFdm1HcmFudENyZWF0ZVJlcXVlc3QSMwoGc2hhcmVkGAEgASgLMhsuYXJiaXRlci5ldm0uU2'
'hhcmVkU2V0dGluZ3NSBnNoYXJlZBI2CghzcGVjaWZpYxgCIAEoCzIaLmFyYml0ZXIuZXZtLlNw'
'ZWNpZmljR3JhbnRSCHNwZWNpZmlj');
@$core.Deprecated('Use evmGrantCreateResponseDescriptor instead')
const EvmGrantCreateResponse$json = {
@@ -734,7 +733,7 @@ const GrantEntry$json = {
'1': 'GrantEntry',
'2': [
{'1': 'id', '3': 1, '4': 1, '5': 5, '10': 'id'},
{'1': 'client_id', '3': 2, '4': 1, '5': 5, '10': 'clientId'},
{'1': 'wallet_access_id', '3': 2, '4': 1, '5': 5, '10': 'walletAccessId'},
{
'1': 'shared',
'3': 3,
@@ -756,34 +755,34 @@ const GrantEntry$json = {
/// Descriptor for `GrantEntry`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List grantEntryDescriptor = $convert.base64Decode(
'CgpHcmFudEVudHJ5Eg4KAmlkGAEgASgFUgJpZBIbCgljbGllbnRfaWQYAiABKAVSCGNsaWVudE'
'lkEjMKBnNoYXJlZBgDIAEoCzIbLmFyYml0ZXIuZXZtLlNoYXJlZFNldHRpbmdzUgZzaGFyZWQS'
'NgoIc3BlY2lmaWMYBCABKAsyGi5hcmJpdGVyLmV2bS5TcGVjaWZpY0dyYW50UghzcGVjaWZpYw'
'==');
'CgpHcmFudEVudHJ5Eg4KAmlkGAEgASgFUgJpZBIoChB3YWxsZXRfYWNjZXNzX2lkGAIgASgFUg'
'53YWxsZXRBY2Nlc3NJZBIzCgZzaGFyZWQYAyABKAsyGy5hcmJpdGVyLmV2bS5TaGFyZWRTZXR0'
'aW5nc1IGc2hhcmVkEjYKCHNwZWNpZmljGAQgASgLMhouYXJiaXRlci5ldm0uU3BlY2lmaWNHcm'
'FudFIIc3BlY2lmaWM=');
@$core.Deprecated('Use evmGrantListRequestDescriptor instead')
const EvmGrantListRequest$json = {
'1': 'EvmGrantListRequest',
'2': [
{
'1': 'wallet_id',
'1': 'wallet_access_id',
'3': 1,
'4': 1,
'5': 5,
'9': 0,
'10': 'walletId',
'10': 'walletAccessId',
'17': true
},
],
'8': [
{'1': '_wallet_id'},
{'1': '_wallet_access_id'},
],
};
/// Descriptor for `EvmGrantListRequest`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List evmGrantListRequestDescriptor = $convert.base64Decode(
'ChNFdm1HcmFudExpc3RSZXF1ZXN0EiAKCXdhbGxldF9pZBgBIAEoBUgAUgh3YWxsZXRJZIgBAU'
'IMCgpfd2FsbGV0X2lk');
'ChNFdm1HcmFudExpc3RSZXF1ZXN0Ei0KEHdhbGxldF9hY2Nlc3NfaWQYASABKAVIAFIOd2FsbG'
'V0QWNjZXNzSWSIAQFCEwoRX3dhbGxldF9hY2Nlc3NfaWQ=');
@$core.Deprecated('Use evmGrantListResponseDescriptor instead')
const EvmGrantListResponse$json = {

File diff suppressed because it is too large Load Diff

View File

@@ -39,6 +39,36 @@ class KeyType extends $pb.ProtobufEnum {
const KeyType._(super.value, super.name);
}
class SdkClientError extends $pb.ProtobufEnum {
static const SdkClientError SDK_CLIENT_ERROR_UNSPECIFIED =
SdkClientError._(0, _omitEnumNames ? '' : 'SDK_CLIENT_ERROR_UNSPECIFIED');
static const SdkClientError SDK_CLIENT_ERROR_ALREADY_EXISTS =
SdkClientError._(
1, _omitEnumNames ? '' : 'SDK_CLIENT_ERROR_ALREADY_EXISTS');
static const SdkClientError SDK_CLIENT_ERROR_NOT_FOUND =
SdkClientError._(2, _omitEnumNames ? '' : 'SDK_CLIENT_ERROR_NOT_FOUND');
static const SdkClientError SDK_CLIENT_ERROR_HAS_RELATED_DATA =
SdkClientError._(
3, _omitEnumNames ? '' : 'SDK_CLIENT_ERROR_HAS_RELATED_DATA');
static const SdkClientError SDK_CLIENT_ERROR_INTERNAL =
SdkClientError._(4, _omitEnumNames ? '' : 'SDK_CLIENT_ERROR_INTERNAL');
static const $core.List<SdkClientError> values = <SdkClientError>[
SDK_CLIENT_ERROR_UNSPECIFIED,
SDK_CLIENT_ERROR_ALREADY_EXISTS,
SDK_CLIENT_ERROR_NOT_FOUND,
SDK_CLIENT_ERROR_HAS_RELATED_DATA,
SDK_CLIENT_ERROR_INTERNAL,
];
static final $core.List<SdkClientError?> _byValue =
$pb.ProtobufEnum.$_initByValueList(values, 4);
static SdkClientError? valueOf($core.int value) =>
value < 0 || value >= _byValue.length ? null : _byValue[value];
const SdkClientError._(super.value, super.name);
}
class AuthResult extends $pb.ProtobufEnum {
static const AuthResult AUTH_RESULT_UNSPECIFIED =
AuthResult._(0, _omitEnumNames ? '' : 'AUTH_RESULT_UNSPECIFIED');

View File

@@ -31,6 +31,25 @@ final $typed_data.Uint8List keyTypeDescriptor = $convert.base64Decode(
'CgdLZXlUeXBlEhgKFEtFWV9UWVBFX1VOU1BFQ0lGSUVEEAASFAoQS0VZX1RZUEVfRUQyNTUxOR'
'ABEhwKGEtFWV9UWVBFX0VDRFNBX1NFQ1AyNTZLMRACEhAKDEtFWV9UWVBFX1JTQRAD');
@$core.Deprecated('Use sdkClientErrorDescriptor instead')
const SdkClientError$json = {
'1': 'SdkClientError',
'2': [
{'1': 'SDK_CLIENT_ERROR_UNSPECIFIED', '2': 0},
{'1': 'SDK_CLIENT_ERROR_ALREADY_EXISTS', '2': 1},
{'1': 'SDK_CLIENT_ERROR_NOT_FOUND', '2': 2},
{'1': 'SDK_CLIENT_ERROR_HAS_RELATED_DATA', '2': 3},
{'1': 'SDK_CLIENT_ERROR_INTERNAL', '2': 4},
],
};
/// Descriptor for `SdkClientError`. Decode as a `google.protobuf.EnumDescriptorProto`.
final $typed_data.Uint8List sdkClientErrorDescriptor = $convert.base64Decode(
'Cg5TZGtDbGllbnRFcnJvchIgChxTREtfQ0xJRU5UX0VSUk9SX1VOU1BFQ0lGSUVEEAASIwofU0'
'RLX0NMSUVOVF9FUlJPUl9BTFJFQURZX0VYSVNUUxABEh4KGlNES19DTElFTlRfRVJST1JfTk9U'
'X0ZPVU5EEAISJQohU0RLX0NMSUVOVF9FUlJPUl9IQVNfUkVMQVRFRF9EQVRBEAMSHQoZU0RLX0'
'NMSUVOVF9FUlJPUl9JTlRFUk5BTBAE');
@$core.Deprecated('Use authResultDescriptor instead')
const AuthResult$json = {
'1': 'AuthResult',
@@ -105,6 +124,131 @@ final $typed_data.Uint8List vaultStateDescriptor = $convert.base64Decode(
'VfVU5CT09UU1RSQVBQRUQQARIWChJWQVVMVF9TVEFURV9TRUFMRUQQAhIYChRWQVVMVF9TVEFU'
'RV9VTlNFQUxFRBADEhUKEVZBVUxUX1NUQVRFX0VSUk9SEAQ=');
@$core.Deprecated('Use sdkClientRevokeRequestDescriptor instead')
const SdkClientRevokeRequest$json = {
'1': 'SdkClientRevokeRequest',
'2': [
{'1': 'client_id', '3': 1, '4': 1, '5': 5, '10': 'clientId'},
],
};
/// Descriptor for `SdkClientRevokeRequest`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List sdkClientRevokeRequestDescriptor =
$convert.base64Decode(
'ChZTZGtDbGllbnRSZXZva2VSZXF1ZXN0EhsKCWNsaWVudF9pZBgBIAEoBVIIY2xpZW50SWQ=');
@$core.Deprecated('Use sdkClientEntryDescriptor instead')
const SdkClientEntry$json = {
'1': 'SdkClientEntry',
'2': [
{'1': 'id', '3': 1, '4': 1, '5': 5, '10': 'id'},
{'1': 'pubkey', '3': 2, '4': 1, '5': 12, '10': 'pubkey'},
{
'1': 'info',
'3': 3,
'4': 1,
'5': 11,
'6': '.arbiter.client.ClientInfo',
'10': 'info'
},
{'1': 'created_at', '3': 4, '4': 1, '5': 5, '10': 'createdAt'},
],
};
/// Descriptor for `SdkClientEntry`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List sdkClientEntryDescriptor = $convert.base64Decode(
'Cg5TZGtDbGllbnRFbnRyeRIOCgJpZBgBIAEoBVICaWQSFgoGcHVia2V5GAIgASgMUgZwdWJrZX'
'kSLgoEaW5mbxgDIAEoCzIaLmFyYml0ZXIuY2xpZW50LkNsaWVudEluZm9SBGluZm8SHQoKY3Jl'
'YXRlZF9hdBgEIAEoBVIJY3JlYXRlZEF0');
@$core.Deprecated('Use sdkClientListDescriptor instead')
const SdkClientList$json = {
'1': 'SdkClientList',
'2': [
{
'1': 'clients',
'3': 1,
'4': 3,
'5': 11,
'6': '.arbiter.user_agent.SdkClientEntry',
'10': 'clients'
},
],
};
/// Descriptor for `SdkClientList`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List sdkClientListDescriptor = $convert.base64Decode(
'Cg1TZGtDbGllbnRMaXN0EjwKB2NsaWVudHMYASADKAsyIi5hcmJpdGVyLnVzZXJfYWdlbnQuU2'
'RrQ2xpZW50RW50cnlSB2NsaWVudHM=');
@$core.Deprecated('Use sdkClientRevokeResponseDescriptor instead')
const SdkClientRevokeResponse$json = {
'1': 'SdkClientRevokeResponse',
'2': [
{
'1': 'ok',
'3': 1,
'4': 1,
'5': 11,
'6': '.google.protobuf.Empty',
'9': 0,
'10': 'ok'
},
{
'1': 'error',
'3': 2,
'4': 1,
'5': 14,
'6': '.arbiter.user_agent.SdkClientError',
'9': 0,
'10': 'error'
},
],
'8': [
{'1': 'result'},
],
};
/// Descriptor for `SdkClientRevokeResponse`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List sdkClientRevokeResponseDescriptor = $convert.base64Decode(
'ChdTZGtDbGllbnRSZXZva2VSZXNwb25zZRIoCgJvaxgBIAEoCzIWLmdvb2dsZS5wcm90b2J1Zi'
'5FbXB0eUgAUgJvaxI6CgVlcnJvchgCIAEoDjIiLmFyYml0ZXIudXNlcl9hZ2VudC5TZGtDbGll'
'bnRFcnJvckgAUgVlcnJvckIICgZyZXN1bHQ=');
@$core.Deprecated('Use sdkClientListResponseDescriptor instead')
const SdkClientListResponse$json = {
'1': 'SdkClientListResponse',
'2': [
{
'1': 'clients',
'3': 1,
'4': 1,
'5': 11,
'6': '.arbiter.user_agent.SdkClientList',
'9': 0,
'10': 'clients'
},
{
'1': 'error',
'3': 2,
'4': 1,
'5': 14,
'6': '.arbiter.user_agent.SdkClientError',
'9': 0,
'10': 'error'
},
],
'8': [
{'1': 'result'},
],
};
/// Descriptor for `SdkClientListResponse`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List sdkClientListResponseDescriptor = $convert.base64Decode(
'ChVTZGtDbGllbnRMaXN0UmVzcG9uc2USPQoHY2xpZW50cxgBIAEoCzIhLmFyYml0ZXIudXNlcl'
'9hZ2VudC5TZGtDbGllbnRMaXN0SABSB2NsaWVudHMSOgoFZXJyb3IYAiABKA4yIi5hcmJpdGVy'
'LnVzZXJfYWdlbnQuU2RrQ2xpZW50RXJyb3JIAFIFZXJyb3JCCAoGcmVzdWx0');
@$core.Deprecated('Use authChallengeRequestDescriptor instead')
const AuthChallengeRequest$json = {
'1': 'AuthChallengeRequest',
@@ -224,46 +368,61 @@ final $typed_data.Uint8List bootstrapEncryptedKeyDescriptor = $convert.base64Dec
'RleHQYAiABKAxSCmNpcGhlcnRleHQSJwoPYXNzb2NpYXRlZF9kYXRhGAMgASgMUg5hc3NvY2lh'
'dGVkRGF0YQ==');
@$core.Deprecated('Use clientConnectionRequestDescriptor instead')
const ClientConnectionRequest$json = {
'1': 'ClientConnectionRequest',
@$core.Deprecated('Use sdkClientConnectionRequestDescriptor instead')
const SdkClientConnectionRequest$json = {
'1': 'SdkClientConnectionRequest',
'2': [
{'1': 'pubkey', '3': 1, '4': 1, '5': 12, '10': 'pubkey'},
{
'1': 'info',
'3': 2,
'4': 1,
'5': 11,
'6': '.arbiter.client.ClientInfo',
'10': 'info'
},
],
};
/// Descriptor for `SdkClientConnectionRequest`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List sdkClientConnectionRequestDescriptor =
$convert.base64Decode(
'ChpTZGtDbGllbnRDb25uZWN0aW9uUmVxdWVzdBIWCgZwdWJrZXkYASABKAxSBnB1YmtleRIuCg'
'RpbmZvGAIgASgLMhouYXJiaXRlci5jbGllbnQuQ2xpZW50SW5mb1IEaW5mbw==');
@$core.Deprecated('Use sdkClientConnectionResponseDescriptor instead')
const SdkClientConnectionResponse$json = {
'1': 'SdkClientConnectionResponse',
'2': [
{'1': 'approved', '3': 1, '4': 1, '5': 8, '10': 'approved'},
{'1': 'pubkey', '3': 2, '4': 1, '5': 12, '10': 'pubkey'},
],
};
/// Descriptor for `SdkClientConnectionResponse`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List sdkClientConnectionResponseDescriptor =
$convert.base64Decode(
'ChtTZGtDbGllbnRDb25uZWN0aW9uUmVzcG9uc2USGgoIYXBwcm92ZWQYASABKAhSCGFwcHJvdm'
'VkEhYKBnB1YmtleRgCIAEoDFIGcHVia2V5');
@$core.Deprecated('Use sdkClientConnectionCancelDescriptor instead')
const SdkClientConnectionCancel$json = {
'1': 'SdkClientConnectionCancel',
'2': [
{'1': 'pubkey', '3': 1, '4': 1, '5': 12, '10': 'pubkey'},
],
};
/// Descriptor for `ClientConnectionRequest`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List clientConnectionRequestDescriptor =
/// Descriptor for `SdkClientConnectionCancel`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List sdkClientConnectionCancelDescriptor =
$convert.base64Decode(
'ChdDbGllbnRDb25uZWN0aW9uUmVxdWVzdBIWCgZwdWJrZXkYASABKAxSBnB1YmtleQ==');
@$core.Deprecated('Use clientConnectionResponseDescriptor instead')
const ClientConnectionResponse$json = {
'1': 'ClientConnectionResponse',
'2': [
{'1': 'approved', '3': 1, '4': 1, '5': 8, '10': 'approved'},
],
};
/// Descriptor for `ClientConnectionResponse`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List clientConnectionResponseDescriptor =
$convert.base64Decode(
'ChhDbGllbnRDb25uZWN0aW9uUmVzcG9uc2USGgoIYXBwcm92ZWQYASABKAhSCGFwcHJvdmVk');
@$core.Deprecated('Use clientConnectionCancelDescriptor instead')
const ClientConnectionCancel$json = {
'1': 'ClientConnectionCancel',
};
/// Descriptor for `ClientConnectionCancel`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List clientConnectionCancelDescriptor =
$convert.base64Decode('ChZDbGllbnRDb25uZWN0aW9uQ2FuY2Vs');
'ChlTZGtDbGllbnRDb25uZWN0aW9uQ2FuY2VsEhYKBnB1YmtleRgBIAEoDFIGcHVia2V5');
@$core.Deprecated('Use userAgentRequestDescriptor instead')
const UserAgentRequest$json = {
'1': 'UserAgentRequest',
'2': [
{'1': 'id', '3': 14, '4': 1, '5': 5, '10': 'id'},
{'1': 'id', '3': 16, '4': 1, '5': 5, '10': 'id'},
{
'1': 'auth_challenge_request',
'3': 1,
@@ -355,17 +514,35 @@ const UserAgentRequest$json = {
'10': 'evmGrantList'
},
{
'1': 'client_connection_response',
'1': 'sdk_client_connection_response',
'3': 11,
'4': 1,
'5': 11,
'6': '.arbiter.user_agent.ClientConnectionResponse',
'6': '.arbiter.user_agent.SdkClientConnectionResponse',
'9': 0,
'10': 'clientConnectionResponse'
'10': 'sdkClientConnectionResponse'
},
{
'1': 'sdk_client_revoke',
'3': 13,
'4': 1,
'5': 11,
'6': '.arbiter.user_agent.SdkClientRevokeRequest',
'9': 0,
'10': 'sdkClientRevoke'
},
{
'1': 'sdk_client_list',
'3': 14,
'4': 1,
'5': 11,
'6': '.google.protobuf.Empty',
'9': 0,
'10': 'sdkClientList'
},
{
'1': 'bootstrap_encrypted_key',
'3': 12,
'3': 15,
'4': 1,
'5': 11,
'6': '.arbiter.user_agent.BootstrapEncryptedKey',
@@ -380,7 +557,7 @@ const UserAgentRequest$json = {
/// Descriptor for `UserAgentRequest`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List userAgentRequestDescriptor = $convert.base64Decode(
'ChBVc2VyQWdlbnRSZXF1ZXN0Eg4KAmlkGA4gASgFUgJpZBJgChZhdXRoX2NoYWxsZW5nZV9yZX'
'ChBVc2VyQWdlbnRSZXF1ZXN0Eg4KAmlkGBAgASgFUgJpZBJgChZhdXRoX2NoYWxsZW5nZV9yZX'
'F1ZXN0GAEgASgLMiguYXJiaXRlci51c2VyX2FnZW50LkF1dGhDaGFsbGVuZ2VSZXF1ZXN0SABS'
'FGF1dGhDaGFsbGVuZ2VSZXF1ZXN0EmMKF2F1dGhfY2hhbGxlbmdlX3NvbHV0aW9uGAIgASgLMi'
'kuYXJiaXRlci51c2VyX2FnZW50LkF1dGhDaGFsbGVuZ2VTb2x1dGlvbkgAUhVhdXRoQ2hhbGxl'
@@ -395,17 +572,20 @@ final $typed_data.Uint8List userAgentRequestDescriptor = $convert.base64Decode(
'DmV2bUdyYW50Q3JlYXRlEk4KEGV2bV9ncmFudF9kZWxldGUYCSABKAsyIi5hcmJpdGVyLmV2bS'
'5Fdm1HcmFudERlbGV0ZVJlcXVlc3RIAFIOZXZtR3JhbnREZWxldGUSSAoOZXZtX2dyYW50X2xp'
'c3QYCiABKAsyIC5hcmJpdGVyLmV2bS5Fdm1HcmFudExpc3RSZXF1ZXN0SABSDGV2bUdyYW50TG'
'lzdBJsChpjbGllbnRfY29ubmVjdGlvbl9yZXNwb25zZRgLIAEoCzIsLmFyYml0ZXIudXNlcl9h'
'Z2VudC5DbGllbnRDb25uZWN0aW9uUmVzcG9uc2VIAFIYY2xpZW50Q29ubmVjdGlvblJlc3Bvbn'
'NlEmMKF2Jvb3RzdHJhcF9lbmNyeXB0ZWRfa2V5GAwgASgLMikuYXJiaXRlci51c2VyX2FnZW50'
'LkJvb3RzdHJhcEVuY3J5cHRlZEtleUgAUhVib290c3RyYXBFbmNyeXB0ZWRLZXlCCQoHcGF5bG'
'9hZA==');
'lzdBJ2Ch5zZGtfY2xpZW50X2Nvbm5lY3Rpb25fcmVzcG9uc2UYCyABKAsyLy5hcmJpdGVyLnVz'
'ZXJfYWdlbnQuU2RrQ2xpZW50Q29ubmVjdGlvblJlc3BvbnNlSABSG3Nka0NsaWVudENvbm5lY3'
'Rpb25SZXNwb25zZRJYChFzZGtfY2xpZW50X3Jldm9rZRgNIAEoCzIqLmFyYml0ZXIudXNlcl9h'
'Z2VudC5TZGtDbGllbnRSZXZva2VSZXF1ZXN0SABSD3Nka0NsaWVudFJldm9rZRJACg9zZGtfY2'
'xpZW50X2xpc3QYDiABKAsyFi5nb29nbGUucHJvdG9idWYuRW1wdHlIAFINc2RrQ2xpZW50TGlz'
'dBJjChdib290c3RyYXBfZW5jcnlwdGVkX2tleRgPIAEoCzIpLmFyYml0ZXIudXNlcl9hZ2VudC'
'5Cb290c3RyYXBFbmNyeXB0ZWRLZXlIAFIVYm9vdHN0cmFwRW5jcnlwdGVkS2V5QgkKB3BheWxv'
'YWQ=');
@$core.Deprecated('Use userAgentResponseDescriptor instead')
const UserAgentResponse$json = {
'1': 'UserAgentResponse',
'2': [
{'1': 'id', '3': 14, '4': 1, '5': 5, '9': 1, '10': 'id', '17': true},
{'1': 'id', '3': 16, '4': 1, '5': 5, '9': 1, '10': 'id', '17': true},
{
'1': 'auth_challenge',
'3': 1,
@@ -497,26 +677,44 @@ const UserAgentResponse$json = {
'10': 'evmGrantList'
},
{
'1': 'client_connection_request',
'1': 'sdk_client_connection_request',
'3': 11,
'4': 1,
'5': 11,
'6': '.arbiter.user_agent.ClientConnectionRequest',
'6': '.arbiter.user_agent.SdkClientConnectionRequest',
'9': 0,
'10': 'clientConnectionRequest'
'10': 'sdkClientConnectionRequest'
},
{
'1': 'client_connection_cancel',
'1': 'sdk_client_connection_cancel',
'3': 12,
'4': 1,
'5': 11,
'6': '.arbiter.user_agent.ClientConnectionCancel',
'6': '.arbiter.user_agent.SdkClientConnectionCancel',
'9': 0,
'10': 'clientConnectionCancel'
'10': 'sdkClientConnectionCancel'
},
{
'1': 'sdk_client_revoke_response',
'3': 13,
'4': 1,
'5': 11,
'6': '.arbiter.user_agent.SdkClientRevokeResponse',
'9': 0,
'10': 'sdkClientRevokeResponse'
},
{
'1': 'sdk_client_list_response',
'3': 14,
'4': 1,
'5': 11,
'6': '.arbiter.user_agent.SdkClientListResponse',
'9': 0,
'10': 'sdkClientListResponse'
},
{
'1': 'bootstrap_result',
'3': 13,
'3': 15,
'4': 1,
'5': 14,
'6': '.arbiter.user_agent.BootstrapResult',
@@ -532,7 +730,7 @@ const UserAgentResponse$json = {
/// Descriptor for `UserAgentResponse`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List userAgentResponseDescriptor = $convert.base64Decode(
'ChFVc2VyQWdlbnRSZXNwb25zZRITCgJpZBgOIAEoBUgBUgJpZIgBARJKCg5hdXRoX2NoYWxsZW'
'ChFVc2VyQWdlbnRSZXNwb25zZRITCgJpZBgQIAEoBUgBUgJpZIgBARJKCg5hdXRoX2NoYWxsZW'
'5nZRgBIAEoCzIhLmFyYml0ZXIudXNlcl9hZ2VudC5BdXRoQ2hhbGxlbmdlSABSDWF1dGhDaGFs'
'bGVuZ2USQQoLYXV0aF9yZXN1bHQYAiABKA4yHi5hcmJpdGVyLnVzZXJfYWdlbnQuQXV0aFJlc3'
'VsdEgAUgphdXRoUmVzdWx0El0KFXVuc2VhbF9zdGFydF9yZXNwb25zZRgDIAEoCzInLmFyYml0'
@@ -546,10 +744,14 @@ final $typed_data.Uint8List userAgentResponseDescriptor = $convert.base64Decode(
'5ldm0uRXZtR3JhbnRDcmVhdGVSZXNwb25zZUgAUg5ldm1HcmFudENyZWF0ZRJPChBldm1fZ3Jh'
'bnRfZGVsZXRlGAkgASgLMiMuYXJiaXRlci5ldm0uRXZtR3JhbnREZWxldGVSZXNwb25zZUgAUg'
'5ldm1HcmFudERlbGV0ZRJJCg5ldm1fZ3JhbnRfbGlzdBgKIAEoCzIhLmFyYml0ZXIuZXZtLkV2'
'bUdyYW50TGlzdFJlc3BvbnNlSABSDGV2bUdyYW50TGlzdBJpChljbGllbnRfY29ubmVjdGlvbl'
'9yZXF1ZXN0GAsgASgLMisuYXJiaXRlci51c2VyX2FnZW50LkNsaWVudENvbm5lY3Rpb25SZXF1'
'ZXN0SABSF2NsaWVudENvbm5lY3Rpb25SZXF1ZXN0EmYKGGNsaWVudF9jb25uZWN0aW9uX2Nhbm'
'NlbBgMIAEoCzIqLmFyYml0ZXIudXNlcl9hZ2VudC5DbGllbnRDb25uZWN0aW9uQ2FuY2VsSABS'
'FmNsaWVudENvbm5lY3Rpb25DYW5jZWwSUAoQYm9vdHN0cmFwX3Jlc3VsdBgNIAEoDjIjLmFyYm'
'l0ZXIudXNlcl9hZ2VudC5Cb290c3RyYXBSZXN1bHRIAFIPYm9vdHN0cmFwUmVzdWx0QgkKB3Bh'
'eWxvYWRCBQoDX2lk');
'bUdyYW50TGlzdFJlc3BvbnNlSABSDGV2bUdyYW50TGlzdBJzCh1zZGtfY2xpZW50X2Nvbm5lY3'
'Rpb25fcmVxdWVzdBgLIAEoCzIuLmFyYml0ZXIudXNlcl9hZ2VudC5TZGtDbGllbnRDb25uZWN0'
'aW9uUmVxdWVzdEgAUhpzZGtDbGllbnRDb25uZWN0aW9uUmVxdWVzdBJwChxzZGtfY2xpZW50X2'
'Nvbm5lY3Rpb25fY2FuY2VsGAwgASgLMi0uYXJiaXRlci51c2VyX2FnZW50LlNka0NsaWVudENv'
'bm5lY3Rpb25DYW5jZWxIAFIZc2RrQ2xpZW50Q29ubmVjdGlvbkNhbmNlbBJqChpzZGtfY2xpZW'
'50X3Jldm9rZV9yZXNwb25zZRgNIAEoCzIrLmFyYml0ZXIudXNlcl9hZ2VudC5TZGtDbGllbnRS'
'ZXZva2VSZXNwb25zZUgAUhdzZGtDbGllbnRSZXZva2VSZXNwb25zZRJkChhzZGtfY2xpZW50X2'
'xpc3RfcmVzcG9uc2UYDiABKAsyKS5hcmJpdGVyLnVzZXJfYWdlbnQuU2RrQ2xpZW50TGlzdFJl'
'c3BvbnNlSABSFXNka0NsaWVudExpc3RSZXNwb25zZRJQChBib290c3RyYXBfcmVzdWx0GA8gAS'
'gOMiMuYXJiaXRlci51c2VyX2FnZW50LkJvb3RzdHJhcFJlc3VsdEgAUg9ib290c3RyYXBSZXN1'
'bHRCCQoHcGF5bG9hZEIFCgNfaWQ=');

View File

@@ -0,0 +1,34 @@
import 'package:arbiter/proto/user_agent.pb.dart';
import 'package:arbiter/providers/connection/connection_manager.dart';
import 'package:protobuf/well_known_types/google/protobuf/empty.pb.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'list.g.dart';
@riverpod
Future<List<SdkClientEntry>?> sdkClients(Ref ref) async {
final connection = await ref.watch(connectionManagerProvider.future);
if (connection == null) {
return null;
}
final resp = await connection.request(
UserAgentRequest(sdkClientList: Empty()),
);
if (!resp.hasSdkClientListResponse()) {
throw Exception(
'Expected SDK client list response, got ${resp.whichPayload()}',
);
}
final result = resp.sdkClientListResponse;
switch (result.whichResult()) {
case SdkClientListResponse_Result.clients:
return result.clients.clients.toList(growable: false);
case SdkClientListResponse_Result.error:
throw Exception('Error listing SDK clients: ${result.error}');
case SdkClientListResponse_Result.notSet:
throw Exception('SDK client list response was empty.');
}
}

View File

@@ -0,0 +1,51 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'list.dart';
// **************************************************************************
// RiverpodGenerator
// **************************************************************************
// GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint, type=warning
@ProviderFor(sdkClients)
final sdkClientsProvider = SdkClientsProvider._();
final class SdkClientsProvider
extends
$FunctionalProvider<
AsyncValue<List<SdkClientEntry>?>,
List<SdkClientEntry>?,
FutureOr<List<SdkClientEntry>?>
>
with
$FutureModifier<List<SdkClientEntry>?>,
$FutureProvider<List<SdkClientEntry>?> {
SdkClientsProvider._()
: super(
from: null,
argument: null,
retry: null,
name: r'sdkClientsProvider',
isAutoDispose: true,
dependencies: null,
$allTransitiveDependencies: null,
);
@override
String debugGetCreateSourceHash() => _$sdkClientsHash();
@$internal
@override
$FutureProviderElement<List<SdkClientEntry>?> $createElement(
$ProviderPointer pointer,
) => $FutureProviderElement(pointer);
@override
FutureOr<List<SdkClientEntry>?> create(Ref ref) {
return sdkClients(ref);
}
}
String _$sdkClientsHash() => r'833c249d9cc2f83921453e0ece354a9a2d9f4482';

View File

@@ -17,7 +17,7 @@ class Router extends RootStackRouter {
path: '/dashboard',
children: [
AutoRoute(page: EvmRoute.page, path: 'evm'),
AutoRoute(page: EvmGrantsRoute.page, path: 'grants'),
AutoRoute(page: ClientsRoute.page, path: 'clients'),
AutoRoute(page: AboutRoute.page, path: 'about'),
],
),

View File

@@ -10,11 +10,11 @@
// ignore_for_file: no_leading_underscores_for_library_prefixes
import 'package:arbiter/screens/bootstrap.dart' as _i2;
import 'package:arbiter/screens/dashboard.dart' as _i4;
import 'package:arbiter/screens/dashboard.dart' as _i5;
import 'package:arbiter/screens/dashboard/about.dart' as _i1;
import 'package:arbiter/screens/dashboard/evm.dart' as _i6;
import 'package:arbiter/screens/dashboard/evm_grant_create.dart' as _i3;
import 'package:arbiter/screens/dashboard/evm_grants.dart' as _i5;
import 'package:arbiter/screens/dashboard/clients/table.dart' as _i3;
import 'package:arbiter/screens/dashboard/evm/evm.dart' as _i6;
import 'package:arbiter/screens/dashboard/evm/grants/grant_create.dart' as _i4;
import 'package:arbiter/screens/server_connection.dart' as _i7;
import 'package:arbiter/screens/server_info_setup.dart' as _i8;
import 'package:arbiter/screens/vault_setup.dart' as _i9;
@@ -54,7 +54,23 @@ class Bootstrap extends _i10.PageRouteInfo<void> {
}
/// generated route for
/// [_i3.CreateEvmGrantScreen]
/// [_i3.ClientsScreen]
class ClientsRoute extends _i10.PageRouteInfo<void> {
const ClientsRoute({List<_i10.PageRouteInfo>? children})
: super(ClientsRoute.name, initialChildren: children);
static const String name = 'ClientsRoute';
static _i10.PageInfo page = _i10.PageInfo(
name,
builder: (data) {
return const _i3.ClientsScreen();
},
);
}
/// generated route for
/// [_i4.CreateEvmGrantScreen]
class CreateEvmGrantRoute extends _i10.PageRouteInfo<void> {
const CreateEvmGrantRoute({List<_i10.PageRouteInfo>? children})
: super(CreateEvmGrantRoute.name, initialChildren: children);
@@ -64,13 +80,13 @@ class CreateEvmGrantRoute extends _i10.PageRouteInfo<void> {
static _i10.PageInfo page = _i10.PageInfo(
name,
builder: (data) {
return const _i3.CreateEvmGrantScreen();
return const _i4.CreateEvmGrantScreen();
},
);
}
/// generated route for
/// [_i4.DashboardRouter]
/// [_i5.DashboardRouter]
class DashboardRouter extends _i10.PageRouteInfo<void> {
const DashboardRouter({List<_i10.PageRouteInfo>? children})
: super(DashboardRouter.name, initialChildren: children);
@@ -80,23 +96,7 @@ class DashboardRouter extends _i10.PageRouteInfo<void> {
static _i10.PageInfo page = _i10.PageInfo(
name,
builder: (data) {
return const _i4.DashboardRouter();
},
);
}
/// generated route for
/// [_i5.EvmGrantsScreen]
class EvmGrantsRoute extends _i10.PageRouteInfo<void> {
const EvmGrantsRoute({List<_i10.PageRouteInfo>? children})
: super(EvmGrantsRoute.name, initialChildren: children);
static const String name = 'EvmGrantsRoute';
static _i10.PageInfo page = _i10.PageInfo(
name,
builder: (data) {
return const _i5.EvmGrantsScreen();
return const _i5.DashboardRouter();
},
);
}

View File

@@ -5,7 +5,7 @@ import 'package:flutter_adaptive_scaffold/flutter_adaptive_scaffold.dart';
const breakpoints = MaterialAdaptiveBreakpoints();
final routes = [const EvmRoute(), const EvmGrantsRoute(), const AboutRoute()];
final routes = [const EvmRoute(), const ClientsRoute(), const AboutRoute()];
@RoutePage()
class DashboardRouter extends StatelessWidget {
@@ -35,6 +35,11 @@ class DashboardRouter extends StatelessWidget {
selectedIcon: Icon(Icons.rule_folder),
label: "Grants",
),
NavigationDestination(
icon: Icon(Icons.devices_other_outlined),
selectedIcon: Icon(Icons.devices_other),
label: "Clients",
),
NavigationDestination(
icon: Icon(Icons.info_outline),
selectedIcon: Icon(Icons.info),

View File

@@ -0,0 +1,585 @@
import 'dart:math' as math;
import 'package:arbiter/proto/user_agent.pb.dart';
import 'package:arbiter/providers/connection/connection_manager.dart';
import 'package:arbiter/providers/sdk_clients/list.dart';
import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:sizer/sizer.dart';
// ─── Palette ──────────────────────────────────────────────────────────────────
class _Palette {
static const ink = Color(0xFF15263C);
static const coral = Color(0xFFE26254);
static const cream = Color(0xFFFFFAF4);
static const line = Color(0x1A15263C);
}
// ─── Column width getters ─────────────────────────────────────────────────────
double get _accentStripWidth => 0.8.w;
double get _cellHPad => 1.8.w;
double get _colGap => 1.8.w;
double get _idColWidth => 8.w;
double get _nameColWidth => 20.w;
double get _versionColWidth => 12.w;
double get _registeredColWidth => 18.w;
double get _chevronColWidth => 4.w;
double get _tableMinWidth => 72.w;
// ─── Helpers ──────────────────────────────────────────────────────────────────
Color _accentColor(List<int> bytes) {
final seed = bytes.fold<int>(0, (v, b) => v + b);
final hue = (seed * 17) % 360;
return HSLColor.fromAHSL(1, hue.toDouble(), 0.68, 0.54).toColor();
}
// ed25519 public keys are always 32 bytes (64 hex chars); guard is defensive.
String _shortPubkey(List<int> bytes) {
final hex = bytes.map((b) => b.toRadixString(16).padLeft(2, '0')).join();
if (hex.length < 12) return '0x$hex';
return '0x${hex.substring(0, 8)}...${hex.substring(hex.length - 4)}';
}
String _fullPubkey(List<int> bytes) {
final hex = bytes.map((b) => b.toRadixString(16).padLeft(2, '0')).join();
return '0x$hex';
}
String _formatDate(int unixSecs) {
final dt = DateTime.fromMillisecondsSinceEpoch(unixSecs * 1000).toLocal();
return '${dt.year}-'
'${dt.month.toString().padLeft(2, '0')}-'
'${dt.day.toString().padLeft(2, '0')}';
}
String _formatError(Object error) {
final message = error.toString();
if (message.startsWith('Exception: ')) {
return message.substring('Exception: '.length);
}
return message;
}
// ─── State panel ─────────────────────────────────────────────────────────────
class _StatePanel extends StatelessWidget {
const _StatePanel({
required this.icon,
required this.title,
required this.body,
this.actionLabel,
this.onAction,
this.busy = false,
});
final IconData icon;
final String title;
final String body;
final String? actionLabel;
final Future<void> Function()? onAction;
final bool busy;
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(24),
color: _Palette.cream.withValues(alpha: 0.92),
border: Border.all(color: _Palette.line),
),
child: Padding(
padding: EdgeInsets.all(2.8.h),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (busy)
SizedBox(
width: 2.8.h,
height: 2.8.h,
child: const CircularProgressIndicator(strokeWidth: 2.5),
)
else
Icon(icon, size: 34, color: _Palette.coral),
SizedBox(height: 1.8.h),
Text(
title,
style: theme.textTheme.headlineSmall?.copyWith(
color: _Palette.ink,
fontWeight: FontWeight.w800,
),
),
SizedBox(height: 1.h),
Text(
body,
style: theme.textTheme.bodyLarge?.copyWith(
color: _Palette.ink.withValues(alpha: 0.72),
height: 1.5,
),
),
if (actionLabel != null && onAction != null) ...[
SizedBox(height: 2.h),
OutlinedButton.icon(
onPressed: () => onAction!(),
icon: const Icon(Icons.refresh),
label: Text(actionLabel!),
),
],
],
),
),
);
}
}
// ─── Header ───────────────────────────────────────────────────────────────────
class _Header extends StatelessWidget {
const _Header({required this.isBusy, required this.onRefresh});
final bool isBusy;
final Future<void> Function() onRefresh;
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
return Container(
padding: EdgeInsets.symmetric(horizontal: 1.6.w, vertical: 1.2.h),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(18),
color: _Palette.cream,
border: Border.all(color: _Palette.line),
),
child: Row(
children: [
Expanded(
child: Text(
'SDK Clients',
style: theme.textTheme.titleMedium?.copyWith(
color: _Palette.ink,
fontWeight: FontWeight.w800,
),
),
),
if (isBusy) ...[
Text(
'Syncing',
style: theme.textTheme.bodySmall?.copyWith(
color: _Palette.ink.withValues(alpha: 0.62),
fontWeight: FontWeight.w700,
),
),
SizedBox(width: 1.w),
],
OutlinedButton.icon(
onPressed: () => onRefresh(),
style: OutlinedButton.styleFrom(
foregroundColor: _Palette.ink,
side: BorderSide(color: _Palette.line),
padding: EdgeInsets.symmetric(
horizontal: 1.4.w,
vertical: 1.2.h,
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(14),
),
),
icon: const Icon(Icons.refresh, size: 18),
label: const Text('Refresh'),
),
],
),
);
}
}
// ─── Table header row ─────────────────────────────────────────────────────────
class _ClientTableHeader extends StatelessWidget {
const _ClientTableHeader();
@override
Widget build(BuildContext context) {
final style = Theme.of(context).textTheme.labelLarge?.copyWith(
color: _Palette.ink.withValues(alpha: 0.72),
fontWeight: FontWeight.w800,
letterSpacing: 0.3,
);
return Container(
padding: EdgeInsets.symmetric(vertical: 1.4.h),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16),
color: _Palette.ink.withValues(alpha: 0.04),
),
child: Row(
children: [
SizedBox(width: _accentStripWidth + _cellHPad),
SizedBox(width: _idColWidth, child: Text('ID', style: style)),
SizedBox(width: _colGap),
SizedBox(width: _nameColWidth, child: Text('Name', style: style)),
SizedBox(width: _colGap),
SizedBox(
width: _versionColWidth,
child: Text('Version', style: style),
),
SizedBox(width: _colGap),
SizedBox(
width: _registeredColWidth,
child: Text('Registered', style: style),
),
SizedBox(width: _colGap),
SizedBox(width: _chevronColWidth),
SizedBox(width: _cellHPad),
],
),
);
}
}
// ─── Table row (owns its own expand state) ────────────────────────────────────
class _ClientTableRow extends HookWidget {
const _ClientTableRow({required this.client});
final SdkClientEntry client;
@override
Widget build(BuildContext context) {
final expanded = useState(false);
final accent = _accentColor(client.pubkey);
final theme = Theme.of(context);
final muted = _Palette.ink.withValues(alpha: 0.62);
final name = client.info.name.isEmpty ? '' : client.info.name;
final version = client.info.version.isEmpty ? '' : client.info.version;
final registered = _formatDate(client.createdAt);
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// ── Collapsed row ──────────────────────────────────────────────────────
GestureDetector(
onTap: () => expanded.value = !expanded.value,
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(18),
color: accent.withValues(alpha: 0.10),
border: Border.all(color: accent.withValues(alpha: 0.28)),
),
child: IntrinsicHeight(
child: Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Container(
width: _accentStripWidth,
decoration: BoxDecoration(
color: accent,
borderRadius: const BorderRadius.horizontal(
left: Radius.circular(18),
),
),
),
Expanded(
child: Padding(
padding: EdgeInsets.symmetric(
horizontal: _cellHPad,
vertical: 1.4.h,
),
child: Row(
children: [
SizedBox(
width: _idColWidth,
child: Text(
'${client.id}',
style: theme.textTheme.bodyLarge?.copyWith(
color: _Palette.ink,
),
),
),
SizedBox(width: _colGap),
SizedBox(
width: _nameColWidth,
child: Text(
name,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: theme.textTheme.bodyMedium?.copyWith(
color: _Palette.ink,
),
),
),
SizedBox(width: _colGap),
SizedBox(
width: _versionColWidth,
child: Text(
version,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: theme.textTheme.bodySmall?.copyWith(
color: muted,
),
),
),
SizedBox(width: _colGap),
SizedBox(
width: _registeredColWidth,
child: Text(
registered,
style: theme.textTheme.bodySmall?.copyWith(
color: muted,
),
),
),
SizedBox(width: _colGap),
SizedBox(
width: _chevronColWidth,
child: Icon(
expanded.value
? Icons.expand_more
: Icons.chevron_right,
color: muted,
),
),
],
),
),
),
],
),
),
),
),
// ── Expansion panel (AnimatedSize wraps only this section) ────────────
AnimatedSize(
duration: const Duration(milliseconds: 200),
curve: Curves.easeInOut,
child: expanded.value
? Container(
margin: EdgeInsets.only(top: 0.6.h),
padding: EdgeInsets.symmetric(
horizontal: 1.6.w,
vertical: 1.4.h,
),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(14),
color: accent.withValues(alpha: 0.06),
border: Border(
left: BorderSide(color: accent, width: 0.4.w),
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
client.info.description.isEmpty
? 'No description provided.'
: client.info.description,
style: theme.textTheme.bodyMedium?.copyWith(
color: muted,
height: 1.5,
),
),
SizedBox(height: 1.h),
Row(
children: [
Expanded(
child: Text(
_shortPubkey(client.pubkey),
style: theme.textTheme.bodySmall?.copyWith(
color: _Palette.ink,
fontFamily: 'monospace',
),
),
),
IconButton(
icon: const Icon(Icons.copy_rounded, size: 18),
color: muted,
onPressed: () async {
await Clipboard.setData(
ClipboardData(
text: _fullPubkey(client.pubkey),
),
);
if (!context.mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Public key copied.'),
behavior: SnackBarBehavior.floating,
),
);
},
),
],
),
],
),
)
: const SizedBox.shrink(),
),
],
);
}
}
// ─── Table container ──────────────────────────────────────────────────────────
class _ClientTable extends StatelessWidget {
const _ClientTable({required this.clients});
final List<SdkClientEntry> clients;
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(24),
color: _Palette.cream.withValues(alpha: 0.92),
border: Border.all(color: _Palette.line),
),
child: Padding(
padding: EdgeInsets.all(2.h),
child: LayoutBuilder(
builder: (context, constraints) {
final tableWidth = math.max(_tableMinWidth, constraints.maxWidth);
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Registered clients',
style: theme.textTheme.titleLarge?.copyWith(
color: _Palette.ink,
fontWeight: FontWeight.w800,
),
),
SizedBox(height: 0.6.h),
Text(
'Every entry here has authenticated with Arbiter at least once.',
style: theme.textTheme.bodyMedium?.copyWith(
color: _Palette.ink.withValues(alpha: 0.70),
height: 1.4,
),
),
SizedBox(height: 1.6.h),
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: SizedBox(
width: tableWidth,
child: Column(
children: [
const _ClientTableHeader(),
SizedBox(height: 1.h),
for (var i = 0; i < clients.length; i++)
Padding(
padding: EdgeInsets.only(
bottom: i == clients.length - 1 ? 0 : 1.h,
),
child: _ClientTableRow(client: clients[i]),
),
],
),
),
),
],
);
},
),
),
);
}
}
// ─── Screen ───────────────────────────────────────────────────────────────────
@RoutePage()
class ClientsScreen extends HookConsumerWidget {
const ClientsScreen({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final clientsAsync = ref.watch(sdkClientsProvider);
final isConnected =
ref.watch(connectionManagerProvider).asData?.value != null;
void showMessage(String message) {
if (!context.mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(message), behavior: SnackBarBehavior.floating),
);
}
Future<void> refresh() async {
try {
final future = ref.refresh(sdkClientsProvider.future);
await future;
} catch (error) {
showMessage(_formatError(error));
}
}
final clients = clientsAsync.asData?.value;
final content = switch (clientsAsync) {
AsyncLoading() when clients == null => const _StatePanel(
icon: Icons.hourglass_top,
title: 'Loading clients',
body: 'Pulling client registry from Arbiter.',
busy: true,
),
AsyncError(:final error) => _StatePanel(
icon: Icons.sync_problem,
title: 'Client registry unavailable',
body: _formatError(error),
actionLabel: 'Retry',
onAction: refresh,
),
_ when !isConnected => _StatePanel(
icon: Icons.portable_wifi_off,
title: 'No active server connection',
body: 'Reconnect to Arbiter to list SDK clients.',
actionLabel: 'Refresh',
onAction: refresh,
),
_ when clients != null && clients.isEmpty => _StatePanel(
icon: Icons.devices_other_outlined,
title: 'No clients yet',
body: 'SDK clients appear here once they register with Arbiter.',
actionLabel: 'Refresh',
onAction: refresh,
),
_ => _ClientTable(clients: clients ?? const []),
};
return Scaffold(
body: SafeArea(
child: RefreshIndicator.adaptive(
color: _Palette.ink,
backgroundColor: Colors.white,
onRefresh: refresh,
child: ListView(
physics: const BouncingScrollPhysics(
parent: AlwaysScrollableScrollPhysics(),
),
padding: EdgeInsets.fromLTRB(2.4.w, 2.4.h, 2.4.w, 3.2.h),
children: [
_Header(isBusy: clientsAsync.isLoading, onRefresh: refresh),
SizedBox(height: 1.8.h),
content,
],
),
),
),
);
}
}

View File

@@ -2,7 +2,7 @@ import 'dart:math' as math;
import 'package:arbiter/proto/evm.pb.dart';
import 'package:arbiter/providers/connection/connection_manager.dart';
import 'package:arbiter/providers/evm.dart';
import 'package:arbiter/providers/evm/evm.dart';
import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';

View File

@@ -1,6 +1,6 @@
import 'package:arbiter/proto/evm.pb.dart';
import 'package:arbiter/providers/evm.dart';
import 'package:arbiter/providers/evm_grants.dart';
import 'package:arbiter/providers/evm/evm.dart';
import 'package:arbiter/providers/evm/evm_grants.dart';
import 'package:auto_route/auto_route.dart';
import 'package:fixnum/fixnum.dart';
import 'package:flutter/material.dart';

File diff suppressed because it is too large Load Diff