pub struct WalletsClient { /* private fields */ }Expand description
Client for wallets operations
Implementations§
Source§impl WalletsClient
impl WalletsClient
Sourcepub async fn rpc<'a>(
&'a self,
wallet_id: &'a str,
ctx: &'a AuthorizationContext,
privy_idempotency_key: Option<&'a str>,
body: &'a WalletRpcBody,
) -> Result<ResponseValue<WalletRpcResponse>, PrivySignedApiError>
pub async fn rpc<'a>( &'a self, wallet_id: &'a str, ctx: &'a AuthorizationContext, privy_idempotency_key: Option<&'a str>, body: &'a WalletRpcBody, ) -> Result<ResponseValue<WalletRpcResponse>, PrivySignedApiError>
Make a wallet rpc call
§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.
Examples found in repository?
31async fn main() -> Result<()> {
32 tracing_subscriber::fmt()
33 .with_env_filter(
34 EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info")),
35 )
36 .init();
37
38 // Get wallet ID from environment
39 let wallet_id =
40 std::env::var("PRIVY_WALLET_ID").expect("PRIVY_WALLET_ID environment variable not set");
41
42 tracing::info!(
43 "initializing privy client from environment, wallet_id: {}",
44 wallet_id
45 );
46
47 let private_key = std::fs::read_to_string("private_key.pem")?;
48
49 let client = PrivyClient::new_from_env()?;
50
51 let ctx = AuthorizationContext::new()
52 .push(PrivateKey(private_key))
53 .push(JwtUser(client.clone(), "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhbGV4QGFybHlvbi5kZXYiLCJpYXQiOjEwMDAwMDAwMDAwMH0.IpNgavH95CFZPjkzQW4eyxMIfJ-O_5cIaDyu_6KRXffykjYDRwxTgFJuYq0F6d8wSXf4de-vzfBRWSKMISM3rJdlhximYINGJB14mJFCD87VMLFbTpHIXcv7hc1AAYMPGhOsRkYfYXuvVopKszMvhupmQYJ1npSvKWNeBniIyOHYv4xebZD8L0RVlPvuEKTXTu-CDfs2rMwvD9g_wiBznS3uMF3v_KPaY6x0sx9zeCSxAH9zvhMMtct_Ad9kuoUncGpRzNhEk6JlVccN2Leb1JzbldxSywyS2AApD05u-GFAgFDN3P39V3qgRTGDuuUfUvKQ9S4rbu5El9Qq1CJTeA".to_string()));
54
55 // Example: Sign a Solana transaction
56 let rpc_response = match client
57 .wallets()
58 .rpc(
59 &wallet_id,
60 &ctx,
61 None, // No idempotency key
62 &WalletRpcBody::SolanaSignMessageRpcInput(SolanaSignMessageRpcInput {
63 address: Some("7EcDhSYGxXyscszYEp35KHN8vvw3svAuLKTzXwCFLtV".to_string()),
64 chain_type: None,
65 method: SolanaSignMessageRpcInputMethod::SignMessage,
66 params: SolanaSignMessageRpcInputParams {
67 encoding: SolanaSignMessageRpcInputParamsEncoding::Base64,
68 message: STANDARD.encode("hello world"),
69 },
70 }),
71 )
72 .await
73 {
74 Ok(r) => r,
75 Err(PrivySignedApiError::Api(PrivyApiError::UnexpectedResponse(resp))) => {
76 tracing::error!("Unexpected response: {:?}", resp.text().await);
77 return Err(anyhow::anyhow!("Unexpected response"));
78 }
79 Err(e) => return Err(e.into()),
80 };
81
82 tracing::info!("RPC response: {:?}", rpc_response);
83
84 Ok(())
85}Sourcepub async fn raw_sign<'a>(
&'a self,
wallet_id: &'a str,
ctx: &'a AuthorizationContext,
privy_idempotency_key: Option<&'a str>,
body: &'a RawSign,
) -> Result<ResponseValue<RawSignResponse>, PrivySignedApiError>
pub async fn raw_sign<'a>( &'a self, wallet_id: &'a str, ctx: &'a AuthorizationContext, privy_idempotency_key: Option<&'a str>, body: &'a RawSign, ) -> Result<ResponseValue<RawSignResponse>, PrivySignedApiError>
Make a wallet raw sign call
§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.
Examples found in repository?
27async fn main() -> Result<()> {
28 tracing_subscriber::fmt()
29 .with_env_filter(
30 EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info")),
31 )
32 .init();
33
34 // Get wallet ID from environment
35 let wallet_id =
36 std::env::var("PRIVY_WALLET_ID").expect("PRIVY_WALLET_ID environment variable not set");
37
38 tracing::info!(
39 "initializing privy client from environment, wallet_id: {}",
40 wallet_id
41 );
42
43 let private_key = std::fs::read_to_string("private_key.pem")?;
44
45 let client = PrivyClient::new_from_env()?;
46
47 let ctx = AuthorizationContext::new()
48 .push(PrivateKey(private_key))
49 .push(JwtUser(client.clone(), "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhbGV4QGFybHlvbi5kZXYiLCJpYXQiOjEwMDAwMDAwMDAwMH0.IpNgavH95CFZPjkzQW4eyxMIfJ-O_5cIaDyu_6KRXffykjYDRwxTgFJuYq0F6d8wSXf4de-vzfBRWSKMISM3rJdlhximYINGJB14mJFCD87VMLFbTpHIXcv7hc1AAYMPGhOsRkYfYXuvVopKszMvhupmQYJ1npSvKWNeBniIyOHYv4xebZD8L0RVlPvuEKTXTu-CDfs2rMwvD9g_wiBznS3uMF3v_KPaY6x0sx9zeCSxAH9zvhMMtct_Ad9kuoUncGpRzNhEk6JlVccN2Leb1JzbldxSywyS2AApD05u-GFAgFDN3P39V3qgRTGDuuUfUvKQ9S4rbu5El9Qq1CJTeA".to_string()));
50
51 // Example: Sign raw message data
52 let raw_sign_response = match client
53 .wallets()
54 .raw_sign(
55 &wallet_id,
56 &ctx,
57 None, // No idempotency key
58 &RawSign {
59 params: RawSignParams::Variant0 {
60 hash: "0xdeadbeef".to_string(),
61 },
62 },
63 )
64 .await
65 {
66 Ok(r) => r,
67 Err(PrivySignedApiError::Api(PrivyApiError::UnexpectedResponse(resp))) => {
68 tracing::error!("Unexpected response: {:?}", resp.text().await);
69 return Err(anyhow::anyhow!("Unexpected response"));
70 }
71 Err(e) => return Err(e.into()),
72 };
73
74 tracing::info!("Raw sign response: {:?}", raw_sign_response);
75
76 Ok(())
77}Sourcepub async fn update<'a>(
&'a self,
wallet_id: &'a str,
ctx: &'a AuthorizationContext,
body: &'a UpdateWalletBody,
) -> Result<ResponseValue<Wallet>, PrivySignedApiError>
pub async fn update<'a>( &'a self, wallet_id: &'a str, ctx: &'a AuthorizationContext, body: &'a UpdateWalletBody, ) -> Result<ResponseValue<Wallet>, PrivySignedApiError>
Update a wallet
§Errors
Can fail either if the authorization signature could not be generated, or if the api call fails whether than be due to
Examples found in repository?
29async fn main() -> Result<()> {
30 tracing_subscriber::fmt()
31 .with_env_filter(
32 EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info")),
33 )
34 .init();
35
36 // Get wallet ID from environment
37 let wallet_id =
38 std::env::var("PRIVY_WALLET_ID").expect("PRIVY_WALLET_ID environment variable not set");
39
40 tracing::info!(
41 "initializing privy client from environment, wallet_id: {}",
42 wallet_id
43 );
44
45 let file = std::fs::read_to_string("private_key.pem")?;
46
47 let key = PrivateKey(file);
48 let public_key = key.get_key().await?.public_key();
49
50 let client = PrivyClient::new_from_env()?;
51
52 let ctx = AuthorizationContext::new()
53 .push(key)
54 .push(JwtUser(client.clone(), "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhbGV4QGFybHlvbi5kZXYiLCJpYXQiOjEwMDAwMDAwMDAwMH0.IpNgavH95CFZPjkzQW4eyxMIfJ-O_5cIaDyu_6KRXffykjYDRwxTgFJuYq0F6d8wSXf4de-vzfBRWSKMISM3rJdlhximYINGJB14mJFCD87VMLFbTpHIXcv7hc1AAYMPGhOsRkYfYXuvVopKszMvhupmQYJ1npSvKWNeBniIyOHYv4xebZD8L0RVlPvuEKTXTu-CDfs2rMwvD9g_wiBznS3uMF3v_KPaY6x0sx9zeCSxAH9zvhMMtct_Ad9kuoUncGpRzNhEk6JlVccN2Leb1JzbldxSywyS2AApD05u-GFAgFDN3P39V3qgRTGDuuUfUvKQ9S4rbu5El9Qq1CJTeA".to_string()));
55
56 let wallets_client = client.wallets();
57 let wallet = wallets_client.get(&wallet_id).await?;
58
59 tracing::info!("got wallet: {:?}", wallet);
60
61 let wallet = match wallets_client
62 .update(
63 &wallet_id,
64 &ctx,
65 &UpdateWalletBody {
66 owner: Some(OwnerInput::PublicKey(public_key.to_string())),
67 ..Default::default()
68 },
69 )
70 .await
71 {
72 Ok(wallet) => wallet,
73 Err(PrivySignedApiError::Api(PrivyApiError::UnexpectedResponse(r))) => {
74 let text = r.text().await.unwrap_or_default();
75 tracing::warn!("unexpected response: {:?}", text);
76 anyhow::bail!("unexpected response")
77 }
78 Err(e) => {
79 anyhow::bail!("unexpected error: {e:?}")
80 }
81 };
82
83 tracing::info!("got updated wallet: {:?}", wallet);
84
85 Ok(())
86}Sourcepub async fn export<'a>(
&'a self,
wallet_id: &'a str,
ctx: &'a AuthorizationContext,
) -> Result<Vec<u8>, PrivyExportError>
pub async fn export<'a>( &'a self, wallet_id: &'a str, ctx: &'a AuthorizationContext, ) -> Result<Vec<u8>, PrivyExportError>
Export a wallet
§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. Additionally, if the privy platform
were to produce a response from which we cannot decrypt the secret key,
a PrivyExportError::Key will be returned.
Examples found in repository?
28async fn main() -> Result<()> {
29 tracing_subscriber::fmt()
30 .with_env_filter(
31 EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info")),
32 )
33 .init();
34
35 // Get wallet ID from environment
36 let wallet_id =
37 std::env::var("PRIVY_WALLET_ID").expect("PRIVY_WALLET_ID environment variable not set");
38
39 tracing::info!(
40 "initializing privy client from environment, wallet_id: {}",
41 wallet_id
42 );
43
44 tracing::info!("Generated HPKE key pair for encryption");
45
46 let private_key = std::fs::read_to_string("private_key.pem")?;
47
48 let client = PrivyClient::new_from_env()?;
49
50 let ctx = AuthorizationContext::new()
51 .push(PrivateKey(private_key))
52 .push(JwtUser(client.clone(), "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhbGV4QGFybHlvbi5kZXYiLCJpYXQiOjEwMDAwMDAwMDAwMH0.IpNgavH95CFZPjkzQW4eyxMIfJ-O_5cIaDyu_6KRXffykjYDRwxTgFJuYq0F6d8wSXf4de-vzfBRWSKMISM3rJdlhximYINGJB14mJFCD87VMLFbTpHIXcv7hc1AAYMPGhOsRkYfYXuvVopKszMvhupmQYJ1npSvKWNeBniIyOHYv4xebZD8L0RVlPvuEKTXTu-CDfs2rMwvD9g_wiBznS3uMF3v_KPaY6x0sx9zeCSxAH9zvhMMtct_Ad9kuoUncGpRzNhEk6JlVccN2Leb1JzbldxSywyS2AApD05u-GFAgFDN3P39V3qgRTGDuuUfUvKQ9S4rbu5El9Qq1CJTeA".to_string()));
53
54 // Export wallet private key (requires authorization signature)
55 let secret_key = client.wallets().export(&wallet_id, &ctx).await?;
56
57 tracing::info!("Successfully decrypted private key");
58 tracing::warn!("SECURITY WARNING: Private key exported and decrypted!");
59 println!(
60 "Decrypted private key (hex): {}",
61 secret_key.encode_hex::<String>()
62 );
63
64 Ok(())
65}More examples
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}Sourcepub async fn import(
&self,
address: String,
private_key_hex: &str,
chain_type: WalletImportSupportedChains,
owner: Option<WalletImportSubmissionRequestOwner>,
policy_ids: Vec<String>,
additional_signers: Vec<WalletImportSubmissionRequestAdditionalSignersItem>,
) -> Result<ResponseValue<Wallet>, PrivyApiError>
pub async fn import( &self, address: String, private_key_hex: &str, chain_type: WalletImportSupportedChains, owner: Option<WalletImportSubmissionRequestOwner>, policy_ids: Vec<String>, additional_signers: Vec<WalletImportSubmissionRequestAdditionalSignersItem>, ) -> Result<ResponseValue<Wallet>, PrivyApiError>
Import a wallet into the Privy app
§Errors
Sourcepub fn ethereum(&self) -> EthereumService
pub fn ethereum(&self) -> EthereumService
Returns an EthereumService instance for interacting with the Ethereum API
Sourcepub fn solana(&self) -> SolanaService
pub fn solana(&self) -> SolanaService
Returns an SolanaService instance for interacting with the Solana API
Source§impl WalletsClient
impl WalletsClient
Sourcepub fn new(client: Client, app_id: String, base_url: String) -> Self
pub fn new(client: Client, app_id: String, base_url: String) -> Self
Create a new client instance
Sourcepub async fn list<'a>(
&'a self,
chain_type: Option<GetWalletsChainType>,
cursor: Option<&'a GetWalletsCursor>,
limit: Option<f64>,
user_id: Option<&'a str>,
) -> Result<ResponseValue<GetWalletsResponse>, Error<()>>
pub async fn list<'a>( &'a self, chain_type: Option<GetWalletsChainType>, cursor: Option<&'a GetWalletsCursor>, limit: Option<f64>, user_id: Option<&'a str>, ) -> Result<ResponseValue<GetWalletsResponse>, Error<()>>
Get all wallets
Get all wallets in your app.
Sends a GET request to /v1/wallets
Examples found in repository?
25async fn main() -> Result<()> {
26 tracing_subscriber::fmt()
27 .with_env_filter(
28 EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info")),
29 )
30 .init();
31
32 // Get additional environment variables and initialize client
33 let wallet_id =
34 std::env::var("PRIVY_WALLET_ID").expect("PRIVY_WALLET_ID environment variable not set");
35 let public_key =
36 std::env::var("PRIVY_PUBLIC_KEY").expect("PRIVY_PUBLIC_KEY environment variable not set");
37 let client = PrivyClient::new_from_env()?;
38
39 tracing::info!(
40 "initialized privy client from environment, wallet_id: {}, public_key: {}",
41 wallet_id,
42 public_key
43 );
44
45 let wallets = client.wallets().list(None, None, Some(5.0), None).await?;
46
47 tracing::info!("got wallets: {:?}", wallets);
48
49 Ok(())
50}Sourcepub async fn create<'a>(
&'a self,
privy_idempotency_key: Option<&'a str>,
body: &'a CreateWalletBody,
) -> Result<ResponseValue<Wallet>, Error<()>>
pub async fn create<'a>( &'a self, privy_idempotency_key: Option<&'a str>, body: &'a CreateWalletBody, ) -> Result<ResponseValue<Wallet>, Error<()>>
Create wallet
Create a new wallet.
Sends a POST request to /v1/wallets
Examples found in repository?
27async fn main() -> Result<()> {
28 tracing_subscriber::fmt()
29 .with_env_filter(
30 EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info")),
31 )
32 .init();
33
34 // Initialize client from environment variables
35 let client = PrivyClient::new_from_env()?;
36
37 tracing::info!("initialized privy client from environment");
38
39 let wallet = client
40 .wallets()
41 .create(
42 None,
43 &CreateWalletBody {
44 chain_type: WalletChainType::Solana,
45 additional_signers: None,
46 owner: None,
47 owner_id: None,
48 policy_ids: vec![],
49 },
50 )
51 .await?;
52
53 tracing::info!("got new wallet: {:?}", wallet);
54
55 Ok(())
56}More examples
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}Sourcepub async fn get<'a>(
&'a self,
wallet_id: &'a str,
) -> Result<ResponseValue<Wallet>, Error<()>>
pub async fn get<'a>( &'a self, wallet_id: &'a str, ) -> Result<ResponseValue<Wallet>, Error<()>>
Get wallet
Get a wallet by wallet ID.
Sends a GET request to /v1/wallets/{wallet_id}
Examples found in repository?
24async fn main() -> Result<()> {
25 tracing_subscriber::fmt()
26 .with_env_filter(
27 EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info")),
28 )
29 .init();
30
31 // Get wallet ID from environment and initialize client
32 let wallet_id =
33 std::env::var("PRIVY_WALLET_ID").expect("PRIVY_WALLET_ID environment variable not set");
34 let client = PrivyClient::new_from_env()?;
35
36 tracing::info!(
37 "initialized privy client from environment, wallet_id: {}",
38 wallet_id
39 );
40
41 let wallet = client.wallets().get(&wallet_id).await?;
42
43 tracing::info!("got wallet: {:?}", wallet);
44
45 Ok(())
46}More examples
29async fn main() -> Result<()> {
30 tracing_subscriber::fmt()
31 .with_env_filter(
32 EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info")),
33 )
34 .init();
35
36 // Get wallet ID from environment
37 let wallet_id =
38 std::env::var("PRIVY_WALLET_ID").expect("PRIVY_WALLET_ID environment variable not set");
39
40 tracing::info!(
41 "initializing privy client from environment, wallet_id: {}",
42 wallet_id
43 );
44
45 let file = std::fs::read_to_string("private_key.pem")?;
46
47 let key = PrivateKey(file);
48 let public_key = key.get_key().await?.public_key();
49
50 let client = PrivyClient::new_from_env()?;
51
52 let ctx = AuthorizationContext::new()
53 .push(key)
54 .push(JwtUser(client.clone(), "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhbGV4QGFybHlvbi5kZXYiLCJpYXQiOjEwMDAwMDAwMDAwMH0.IpNgavH95CFZPjkzQW4eyxMIfJ-O_5cIaDyu_6KRXffykjYDRwxTgFJuYq0F6d8wSXf4de-vzfBRWSKMISM3rJdlhximYINGJB14mJFCD87VMLFbTpHIXcv7hc1AAYMPGhOsRkYfYXuvVopKszMvhupmQYJ1npSvKWNeBniIyOHYv4xebZD8L0RVlPvuEKTXTu-CDfs2rMwvD9g_wiBznS3uMF3v_KPaY6x0sx9zeCSxAH9zvhMMtct_Ad9kuoUncGpRzNhEk6JlVccN2Leb1JzbldxSywyS2AApD05u-GFAgFDN3P39V3qgRTGDuuUfUvKQ9S4rbu5El9Qq1CJTeA".to_string()));
55
56 let wallets_client = client.wallets();
57 let wallet = wallets_client.get(&wallet_id).await?;
58
59 tracing::info!("got wallet: {:?}", wallet);
60
61 let wallet = match wallets_client
62 .update(
63 &wallet_id,
64 &ctx,
65 &UpdateWalletBody {
66 owner: Some(OwnerInput::PublicKey(public_key.to_string())),
67 ..Default::default()
68 },
69 )
70 .await
71 {
72 Ok(wallet) => wallet,
73 Err(PrivySignedApiError::Api(PrivyApiError::UnexpectedResponse(r))) => {
74 let text = r.text().await.unwrap_or_default();
75 tracing::warn!("unexpected response: {:?}", text);
76 anyhow::bail!("unexpected response")
77 }
78 Err(e) => {
79 anyhow::bail!("unexpected error: {e:?}")
80 }
81 };
82
83 tracing::info!("got updated wallet: {:?}", wallet);
84
85 Ok(())
86}Sourcepub async fn authenticate_with_jwt<'a>(
&'a self,
body: &'a AuthenticateBody,
) -> Result<ResponseValue<AuthenticateResponse>, Error<()>>
pub async fn authenticate_with_jwt<'a>( &'a self, body: &'a AuthenticateBody, ) -> Result<ResponseValue<AuthenticateResponse>, Error<()>>
Obtain a session key to enable wallet access
Obtain a session key to enable wallet access.
Sends a POST request to /v1/wallets/authenticate
Examples found in repository?
25async fn main() -> Result<()> {
26 tracing_subscriber::fmt()
27 .with_env_filter(
28 EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info")),
29 )
30 .init();
31
32 // Get JWT from environment and initialize client
33 let user_jwt =
34 std::env::var("PRIVY_USER_JWT").expect("PRIVY_USER_JWT environment variable not set");
35 let client = PrivyClient::new_from_env()?;
36
37 tracing::info!("initialized privy client from environment");
38
39 let jwt_auth = client
40 .wallets()
41 .authenticate_with_jwt(&AuthenticateBody {
42 user_jwt,
43 encryption_type: None,
44 recipient_public_key: None,
45 })
46 .await?;
47
48 tracing::info!("got jwt auth: {:?}", jwt_auth);
49
50 Ok(())
51}Sourcepub async fn _rpc<'a>(
&'a self,
wallet_id: &'a str,
privy_authorization_signature: Option<&'a str>,
privy_idempotency_key: Option<&'a str>,
body: &'a WalletRpcBody,
) -> Result<ResponseValue<WalletRpcResponse>, Error<()>>
pub async fn _rpc<'a>( &'a self, wallet_id: &'a str, privy_authorization_signature: Option<&'a str>, privy_idempotency_key: Option<&'a str>, body: &'a WalletRpcBody, ) -> Result<ResponseValue<WalletRpcResponse>, Error<()>>
Create a signature or transaction
Sign a message or transaction with a wallet by wallet ID.
Sends a POST request to /v1/wallets/{wallet_id}/rpc
Sourcepub async fn _raw_sign<'a>(
&'a self,
wallet_id: &'a str,
privy_authorization_signature: Option<&'a str>,
privy_idempotency_key: Option<&'a str>,
body: &'a RawSign,
) -> Result<ResponseValue<RawSignResponse>, Error<()>>
pub async fn _raw_sign<'a>( &'a self, wallet_id: &'a str, privy_authorization_signature: Option<&'a str>, privy_idempotency_key: Option<&'a str>, body: &'a RawSign, ) -> Result<ResponseValue<RawSignResponse>, Error<()>>
Raw sign
Sign a message with a wallet by wallet ID.
Sends a POST request to /v1/wallets/{wallet_id}/raw_sign
Sourcepub async fn _update<'a>(
&'a self,
wallet_id: &'a str,
privy_authorization_signature: Option<&'a str>,
body: &'a UpdateWalletBody,
) -> Result<ResponseValue<Wallet>, Error<()>>
pub async fn _update<'a>( &'a self, wallet_id: &'a str, privy_authorization_signature: Option<&'a str>, body: &'a UpdateWalletBody, ) -> Result<ResponseValue<Wallet>, Error<()>>
Update wallet
Update a wallet’s policies or authorization key configuration.
Sends a PATCH request to /v1/wallets/{wallet_id}
Sourcepub async fn _export<'a>(
&'a self,
wallet_id: &'a str,
privy_authorization_signature: Option<&'a str>,
body: &'a WalletExportRequestBody,
) -> Result<ResponseValue<WalletExportResponseBody>, Error<()>>
pub async fn _export<'a>( &'a self, wallet_id: &'a str, privy_authorization_signature: Option<&'a str>, body: &'a WalletExportRequestBody, ) -> Result<ResponseValue<WalletExportResponseBody>, Error<()>>
Export wallet
Export a wallet’s private key
Sends a POST request to /v1/wallets/{wallet_id}/export
Sourcepub async fn _init_import<'a>(
&'a self,
body: &'a WalletImportInitializationRequest,
) -> Result<ResponseValue<WalletImportInitializationResponse>, Error<()>>
pub async fn _init_import<'a>( &'a self, body: &'a WalletImportInitializationRequest, ) -> Result<ResponseValue<WalletImportInitializationResponse>, Error<()>>
Initialize import
Initialize a wallet import. Complete by submitting the import.
Sends a POST request to /v1/wallets/import/init
Sourcepub async fn _submit_import<'a>(
&'a self,
body: &'a WalletImportSubmissionRequest,
) -> Result<ResponseValue<Wallet>, Error<()>>
pub async fn _submit_import<'a>( &'a self, body: &'a WalletImportSubmissionRequest, ) -> Result<ResponseValue<Wallet>, Error<()>>
Submit import
Submit a wallet import request.
Sends a POST request to /v1/wallets/import/submit
Sourcepub fn transactions(&self) -> WalletsTransactionsClient
pub fn transactions(&self) -> WalletsTransactionsClient
Access the transactions subclient
Examples found in repository?
29async fn main() -> Result<()> {
30 tracing_subscriber::fmt()
31 .with_env_filter(
32 EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info")),
33 )
34 .init();
35
36 // Get wallet ID from environment and initialize client
37 let wallet_id =
38 std::env::var("PRIVY_WALLET_ID").expect("PRIVY_WALLET_ID environment variable not set");
39 let client = PrivyClient::new_from_env()?;
40
41 tracing::info!(
42 "initialized privy client from environment, wallet_id: {}",
43 wallet_id
44 );
45
46 // Get SOL transactions on Solana mainnet
47 let transactions = client
48 .wallets()
49 .transactions()
50 .get(
51 &wallet_id,
52 &WalletTransactionsAsset::String(WalletTransactionsAssetString::Sol),
53 WalletTransactionsChain::Base,
54 None, // No cursor for first page
55 Some(10.0), // Limit to 10 transactions,
56 None,
57 )
58 .await?;
59
60 tracing::info!("got wallet transactions: {:?}", transactions);
61
62 Ok(())
63}Sourcepub fn balance(&self) -> WalletsBalanceClient
pub fn balance(&self) -> WalletsBalanceClient
Access the balance subclient
Examples found in repository?
30async fn main() -> Result<()> {
31 tracing_subscriber::fmt()
32 .with_env_filter(
33 EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info")),
34 )
35 .init();
36
37 // Get wallet ID from environment and initialize client
38 let wallet_id =
39 std::env::var("PRIVY_WALLET_ID").expect("PRIVY_WALLET_ID environment variable not set");
40 let client = PrivyClient::new_from_env()?;
41
42 tracing::info!(
43 "initialized privy client from environment, wallet_id: {}",
44 wallet_id
45 );
46
47 // Get SOL balance on Solana
48 let balance = client
49 .wallets()
50 .balance()
51 .get(
52 &wallet_id,
53 &GetWalletBalanceAsset::String(GetWalletBalanceAssetString::Sol),
54 &GetWalletBalanceChain::String(GetWalletBalanceChainString::Solana),
55 Some(GetWalletBalanceIncludeCurrency::Usd),
56 )
57 .await?;
58
59 tracing::info!("got wallet balance: {:?}", balance);
60
61 Ok(())
62}Trait Implementations§
Source§impl Clone for WalletsClient
impl Clone for WalletsClient
Source§fn clone(&self) -> WalletsClient
fn clone(&self) -> WalletsClient
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more