KeyQuorumsClient

Struct KeyQuorumsClient 

Source
pub struct KeyQuorumsClient { /* private fields */ }
Expand description

Client for key_quorums operations

Implementations§

Source§

impl KeyQuorumsClient

Source

pub async fn update<'a>( &'a self, key_quorum_id: &'a str, ctx: &'a AuthorizationContext, body: &'a UpdateKeyQuorumBody, ) -> Result<ResponseValue<KeyQuorum>, PrivySignedApiError>

Update a key quorum

§Errors

Can fail either if the authorization signature could not be generated, or if the api call fails whether than be due to network issues, auth problems, or the Privy API returning an error.

Source

pub async fn delete<'a>( &'a self, key_quorum_id: &'a str, ctx: &'a AuthorizationContext, ) -> Result<ResponseValue<DeleteKeyQuorumResponse>, PrivySignedApiError>

Delete a key quorum

§Errors

Can fail either if the authorization signature could not be generated, or if the api call fails whether than be due to network issues, auth problems, or the Privy API returning an error.

Source§

impl KeyQuorumsClient

Source

pub fn new(client: Client, app_id: String, base_url: String) -> Self

Create a new client instance

Source

pub async fn create<'a>( &'a self, body: &'a CreateKeyQuorumBody, ) -> Result<ResponseValue<KeyQuorum>, Error<()>>

Create key quorum

Create a new key quorum.

Sends a POST request to /v1/key_quorums

Examples found in repository?
examples/quorum_wallet.rs (line 84)
35async fn main() -> Result<()> {
36    tracing_subscriber::fmt()
37        .with_env_filter(
38            EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info")),
39        )
40        .init();
41
42    // Initialize client from environment variables
43    let client = PrivyClient::new_from_env()?;
44
45    tracing::info!("initialized privy client from environment");
46
47    // Generate unique identifiers for this example run
48    let timestamp = std::time::SystemTime::now()
49        .duration_since(std::time::SystemTime::UNIX_EPOCH)?
50        .as_secs();
51    let wallet_idempotency_key = format!("quorum-wallet-{}", Uuid::new_v4());
52
53    tracing::info!("Starting quorum wallet example");
54
55    // Step 1: Generate three P-256 private keys for quorum
56    tracing::info!("Generating three P-256 private keys for 2-of-3 quorum");
57    let mut rng = rand::thread_rng();
58    let key1 = SecretKey::<p256::NistP256>::random(&mut rng);
59    let key2 = SecretKey::<p256::NistP256>::random(&mut rng);
60    let key3 = SecretKey::<p256::NistP256>::random(&mut rng);
61
62    let pubkey1 = key1.public_key().to_string();
63    let pubkey2 = key2.public_key().to_string();
64    let pubkey3 = key3.public_key().to_string();
65
66    tracing::info!("Generated public keys:");
67    tracing::info!("Key 1: {}", pubkey1);
68    tracing::info!("Key 2: {}", pubkey2);
69    tracing::info!("Key 3: {}", pubkey3);
70
71    // Step 2: Create a 2-of-3 key quorum
72    tracing::info!("Creating 2-of-3 key quorum");
73
74    let quorum_display_name =
75        CreateKeyQuorumBodyDisplayName::try_from(format!("Quorum Example {timestamp}").as_str())?;
76
77    let quorum_body = CreateKeyQuorumBody {
78        authorization_threshold: Some(2.0), // 2-of-3 threshold
79        display_name: Some(quorum_display_name),
80        public_keys: vec![pubkey1, pubkey2, pubkey3],
81        user_ids: vec![],
82    };
83
84    let key_quorum = client.key_quorums().create(&quorum_body).await?;
85
86    tracing::info!("Created key quorum with ID: {}", key_quorum.id);
87    tracing::info!("Quorum threshold: {:?}", key_quorum.authorization_threshold);
88
89    // Step 3: Create a new Ethereum wallet owned by the quorum
90    tracing::info!(
91        "Creating new Ethereum wallet owned by quorum with idempotency key: {}",
92        wallet_idempotency_key
93    );
94
95    let create_body = CreateWalletBody {
96        chain_type: WalletChainType::Ethereum,
97        additional_signers: None,
98        owner: None,
99        owner_id: Some(key_quorum.id.parse().unwrap()),
100        policy_ids: vec![],
101    };
102
103    let wallet = client
104        .wallets()
105        .create(Some(&wallet_idempotency_key), &create_body)
106        .await?;
107
108    tracing::info!("Created wallet with ID: {}", wallet.id);
109    tracing::info!("Wallet address: {}", wallet.address);
110    tracing::info!("Wallet owner ID: {:?}", wallet.owner_id);
111
112    // Step 4: Test signing with only one key (should fail)
113    tracing::info!("Testing wallet export with only one key (should fail due to quorum threshold)");
114
115    let single_key_ctx = AuthorizationContext::new().push(PrivateKey(
116        key1.to_sec1_pem(der::pem::LineEnding::LF)
117            .unwrap()
118            .as_str()
119            .to_owned(),
120    ));
121
122    let single_key_result = client.wallets().export(&wallet.id, &single_key_ctx).await;
123
124    match single_key_result {
125        Err(err) => {
126            tracing::info!(
127                "✓ Single key authorization correctly failed as expected: {:?}",
128                err
129            );
130        }
131        Ok(_) => {
132            tracing::error!("✗ Single key authorization should have failed but succeeded!");
133            return Err(anyhow::anyhow!(
134                "Single key authorization should have failed due to quorum threshold"
135            ));
136        }
137    }
138
139    // Step 5: Test signing with two keys (should succeed)
140    tracing::info!("Testing wallet export with two keys (should succeed)");
141
142    let two_key_ctx = single_key_ctx.push(PrivateKey(
143        key2.to_sec1_pem(der::pem::LineEnding::LF)
144            .unwrap()
145            .as_str()
146            .to_owned(),
147    ));
148
149    let two_key_result = client.wallets().export(&wallet.id, &two_key_ctx).await;
150
151    match two_key_result {
152        Ok(export_result) => {
153            tracing::info!("✓ Two key authorization succeeded as expected");
154            tracing::info!("Exported private key length: {} bytes", export_result.len());
155        }
156        Err(err) => {
157            tracing::error!("✗ Two key authorization failed unexpectedly: {:?}", err);
158            return Err(anyhow::anyhow!(
159                "Two key authorization should have succeeded"
160            ));
161        }
162    }
163
164    Ok(())
165}
Source

pub async fn get<'a>( &'a self, key_quorum_id: &'a str, ) -> Result<ResponseValue<KeyQuorum>, Error<()>>

Get key quorum

Get a key quorum by ID.

Sends a GET request to /v1/key_quorums/{key_quorum_id}

Source

pub async fn _update<'a>( &'a self, key_quorum_id: &'a str, privy_authorization_signature: Option<&'a str>, body: &'a UpdateKeyQuorumBody, ) -> Result<ResponseValue<KeyQuorum>, Error<()>>

Update key quorum

Update a key quorum by key quorum ID.

Sends a PATCH request to /v1/key_quorums/{key_quorum_id}

Source

pub async fn _delete<'a>( &'a self, key_quorum_id: &'a str, privy_authorization_signature: Option<&'a str>, ) -> Result<ResponseValue<DeleteKeyQuorumResponse>, Error<()>>

Delete key quorum

Delete a key quorum by key quorum ID.

Sends a DELETE request to /v1/key_quorums/{key_quorum_id}

Trait Implementations§

Source§

impl Clone for KeyQuorumsClient

Source§

fn clone(&self) -> KeyQuorumsClient

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for KeyQuorumsClient

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more