Skip to content

Commit aad9f5e

Browse files
authored
cli: Add upgrade did command to cli (#1075)
* Protos * Add upgrade did to cli * Cleanup imports
1 parent 1ff13db commit aad9f5e

File tree

6 files changed

+298
-22
lines changed

6 files changed

+298
-22
lines changed

cli/src/cli.yaml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,31 @@ subcommands:
329329
required: false
330330
- invitation_status:
331331
about: Check invitation status
332+
- upgrade-did:
333+
about: Upgrade a public DID to a different method
334+
args:
335+
- email:
336+
long: email
337+
help: Email address of the wallet owner
338+
takes_value: true
339+
required: false
340+
- wallet-id:
341+
long: wallet-id
342+
help: Wallet ID of the owner
343+
takes_value: true
344+
required: false
345+
- method:
346+
long: method
347+
help: "DID method to upgrade to (ex: 'ion')"
348+
takes_value: true
349+
required: true
350+
- method-options:
351+
long: method-options
352+
help: "DID method options (ex: 'mainnet', 'testnet')"
353+
takes_value: true
354+
required: false
355+
356+
332357
args:
333358
- json:
334359
long: json

cli/src/parser/provider.rs

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,19 @@ use std::fmt::{self, Display, Formatter};
44

55
pub(crate) fn parse(args: &ArgMatches) -> Result<Command, Error> {
66
if args.subcommand_matches("create-ecosystem").is_some() {
7-
create_ecosystem(&args.subcommand_matches("create-ecosystem").expect("Error parsing request"))
7+
create_ecosystem(args.subcommand_matches("create-ecosystem").ok_or(Error::MissingArguments)?)
88
} else if args.subcommand_matches("update-ecosystem").is_some() {
9-
update_ecosystem(&args.subcommand_matches("update-ecosystem").expect("Error parsing request"))
9+
update_ecosystem(args.subcommand_matches("update-ecosystem").ok_or(Error::MissingArguments)?)
1010
} else if args.subcommand_matches("ecosystem-info").is_some() {
1111
ecosystem_info()
1212
} else if args.subcommand_matches("invite").is_some() {
13-
invite(&args.subcommand_matches("invite").expect("Error parsing request"))
13+
invite(args.subcommand_matches("invite").ok_or(Error::MissingArguments)?)
1414
} else if args.subcommand_matches("add-webhook").is_some() {
15-
add_webhook(&args.subcommand_matches("add-webhook").expect("Error parsing request"))
15+
add_webhook(args.subcommand_matches("add-webhook").ok_or(Error::MissingArguments)?)
1616
} else if args.subcommand_matches("delete-webhook").is_some() {
17-
delete_webhook(&args.subcommand_matches("delete-webhook").expect("Error parsing request"))
17+
delete_webhook(args.subcommand_matches("delete-webhook").ok_or(Error::MissingArguments)?)
18+
} else if args.subcommand_matches("upgrade-did").is_some() {
19+
upgrade_did(args.subcommand_matches("upgrade-did").ok_or(Error::MissingArguments)?)
1820
} else {
1921
Err(Error::MissingArguments)
2022
}
@@ -89,6 +91,17 @@ fn invite(args: &ArgMatches) -> Result<Command, Error> {
8991
}))
9092
}
9193

94+
fn upgrade_did(args: &ArgMatches) -> Result<Command, Error> {
95+
let ecosystem = UpgradeDidArgs {
96+
method: args.value_of("method").ok_or_else(|| Error::MissingArguments)?.into(),
97+
email: args.value_of("email").map(|x| x.into()),
98+
wallet_id: args.value_of("wallet-id").map(|x| x.into()),
99+
method_options: args.value_of("method-options").map(|x| x.into()),
100+
};
101+
102+
Ok(Command::UpgradeDid(ecosystem))
103+
}
104+
92105
#[derive(Debug, PartialEq)]
93106
pub enum Command<'a> {
94107
CreateEcosystem(CreateEcosystemArgs),
@@ -97,6 +110,7 @@ pub enum Command<'a> {
97110
AddWebhook(AddWebhookArgs),
98111
DeleteWebhook(DeleteWebhookArgs),
99112
Invite(InviteArgs<'a>),
113+
UpgradeDid(UpgradeDidArgs),
100114
InvitationStatus,
101115
}
102116

