186 lines
6.6 KiB
C
186 lines
6.6 KiB
C
/*
|
|
* NIP-60 Cashu Wallet Test Suite
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include "../nostr_core/nostr_core.h"
|
|
|
|
static int tests_run = 0;
|
|
static int tests_passed = 0;
|
|
|
|
#define TEST_ASSERT(cond, msg) do { \
|
|
tests_run++; \
|
|
if (cond) { tests_passed++; printf("✅ %s\n", msg); } \
|
|
else { printf("❌ %s\n", msg); } \
|
|
} while (0)
|
|
|
|
static int hex_to_bytes32(const char* hex, unsigned char out[32]) {
|
|
return nostr_hex_to_bytes(hex, out, 32) == 0 ? 0 : -1;
|
|
}
|
|
|
|
static void test_wallet_roundtrip(void) {
|
|
printf("\n=== test_wallet_roundtrip ===\n");
|
|
|
|
const char* sk_hex = "91ba716fa9e7ea2fcbad360cf4f8e0d312f73984da63d90f524ad61a6a1e7dbe";
|
|
unsigned char sk[32];
|
|
TEST_ASSERT(hex_to_bytes32(sk_hex, sk) == 0, "parse private key");
|
|
|
|
char* mints[] = {
|
|
"https://mint1.example.com",
|
|
"https://mint2.example.com"
|
|
};
|
|
|
|
nostr_nip60_wallet_data_t in;
|
|
memset(&in, 0, sizeof(in));
|
|
strcpy(in.privkey, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
|
|
in.mint_urls = mints;
|
|
in.mint_count = 2;
|
|
|
|
cJSON* evt = nostr_nip60_create_wallet_event(&in, sk, 0);
|
|
TEST_ASSERT(evt != NULL, "create wallet event");
|
|
|
|
nostr_nip60_wallet_data_t out;
|
|
memset(&out, 0, sizeof(out));
|
|
int rc = nostr_nip60_parse_wallet_event(evt, sk, &out);
|
|
TEST_ASSERT(rc == NOSTR_SUCCESS, "parse wallet event");
|
|
TEST_ASSERT(strcmp(out.privkey, in.privkey) == 0, "wallet privkey preserved");
|
|
TEST_ASSERT(out.mint_count == 2, "wallet mint count");
|
|
TEST_ASSERT(strcmp(out.mint_urls[0], mints[0]) == 0, "wallet mint 0");
|
|
TEST_ASSERT(strcmp(out.mint_urls[1], mints[1]) == 0, "wallet mint 1");
|
|
|
|
nostr_nip60_free_wallet_data(&out);
|
|
cJSON_Delete(evt);
|
|
}
|
|
|
|
static void test_token_roundtrip_and_sum(void) {
|
|
printf("\n=== test_token_roundtrip_and_sum ===\n");
|
|
|
|
const char* sk_hex = "96f6fa197aa07477ab88f6981118466ae3a982faab8ad5db9d5426870c73d220";
|
|
unsigned char sk[32];
|
|
TEST_ASSERT(hex_to_bytes32(sk_hex, sk) == 0, "parse private key");
|
|
|
|
nostr_cashu_proof_t proofs[2];
|
|
memset(proofs, 0, sizeof(proofs));
|
|
|
|
strcpy(proofs[0].id, "005c2502034d4f12");
|
|
proofs[0].amount = 1;
|
|
proofs[0].secret = "secret-1";
|
|
proofs[0].C = "0241d98a8197ef238a192d47edf191a9de78b657308937b4f7dd0aa53beae72c46";
|
|
|
|
strcpy(proofs[1].id, "005c2502034d4f12");
|
|
proofs[1].amount = 8;
|
|
proofs[1].secret = "secret-8";
|
|
proofs[1].C = "02aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
|
|
|
|
char* del_ids[] = {"event-id-1"};
|
|
|
|
nostr_nip60_token_data_t token;
|
|
memset(&token, 0, sizeof(token));
|
|
token.mint_url = "https://mint.example.com";
|
|
token.proofs = proofs;
|
|
token.proof_count = 2;
|
|
token.deleted_token_ids = del_ids;
|
|
token.deleted_count = 1;
|
|
|
|
TEST_ASSERT(nostr_nip60_sum_proofs(proofs, 2) == 9, "proof sum");
|
|
|
|
cJSON* evt = nostr_nip60_create_token_event(&token, sk, 0);
|
|
TEST_ASSERT(evt != NULL, "create token event");
|
|
|
|
nostr_nip60_token_data_t out;
|
|
memset(&out, 0, sizeof(out));
|
|
int rc = nostr_nip60_parse_token_event(evt, sk, &out);
|
|
TEST_ASSERT(rc == NOSTR_SUCCESS, "parse token event");
|
|
TEST_ASSERT(strcmp(out.mint_url, token.mint_url) == 0, "token mint");
|
|
TEST_ASSERT(out.proof_count == 2, "token proof count");
|
|
TEST_ASSERT(out.deleted_count == 1, "token del count");
|
|
TEST_ASSERT(nostr_nip60_sum_proofs(out.proofs, out.proof_count) == 9, "parsed proof sum");
|
|
|
|
cJSON* del_evt = nostr_nip60_create_token_deletion("event-id-1", sk, 0);
|
|
TEST_ASSERT(del_evt != NULL, "create token deletion event");
|
|
|
|
nostr_nip60_free_token_data(&out);
|
|
cJSON_Delete(del_evt);
|
|
cJSON_Delete(evt);
|
|
}
|
|
|
|
static void test_history_quote_and_filters(void) {
|
|
printf("\n=== test_history_quote_and_filters ===\n");
|
|
|
|
const char* sk_hex = "1111111111111111111111111111111111111111111111111111111111111111";
|
|
unsigned char sk[32];
|
|
TEST_ASSERT(hex_to_bytes32(sk_hex, sk) == 0, "parse private key");
|
|
|
|
nostr_nip60_history_ref_t refs[2];
|
|
memset(refs, 0, sizeof(refs));
|
|
strcpy(refs[0].event_id, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
|
|
strcpy(refs[0].relay_hint, "wss://relay.example.com");
|
|
refs[0].marker = NOSTR_NIP60_REF_DESTROYED;
|
|
strcpy(refs[1].event_id, "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb");
|
|
refs[1].marker = NOSTR_NIP60_REF_CREATED;
|
|
|
|
nostr_nip60_history_data_t hist;
|
|
memset(&hist, 0, sizeof(hist));
|
|
hist.direction = NOSTR_NIP60_DIRECTION_OUT;
|
|
hist.amount = 4;
|
|
hist.refs = refs;
|
|
hist.ref_count = 2;
|
|
|
|
cJSON* hist_evt = nostr_nip60_create_history_event(&hist, sk, 0);
|
|
TEST_ASSERT(hist_evt != NULL, "create history event");
|
|
|
|
nostr_nip60_history_data_t parsed;
|
|
memset(&parsed, 0, sizeof(parsed));
|
|
int rc = nostr_nip60_parse_history_event(hist_evt, sk, &parsed);
|
|
TEST_ASSERT(rc == NOSTR_SUCCESS, "parse history event");
|
|
TEST_ASSERT(parsed.direction == NOSTR_NIP60_DIRECTION_OUT, "history direction");
|
|
TEST_ASSERT(parsed.amount == 4, "history amount");
|
|
TEST_ASSERT(parsed.ref_count == 2, "history refs");
|
|
|
|
time_t exp = 2000000000;
|
|
cJSON* quote_evt = nostr_nip60_create_quote_event("quote-123", "https://mint.example.com", exp, sk, 0);
|
|
TEST_ASSERT(quote_evt != NULL, "create quote event");
|
|
|
|
char quote_id[128];
|
|
char mint[256];
|
|
time_t exp_out = 0;
|
|
rc = nostr_nip60_parse_quote_event(quote_evt, sk, quote_id, sizeof(quote_id), mint, sizeof(mint), &exp_out);
|
|
TEST_ASSERT(rc == NOSTR_SUCCESS, "parse quote event");
|
|
TEST_ASSERT(strcmp(quote_id, "quote-123") == 0, "quote id");
|
|
TEST_ASSERT(strcmp(mint, "https://mint.example.com") == 0, "quote mint");
|
|
TEST_ASSERT(exp_out == exp, "quote expiration");
|
|
|
|
cJSON* wf = nostr_nip60_create_wallet_filter("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
|
|
cJSON* hf = nostr_nip60_create_history_filter("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 1700000000);
|
|
TEST_ASSERT(wf != NULL, "wallet filter");
|
|
TEST_ASSERT(hf != NULL, "history filter");
|
|
|
|
cJSON_Delete(wf);
|
|
cJSON_Delete(hf);
|
|
cJSON_Delete(quote_evt);
|
|
nostr_nip60_free_history_data(&parsed);
|
|
cJSON_Delete(hist_evt);
|
|
}
|
|
|
|
int main(void) {
|
|
printf("NIP-60 Cashu Wallet Tests\n");
|
|
printf("==========================\n");
|
|
|
|
if (nostr_init() != NOSTR_SUCCESS) {
|
|
printf("❌ Failed to initialize NOSTR library\n");
|
|
return 1;
|
|
}
|
|
|
|
test_wallet_roundtrip();
|
|
test_token_roundtrip_and_sum();
|
|
test_history_quote_and_filters();
|
|
|
|
printf("\n=== Test Summary ===\n");
|
|
printf("Passed: %d/%d\n", tests_passed, tests_run);
|
|
|
|
nostr_cleanup();
|
|
return (tests_passed == tests_run) ? 0 : 1;
|
|
}
|