Skip to content

feat: adding supabase db#1540

Draft
asmogo wants to merge 43 commits intocashubtc:mainfrom
asmogo:feat/wallet-supabase
Draft

feat: adding supabase db#1540
asmogo wants to merge 43 commits intocashubtc:mainfrom
asmogo:feat/wallet-supabase

Conversation

@asmogo
Copy link
Collaborator

@asmogo asmogo commented Jan 19, 2026

Description

Introducing supabase db to the cdk wallet.

  • added supabase crate
  • moved oicd client to common crate
  • auto refresh jwt token in the supabase crate
  • exported constructor, wrapper and helper functions (set_jwt_token, set_refresh_token and set_token_expiration)

Todo:

  • move migrations to common package + auto migrate
  • add call_rpc function to invoke custom db rpc
  • cleanup
  • remove SetTokenExpiration (set exp internally based on access token)
  • replace extra fields from other applications (dead_code) using serde(flatten) ?.
  • test with supabase provided authentication
  • make use of the ffi database macro crate::impl_ffi_wallet_database!

This example reuses the keycloak token for auth wallet and supabase.

My supabase is configured to use the jwt token from keycloak for user authentication and RBAC (golang):

// ProvideWallet creates the CDK FFI wallet instance with CAT token authentication
func ProvideWallet(params WalletParams) (WalletResult, error) {
	cfg := params.Config
	log := logger.WithComponent("wallet_provider")
	cdk_ffi.InitLogging("debug")

	ctx := context.Background()

	catToken, err := params.KeycloakClient.Login(ctx, cfg.Wallet.Username, cfg.Wallet.Password)
	if err != nil {
		return WalletResult{}, fmt.Errorf("failed to login to keycloak for wallet: %w", err)
	}
	log.Info("Obtained CAT token for wallet authentication")
	apiKey := "<my-supabase-public-anon-key>"

	wdb, err := cdk_ffi.WalletSupabaseDatabaseWithOidc("https://supabase.domain.com",
		apiKey,
		"https://auth.domain.com/realms/my-application-realm/.well-known/openid-configuration",
		&cfg.Keycloak.Verification.ClientID)

	if err != nil {
		return WalletResult{}, fmt.Errorf("failed to create supabase db concetion: %w", err)
	}
	wdb.SetJwtToken(&catToken.AccessToken)
	wdb.SetRefreshToken(&catToken.RefreshToken)
	
	exp := uint64(time.Now().Add(time.Duration(catToken.ExpiresIn)).Unix())
	wdb.SetTokenExpiration(&exp)

	wallet, err := cdk_ffi.NewWallet(
		cfg.Wallet.Mint,
		cdk_ffi.CurrencyUnitUsd{},
		cfg.Wallet.Mnemonic,
		wdb,
		cdk_ffi.WalletConfig{
			TargetProofCount: nil,
		},
	)

	if err != nil {
		return WalletResult{}, fmt.Errorf("failed to create wallet: %w", err)
	}
    // Set CAT token for wallet authentication (NUT-21 and NUT-22 auth wallet)
	if err := wallet.SetCat(catToken.AccessToken); err != nil {
		return WalletResult{}, fmt.Errorf("failed to set CAT token: %w", err)
	}

	// Set refresh token
	if err := wallet.SetRefreshToken(catToken.RefreshToken); err != nil {
		return WalletResult{}, fmt.Errorf("failed to set refresh token: %w", err)
	}

	return WalletResult{
		Wallet:          wallet,
	}, nil
}

Notes to the reviewers


Suggested CHANGELOG Updates

CHANGED

ADDED

REMOVED

FIXED


Checklist

@github-project-automation github-project-automation bot moved this to Backlog in CDK Jan 19, 2026
@asmogo asmogo added the wallet label Jan 19, 2026
@asmogo
Copy link
Collaborator Author

asmogo commented Jan 24, 2026

Here’s another example for using this with supabase native authentication and e2e encryption.

	apiKey := "sb_publishable_key"
	supabaseURL := "https://myrandomstring.supabase.co"
	username := "user@domain.com"
	password := "mypassword"
	response, err := cdk_ffi.SupabaseSignin(supabaseURL, apiKey, username, password)
	if err != nil {
		return WalletResult{}, err
	}
	wdb, err := cdk_ffi.WalletSupabaseDatabaseWithSupabaseAuth(supabaseURL,
		apiKey)
	if err != nil {
		return WalletResult{}, fmt.Errorf("failed to create supabase db concetion: %w", err)
	}
	wdb.SetEncryptionPassword(password, "salt")
	wdb.SetJwtToken(&response.AccessToken)
	wdb.SetRefreshToken(response.RefreshToken)
        
    err = wdb.KvWrite("test", "namespace", "key", []byte("value"))
	if err != nil {
		return WalletResult{}, fmt.Errorf("failed to get mint info: %w", err)
	}
	value, err := wdb.KvRead("test", "namespace", "value")
	if err != nil {
		return WalletResult{}, fmt.Errorf("failed to get mint info: %w", err)
	}

@ye0man ye0man moved this from Backlog to In progress in CDK Feb 4, 2026
@thesimplekid thesimplekid added this to the 0.16.0 milestone Feb 18, 2026
asmogo and others added 15 commits March 10, 2026 09:40
Resolve conflicts keeping main's 0.15.1 versions and API changes
while preserving supabase and auth feature additions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Update the Supabase wallet database backend to support main's new
WalletDatabase trait methods:

- Saga operations: add_saga, get_saga, update_saga (with optimistic
  locking), delete_saga, get_incomplete_sagas
- Proof reservation: reserve_proofs, release_proofs, get_reserved_proofs
- Quote reservation: reserve_melt_quote, release_melt_quote,
  reserve_mint_quote, release_mint_quote
- KV store: kv_read, kv_list (delegated from Database trait)

Also adds new fields to table structs and conversions:
- MintQuote/MeltQuote: used_by_operation, version
- ProofInfo: used_by_operation, created_by_operation
- Transaction: saga_id

Includes SQL migration 002 for new columns and saga table.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…wallet-supabase

# Conflicts:
#	Cargo.lock.msrv
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: In progress

Development

Successfully merging this pull request may close these issues.

3 participants