@@ -107,6 +121,14 @@ pub struct CreateEcosystemArgs {
107121
pub alias: String,
108122
}
109123

124+
#[derive(Debug, PartialEq)]
125+
pub struct UpgradeDidArgs {
126+
pub method: String,
127+
pub method_options: Option<String>,
128+
pub email: Option<String>,
129+
pub wallet_id: Option<String>,
130+
}
131+
110132
#[derive(Debug, PartialEq)]
111133
pub struct UpdateEcosystemArgs {
112134
pub description: Option<String>,

cli/src/proto/services/common/v1/mod.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,24 @@ impl ResponseStatus {
3434
}
3535
}
3636
}
37+
/// Enum of all supported DID Methods
38+
#[derive(::serde::Serialize, ::serde::Deserialize, Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
39+
#[repr(i32)]
40+
pub enum SupportedDidMethod {
41+
/// The did:key method -- all wallets use this by default
42+
Key = 0,
43+
/// The did:ion method
44+
Ion = 1,
45+
}
46+
impl SupportedDidMethod {
47+
/// String value of the enum field names used in the ProtoBuf definition.
48+
///
49+
/// The values are not transformed in any way and thus are considered stable
50+
/// (if the ProtoBuf definition does not change) and safe for programmatic use.
51+
pub fn as_str_name(&self) -> &'static str {
52+
match self {
53+
SupportedDidMethod::Key => "KEY",
54+
SupportedDidMethod::Ion => "ION",
55+
}
56+
}
57+
}

cli/src/proto/services/provider/v1/mod.rs

