refactor(proto): restructure wallet access messages for improved data organization

This commit is contained in:
hdbg
2026-03-28 12:49:47 +01:00
parent 27428f709a
commit ca35b9fed7
10 changed files with 212 additions and 113 deletions

View File

@@ -132,17 +132,22 @@ message SdkClientConnectionCancel {
bytes pubkey = 1;
}
message WalletAccess {
int32 wallet_id = 1;
int32 sdk_client_id = 2;
}
message SdkClientWalletAccess {
int32 client_id = 1;
int32 wallet_id = 2;
int32 id = 1;
WalletAccess access = 2;
}
message SdkClientGrantWalletAccess {
repeated SdkClientWalletAccess accesses = 1;
repeated WalletAccess accesses = 1;
}
message SdkClientRevokeWalletAccess {
repeated SdkClientWalletAccess accesses = 1;
repeated int32 accesses = 1;
}
message ListWalletAccessResponse {

View File

@@ -3,11 +3,6 @@ use crate::{
db::{self, models::KeyType},
};
pub struct EvmAccessEntry {
pub wallet_id: i32,
pub sdk_client_id: i32,
}
/// Abstraction over Ed25519 / ECDSA-secp256k1 / RSA public keys used during the auth handshake.
#[derive(Clone, Debug)]
pub enum AuthPublicKey {

View File

@@ -13,9 +13,10 @@ use x25519_dalek::{EphemeralSecret, PublicKey};
use crate::actors::flow_coordinator::client_connect_approval::ClientApprovalAnswer;
use crate::actors::keyholder::KeyHolderState;
use crate::actors::user_agent::EvmAccessEntry;
use crate::actors::user_agent::session::Error;
use crate::db::models::{ProgramClient, ProgramClientMetadata};
use crate::db::models::{
CoreEvmWalletAccess, EvmWalletAccess, NewEvmWalletAccess, ProgramClient, ProgramClientMetadata,
};
use crate::db::schema::evm_wallet_access;
use crate::evm::policies::{Grant, SpecificGrant};
use crate::safe_cell::SafeCell;
@@ -304,8 +305,6 @@ impl UserAgentSession {
}
}
#[messages]
impl UserAgentSession {
#[message]
@@ -360,20 +359,16 @@ impl UserAgentSession {
#[message]
pub(crate) async fn handle_grant_evm_wallet_access(
&mut self,
entries: Vec<EvmAccessEntry>,
entries: Vec<NewEvmWalletAccess>,
) -> Result<(), Error> {
let mut conn = self.props.db.get().await?;
conn.transaction(|conn| {
Box::pin(async move {
use crate::db::models::NewEvmWalletAccess;
use crate::db::schema::evm_wallet_access;
for entry in entries {
diesel::insert_into(evm_wallet_access::table)
.values(&NewEvmWalletAccess {
wallet_id: entry.wallet_id,
client_id: entry.sdk_client_id,
})
.values(&entry)
.on_conflict_do_nothing()
.execute(conn)
.await?;
@@ -389,7 +384,7 @@ impl UserAgentSession {
#[message]
pub(crate) async fn handle_revoke_evm_wallet_access(
&mut self,
entries: Vec<EvmAccessEntry>,
entries: Vec<i32>,
) -> Result<(), Error> {
let mut conn = self.props.db.get().await?;
conn.transaction(|conn| {
@@ -397,11 +392,7 @@ impl UserAgentSession {
use crate::db::schema::evm_wallet_access;
for entry in entries {
diesel::delete(evm_wallet_access::table)
.filter(
evm_wallet_access::wallet_id
.eq(entry.wallet_id)
.and(evm_wallet_access::client_id.eq(entry.sdk_client_id)),
)
.filter(evm_wallet_access::wallet_id.eq(entry))
.execute(conn)
.await?;
}
@@ -414,19 +405,15 @@ impl UserAgentSession {
}
#[message]
pub(crate) async fn handle_list_wallet_access(&mut self) -> Result<Vec<EvmAccessEntry>, Error> {
pub(crate) async fn handle_list_wallet_access(
&mut self,
) -> Result<Vec<EvmWalletAccess>, Error> {
let mut conn = self.props.db.get().await?;
use crate::db::schema::evm_wallet_access;
let access_entries = evm_wallet_access::table
.select((evm_wallet_access::wallet_id, evm_wallet_access::client_id))
.load::<(i32, i32)>(&mut conn)
.await?
.into_iter()
.map(|(wallet_id, sdk_client_id)| EvmAccessEntry {
wallet_id,
sdk_client_id,
})
.collect();
.select(EvmWalletAccess::as_select())
.load::<_>(&mut conn)
.await?;
Ok(access_entries)
}
}

View File

@@ -193,6 +193,12 @@ pub struct EvmWallet {
omit(id, created_at),
attributes_with = "deriveless"
)]
#[view(
CoreEvmWalletAccess,
derive(Insertable),
omit(created_at),
attributes_with = "deriveless"
)]
pub struct EvmWalletAccess {
pub id: i32,
pub wallet_id: i32,

View File

@@ -45,10 +45,15 @@ use crate::{
user_agent::{
OutOfBand, UserAgentConnection, UserAgentSession,
session::connection::{
BootstrapError, HandleBootstrapEncryptedKey, HandleEvmWalletCreate, HandleEvmWalletList, HandleGrantCreate, HandleGrantDelete, HandleGrantEvmWalletAccess, HandleGrantList, HandleListWalletAccess, HandleNewClientApprove, HandleQueryVaultState, HandleRevokeEvmWalletAccess, HandleSdkClientList, HandleUnsealEncryptedKey, HandleUnsealRequest, UnsealError
BootstrapError, HandleBootstrapEncryptedKey, HandleEvmWalletCreate,
HandleEvmWalletList, HandleGrantCreate, HandleGrantDelete,
HandleGrantEvmWalletAccess, HandleGrantList, HandleListWalletAccess,
HandleNewClientApprove, HandleQueryVaultState, HandleRevokeEvmWalletAccess,
HandleSdkClientList, HandleUnsealEncryptedKey, HandleUnsealRequest, UnsealError,
},
},
},
db::models::{CoreEvmWalletAccess, NewEvmWalletAccess},
grpc::{Convert, TryConvert, request_tracker::RequestTracker},
};
mod auth;
@@ -383,7 +388,8 @@ async fn dispatch_inner(
}
UserAgentRequestPayload::GrantWalletAccess(SdkClientGrantWalletAccess { accesses }) => {
let entries = accesses.try_convert()?;
let entries: Vec<NewEvmWalletAccess> =
accesses.into_iter().map(|a| a.convert()).collect();
match actor.ask(HandleGrantEvmWalletAccess { entries }).await {
Ok(()) => {
@@ -398,9 +404,7 @@ async fn dispatch_inner(
}
UserAgentRequestPayload::RevokeWalletAccess(SdkClientRevokeWalletAccess { accesses }) => {
let entries = accesses.try_convert()?;
match actor.ask(HandleRevokeEvmWalletAccess { entries }).await {
match actor.ask(HandleRevokeEvmWalletAccess { entries: accesses }).await {
Ok(()) => {
info!("Successfully revoked wallet access");
return Ok(None);

View File

@@ -1,23 +1,21 @@
use alloy::primitives::{Address, U256};
use arbiter_proto::proto::evm::{
EtherTransferSettings as ProtoEtherTransferSettings,
SharedSettings as ProtoSharedSettings,
SpecificGrant as ProtoSpecificGrant,
TokenTransferSettings as ProtoTokenTransferSettings,
TransactionRateLimit as ProtoTransactionRateLimit,
VolumeRateLimit as ProtoVolumeRateLimit,
EtherTransferSettings as ProtoEtherTransferSettings, SharedSettings as ProtoSharedSettings,
SpecificGrant as ProtoSpecificGrant, TokenTransferSettings as ProtoTokenTransferSettings,
TransactionRateLimit as ProtoTransactionRateLimit, VolumeRateLimit as ProtoVolumeRateLimit,
specific_grant::Grant as ProtoSpecificGrantType,
};
use arbiter_proto::proto::user_agent::SdkClientWalletAccess;
use alloy::primitives::{Address, U256};
use arbiter_proto::proto::user_agent::{SdkClientWalletAccess, WalletAccess};
use chrono::{DateTime, TimeZone, Utc};
use prost_types::Timestamp as ProtoTimestamp;
use tonic::Status;
use crate::actors::user_agent::EvmAccessEntry;
use crate::db::models::{CoreEvmWalletAccess, NewEvmWallet, NewEvmWalletAccess};
use crate::grpc::Convert;
use crate::{
evm::policies::{
SharedGrantSettings, SpecificGrant, TransactionRateLimit, VolumeRateLimit,
ether_transfer, token_transfers,
SharedGrantSettings, SpecificGrant, TransactionRateLimit, VolumeRateLimit, ether_transfer,
token_transfers,
},
grpc::TryConvert,
};
@@ -79,8 +77,14 @@ impl TryConvert for ProtoSharedSettings {
Ok(SharedGrantSettings {
wallet_access_id: self.wallet_access_id,
chain: self.chain_id,
valid_from: self.valid_from.map(ProtoTimestamp::try_convert).transpose()?,
valid_until: self.valid_until.map(ProtoTimestamp::try_convert).transpose()?,
valid_from: self
.valid_from
.map(ProtoTimestamp::try_convert)
.transpose()?,
valid_until: self
.valid_until
.map(ProtoTimestamp::try_convert)
.transpose()?,
max_gas_fee_per_gas: self
.max_gas_fee_per_gas
.as_deref()
@@ -136,17 +140,29 @@ impl TryConvert for ProtoSpecificGrant {
}
}
impl TryConvert for Vec<SdkClientWalletAccess> {
type Output = Vec<EvmAccessEntry>;
impl Convert for WalletAccess {
type Output = NewEvmWalletAccess;
fn convert(self) -> Self::Output {
NewEvmWalletAccess {
wallet_id: self.wallet_id,
client_id: self.sdk_client_id,
}
}
}
impl TryConvert for SdkClientWalletAccess {
type Output = CoreEvmWalletAccess;
type Error = Status;
fn try_convert(self) -> Result<Vec<EvmAccessEntry>, Status> {
Ok(self
.into_iter()
.map(|SdkClientWalletAccess { client_id, wallet_id }| EvmAccessEntry {
wallet_id,
sdk_client_id: client_id,
fn try_convert(self) -> Result<CoreEvmWalletAccess, Status> {
let Some(access) = self.access else {
return Err(Status::invalid_argument("Missing wallet access entry"));
};
Ok(CoreEvmWalletAccess {
wallet_id: access.wallet_id,
client_id: access.sdk_client_id,
id: self.id,
})
.collect())
}
}

View File

@@ -5,13 +5,13 @@ use arbiter_proto::proto::{
TransactionRateLimit as ProtoTransactionRateLimit, VolumeRateLimit as ProtoVolumeRateLimit,
specific_grant::Grant as ProtoSpecificGrantType,
},
user_agent::SdkClientWalletAccess as ProtoSdkClientWalletAccess,
user_agent::{SdkClientWalletAccess as ProtoSdkClientWalletAccess, WalletAccess},
};
use chrono::{DateTime, Utc};
use prost_types::Timestamp as ProtoTimestamp;
use crate::{
actors::user_agent::EvmAccessEntry,
db::models::EvmWalletAccess,
evm::policies::{SharedGrantSettings, SpecificGrant, TransactionRateLimit, VolumeRateLimit},
grpc::Convert,
};
@@ -96,13 +96,16 @@ impl Convert for SpecificGrant {
}
}
impl Convert for EvmAccessEntry {
impl Convert for EvmWalletAccess {
type Output = ProtoSdkClientWalletAccess;
fn convert(self) -> Self::Output {
ProtoSdkClientWalletAccess {
client_id: self.sdk_client_id,
Self::Output {
id: self.id,
access: Some(WalletAccess {
wallet_id: self.wallet_id,
sdk_client_id: self.client_id,
}),
}
}
}

View File

@@ -15,8 +15,8 @@ Future<Set<int>> readClientWalletAccess(
);
}
return {
for (final access in response.listWalletAccessResponse.accesses)
if (access.clientId == clientId) access.walletId,
for (final entry in response.listWalletAccessResponse.accesses)
if (entry.access != null && entry.access.sdkClientId == clientId) entry.access.walletId,
};
}
@@ -36,7 +36,7 @@ Future<void> writeClientWalletAccess(
grantWalletAccess: SdkClientGrantWalletAccess(
accesses: [
for (final walletId in toGrant)
SdkClientWalletAccess(clientId: clientId, walletId: walletId),
WalletAccess(sdkClientId: clientId, walletId: walletId),
],
),
),
@@ -49,7 +49,7 @@ Future<void> writeClientWalletAccess(
revokeWalletAccess: SdkClientRevokeWalletAccess(
accesses: [
for (final walletId in toRevoke)
SdkClientWalletAccess(clientId: clientId, walletId: walletId),
walletId
],
),
),

View File

@@ -1072,14 +1072,81 @@ class SdkClientConnectionCancel extends $pb.GeneratedMessage {
void clearPubkey() => $_clearField(1);
}
class SdkClientWalletAccess extends $pb.GeneratedMessage {
factory SdkClientWalletAccess({
$core.int? clientId,
class WalletAccess extends $pb.GeneratedMessage {
factory WalletAccess({
$core.int? walletId,
$core.int? sdkClientId,
}) {
final result = create();
if (clientId != null) result.clientId = clientId;
if (walletId != null) result.walletId = walletId;
if (sdkClientId != null) result.sdkClientId = sdkClientId;
return result;
}
WalletAccess._();
factory WalletAccess.fromBuffer($core.List<$core.int> data,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromBuffer(data, registry);
factory WalletAccess.fromJson($core.String json,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromJson(json, registry);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
_omitMessageNames ? '' : 'WalletAccess',
package:
const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.user_agent'),
createEmptyInstance: create)
..aI(1, _omitFieldNames ? '' : 'walletId')
..aI(2, _omitFieldNames ? '' : 'sdkClientId')
..hasRequiredFields = false;
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
WalletAccess clone() => deepCopy();
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
WalletAccess copyWith(void Function(WalletAccess) updates) =>
super.copyWith((message) => updates(message as WalletAccess))
as WalletAccess;
@$core.override
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static WalletAccess create() => WalletAccess._();
@$core.override
WalletAccess createEmptyInstance() => create();
@$core.pragma('dart2js:noInline')
static WalletAccess getDefault() => _defaultInstance ??=
$pb.GeneratedMessage.$_defaultFor<WalletAccess>(create);
static WalletAccess? _defaultInstance;
@$pb.TagNumber(1)
$core.int get walletId => $_getIZ(0);
@$pb.TagNumber(1)
set walletId($core.int value) => $_setSignedInt32(0, value);
@$pb.TagNumber(1)
$core.bool hasWalletId() => $_has(0);
@$pb.TagNumber(1)
void clearWalletId() => $_clearField(1);
@$pb.TagNumber(2)
$core.int get sdkClientId => $_getIZ(1);
@$pb.TagNumber(2)
set sdkClientId($core.int value) => $_setSignedInt32(1, value);
@$pb.TagNumber(2)
$core.bool hasSdkClientId() => $_has(1);
@$pb.TagNumber(2)
void clearSdkClientId() => $_clearField(2);
}
class SdkClientWalletAccess extends $pb.GeneratedMessage {
factory SdkClientWalletAccess({
$core.int? id,
WalletAccess? access,
}) {
final result = create();
if (id != null) result.id = id;
if (access != null) result.access = access;
return result;
}
@@ -1097,8 +1164,9 @@ class SdkClientWalletAccess extends $pb.GeneratedMessage {
package:
const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.user_agent'),
createEmptyInstance: create)
..aI(1, _omitFieldNames ? '' : 'clientId')
..aI(2, _omitFieldNames ? '' : 'walletId')
..aI(1, _omitFieldNames ? '' : 'id')
..aOM<WalletAccess>(2, _omitFieldNames ? '' : 'access',
subBuilder: WalletAccess.create)
..hasRequiredFields = false;
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
@@ -1122,27 +1190,29 @@ class SdkClientWalletAccess extends $pb.GeneratedMessage {
static SdkClientWalletAccess? _defaultInstance;
@$pb.TagNumber(1)
$core.int get clientId => $_getIZ(0);
$core.int get id => $_getIZ(0);
@$pb.TagNumber(1)
set clientId($core.int value) => $_setSignedInt32(0, value);
set id($core.int value) => $_setSignedInt32(0, value);
@$pb.TagNumber(1)
$core.bool hasClientId() => $_has(0);
$core.bool hasId() => $_has(0);
@$pb.TagNumber(1)
void clearClientId() => $_clearField(1);
void clearId() => $_clearField(1);
@$pb.TagNumber(2)
$core.int get walletId => $_getIZ(1);
WalletAccess get access => $_getN(1);
@$pb.TagNumber(2)
set walletId($core.int value) => $_setSignedInt32(1, value);
set access(WalletAccess value) => $_setField(2, value);
@$pb.TagNumber(2)
$core.bool hasWalletId() => $_has(1);
$core.bool hasAccess() => $_has(1);
@$pb.TagNumber(2)
void clearWalletId() => $_clearField(2);
void clearAccess() => $_clearField(2);
@$pb.TagNumber(2)
WalletAccess ensureAccess() => $_ensure(1);
}
class SdkClientGrantWalletAccess extends $pb.GeneratedMessage {
factory SdkClientGrantWalletAccess({
$core.Iterable<SdkClientWalletAccess>? accesses,
$core.Iterable<WalletAccess>? accesses,
}) {
final result = create();
if (accesses != null) result.accesses.addAll(accesses);
@@ -1163,8 +1233,8 @@ class SdkClientGrantWalletAccess extends $pb.GeneratedMessage {
package:
const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.user_agent'),
createEmptyInstance: create)
..pPM<SdkClientWalletAccess>(1, _omitFieldNames ? '' : 'accesses',
subBuilder: SdkClientWalletAccess.create)
..pPM<WalletAccess>(1, _omitFieldNames ? '' : 'accesses',
subBuilder: WalletAccess.create)
..hasRequiredFields = false;
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
@@ -1189,12 +1259,12 @@ class SdkClientGrantWalletAccess extends $pb.GeneratedMessage {
static SdkClientGrantWalletAccess? _defaultInstance;
@$pb.TagNumber(1)
$pb.PbList<SdkClientWalletAccess> get accesses => $_getList(0);
$pb.PbList<WalletAccess> get accesses => $_getList(0);
}
class SdkClientRevokeWalletAccess extends $pb.GeneratedMessage {
factory SdkClientRevokeWalletAccess({
$core.Iterable<SdkClientWalletAccess>? accesses,
$core.Iterable<$core.int>? accesses,
}) {
final result = create();
if (accesses != null) result.accesses.addAll(accesses);
@@ -1215,8 +1285,7 @@ class SdkClientRevokeWalletAccess extends $pb.GeneratedMessage {
package:
const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.user_agent'),
createEmptyInstance: create)
..pPM<SdkClientWalletAccess>(1, _omitFieldNames ? '' : 'accesses',
subBuilder: SdkClientWalletAccess.create)
..p<$core.int>(1, _omitFieldNames ? '' : 'accesses', $pb.PbFieldType.K3)
..hasRequiredFields = false;
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
@@ -1242,7 +1311,7 @@ class SdkClientRevokeWalletAccess extends $pb.GeneratedMessage {
static SdkClientRevokeWalletAccess? _defaultInstance;
@$pb.TagNumber(1)
$pb.PbList<SdkClientWalletAccess> get accesses => $_getList(0);
$pb.PbList<$core.int> get accesses => $_getList(0);
}
class ListWalletAccessResponse extends $pb.GeneratedMessage {

View File

@@ -418,19 +418,40 @@ final $typed_data.Uint8List sdkClientConnectionCancelDescriptor =
$convert.base64Decode(
'ChlTZGtDbGllbnRDb25uZWN0aW9uQ2FuY2VsEhYKBnB1YmtleRgBIAEoDFIGcHVia2V5');
@$core.Deprecated('Use walletAccessDescriptor instead')
const WalletAccess$json = {
'1': 'WalletAccess',
'2': [
{'1': 'wallet_id', '3': 1, '4': 1, '5': 5, '10': 'walletId'},
{'1': 'sdk_client_id', '3': 2, '4': 1, '5': 5, '10': 'sdkClientId'},
],
};
/// Descriptor for `WalletAccess`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List walletAccessDescriptor = $convert.base64Decode(
'CgxXYWxsZXRBY2Nlc3MSGwoJd2FsbGV0X2lkGAEgASgFUgh3YWxsZXRJZBIiCg1zZGtfY2xpZW'
'50X2lkGAIgASgFUgtzZGtDbGllbnRJZA==');
@$core.Deprecated('Use sdkClientWalletAccessDescriptor instead')
const SdkClientWalletAccess$json = {
'1': 'SdkClientWalletAccess',
'2': [
{'1': 'client_id', '3': 1, '4': 1, '5': 5, '10': 'clientId'},
{'1': 'wallet_id', '3': 2, '4': 1, '5': 5, '10': 'walletId'},
{'1': 'id', '3': 1, '4': 1, '5': 5, '10': 'id'},
{
'1': 'access',
'3': 2,
'4': 1,
'5': 11,
'6': '.arbiter.user_agent.WalletAccess',
'10': 'access'
},
],
};
/// Descriptor for `SdkClientWalletAccess`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List sdkClientWalletAccessDescriptor = $convert.base64Decode(
'ChVTZGtDbGllbnRXYWxsZXRBY2Nlc3MSGwoJY2xpZW50X2lkGAEgASgFUghjbGllbnRJZBIbCg'
'l3YWxsZXRfaWQYAiABKAVSCHdhbGxldElk');
'ChVTZGtDbGllbnRXYWxsZXRBY2Nlc3MSDgoCaWQYASABKAVSAmlkEjgKBmFjY2VzcxgCIAEoCz'
'IgLmFyYml0ZXIudXNlcl9hZ2VudC5XYWxsZXRBY2Nlc3NSBmFjY2Vzcw==');
@$core.Deprecated('Use sdkClientGrantWalletAccessDescriptor instead')
const SdkClientGrantWalletAccess$json = {
@@ -441,7 +462,7 @@ const SdkClientGrantWalletAccess$json = {
'3': 1,
'4': 3,
'5': 11,
'6': '.arbiter.user_agent.SdkClientWalletAccess',
'6': '.arbiter.user_agent.WalletAccess',
'10': 'accesses'
},
],
@@ -450,29 +471,22 @@ const SdkClientGrantWalletAccess$json = {
/// Descriptor for `SdkClientGrantWalletAccess`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List sdkClientGrantWalletAccessDescriptor =
$convert.base64Decode(
'ChpTZGtDbGllbnRHcmFudFdhbGxldEFjY2VzcxJFCghhY2Nlc3NlcxgBIAMoCzIpLmFyYml0ZX'
'IudXNlcl9hZ2VudC5TZGtDbGllbnRXYWxsZXRBY2Nlc3NSCGFjY2Vzc2Vz');
'ChpTZGtDbGllbnRHcmFudFdhbGxldEFjY2VzcxI8CghhY2Nlc3NlcxgBIAMoCzIgLmFyYml0ZX'
'IudXNlcl9hZ2VudC5XYWxsZXRBY2Nlc3NSCGFjY2Vzc2Vz');
@$core.Deprecated('Use sdkClientRevokeWalletAccessDescriptor instead')
const SdkClientRevokeWalletAccess$json = {
'1': 'SdkClientRevokeWalletAccess',
'2': [
{
'1': 'accesses',
'3': 1,
'4': 3,
'5': 11,
'6': '.arbiter.user_agent.SdkClientWalletAccess',
'10': 'accesses'
},
{'1': 'accesses', '3': 1, '4': 3, '5': 5, '10': 'accesses'},
],
};
/// Descriptor for `SdkClientRevokeWalletAccess`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List sdkClientRevokeWalletAccessDescriptor =
$convert.base64Decode(
'ChtTZGtDbGllbnRSZXZva2VXYWxsZXRBY2Nlc3MSRQoIYWNjZXNzZXMYASADKAsyKS5hcmJpdG'
'VyLnVzZXJfYWdlbnQuU2RrQ2xpZW50V2FsbGV0QWNjZXNzUghhY2Nlc3Nlcw==');
'ChtTZGtDbGllbnRSZXZva2VXYWxsZXRBY2Nlc3MSGgoIYWNjZXNzZXMYASADKAVSCGFjY2Vzc2'
'Vz');
@$core.Deprecated('Use listWalletAccessResponseDescriptor instead')
const ListWalletAccessResponse$json = {