use std::sync::Arc;
use cdk_common::auth::oidc::OidcClient;
use cdk_common::database::Error as CdkDatabaseError;
use cdk_supabase::SupabaseWalletDatabase;
use crate::{
CurrencyUnit, FfiError, FfiWalletDatabaseWrapper, Id, KeySet, KeySetInfo, Keys, MeltQuote,
MintInfo, MintQuote, MintUrl, P2PKSigningKey, ProofInfo, ProofState, PublicKey,
SpendingConditions, Transaction, TransactionDirection, TransactionId, WalletDatabase,
};
#[derive(uniffi::Object)]
pub struct WalletSupabaseDatabase {
inner: Arc<FfiWalletDatabaseWrapper<SupabaseWalletDatabase, CdkDatabaseError>>,
}
#[uniffi::export(async_runtime = "tokio")]
impl WalletSupabaseDatabase {
#[uniffi::constructor]
pub async fn new(url: String, api_key: String) -> Result<Arc<Self>, FfiError> {
let url = url::Url::parse(&url).map_err(|e| FfiError::Internal {
error_message: e.to_string(),
})?;
let db = SupabaseWalletDatabase::new(url, api_key)
.await
.map_err(|e| FfiError::Internal {
error_message: e.to_string(),
})?;
Ok(Arc::new(WalletSupabaseDatabase {
inner: FfiWalletDatabaseWrapper::new(db),
}))
}
#[uniffi::constructor]
pub async fn with_supabase_auth(url: String, api_key: String) -> Result<Arc<Self>, FfiError> {
let url = url::Url::parse(&url).map_err(|e| FfiError::Internal {
error_message: e.to_string(),
})?;
let db = SupabaseWalletDatabase::with_supabase_auth(url, api_key)
.await
.map_err(|e| FfiError::Internal {
error_message: e.to_string(),
})?;
Ok(Arc::new(WalletSupabaseDatabase {
inner: FfiWalletDatabaseWrapper::new(db),
}))
}
#[uniffi::constructor]
pub async fn with_oidc(
url: String,
api_key: String,
openid_discovery: String,
client_id: Option<String>,
) -> Result<Arc<Self>, FfiError> {
let url = url::Url::parse(&url).map_err(|e| FfiError::Internal {
error_message: e.to_string(),
})?;
let oidc_client = OidcClient::new(openid_discovery, client_id);
let db = SupabaseWalletDatabase::with_oidc(url, api_key, oidc_client)
.await
.map_err(|e| FfiError::Internal {
error_message: e.to_string(),
})?;
Ok(Arc::new(WalletSupabaseDatabase {
inner: FfiWalletDatabaseWrapper::new(db),
}))
}
pub async fn set_jwt_token(&self, token: Option<String>) {
self.inner.inner().set_jwt_token(token).await;
}
pub async fn get_jwt_token(&self) -> Option<String> {
self.inner.inner().get_jwt_token().await
}
pub async fn set_refresh_token(&self, token: Option<String>) {
self.inner.inner().set_refresh_token(token).await;
}
pub async fn set_encryption_password(&self, password: String) -> Result<(), FfiError> {
self.inner
.inner()
.set_encryption_password(&password)
.await
.map_err(|e| FfiError::Internal {
error_message: e.to_string(),
})
}
pub async fn check_schema_compatibility(&self) -> Result<(), FfiError> {
self.inner
.inner()
.check_schema_compatibility()
.await
.map_err(|e| FfiError::Internal {
error_message: e.to_string(),
})
}
pub async fn refresh_access_token(&self) -> Result<(), FfiError> {
self.inner
.inner()
.refresh_access_token()
.await
.map_err(|e| FfiError::Internal {
error_message: e.to_string(),
})
}
pub async fn call_rpc(
&self,
function_name: String,
params_json: String,
) -> Result<String, FfiError> {
self.inner
.inner()
.call_rpc(&function_name, ¶ms_json)
.await
.map_err(|e| FfiError::Internal {
error_message: e.to_string(),
})
}
pub async fn signup(&self, email: String, password: String) -> Result<AuthResponse, FfiError> {
let response = self
.inner
.inner()
.signup(&email, &password)
.await
.map_err(|e| FfiError::Internal {
error_message: e.to_string(),
})?;
Ok(response.into())
}
pub async fn signin(&self, email: String, password: String) -> Result<AuthResponse, FfiError> {
let response = self
.inner
.inner()
.signin(&email, &password)
.await
.map_err(|e| FfiError::Internal {
error_message: e.to_string(),
})?;
Ok(response.into())
}
}
crate::impl_ffi_wallet_database!(WalletSupabaseDatabase);
#[derive(Debug, uniffi::Record)]
pub struct AuthResponse {
pub access_token: String,
pub token_type: String,
pub expires_in: Option<i64>,
pub refresh_token: Option<String>,
pub user_json: String,
}
impl From<cdk_supabase::SupabaseAuthResponse> for AuthResponse {
fn from(r: cdk_supabase::SupabaseAuthResponse) -> Self {
Self {
access_token: r.access_token,
token_type: r.token_type,
expires_in: r.expires_in,
refresh_token: r.refresh_token,
user_json: r.user.to_string(),
}
}
}
#[uniffi::export(async_runtime = "tokio")]
pub async fn supabase_signup(
url: String,
api_key: String,
email: String,
password: String,
) -> Result<AuthResponse, FfiError> {
let url = url::Url::parse(&url).map_err(|e| FfiError::Internal {
error_message: e.to_string(),
})?;
let response = cdk_supabase::SupabaseAuth::signup(&url, &api_key, &email, &password)
.await
.map_err(|e| FfiError::Internal {
error_message: e.to_string(),
})?;
Ok(response.into())
}
#[uniffi::export(async_runtime = "tokio")]
pub async fn supabase_signin(
url: String,
api_key: String,
email: String,
password: String,
) -> Result<AuthResponse, FfiError> {
let url = url::Url::parse(&url).map_err(|e| FfiError::Internal {
error_message: e.to_string(),
})?;
let response = cdk_supabase::SupabaseAuth::signin(&url, &api_key, &email, &password)
.await
.map_err(|e| FfiError::Internal {
error_message: e.to_string(),
})?;
Ok(response.into())
}
#[uniffi::export]
pub fn supabase_get_schema_sql() -> String {
SupabaseWalletDatabase::get_schema_sql()
}
#[uniffi::export]
pub fn supabase_required_schema_version() -> u32 {
SupabaseWalletDatabase::REQUIRED_SCHEMA_VERSION
}