Lines changed: 185 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -248,10 +248,38 @@ pub struct EcosystemInfoRequest {}
248248
/// Response to `InfoRequest`
249249
#[derive(::serde::Serialize, ::serde::Deserialize, Clone, PartialEq, ::prost::Message)]
250250
pub struct EcosystemInfoResponse {
251-
/// Ecosystem corresponding to requested `ecosystem_id`
251+
/// Ecosystem corresponding to current ecosystem in the account token
252252
#[prost(message, optional, tag = "1")]
253253
pub ecosystem: ::core::option::Option<Ecosystem>,
254254
}
255+
/// Request to fetch information about an ecosystem
256+
#[derive(::serde::Serialize, ::serde::Deserialize, Clone, PartialEq, ::prost::Message)]
257+
pub struct GetPublicEcosystemInfoRequest {
258+
#[prost(string, tag = "1")]
259+
pub ecosystem_id: ::prost::alloc::string::String,
260+
}
261+
/// Response to `InfoRequest`
262+
#[derive(::serde::Serialize, ::serde::Deserialize, Clone, PartialEq, ::prost::Message)]
263+
pub struct GetPublicEcosystemInfoResponse {
264+
/// Ecosystem corresponding to requested `ecosystem_id`
265+
#[prost(message, optional, tag = "1")]
266+
pub ecosystem: ::core::option::Option<PublicEcosystemInformation>,
267+
}
268+
#[derive(::serde::Serialize, ::serde::Deserialize, Clone, PartialEq, ::prost::Message)]
269+
pub struct PublicEcosystemInformation {
270+
/// Public name of this ecosystem
271+
#[prost(string, tag = "1")]
272+
pub name: ::prost::alloc::string::String,
273+
/// Public domain for the owner of this ecosystem
274+
#[prost(string, tag = "2")]
275+
pub domain: ::prost::alloc::string::String,
276+
/// Trinsic verified the domain is owned by the owner of this ecosystem
277+
#[prost(bool, tag = "3")]
278+
pub domain_verified: bool,
279+
/// Style display information
280+
#[prost(message, optional, tag = "4")]
281+
pub style_display: ::core::option::Option<EcosystemDisplay>,
282+
}
255283
/// Request to generate an authentication token for the current account
256284
#[derive(::serde::Serialize, ::serde::Deserialize, Clone, PartialEq, ::prost::Message)]
257285
pub struct GenerateTokenRequest {
@@ -293,19 +321,18 @@ pub struct GetEventTokenResponse {
293321
pub token: ::prost::alloc::string::String,
294322
}
295323
#[derive(::serde::Serialize, ::serde::Deserialize, Clone, PartialEq, ::prost::Message)]
296-
pub struct RetrieveVerificationRecordRequest {}
324+
pub struct RetrieveDomainVerificationRecordRequest {}
297325
/// Response message containing a TXT record content for domain url verification
298326
#[derive(::serde::Serialize, ::serde::Deserialize, Clone, PartialEq, ::prost::Message)]
299-
pub struct RetrieveVerificationRecordResponse {
327+
pub struct RetrieveDomainVerificationRecordResponse {
300328
/// TXT code to use for domain verification
301329
#[prost(string, tag = "1")]
302330
pub verification_txt: ::prost::alloc::string::String,
303331
}
304-
/// TODO - Should we allow specifying which ecosystem to use?
305332
#[derive(::serde::Serialize, ::serde::Deserialize, Clone, PartialEq, ::prost::Message)]
306-
pub struct RefreshVerificationStatusRequest {}
333+
pub struct RefreshDomainVerificationStatusRequest {}
307334
#[derive(::serde::Serialize, ::serde::Deserialize, Clone, PartialEq, ::prost::Message)]
308-
pub struct RefreshVerificationStatusResponse {
335+
pub struct RefreshDomainVerificationStatusResponse {
309336
/// Domain URL verified
310337
#[prost(string, tag = "1")]
311338
pub domain: ::prost::alloc::string::String,
@@ -384,6 +411,109 @@ pub struct GetAuthorizationsResponse {
384411
#[prost(message, repeated, tag = "1")]
385412
pub grants: ::prost::alloc::vec::Vec<Grant>,
386413
}
414+
/// Search for issuers/holders/verifiers
415+
#[derive(::serde::Serialize, ::serde::Deserialize, Clone, PartialEq, ::prost::Message)]
416+
pub struct SearchWalletConfigurationsRequest {
417+
/// SQL filter to execute. `SELECT * FROM _ WHERE \[**queryFilter**\]`
418+
#[prost(string, tag = "1")]
419+
pub query_filter: ::prost::alloc::string::String,
420+
/// Token provided by previous `SearchResponse`
421+
/// if more data is available for query
422+
#[prost(string, tag = "2")]
423+
pub continuation_token: ::prost::alloc::string::String,
424+
}
425+
#[derive(::serde::Serialize, ::serde::Deserialize, Clone, PartialEq, ::prost::Message)]
426+
pub struct SearchWalletConfigurationResponse {
427+
/// Results matching the search query
428+
#[prost(message, repeated, tag = "1")]
429+
pub results: ::prost::alloc::vec::Vec<WalletConfiguration>,
430+
/// Whether more results are available for this query via `continuation_token`
431+
#[prost(bool, tag = "2")]
432+
pub has_more: bool,
433+
/// Token to fetch next set of results via `SearchRequest`
434+
#[prost(string, tag = "4")]
435+
pub continuation_token: ::prost::alloc::string::String,
436+
}
437+
/// Strongly typed information about wallet configurations
438+
#[derive(::serde::Serialize, ::serde::Deserialize, Clone, PartialEq, ::prost::Message)]
439+
pub struct WalletConfiguration {
440+
#[prost(string, tag = "1")]
441+
pub name: ::prost::alloc::string::String,
442+
#[prost(string, tag = "2")]
443+
pub email: ::prost::alloc::string::String,
444+
#[prost(string, tag = "3")]
445+
pub sms: ::prost::alloc::string::String,
446+
#[prost(string, tag = "4")]
447+
pub wallet_id: ::prost::alloc::string::String,
448+
#[prost(string, tag = "5")]
449+
pub public_did: ::prost::alloc::string::String,
450+
}
451+
/// Options for creation of DID on the ION network
452+
#[derive(::serde::Serialize, ::serde::Deserialize, Clone, PartialEq, ::prost::Message)]
453+
pub struct IonOptions {
454+
/// ION network on which DID should be published
455+
#[prost(enumeration = "ion_options::IonNetwork", tag = "1")]
456+
pub network: i32,
457+
}
458+
/// Nested message and enum types in `IonOptions`.
459+
pub mod ion_options {
460+
#[derive(::serde::Serialize, ::serde::Deserialize, Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
461+
#[repr(i32)]
462+
pub enum IonNetwork {
463+
TestNet = 0,
464+
MainNet = 1,
465+
}
466+
impl IonNetwork {
467+
/// String value of the enum field names used in the ProtoBuf definition.
468+
///
469+
/// The values are not transformed in any way and thus are considered stable
470+
/// (if the ProtoBuf definition does not change) and safe for programmatic use.
471+
pub fn as_str_name(&self) -> &'static str {
472+
match self {
473+
IonNetwork::TestNet => "TestNet",
474+
IonNetwork::MainNet => "MainNet",
475+
}
476+
}
477+
}
478+
}
479+
/// Request to upgrade a wallet
480+
#[derive(::serde::Serialize, ::serde::Deserialize, Clone, PartialEq, ::prost::Message)]
481+
pub struct UpgradeDidRequest {
482+
/// DID Method to which wallet should be upgraded
483+
#[prost(enumeration = "super::super::common::v1::SupportedDidMethod", tag = "3")]
484+
pub method: i32,
485+
#[prost(oneof = "upgrade_did_request::Account", tags = "1, 2")]
486+
pub account: ::core::option::Option<upgrade_did_request::Account>,
487+
#[prost(oneof = "upgrade_did_request::Options", tags = "4")]
488+
pub options: ::core::option::Option<upgrade_did_request::Options>,
489+
}
490+
/// Nested message and enum types in `UpgradeDidRequest`.
491+
pub mod upgrade_did_request {
492+
#[derive(::serde::Serialize, ::serde::Deserialize, Clone, PartialEq, ::prost::Oneof)]
493+
pub enum Account {
494+
/// Email address of account to upgrade.
495+
/// Mutually exclusive with `walletId`.
496+
#[prost(string, tag = "1")]
497+
Email(::prost::alloc::string::String),
498+
/// Wallet ID of account to upgrade.
499+
/// Mutually exclusive with `email`.
500+
#[prost(string, tag = "2")]
501+
WalletId(::prost::alloc::string::String),
502+
}
503+
#[derive(::serde::Serialize, ::serde::Deserialize, Clone, PartialEq, ::prost::Oneof)]
504+
pub enum Options {
505+
/// Configuration for creation of DID on ION network
506+
#[prost(message, tag = "4")]
507+
IonOptions(super::IonOptions),
508+
}
509+
}
510+
/// Response to `UpgradeDIDRequest`
511+
#[derive(::serde::Serialize, ::serde::Deserialize, Clone, PartialEq, ::prost::Message)]
512+
pub struct UpgradeDidResponse {
513+
/// New DID of wallet
514+
#[prost(string, tag = "1")]
515+
pub did: ::prost::alloc::string::String,
516+
}
387517
/// Type of participant being invited to ecosystem
388518
#[derive(::serde::Serialize, ::serde::Deserialize, Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
389519
#[repr(i32)]
@@ -519,7 +649,7 @@ pub mod provider_client {
519649
let path = http::uri::PathAndQuery::from_static("/services.provider.v1.Provider/RevokeAuthorization");
520650
self.inner.unary(request.into_request(), path, codec).await
521651
}
522-
/// Retreive the list of permissions for this particular account/ecosystem
652+
/// Retrieve the list of permissions for this particular account/ecosystem
523653
pub async fn get_authorizations(
524654
&mut self,
525655
request: impl tonic::IntoRequest<super::GetAuthorizationsRequest>,
@@ -571,6 +701,19 @@ pub mod provider_client {
571701
let path = http::uri::PathAndQuery::from_static("/services.provider.v1.Provider/EcosystemInfo");
572702
self.inner.unary(request.into_request(), path, codec).await
573703
}
704+
/// Get public ecosystem information about *any* ecosystem
705+
pub async fn get_public_ecosystem_info(
706+
&mut self,
707+
request: impl tonic::IntoRequest<super::GetPublicEcosystemInfoRequest>,
708+
) -> Result<tonic::Response<super::GetPublicEcosystemInfoResponse>, tonic::Status> {
709+
self.inner
710+
.ready()
711+
.await
712+
.map_err(|e| tonic::Status::new(tonic::Code::Unknown, format!("Service was not ready: {}", e.into())))?;
713+
let codec = tonic::codec::ProstCodec::default();
714+
let path = http::uri::PathAndQuery::from_static("/services.provider.v1.Provider/GetPublicEcosystemInfo");
715+
self.inner.unary(request.into_request(), path, codec).await
716+
}
574717
/// Generates an unprotected authentication token that can be used to
575718
/// configure server side applications
576719
pub async fn generate_token(
@@ -637,30 +780,56 @@ pub mod provider_client {
637780
let path = http::uri::PathAndQuery::from_static("/services.provider.v1.Provider/GetEventToken");
638781
self.inner.unary(request.into_request(), path, codec).await
639782
}
783+
/// Upgrade a wallet's DID from `did:key` to another method
784+
pub async fn upgrade_did(
785+
&mut self,
786+
request: impl tonic::IntoRequest<super::UpgradeDidRequest>,
787+
) -> Result<tonic::Response<super::UpgradeDidResponse>, tonic::Status> {
788+
self.inner
789+
.ready()
790+
.await
791+
.map_err(|e| tonic::Status::new(tonic::Code::Unknown, format!("Service was not ready: {}", e.into())))?;
792+
let codec = tonic::codec::ProstCodec::default();
793+
let path = http::uri::PathAndQuery::from_static("/services.provider.v1.Provider/UpgradeDID");
794+
self.inner.unary(request.into_request(), path, codec).await
795+
}
640796
/// Retrieve a random hash TXT that can be used to verify domain ownership
641-
pub async fn retrieve_verification_record(
797+
pub async fn retrieve_domain_verification_record(
798+
&mut self,
799+
request: impl tonic::IntoRequest<super::RetrieveDomainVerificationRecordRequest>,
800+
) -> Result<tonic::Response<super::RetrieveDomainVerificationRecordResponse>, tonic::Status> {
801+
self.inner
802+
.ready()
803+
.await
804+
.map_err(|e| tonic::Status::new(tonic::Code::Unknown, format!("Service was not ready: {}", e.into())))?;
805+
let codec = tonic::codec::ProstCodec::default();
806+
let path = http::uri::PathAndQuery::from_static("/services.provider.v1.Provider/RetrieveDomainVerificationRecord");
807+
self.inner.unary(request.into_request(), path, codec).await
808+
}
809+
/// Call to verify domain
810+
pub async fn refresh_domain_verification_status(
642811
&mut self,
643-
request: impl tonic::IntoRequest<super::RetrieveVerificationRecordRequest>,
644-
) -> Result<tonic::Response<super::RetrieveVerificationRecordResponse>, tonic::Status> {
812+
request: impl tonic::IntoRequest<super::RefreshDomainVerificationStatusRequest>,
813+
) -> Result<tonic::Response<super::RefreshDomainVerificationStatusResponse>, tonic::Status> {
645814
self.inner
646815
.ready()
647816
.await
648817
.map_err(|e| tonic::Status::new(tonic::Code::Unknown, format!("Service was not ready: {}", e.into())))?;
649818
let codec = tonic::codec::ProstCodec::default();
650-
let path = http::uri::PathAndQuery::from_static("/services.provider.v1.Provider/RetrieveVerificationRecord");
819+
let path = http::uri::PathAndQuery::from_static("/services.provider.v1.Provider/RefreshDomainVerificationStatus");
651820
self.inner.unary(request.into_request(), path, codec).await
652821
}
653-
/// Call to verif
654-
pub async fn refresh_verification_status(
822+
/// Search for issuers/providers/verifiers in the current ecosystem
823+
pub async fn search_wallet_configurations(
655824
&mut self,
656-
request: impl tonic::IntoRequest<super::RefreshVerificationStatusRequest>,
657-
) -> Result<tonic::Response<super::RefreshVerificationStatusResponse>, tonic::Status> {
825+
request: impl tonic::IntoRequest<super::SearchWalletConfigurationsRequest>,
826+
) -> Result<tonic::Response<super::SearchWalletConfigurationResponse>, tonic::Status> {
658827
self.inner
659828
.ready()
660829
.await
661830
.map_err(|e| tonic::Status::new(tonic::Code::Unknown, format!("Service was not ready: {}", e.into())))?;
662831
let codec = tonic::codec::ProstCodec::default();
663-
let path = http::uri::PathAndQuery::from_static("/services.provider.v1.Provider/RefreshVerificationStatus");
832+
let path = http::uri::PathAndQuery::from_static("/services.provider.v1.Provider/SearchWalletConfigurations");
664833
self.inner.unary(request.into_request(), path, codec).await
665834
}
666835
}

0 commit comments

Comments
 (0)