v0.1.3 - Make cashu wallet initialization unconditional and add lazy wallet readiness for first-run DM tool usage
This commit is contained in:
@@ -55,11 +55,11 @@ Skills compose by adoption-list order (`10123`) and trigger tags carry runtime e
|
||||
|
||||
Didactyl will support local inference, which is very privacy preserving. Remote inference does however have it's advantages, and in those cases Didactyl supports using Bitcoin Lightning and eCash inference providers.
|
||||
|
||||
## Current Status — v0.1.2
|
||||
## Current Status — v0.1.3
|
||||
|
||||
**Active build — this project is barely working. Experiment at your own risk.**
|
||||
|
||||
> Last release update: v0.1.2 — Implement cashu_wallet_receive_token tool flow and integrate Cashu receive/swap handling
|
||||
> Last release update: v0.1.3 — Make cashu wallet initialization unconditional and add lazy wallet readiness for first-run DM tool usage
|
||||
|
||||
- Connects to configured relays with auto-reconnect and relay state transition logging
|
||||
- Publishes configured startup events per relay as each relay becomes connected
|
||||
|
||||
+45
-16
@@ -256,17 +256,35 @@ void cashu_wallet_cleanup(void) {
|
||||
memset(&g_wallet, 0, sizeof(g_wallet));
|
||||
}
|
||||
|
||||
static int ensure_wallet_ready(void) {
|
||||
if (!g_wallet.initialized || !g_wallet.cfg) return -1;
|
||||
|
||||
int wallet_loaded = 0;
|
||||
int auto_load = 0;
|
||||
pthread_mutex_lock(&g_wallet.mutex);
|
||||
wallet_loaded = g_wallet.wallet_loaded;
|
||||
auto_load = g_wallet.cfg->cashu_wallet.auto_load ? 1 : 0;
|
||||
pthread_mutex_unlock(&g_wallet.mutex);
|
||||
|
||||
if (wallet_loaded) return 0;
|
||||
|
||||
int rc = 0;
|
||||
if (auto_load) {
|
||||
rc = cashu_wallet_load_from_relays();
|
||||
if (rc == 0) return 0;
|
||||
}
|
||||
|
||||
rc = cashu_wallet_create_new_from_config();
|
||||
if (rc == 0) return 0;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int cashu_wallet_create_new_from_config(void) {
|
||||
if (!g_wallet.initialized || !g_wallet.cfg) return -1;
|
||||
if (!g_wallet.cfg->cashu_wallet.enabled) return -1;
|
||||
|
||||
pthread_mutex_lock(&g_wallet.mutex);
|
||||
|
||||
if (!g_wallet.cfg->cashu_wallet.mint_urls || g_wallet.cfg->cashu_wallet.mint_count <= 0) {
|
||||
pthread_mutex_unlock(&g_wallet.mutex);
|
||||
return -1;
|
||||
}
|
||||
|
||||
unsigned char priv[32] = {0};
|
||||
unsigned char pub[32] = {0};
|
||||
if (nostr_generate_keypair(priv, pub) != NOSTR_SUCCESS) {
|
||||
@@ -279,19 +297,21 @@ int cashu_wallet_create_new_from_config(void) {
|
||||
nostr_bytes_to_hex(priv, 32, wallet_data.privkey);
|
||||
|
||||
wallet_data.mint_count = g_wallet.cfg->cashu_wallet.mint_count;
|
||||
wallet_data.mint_urls = (char**)calloc((size_t)wallet_data.mint_count, sizeof(char*));
|
||||
if (!wallet_data.mint_urls) {
|
||||
pthread_mutex_unlock(&g_wallet.mutex);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (int i = 0; i < wallet_data.mint_count; i++) {
|
||||
wallet_data.mint_urls[i] = strdup(g_wallet.cfg->cashu_wallet.mint_urls[i]);
|
||||
if (!wallet_data.mint_urls[i]) {
|
||||
nostr_nip60_free_wallet_data(&wallet_data);
|
||||
if (wallet_data.mint_count > 0) {
|
||||
wallet_data.mint_urls = (char**)calloc((size_t)wallet_data.mint_count, sizeof(char*));
|
||||
if (!wallet_data.mint_urls) {
|
||||
pthread_mutex_unlock(&g_wallet.mutex);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (int i = 0; i < wallet_data.mint_count; i++) {
|
||||
wallet_data.mint_urls[i] = strdup(g_wallet.cfg->cashu_wallet.mint_urls[i]);
|
||||
if (!wallet_data.mint_urls[i]) {
|
||||
nostr_nip60_free_wallet_data(&wallet_data);
|
||||
pthread_mutex_unlock(&g_wallet.mutex);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int rc = publish_wallet_event_and_store_locked(&wallet_data, NULL);
|
||||
@@ -397,6 +417,7 @@ int cashu_wallet_load_from_relays(void) {
|
||||
|
||||
int cashu_wallet_balance_json(cJSON** out_json) {
|
||||
if (!out_json || !g_wallet.initialized || !g_wallet.cfg) return -1;
|
||||
(void)ensure_wallet_ready();
|
||||
|
||||
pthread_mutex_lock(&g_wallet.mutex);
|
||||
|
||||
@@ -436,6 +457,7 @@ int cashu_wallet_balance_json(cJSON** out_json) {
|
||||
|
||||
int cashu_wallet_info_json(const char* mint_url, cJSON** out_json) {
|
||||
if (!out_json || !g_wallet.initialized || !g_wallet.cfg) return -1;
|
||||
if (ensure_wallet_ready() != 0) return -1;
|
||||
|
||||
pthread_mutex_lock(&g_wallet.mutex);
|
||||
const char* resolved = resolve_mint_url_locked(mint_url);
|
||||
@@ -483,6 +505,7 @@ int cashu_wallet_info_json(const char* mint_url, cJSON** out_json) {
|
||||
|
||||
int cashu_wallet_mint_quote_json(const char* mint_url, uint64_t amount, const char* unit, cJSON** out_json) {
|
||||
if (!out_json || amount == 0 || !g_wallet.initialized || !g_wallet.cfg) return -1;
|
||||
if (ensure_wallet_ready() != 0) return -1;
|
||||
|
||||
pthread_mutex_lock(&g_wallet.mutex);
|
||||
const char* resolved = resolve_mint_url_locked(mint_url);
|
||||
@@ -516,6 +539,7 @@ int cashu_wallet_mint_quote_json(const char* mint_url, uint64_t amount, const ch
|
||||
|
||||
int cashu_wallet_mint_check_json(const char* mint_url, const char* quote_id, cJSON** out_json) {
|
||||
if (!out_json || !quote_id || quote_id[0] == '\0' || !g_wallet.initialized || !g_wallet.cfg) return -1;
|
||||
if (ensure_wallet_ready() != 0) return -1;
|
||||
|
||||
pthread_mutex_lock(&g_wallet.mutex);
|
||||
const char* resolved = resolve_mint_url_locked(mint_url);
|
||||
@@ -546,6 +570,7 @@ int cashu_wallet_mint_check_json(const char* mint_url, const char* quote_id, cJS
|
||||
|
||||
int cashu_wallet_mint_claim_json(const char* mint_url, const char* quote_id, uint64_t amount, cJSON** out_json) {
|
||||
if (!out_json || !quote_id || quote_id[0] == '\0' || !g_wallet.initialized || !g_wallet.cfg) return -1;
|
||||
if (ensure_wallet_ready() != 0) return -1;
|
||||
|
||||
pthread_mutex_lock(&g_wallet.mutex);
|
||||
const char* resolved = resolve_mint_url_locked(mint_url);
|
||||
@@ -679,6 +704,7 @@ int cashu_wallet_mint_claim_json(const char* mint_url, const char* quote_id, uin
|
||||
|
||||
int cashu_wallet_melt_quote_json(const char* mint_url, const char* payment_request, const char* unit, cJSON** out_json) {
|
||||
if (!out_json || !payment_request || payment_request[0] == '\0' || !g_wallet.initialized || !g_wallet.cfg) return -1;
|
||||
if (ensure_wallet_ready() != 0) return -1;
|
||||
|
||||
pthread_mutex_lock(&g_wallet.mutex);
|
||||
const char* resolved = resolve_mint_url_locked(mint_url);
|
||||
@@ -711,6 +737,7 @@ int cashu_wallet_melt_quote_json(const char* mint_url, const char* payment_reque
|
||||
|
||||
int cashu_wallet_melt_pay_json(const char* mint_url, const char* quote_id, cJSON** out_json) {
|
||||
if (!out_json || !quote_id || quote_id[0] == '\0' || !g_wallet.initialized || !g_wallet.cfg) return -1;
|
||||
if (ensure_wallet_ready() != 0) return -1;
|
||||
|
||||
pthread_mutex_lock(&g_wallet.mutex);
|
||||
const char* resolved = resolve_mint_url_locked(mint_url);
|
||||
@@ -891,6 +918,7 @@ int cashu_wallet_melt_pay_json(const char* mint_url, const char* quote_id, cJSON
|
||||
|
||||
int cashu_wallet_check_proofs_json(const char* mint_url, cJSON** out_json) {
|
||||
if (!out_json || !g_wallet.initialized || !g_wallet.cfg) return -1;
|
||||
if (ensure_wallet_ready() != 0) return -1;
|
||||
|
||||
pthread_mutex_lock(&g_wallet.mutex);
|
||||
const char* resolved = resolve_mint_url_locked(mint_url);
|
||||
@@ -990,6 +1018,7 @@ int cashu_wallet_check_proofs_json(const char* mint_url, cJSON** out_json) {
|
||||
|
||||
int cashu_wallet_receive_token_json(const char* token_string, const char* mint_url, cJSON** out_json) {
|
||||
if (!out_json || !token_string || token_string[0] == '\0' || !g_wallet.initialized || !g_wallet.cfg) return -1;
|
||||
if (ensure_wallet_ready() != 0) return -1;
|
||||
|
||||
cashu_decoded_token_t decoded;
|
||||
memset(&decoded, 0, sizeof(decoded));
|
||||
|
||||
+16
-18
@@ -1385,25 +1385,23 @@ int main(int argc, char** argv) {
|
||||
DEBUG_INFO("[didactyl] startup phase: subscribe DMs end");
|
||||
startup_step_ok(15, "Subscribe DMs", NULL);
|
||||
|
||||
if (cfg.cashu_wallet.enabled) {
|
||||
startup_step_begin(16, "Initialize cashu wallet");
|
||||
if (cashu_wallet_init(&cfg) != 0) {
|
||||
DEBUG_WARN("[didactyl] startup phase: cashu_wallet_init failed (continuing without wallet)");
|
||||
startup_step_fail(16, "Initialize cashu wallet", "cashu_wallet_init failed; wallet features disabled for this run");
|
||||
startup_step_begin(16, "Initialize cashu wallet");
|
||||
if (cashu_wallet_init(&cfg) != 0) {
|
||||
DEBUG_WARN("[didactyl] startup phase: cashu_wallet_init failed (continuing without wallet)");
|
||||
startup_step_fail(16, "Initialize cashu wallet", "cashu_wallet_init failed; wallet tools may return errors");
|
||||
} else {
|
||||
int wallet_rc = 0;
|
||||
if (cfg.cashu_wallet.auto_load) {
|
||||
wallet_rc = cashu_wallet_load_from_relays();
|
||||
}
|
||||
if (wallet_rc != 0 && cfg.cashu_wallet.mint_count > 0) {
|
||||
wallet_rc = cashu_wallet_create_new_from_config();
|
||||
}
|
||||
if (wallet_rc != 0) {
|
||||
DEBUG_WARN("[didactyl] startup phase: cashu wallet load/create deferred to first tool call");
|
||||
startup_step_ok(16, "Initialize cashu wallet", "initialized; load/create deferred");
|
||||
} else {
|
||||
int wallet_rc = 0;
|
||||
if (cfg.cashu_wallet.auto_load) {
|
||||
wallet_rc = cashu_wallet_load_from_relays();
|
||||
}
|
||||
if (wallet_rc != 0 && cfg.cashu_wallet.mint_count > 0) {
|
||||
wallet_rc = cashu_wallet_create_new_from_config();
|
||||
}
|
||||
if (wallet_rc != 0) {
|
||||
DEBUG_WARN("[didactyl] startup phase: cashu wallet load/create failed (continuing)");
|
||||
startup_step_fail(16, "Initialize cashu wallet", "wallet load/create failed; tools may return errors until wallet is configured");
|
||||
} else {
|
||||
startup_step_ok(16, "Initialize cashu wallet", cfg.cashu_wallet.auto_load ? "loaded or created" : "initialized");
|
||||
}
|
||||
startup_step_ok(16, "Initialize cashu wallet", cfg.cashu_wallet.auto_load ? "loaded or created" : "initialized");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -12,8 +12,8 @@
|
||||
// Using DIDACTYL_ prefix to avoid conflicts with nostr_core_lib VERSION macros
|
||||
#define DIDACTYL_VERSION_MAJOR 0
|
||||
#define DIDACTYL_VERSION_MINOR 1
|
||||
#define DIDACTYL_VERSION_PATCH 2
|
||||
#define DIDACTYL_VERSION "v0.1.2"
|
||||
#define DIDACTYL_VERSION_PATCH 3
|
||||
#define DIDACTYL_VERSION "v0.1.3"
|
||||
|
||||
// Agent metadata
|
||||
#define DIDACTYL_NAME "Didactyl"
|
||||
|
||||
Reference in New Issue
Block a user