upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/tests/unit
diff options
context:
space:
mode:
Diffstat (limited to 'tests/unit')
-rw-r--r--tests/unit/Makefile12
-rw-r--r--tests/unit/stubs/esp_wifi.h64
-rw-r--r--tests/unit/test_beacon_price.c132
-rw-r--r--tests/unit/test_market.c177
-rw-r--r--tests/unit/test_tollgate_client.c1
5 files changed, 383 insertions, 3 deletions
diff --git a/tests/unit/Makefile b/tests/unit/Makefile
index 6d13e4d..7bd3f1e 100644
--- a/tests/unit/Makefile
+++ b/tests/unit/Makefile
@@ -22,7 +22,7 @@ LDFLAGS := -lmbedcrypto -lcjson -lm
22 22
23SECP256K1_OBJ := secp256k1.o precomputed_ecmult.o precomputed_ecmult_gen.o 23SECP256K1_OBJ := secp256k1.o precomputed_ecmult.o precomputed_ecmult_gen.o
24 24
25TESTS := test_geohash test_identity test_nostr_event test_cashu test_session test_tollgate_client test_lnurl_pay test_lightning_payout test_mcp_handler test_nip04 test_cvm_server test_display test_negentropy_adapter 25TESTS := test_geohash test_identity test_nostr_event test_cashu test_session test_tollgate_client test_lnurl_pay test_lightning_payout test_mcp_handler test_nip04 test_cvm_server test_display test_negentropy_adapter test_beacon_price test_market
26 26
27.PHONY: all test clean $(TESTS) 27.PHONY: all test clean $(TESTS)
28 28
@@ -63,8 +63,8 @@ test_cashu: test_cashu.c $(REPO_ROOT)/main/cashu.c
63test_session: test_session.c $(REPO_ROOT)/main/session.c $(REPO_ROOT)/main/cashu.c 63test_session: test_session.c $(REPO_ROOT)/main/session.c $(REPO_ROOT)/main/cashu.c
64 $(CC) $(CFLAGS) $< $(REPO_ROOT)/main/session.c $(REPO_ROOT)/main/cashu.c -o $@ $(LDFLAGS) 64 $(CC) $(CFLAGS) $< $(REPO_ROOT)/main/session.c $(REPO_ROOT)/main/cashu.c -o $@ $(LDFLAGS)
65 65
66test_tollgate_client: test_tollgate_client.c 66test_tollgate_client: test_tollgate_client.c $(REPO_ROOT)/main/market.c $(REPO_ROOT)/main/beacon_price.c
67 $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) 67 $(CC) $(CFLAGS) -I $(REPO_ROOT)/main $< $(REPO_ROOT)/main/market.c $(REPO_ROOT)/main/beacon_price.c -o $@ $(LDFLAGS)
68 68
69test_lnurl_pay: test_lnurl_pay.c 69test_lnurl_pay: test_lnurl_pay.c
70 $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) 70 $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS)
@@ -87,5 +87,11 @@ test_display: test_display.c
87test_negentropy_adapter: test_negentropy_adapter.c 87test_negentropy_adapter: test_negentropy_adapter.c
88 $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) 88 $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS)
89 89
90test_beacon_price: test_beacon_price.c $(REPO_ROOT)/main/beacon_price.c
91 $(CC) $(CFLAGS) -I $(REPO_ROOT)/main $< $(REPO_ROOT)/main/beacon_price.c -o $@ $(LDFLAGS)
92
93test_market: test_market.c $(REPO_ROOT)/main/market.c $(REPO_ROOT)/main/beacon_price.c
94 $(CC) $(CFLAGS) -I $(REPO_ROOT)/main $< $(REPO_ROOT)/main/market.c $(REPO_ROOT)/main/beacon_price.c -o $@ $(LDFLAGS)
95
90clean: 96clean:
91 rm -f $(TESTS) $(SECP256K1_OBJ) 97 rm -f $(TESTS) $(SECP256K1_OBJ)
diff --git a/tests/unit/stubs/esp_wifi.h b/tests/unit/stubs/esp_wifi.h
index 6aa5787..5eb14bf 100644
--- a/tests/unit/stubs/esp_wifi.h
+++ b/tests/unit/stubs/esp_wifi.h
@@ -2,6 +2,7 @@
2#define STUBS_ESP_WIFI_H 2#define STUBS_ESP_WIFI_H
3 3
4#include <stdint.h> 4#include <stdint.h>
5#include <stdbool.h>
5#include <string.h> 6#include <string.h>
6#include "esp_err.h" 7#include "esp_err.h"
7 8
@@ -37,4 +38,67 @@ static inline esp_err_t esp_wifi_set_config(int ifx, const wifi_config_t *cfg) {
37static inline esp_err_t esp_wifi_set_mode(uint8_t mode) { (void)mode; return ESP_OK; } 38static inline esp_err_t esp_wifi_set_mode(uint8_t mode) { (void)mode; return ESP_OK; }
38static inline esp_err_t esp_wifi_start(void) { return ESP_OK; } 39static inline esp_err_t esp_wifi_start(void) { return ESP_OK; }
39 40
41#define WIFI_VENDOR_IE_ELEMENT_ID 0xDD
42
43typedef enum {
44 WIFI_VND_IE_TYPE_BEACON,
45 WIFI_VND_IE_TYPE_PROBE_REQ,
46 WIFI_VND_IE_TYPE_PROBE_RESP,
47 WIFI_VND_IE_TYPE_ASSOC_REQ,
48 WIFI_VND_IE_TYPE_ASSOC_RESP,
49} wifi_vendor_ie_type_t;
50
51typedef enum {
52 WIFI_VND_IE_ID_0,
53 WIFI_VND_IE_ID_1,
54} wifi_vendor_ie_id_t;
55
56typedef struct {
57 uint8_t element_id;
58 uint8_t length;
59 uint8_t vendor_oui[3];
60 uint8_t vendor_oui_type;
61 uint8_t payload[0];
62} vendor_ie_data_t;
63
64typedef void (*esp_vendor_ie_cb_t)(void *ctx, wifi_vendor_ie_type_t type, const uint8_t sa[6], const vendor_ie_data_t *vnd_ie, int rssi);
65
66static inline esp_err_t esp_wifi_set_vendor_ie(bool enable, wifi_vendor_ie_type_t type, wifi_vendor_ie_id_t idx, const void *vnd_ie) { (void)enable; (void)type; (void)idx; (void)vnd_ie; return ESP_OK; }
67static inline esp_err_t esp_wifi_set_vendor_ie_cb(esp_vendor_ie_cb_t cb, void *ctx) { (void)cb; (void)ctx; return ESP_OK; }
68
69#define WIFI_SCAN_TYPE_PASSIVE 0
70
71typedef struct {
72 uint8_t bssid[6];
73 uint8_t ssid[33];
74 uint8_t primary;
75 int second;
76 int8_t rssi;
77 int authmode;
78} wifi_ap_record_t;
79
80typedef struct {
81 uint8_t *ssid;
82 uint8_t *bssid;
83 uint8_t channel;
84 bool show_hidden;
85 int scan_type;
86 union {
87 struct { int min; int max; } active;
88 int passive;
89 } scan_time;
90} wifi_scan_config_t;
91
92static inline esp_err_t esp_wifi_scan_start(const wifi_scan_config_t *cfg, bool block) { (void)cfg; (void)block; return ESP_OK; }
93static inline esp_err_t esp_wifi_scan_get_ap_num(uint16_t *n) { *n = 0; return ESP_OK; }
94static inline esp_err_t esp_wifi_scan_get_ap_records(uint16_t *n, wifi_ap_record_t *records) { (void)records; *n = 0; return ESP_OK; }
95
96#define WIFI_EVENT_SCAN_DONE 3
97
98typedef void *esp_event_handler_instance_t;
99typedef const char *esp_event_base_t;
100#define WIFI_EVENT "WIFI_EVENT"
101
102static inline esp_err_t esp_event_handler_instance_register(esp_event_base_t a, int32_t b, void *c, void *d, esp_event_handler_instance_t *e) { (void)a; (void)b; (void)c; (void)d; (void)e; return ESP_OK; }
103
40#endif 104#endif
diff --git a/tests/unit/test_beacon_price.c b/tests/unit/test_beacon_price.c
new file mode 100644
index 0000000..9574478
--- /dev/null
+++ b/tests/unit/test_beacon_price.c
@@ -0,0 +1,132 @@
1#include "test_framework.h"
2#include "../../main/config.h"
3#include "../../main/identity.h"
4#include <string.h>
5#include <stdio.h>
6#include <mbedtls/sha256.h>
7
8#include "../../main/beacon_price.h"
9
10static tollgate_config_t g_test_config;
11static tollgate_identity_t g_test_identity;
12
13const tollgate_config_t *tollgate_config_get(void) { return &g_test_config; }
14const tollgate_identity_t *identity_get(void) { return &g_test_identity; }
15
16int main(void)
17{
18 printf("=== test_beacon_price ===\n");
19
20 memset(&g_test_config, 0, sizeof(g_test_config));
21 strncpy(g_test_config.mint_url, "https://testnut.cashu.space", sizeof(g_test_config.mint_url) - 1);
22 strncpy(g_test_config.metric, "milliseconds", sizeof(g_test_config.metric) - 1);
23 g_test_config.price_per_step = 21;
24 g_test_config.step_size_ms = 60000;
25 strncpy(g_test_config.nostr_geohash, "u281w0dfz", sizeof(g_test_config.nostr_geohash) - 1);
26
27 memset(&g_test_identity, 0, sizeof(g_test_identity));
28 strncpy(g_test_identity.npub_hex, "abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890", 64);
29 g_test_identity.initialized = true;
30
31 printf("\n--- tollgate_price_payload_t size ---\n");
32 {
33 ASSERT_EQ_INT(26, (int)TOLLGATE_IE_PAYLOAD_SIZE, "payload is 26 bytes");
34 ASSERT_EQ_INT(32, (int)TOLLGATE_IE_TOTAL_SIZE, "total IE is 32 bytes");
35 }
36
37 printf("\n--- beacon_price_hash_mint ---\n");
38 {
39 uint8_t hash[4];
40 beacon_price_hash_mint("https://testnut.cashu.space", hash);
41
42 uint8_t expected[32];
43 mbedtls_sha256((const unsigned char *)"https://testnut.cashu.space",
44 strlen("https://testnut.cashu.space"), expected, 0);
45 ASSERT_MEM_EQ(expected, hash, 4, "mint_hash matches SHA-256 prefix");
46
47 uint8_t hash2[4];
48 beacon_price_hash_mint("https://other.mint.url", hash2);
49 ASSERT(memcmp(hash, hash2, 4) != 0, "different mint URLs produce different hashes");
50 }
51
52 printf("\n--- beacon_price_hash_npub ---\n");
53 {
54 uint8_t hash[4];
55 beacon_price_hash_npub("abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890", hash);
56
57 uint8_t expected[32];
58 mbedtls_sha256((const unsigned char *)"abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890",
59 64, expected, 0);
60 ASSERT_MEM_EQ(expected, hash, 4, "npub_hash matches SHA-256 prefix");
61 }
62
63 printf("\n--- beacon_price_build_ie (time metric) ---\n");
64 {
65 tollgate_price_ie_t ie;
66 beacon_price_build_ie(&ie);
67
68 ASSERT_EQ_INT(0xDD, ie.element_id, "element_id is 0xDD");
69 ASSERT_EQ_INT(4 + 26, ie.length, "length is 30 (4 header + 26 payload)");
70 ASSERT_EQ_INT(0xC0, ie.vendor_oui[0], "OUI byte 0");
71 ASSERT_EQ_INT(0xFF, ie.vendor_oui[1], "OUI byte 1");
72 ASSERT_EQ_INT(0xEE, ie.vendor_oui[2], "OUI byte 2");
73 ASSERT_EQ_INT(0x01, ie.vendor_oui_type, "OUI type is 0x01");
74
75 ASSERT_EQ_INT(1, ie.payload.version, "version is 1");
76 ASSERT_EQ_INT(0, ie.payload.metric, "metric is 0 (milliseconds)");
77 ASSERT_EQ_INT(21, ie.payload.price_per_step, "price is 21");
78 ASSERT_EQ_INT(60000, (int)ie.payload.step_size, "step_size is 60000");
79
80 uint8_t expected_mint_hash[4];
81 beacon_price_hash_mint("https://testnut.cashu.space", expected_mint_hash);
82 ASSERT_MEM_EQ(expected_mint_hash, ie.payload.mint_hash, 4, "mint_hash matches");
83
84 ASSERT_EQ_INT(9, ie.payload.geohash_len, "geohash_len is 9");
85 ASSERT(memcmp(ie.payload.geohash, "u281w0dfz", 9) == 0, "geohash matches");
86 }
87
88 printf("\n--- beacon_price_build_ie (bytes metric) ---\n");
89 {
90 strncpy(g_test_config.metric, "bytes", sizeof(g_test_config.metric) - 1);
91 g_test_config.step_size_bytes = 22020096;
92 g_test_config.price_per_step = 5;
93
94 tollgate_price_ie_t ie;
95 beacon_price_build_ie(&ie);
96
97 ASSERT_EQ_INT(1, ie.payload.metric, "metric is 1 (bytes)");
98 ASSERT_EQ_INT(5, ie.payload.price_per_step, "price is 5");
99 ASSERT_EQ_INT(22020096, (int)ie.payload.step_size, "step_size is 22020096 bytes");
100
101 strncpy(g_test_config.metric, "milliseconds", sizeof(g_test_config.metric) - 1);
102 g_test_config.step_size_ms = 60000;
103 g_test_config.price_per_step = 21;
104 }
105
106 printf("\n--- roundtrip: build → parse ---\n");
107 {
108 tollgate_price_ie_t ie;
109 beacon_price_build_ie(&ie);
110
111 vendor_ie_data_t *vnd_ie = (vendor_ie_data_t *)&ie;
112
113 ASSERT(vnd_ie->length >= 4 + (int)TOLLGATE_IE_PAYLOAD_SIZE, "vendor IE length sufficient");
114
115 const tollgate_price_payload_t *parsed = (const tollgate_price_payload_t *)vnd_ie->payload;
116 ASSERT_EQ_INT(1, parsed->version, "parsed version");
117 ASSERT_EQ_INT(0, parsed->metric, "parsed metric");
118 ASSERT_EQ_INT(21, parsed->price_per_step, "parsed price");
119 ASSERT_EQ_INT(60000, (int)parsed->step_size, "parsed step_size");
120 ASSERT_EQ_INT(9, parsed->geohash_len, "parsed geohash_len");
121 }
122
123 printf("\n--- struct packing check ---\n");
124 {
125 tollgate_price_ie_t ie;
126 memset(&ie, 0, sizeof(ie));
127 int expected_size = 2 + 3 + 1 + 26;
128 ASSERT_EQ_INT(expected_size, (int)sizeof(tollgate_price_ie_t), "no padding in struct");
129 }
130
131 TEST_SUMMARY();
132}
diff --git a/tests/unit/test_market.c b/tests/unit/test_market.c
new file mode 100644
index 0000000..c19d26e
--- /dev/null
+++ b/tests/unit/test_market.c
@@ -0,0 +1,177 @@
1#include "test_framework.h"
2#include "../../main/beacon_price.h"
3#include "../../main/market.h"
4#include "../../main/config.h"
5#include "../../main/identity.h"
6#include <string.h>
7#include <stdio.h>
8#include <stdlib.h>
9
10static tollgate_config_t g_test_config;
11static tollgate_identity_t g_test_identity;
12
13const tollgate_config_t *tollgate_config_get(void) { return &g_test_config; }
14const tollgate_identity_t *identity_get(void) { return &g_test_identity; }
15
16static void build_test_ie(tollgate_price_ie_t *ie, uint16_t price, uint32_t step, uint8_t metric,
17 const char *geohash, const char *mint_url, const char *npub_hex)
18{
19 memset(ie, 0, sizeof(*ie));
20 ie->element_id = 0xDD;
21 ie->length = 4 + TOLLGATE_IE_PAYLOAD_SIZE;
22 ie->vendor_oui[0] = TOLLGATE_OUI_0;
23 ie->vendor_oui[1] = TOLLGATE_OUI_1;
24 ie->vendor_oui[2] = TOLLGATE_OUI_2;
25 ie->vendor_oui_type = TOLLGATE_IE_TYPE;
26
27 ie->payload.version = TOLLGATE_IE_VERSION;
28 ie->payload.metric = metric;
29 ie->payload.price_per_step = price;
30 ie->payload.step_size = step;
31
32 if (mint_url) beacon_price_hash_mint(mint_url, ie->payload.mint_hash);
33 if (npub_hex) beacon_price_hash_npub(npub_hex, ie->payload.npub_hash);
34
35 uint8_t gh_len = (uint8_t)strnlen(geohash, TOLLGATE_IE_GEOHASH_MAX);
36 ie->payload.geohash_len = gh_len;
37 memcpy(ie->payload.geohash, geohash, gh_len);
38}
39
40static void reset_market(void)
41{
42 market_t *m = (market_t *)market_get();
43 memset(m, 0, sizeof(*m));
44}
45
46int main(void)
47{
48 printf("=== test_market ===\n");
49
50 memset(&g_test_config, 0, sizeof(g_test_config));
51 g_test_config.market_enabled = true;
52 g_test_config.market_scan_interval_s = 30;
53 strncpy(g_test_config.metric, "milliseconds", sizeof(g_test_config.metric) - 1);
54
55 memset(&g_test_identity, 0, sizeof(g_test_identity));
56 strncpy(g_test_identity.npub_hex, "0000000000000000000000000000000000000000000000000000000000000001", 64);
57 g_test_identity.initialized = true;
58
59 printf("\n--- parse vendor IE (valid) ---\n");
60 {
61 reset_market();
62 tollgate_price_ie_t ie;
63 build_test_ie(&ie, 21, 60000, 0, "u281w0dfz",
64 "https://testnut.cashu.space",
65 "abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890");
66
67 uint8_t bssid[6] = {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0x01};
68 market_parse_vendor_ie(bssid, (vendor_ie_data_t *)&ie, -45);
69
70 const market_t *m = market_get();
71 ASSERT_EQ_INT(1, m->count, "one entry added");
72 ASSERT(m->entries[0].valid, "entry is valid");
73 ASSERT_EQ_INT(21, m->entries[0].price_per_step, "price is 21");
74 ASSERT_EQ_INT(60000, (int)m->entries[0].step_size, "step_size is 60000");
75 ASSERT_EQ_INT(0, m->entries[0].metric, "metric is 0 (time)");
76 ASSERT_EQ_INT(-45, m->entries[0].rssi, "rssi is -45");
77 ASSERT(memcmp(m->entries[0].bssid, bssid, 6) == 0, "bssid matches");
78 }
79
80 printf("\n--- parse vendor IE (ignore self) ---\n");
81 {
82 reset_market();
83 tollgate_price_ie_t ie;
84 build_test_ie(&ie, 21, 60000, 0, "u281w0dfz",
85 "https://testnut.cashu.space",
86 g_test_identity.npub_hex);
87
88 uint8_t bssid[6] = {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0x02};
89 market_parse_vendor_ie(bssid, (vendor_ie_data_t *)&ie, -50);
90
91 const market_t *m = market_get();
92 ASSERT_EQ_INT(0, m->count, "self-entry ignored");
93 }
94
95 printf("\n--- parse vendor IE (wrong OUI) ---\n");
96 {
97 reset_market();
98 tollgate_price_ie_t ie;
99 build_test_ie(&ie, 21, 60000, 0, "u281w0dfz",
100 "https://testnut.cashu.space",
101 "abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890");
102 ie.vendor_oui[0] = 0x00;
103
104 uint8_t bssid[6] = {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0x03};
105 market_parse_vendor_ie(bssid, (vendor_ie_data_t *)&ie, -40);
106
107 const market_t *m = market_get();
108 ASSERT_EQ_INT(0, m->count, "wrong OUI rejected");
109 }
110
111 printf("\n--- market_find_cheapest ---\n");
112 {
113 reset_market();
114
115 tollgate_price_ie_t ie1, ie2, ie3;
116 build_test_ie(&ie1, 21, 60000, 0, "u281w0dfz",
117 "https://testnut.cashu.space", "aaa...npub1");
118 build_test_ie(&ie2, 10, 60000, 0, "u281w0dfz",
119 "https://testnut.cashu.space", "bbb...npub2");
120 build_test_ie(&ie3, 50, 60000, 0, "u281w0dfz",
121 "https://testnut.cashu.space", "ccc...npub3");
122
123 uint8_t bssid1[6] = {0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
124 uint8_t bssid2[6] = {0x02, 0x02, 0x02, 0x02, 0x02, 0x02};
125 uint8_t bssid3[6] = {0x03, 0x03, 0x03, 0x03, 0x03, 0x03};
126
127 market_parse_vendor_ie(bssid1, (vendor_ie_data_t *)&ie1, -45);
128 market_parse_vendor_ie(bssid2, (vendor_ie_data_t *)&ie2, -50);
129 market_parse_vendor_ie(bssid3, (vendor_ie_data_t *)&ie3, -55);
130
131 const market_t *m = market_get();
132 ASSERT_EQ_INT(3, m->count, "three entries");
133
134 strncpy((char *)m->entries[0].ssid, "TollGate-A", 32);
135 strncpy((char *)m->entries[1].ssid, "TollGate-B", 32);
136 strncpy((char *)m->entries[2].ssid, "TollGate-C", 32);
137
138 int cheapest = market_find_cheapest();
139 ASSERT(cheapest >= 0, "found a cheapest entry");
140 ASSERT_EQ_INT(10, m->entries[cheapest].price_per_step, "cheapest is 10 sats");
141 }
142
143 printf("\n--- update existing entry ---\n");
144 {
145 reset_market();
146 tollgate_price_ie_t ie;
147 build_test_ie(&ie, 21, 60000, 0, "u281w0dfz",
148 "https://testnut.cashu.space", "npub1");
149 uint8_t bssid[6] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06};
150
151 market_parse_vendor_ie(bssid, (vendor_ie_data_t *)&ie, -45);
152 ASSERT_EQ_INT(1, market_get()->count, "first add");
153
154 build_test_ie(&ie, 15, 60000, 0, "u281w0dfz",
155 "https://testnut.cashu.space", "npub1");
156 market_parse_vendor_ie(bssid, (vendor_ie_data_t *)&ie, -47);
157 ASSERT_EQ_INT(1, market_get()->count, "update doesn't increase count");
158 ASSERT_EQ_INT(15, market_get()->entries[0].price_per_step, "price updated to 15");
159 }
160
161 printf("\n--- geohash preserved ---\n");
162 {
163 reset_market();
164 tollgate_price_ie_t ie;
165 build_test_ie(&ie, 21, 60000, 0, "u281w0dfz",
166 "https://testnut.cashu.space", "npub1");
167 uint8_t bssid[6] = {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF};
168
169 market_parse_vendor_ie(bssid, (vendor_ie_data_t *)&ie, -40);
170
171 const market_t *m = market_get();
172 ASSERT(m->entries[0].valid, "entry valid");
173 ASSERT_EQ_STR("u281w0dfz", m->entries[0].geohash, "geohash is u281w0dfz");
174 }
175
176 TEST_SUMMARY();
177}
diff --git a/tests/unit/test_tollgate_client.c b/tests/unit/test_tollgate_client.c
index 686ad19..eebc747 100644
--- a/tests/unit/test_tollgate_client.c
+++ b/tests/unit/test_tollgate_client.c
@@ -13,6 +13,7 @@ const tollgate_config_t *tollgate_config_get(void) {
13 13
14uint64_t nucula_wallet_balance(void) { return 100; } 14uint64_t nucula_wallet_balance(void) { return 100; }
15esp_err_t nucula_wallet_send(uint64_t a, char *b, size_t c) { (void)a; (void)b; (void)c; return ESP_OK; } 15esp_err_t nucula_wallet_send(uint64_t a, char *b, size_t c) { (void)a; (void)b; (void)c; return ESP_OK; }
16const void *identity_get(void) { return NULL; }
16 17
17#include "freertos/FreeRTOS.h" 18#include "freertos/FreeRTOS.h"
18 19