pub struct SupabaseWalletDatabase { /* private fields */ }Expand description
Supabase wallet database implementation
This database uses two types of authentication:
api_key: The Supabase project API key (required, used inapikeyheader)jwt_token: An optional JWT token for user authentication (used inAuthorization: Bearerheader)
When jwt_token is set, requests will include both headers:
apikey: <api_key>Authorization: Bearer <jwt_token>
When jwt_token is not set, the api_key is used for both headers (legacy behavior).
§Authentication Providers
The database supports multiple authentication providers via AuthProvider:
- None: No automatic token refresh, use API key only
- SupabaseAuth: Uses Supabase’s GoTrue API for token refresh
- Oidc: Uses an external OIDC provider for token refresh
Implementations§
Source§impl SupabaseWalletDatabase
impl SupabaseWalletDatabase
Sourcepub const REQUIRED_SCHEMA_VERSION: u32 = 7
pub const REQUIRED_SCHEMA_VERSION: u32 = 7
The schema version required by this SDK version.
This must match the latest schema_version value set in the migration files.
When adding new migrations, update this constant and set the same value
in the new migration’s INSERT INTO schema_info statement.
Sourcepub async fn new(url: Url, api_key: String) -> Result<Self, Error>
pub async fn new(url: Url, api_key: String) -> Result<Self, Error>
Create a new SupabaseWalletDatabase with API key only (legacy behavior)
No automatic token refresh is configured.
Note: This does NOT run or check migrations automatically. After
authentication, call [check_schema_compatibility()] to verify the
database schema is ready. Migrations must be run separately by an
administrator — see [get_schema_sql()] or use supabase db push.
Sourcepub async fn with_supabase_auth(
url: Url,
api_key: String,
) -> Result<Self, Error>
pub async fn with_supabase_auth( url: Url, api_key: String, ) -> Result<Self, Error>
Create a new SupabaseWalletDatabase with Supabase Auth for token refresh
This uses Supabase’s built-in GoTrue authentication system.
Token refresh uses POST /auth/v1/token with grant_type=refresh_token.
Note: This does NOT run or check migrations automatically. After
authentication, call [check_schema_compatibility()] to verify the
database schema is ready. Migrations must be run separately by an
administrator — see [get_schema_sql()] or use supabase db push.
Sourcepub async fn with_oidc(
url: Url,
api_key: String,
oidc_client: OidcClient,
) -> Result<Self, Error>
pub async fn with_oidc( url: Url, api_key: String, oidc_client: OidcClient, ) -> Result<Self, Error>
Create a new SupabaseWalletDatabase with external OIDC client for auth
This uses an external OIDC provider (e.g., Keycloak, Auth0) for token refresh. The OIDC provider must be configured in Supabase to validate the JWTs.
Note: This does NOT run or check migrations automatically. After
authentication, call [check_schema_compatibility()] to verify the
database schema is ready. Migrations must be run separately by an
administrator — see [get_schema_sql()] or use supabase db push.
Sourcepub fn get_schema_sql() -> String
pub fn get_schema_sql() -> String
Get the full database schema SQL
Returns the concatenated SQL of all migration files.
Use this to set up or update the database schema by running the output
through the Supabase Dashboard SQL editor or supabase db push.
This is an admin-only operation — never run this from a client app.
Sourcepub async fn check_schema_compatibility(&self) -> Result<(), Error>
pub async fn check_schema_compatibility(&self) -> Result<(), Error>
Check that the database schema is compatible with this SDK version
This is the recommended client-side startup check. It queries the
schema_info table (which is readable by all authenticated users) to
verify the database has the required schema version.
§Errors
Error::SchemaNotInitializedif theschema_infotable doesn’t exist (database was never set up or is running a pre-v4 schema).Error::SchemaMismatchif the database schema version is older than what this SDK version requires.
§Example
// Call after authentication, before using the database
db.check_schema_compatibility().await?;
// Database is ready for useSourcepub async fn set_jwt_token(&self, token: Option<String>)
pub async fn set_jwt_token(&self, token: Option<String>)
Set or update the JWT token for authentication
Sourcepub async fn set_refresh_token(&self, token: Option<String>)
pub async fn set_refresh_token(&self, token: Option<String>)
Set refresh token
Sourcepub async fn set_encryption_password(&self, password: &str) -> Result<(), Error>
pub async fn set_encryption_password(&self, password: &str) -> Result<(), Error>
Derives an AES-256-GCM encryption key from password via scrypt.
Sourcepub async fn refresh_access_token(&self) -> Result<(), Error>
pub async fn refresh_access_token(&self) -> Result<(), Error>
Refresh the access token using the stored refresh token
This method handles different authentication providers:
- SupabaseAuth: Uses
POST /auth/v1/tokenwithgrant_type=refresh_token - Oidc: Uses the OIDC provider’s token endpoint
- None: Returns an error (no provider configured)
Sourcepub async fn signup(
&self,
email: &str,
password: &str,
) -> Result<SupabaseAuthResponse, Error>
pub async fn signup( &self, email: &str, password: &str, ) -> Result<SupabaseAuthResponse, Error>
Sign up a new user and automatically set tokens if returned
Sourcepub async fn signin(
&self,
email: &str,
password: &str,
) -> Result<SupabaseAuthResponse, Error>
pub async fn signin( &self, email: &str, password: &str, ) -> Result<SupabaseAuthResponse, Error>
Sign in a user and automatically set tokens on the database instance
Sourcepub async fn get_jwt_token(&self) -> Option<String>
pub async fn get_jwt_token(&self) -> Option<String>
Get the current JWT token if set
Trait Implementations§
Source§impl Clone for SupabaseWalletDatabase
impl Clone for SupabaseWalletDatabase
Source§fn clone(&self) -> SupabaseWalletDatabase
fn clone(&self) -> SupabaseWalletDatabase
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Database<Error> for SupabaseWalletDatabase
impl Database<Error> for SupabaseWalletDatabase
Source§fn get_mint<'life0, 'async_trait>(
&'life0 self,
mint_url: MintUrl,
) -> Pin<Box<dyn Future<Output = Result<Option<MintInfo>, DatabaseError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn get_mint<'life0, 'async_trait>(
&'life0 self,
mint_url: MintUrl,
) -> Pin<Box<dyn Future<Output = Result<Option<MintInfo>, DatabaseError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Source§fn get_mints<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<HashMap<MintUrl, Option<MintInfo>>, DatabaseError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn get_mints<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<HashMap<MintUrl, Option<MintInfo>>, DatabaseError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Source§fn get_mint_keysets<'life0, 'async_trait>(
&'life0 self,
mint_url: MintUrl,
) -> Pin<Box<dyn Future<Output = Result<Option<Vec<KeySetInfo>>, DatabaseError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn get_mint_keysets<'life0, 'async_trait>(
&'life0 self,
mint_url: MintUrl,
) -> Pin<Box<dyn Future<Output = Result<Option<Vec<KeySetInfo>>, DatabaseError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Source§fn get_keyset_by_id<'life0, 'life1, 'async_trait>(
&'life0 self,
keyset_id: &'life1 Id,
) -> Pin<Box<dyn Future<Output = Result<Option<KeySetInfo>, DatabaseError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn get_keyset_by_id<'life0, 'life1, 'async_trait>(
&'life0 self,
keyset_id: &'life1 Id,
) -> Pin<Box<dyn Future<Output = Result<Option<KeySetInfo>, DatabaseError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Source§fn get_mint_quote<'life0, 'life1, 'async_trait>(
&'life0 self,
quote_id: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Option<MintQuote>, DatabaseError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn get_mint_quote<'life0, 'life1, 'async_trait>(
&'life0 self,
quote_id: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Option<MintQuote>, DatabaseError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Source§fn get_mint_quotes<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<Vec<MintQuote>, DatabaseError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn get_mint_quotes<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<Vec<MintQuote>, DatabaseError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Source§fn get_unissued_mint_quotes<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<Vec<MintQuote>, DatabaseError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn get_unissued_mint_quotes<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<Vec<MintQuote>, DatabaseError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Source§fn get_melt_quote<'life0, 'life1, 'async_trait>(
&'life0 self,
quote_id: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Option<MeltQuote>, DatabaseError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn get_melt_quote<'life0, 'life1, 'async_trait>(
&'life0 self,
quote_id: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Option<MeltQuote>, DatabaseError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Source§fn get_melt_quotes<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<Vec<MeltQuote>, DatabaseError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn get_melt_quotes<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<Vec<MeltQuote>, DatabaseError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Source§fn get_keys<'life0, 'life1, 'async_trait>(
&'life0 self,
id: &'life1 Id,
) -> Pin<Box<dyn Future<Output = Result<Option<Keys>, DatabaseError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn get_keys<'life0, 'life1, 'async_trait>(
&'life0 self,
id: &'life1 Id,
) -> Pin<Box<dyn Future<Output = Result<Option<Keys>, DatabaseError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Keys from storageSource§fn get_proofs<'life0, 'async_trait>(
&'life0 self,
mint_url: Option<MintUrl>,
unit: Option<CurrencyUnit>,
state: Option<Vec<State>>,
spending_conditions: Option<Vec<SpendingConditions>>,
) -> Pin<Box<dyn Future<Output = Result<Vec<ProofInfo>, DatabaseError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn get_proofs<'life0, 'async_trait>(
&'life0 self,
mint_url: Option<MintUrl>,
unit: Option<CurrencyUnit>,
state: Option<Vec<State>>,
spending_conditions: Option<Vec<SpendingConditions>>,
) -> Pin<Box<dyn Future<Output = Result<Vec<ProofInfo>, DatabaseError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Source§fn get_proofs_by_ys<'life0, 'async_trait>(
&'life0 self,
ys: Vec<PublicKey>,
) -> Pin<Box<dyn Future<Output = Result<Vec<ProofInfo>, DatabaseError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn get_proofs_by_ys<'life0, 'async_trait>(
&'life0 self,
ys: Vec<PublicKey>,
) -> Pin<Box<dyn Future<Output = Result<Vec<ProofInfo>, DatabaseError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Source§fn get_balance<'life0, 'async_trait>(
&'life0 self,
mint_url: Option<MintUrl>,
unit: Option<CurrencyUnit>,
state: Option<Vec<State>>,
) -> Pin<Box<dyn Future<Output = Result<u64, DatabaseError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn get_balance<'life0, 'async_trait>(
&'life0 self,
mint_url: Option<MintUrl>,
unit: Option<CurrencyUnit>,
state: Option<Vec<State>>,
) -> Pin<Box<dyn Future<Output = Result<u64, DatabaseError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Source§fn get_transaction<'life0, 'async_trait>(
&'life0 self,
transaction_id: TransactionId,
) -> Pin<Box<dyn Future<Output = Result<Option<Transaction>, DatabaseError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn get_transaction<'life0, 'async_trait>(
&'life0 self,
transaction_id: TransactionId,
) -> Pin<Box<dyn Future<Output = Result<Option<Transaction>, DatabaseError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Source§fn list_transactions<'life0, 'async_trait>(
&'life0 self,
mint_url: Option<MintUrl>,
direction: Option<TransactionDirection>,
unit: Option<CurrencyUnit>,
) -> Pin<Box<dyn Future<Output = Result<Vec<Transaction>, DatabaseError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn list_transactions<'life0, 'async_trait>(
&'life0 self,
mint_url: Option<MintUrl>,
direction: Option<TransactionDirection>,
unit: Option<CurrencyUnit>,
) -> Pin<Box<dyn Future<Output = Result<Vec<Transaction>, DatabaseError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Source§fn update_proofs<'life0, 'async_trait>(
&'life0 self,
added: Vec<ProofInfo>,
removed_ys: Vec<PublicKey>,
) -> Pin<Box<dyn Future<Output = Result<(), DatabaseError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn update_proofs<'life0, 'async_trait>(
&'life0 self,
added: Vec<ProofInfo>,
removed_ys: Vec<PublicKey>,
) -> Pin<Box<dyn Future<Output = Result<(), DatabaseError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Source§fn update_proofs_state<'life0, 'async_trait>(
&'life0 self,
ys: Vec<PublicKey>,
state: State,
) -> Pin<Box<dyn Future<Output = Result<(), DatabaseError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn update_proofs_state<'life0, 'async_trait>(
&'life0 self,
ys: Vec<PublicKey>,
state: State,
) -> Pin<Box<dyn Future<Output = Result<(), DatabaseError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Source§fn add_transaction<'life0, 'async_trait>(
&'life0 self,
transaction: Transaction,
) -> Pin<Box<dyn Future<Output = Result<(), DatabaseError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn add_transaction<'life0, 'async_trait>(
&'life0 self,
transaction: Transaction,
) -> Pin<Box<dyn Future<Output = Result<(), DatabaseError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Source§fn remove_transaction<'life0, 'async_trait>(
&'life0 self,
transaction_id: TransactionId,
) -> Pin<Box<dyn Future<Output = Result<(), DatabaseError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn remove_transaction<'life0, 'async_trait>(
&'life0 self,
transaction_id: TransactionId,
) -> Pin<Box<dyn Future<Output = Result<(), DatabaseError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Source§fn update_mint_url<'life0, 'async_trait>(
&'life0 self,
old_mint_url: MintUrl,
new_mint_url: MintUrl,
) -> Pin<Box<dyn Future<Output = Result<(), DatabaseError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn update_mint_url<'life0, 'async_trait>(
&'life0 self,
old_mint_url: MintUrl,
new_mint_url: MintUrl,
) -> Pin<Box<dyn Future<Output = Result<(), DatabaseError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Source§fn increment_keyset_counter<'life0, 'life1, 'async_trait>(
&'life0 self,
keyset_id: &'life1 Id,
count: u32,
) -> Pin<Box<dyn Future<Output = Result<u32, DatabaseError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn increment_keyset_counter<'life0, 'life1, 'async_trait>(
&'life0 self,
keyset_id: &'life1 Id,
count: u32,
) -> Pin<Box<dyn Future<Output = Result<u32, DatabaseError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Source§fn add_mint<'life0, 'async_trait>(
&'life0 self,
mint_url: MintUrl,
mint_info: Option<MintInfo>,
) -> Pin<Box<dyn Future<Output = Result<(), DatabaseError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn add_mint<'life0, 'async_trait>(
&'life0 self,
mint_url: MintUrl,
mint_info: Option<MintInfo>,
) -> Pin<Box<dyn Future<Output = Result<(), DatabaseError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Source§fn remove_mint<'life0, 'async_trait>(
&'life0 self,
mint_url: MintUrl,
) -> Pin<Box<dyn Future<Output = Result<(), DatabaseError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn remove_mint<'life0, 'async_trait>(
&'life0 self,
mint_url: MintUrl,
) -> Pin<Box<dyn Future<Output = Result<(), DatabaseError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Source§fn add_mint_keysets<'life0, 'async_trait>(
&'life0 self,
mint_url: MintUrl,
keysets: Vec<KeySetInfo>,
) -> Pin<Box<dyn Future<Output = Result<(), DatabaseError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn add_mint_keysets<'life0, 'async_trait>(
&'life0 self,
mint_url: MintUrl,
keysets: Vec<KeySetInfo>,
) -> Pin<Box<dyn Future<Output = Result<(), DatabaseError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Source§fn add_mint_quote<'life0, 'async_trait>(
&'life0 self,
quote: MintQuote,
) -> Pin<Box<dyn Future<Output = Result<(), DatabaseError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn add_mint_quote<'life0, 'async_trait>(
&'life0 self,
quote: MintQuote,
) -> Pin<Box<dyn Future<Output = Result<(), DatabaseError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Source§fn remove_mint_quote<'life0, 'life1, 'async_trait>(
&'life0 self,
quote_id: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<(), DatabaseError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn remove_mint_quote<'life0, 'life1, 'async_trait>(
&'life0 self,
quote_id: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<(), DatabaseError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Source§fn add_melt_quote<'life0, 'async_trait>(
&'life0 self,
quote: MeltQuote,
) -> Pin<Box<dyn Future<Output = Result<(), DatabaseError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn add_melt_quote<'life0, 'async_trait>(
&'life0 self,
quote: MeltQuote,
) -> Pin<Box<dyn Future<Output = Result<(), DatabaseError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Source§fn remove_melt_quote<'life0, 'life1, 'async_trait>(
&'life0 self,
quote_id: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<(), DatabaseError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn remove_melt_quote<'life0, 'life1, 'async_trait>(
&'life0 self,
quote_id: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<(), DatabaseError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Source§fn add_keys<'life0, 'async_trait>(
&'life0 self,
keyset: KeySet,
) -> Pin<Box<dyn Future<Output = Result<(), DatabaseError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn add_keys<'life0, 'async_trait>(
&'life0 self,
keyset: KeySet,
) -> Pin<Box<dyn Future<Output = Result<(), DatabaseError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Keys to storageSource§fn remove_keys<'life0, 'life1, 'async_trait>(
&'life0 self,
id: &'life1 Id,
) -> Pin<Box<dyn Future<Output = Result<(), DatabaseError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn remove_keys<'life0, 'life1, 'async_trait>(
&'life0 self,
id: &'life1 Id,
) -> Pin<Box<dyn Future<Output = Result<(), DatabaseError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Keys from storage