diff options
Diffstat (limited to 'main/tollgate_api.c')
| -rw-r--r-- | main/tollgate_api.c | 134 |
1 files changed, 132 insertions, 2 deletions
diff --git a/main/tollgate_api.c b/main/tollgate_api.c index efb5cdf..e6880e0 100644 --- a/main/tollgate_api.c +++ b/main/tollgate_api.c | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | #include "config.h" | 3 | #include "config.h" |
| 4 | #include "session.h" | 4 | #include "session.h" |
| 5 | #include "firewall.h" | 5 | #include "firewall.h" |
| 6 | #include "wallet.h" | ||
| 6 | #include "esp_log.h" | 7 | #include "esp_log.h" |
| 7 | #include "cJSON.h" | 8 | #include "cJSON.h" |
| 8 | #include "lwip/sockets.h" | 9 | #include "lwip/sockets.h" |
| @@ -298,9 +299,9 @@ static esp_err_t api_post_payment(httpd_req_t *req) | |||
| 298 | secrets[i] = token->proofs[i].secret; | 299 | secrets[i] = token->proofs[i].secret; |
| 299 | } | 300 | } |
| 300 | session_t *session = session_create(client_ip, allotment, secrets, secret_count); | 301 | session_t *session = session_create(client_ip, allotment, secrets, secret_count); |
| 301 | free(states); | ||
| 302 | free(token); | ||
| 303 | if (!session) { | 302 | if (!session) { |
| 303 | free(states); | ||
| 304 | free(token); | ||
| 304 | cJSON *notice = create_notice("error", "session-error", "Failed to create session"); | 305 | cJSON *notice = create_notice("error", "session-error", "Failed to create session"); |
| 305 | char *json = cJSON_PrintUnformatted(notice); | 306 | char *json = cJSON_PrintUnformatted(notice); |
| 306 | httpd_resp_set_status(req, "503 Service Unavailable"); | 307 | httpd_resp_set_status(req, "503 Service Unavailable"); |
| @@ -317,6 +318,21 @@ static esp_err_t api_post_payment(httpd_req_t *req) | |||
| 317 | httpd_resp_send(req, json, strlen(json)); | 318 | httpd_resp_send(req, json, strlen(json)); |
| 318 | cJSON_free(json); | 319 | cJSON_free(json); |
| 319 | cJSON_Delete(session_event); | 320 | cJSON_Delete(session_event); |
| 321 | |||
| 322 | { | ||
| 323 | wallet_proof_t wproofs[CASHU_MAX_PROOFS]; | ||
| 324 | int wcount = token->proof_count > CASHU_MAX_PROOFS ? CASHU_MAX_PROOFS : token->proof_count; | ||
| 325 | for (int i = 0; i < wcount; i++) { | ||
| 326 | wproofs[i].amount = token->proofs[i].amount; | ||
| 327 | strncpy(wproofs[i].id, token->proofs[i].id, WALLET_KEYSET_ID_LEN - 1); | ||
| 328 | strncpy(wproofs[i].secret, token->proofs[i].secret, WALLET_SECRET_LEN - 1); | ||
| 329 | strncpy(wproofs[i].c, token->proofs[i].c, WALLET_SIG_LEN - 1); | ||
| 330 | } | ||
| 331 | wallet_add_proofs(wproofs, wcount); | ||
| 332 | } | ||
| 333 | |||
| 334 | free(states); | ||
| 335 | free(token); | ||
| 320 | return ESP_OK; | 336 | return ESP_OK; |
| 321 | } | 337 | } |
| 322 | 338 | ||
| @@ -363,10 +379,121 @@ static esp_err_t api_get_whoami(httpd_req_t *req) | |||
| 363 | return ESP_OK; | 379 | return ESP_OK; |
| 364 | } | 380 | } |
| 365 | 381 | ||
| 382 | static esp_err_t api_get_wallet(httpd_req_t *req) | ||
| 383 | { | ||
| 384 | wallet_t *w = wallet_get(); | ||
| 385 | cJSON *root = cJSON_CreateObject(); | ||
| 386 | cJSON_AddNumberToObject(root, "balance", (double)w->balance); | ||
| 387 | cJSON_AddNumberToObject(root, "proof_count", w->proof_count); | ||
| 388 | cJSON_AddNumberToObject(root, "keyset_count", w->keyset_count); | ||
| 389 | |||
| 390 | cJSON *proofs = cJSON_CreateArray(); | ||
| 391 | for (int i = 0; i < w->proof_count; i++) { | ||
| 392 | cJSON *p = cJSON_CreateObject(); | ||
| 393 | cJSON_AddNumberToObject(p, "amount", (double)w->proofs[i].amount); | ||
| 394 | cJSON_AddStringToObject(p, "id", w->proofs[i].id); | ||
| 395 | cJSON_AddItemToArray(proofs, p); | ||
| 396 | } | ||
| 397 | cJSON_AddItemToObject(root, "proofs", proofs); | ||
| 398 | |||
| 399 | char *json = cJSON_PrintUnformatted(root); | ||
| 400 | httpd_resp_set_type(req, "application/json"); | ||
| 401 | httpd_resp_send(req, json, strlen(json)); | ||
| 402 | cJSON_free(json); | ||
| 403 | cJSON_Delete(root); | ||
| 404 | return ESP_OK; | ||
| 405 | } | ||
| 406 | |||
| 407 | static esp_err_t api_post_wallet_swap(httpd_req_t *req) | ||
| 408 | { | ||
| 409 | const tollgate_config_t *cfg = tollgate_config_get(); | ||
| 410 | |||
| 411 | if (wallet_balance() == 0) { | ||
| 412 | httpd_resp_set_status(req, "400 Bad Request"); | ||
| 413 | httpd_resp_set_type(req, "application/json"); | ||
| 414 | httpd_resp_send(req, "{\"error\":\"no proofs to swap\"}", 27); | ||
| 415 | return ESP_OK; | ||
| 416 | } | ||
| 417 | |||
| 418 | wallet_print_status(); | ||
| 419 | |||
| 420 | esp_err_t err = wallet_fetch_keysets(cfg->mint_url); | ||
| 421 | if (err != ESP_OK) { | ||
| 422 | httpd_resp_set_status(req, "502 Bad Gateway"); | ||
| 423 | httpd_resp_set_type(req, "application/json"); | ||
| 424 | httpd_resp_send(req, "{\"error\":\"keyset fetch failed\"}", 29); | ||
| 425 | return ESP_OK; | ||
| 426 | } | ||
| 427 | |||
| 428 | wallet_t *w = wallet_get(); | ||
| 429 | err = wallet_swap_proofs(cfg->mint_url, 0, w->proof_count); | ||
| 430 | if (err != ESP_OK) { | ||
| 431 | httpd_resp_set_status(req, "502 Bad Gateway"); | ||
| 432 | httpd_resp_set_type(req, "application/json"); | ||
| 433 | httpd_resp_send(req, "{\"error\":\"swap failed\"}", 21); | ||
| 434 | return ESP_OK; | ||
| 435 | } | ||
| 436 | |||
| 437 | wallet_print_status(); | ||
| 438 | |||
| 439 | cJSON *root = cJSON_CreateObject(); | ||
| 440 | cJSON_AddNumberToObject(root, "balance", (double)wallet_balance()); | ||
| 441 | cJSON_AddNumberToObject(root, "proof_count", wallet_get()->proof_count); | ||
| 442 | char *json = cJSON_PrintUnformatted(root); | ||
| 443 | httpd_resp_set_type(req, "application/json"); | ||
| 444 | httpd_resp_send(req, json, strlen(json)); | ||
| 445 | cJSON_free(json); | ||
| 446 | cJSON_Delete(root); | ||
| 447 | return ESP_OK; | ||
| 448 | } | ||
| 449 | |||
| 450 | static esp_err_t api_post_wallet_send(httpd_req_t *req) | ||
| 451 | { | ||
| 452 | int content_len = req->content_len; | ||
| 453 | if (content_len <= 0 || content_len > 32) { | ||
| 454 | httpd_resp_set_status(req, "400 Bad Request"); | ||
| 455 | httpd_resp_send(req, "invalid amount", 14); | ||
| 456 | return ESP_OK; | ||
| 457 | } | ||
| 458 | |||
| 459 | char body[32]; | ||
| 460 | int total = 0; | ||
| 461 | while (total < content_len) { | ||
| 462 | int r = httpd_req_recv(req, body + total, content_len - total); | ||
| 463 | if (r <= 0) { httpd_resp_send_500(req); return ESP_OK; } | ||
| 464 | total += r; | ||
| 465 | } | ||
| 466 | body[total] = '\0'; | ||
| 467 | |||
| 468 | uint64_t amount = strtoull(body, NULL, 10); | ||
| 469 | if (amount == 0) { | ||
| 470 | httpd_resp_set_status(req, "400 Bad Request"); | ||
| 471 | httpd_resp_send(req, "invalid amount", 14); | ||
| 472 | return ESP_OK; | ||
| 473 | } | ||
| 474 | |||
| 475 | const tollgate_config_t *cfg = tollgate_config_get(); | ||
| 476 | char token[4096]; | ||
| 477 | esp_err_t err = wallet_send(cfg->mint_url, amount, token, sizeof(token)); | ||
| 478 | if (err != ESP_OK) { | ||
| 479 | httpd_resp_set_status(req, "402 Payment Required"); | ||
| 480 | httpd_resp_set_type(req, "text/plain"); | ||
| 481 | httpd_resp_send(req, "insufficient balance", 20); | ||
| 482 | return ESP_OK; | ||
| 483 | } | ||
| 484 | |||
| 485 | httpd_resp_set_type(req, "text/plain"); | ||
| 486 | httpd_resp_send(req, token, strlen(token)); | ||
| 487 | return ESP_OK; | ||
| 488 | } | ||
| 489 | |||
| 366 | static const httpd_uri_t uri_discovery = { .uri = "/", .method = HTTP_GET, .handler = api_get_discovery }; | 490 | static const httpd_uri_t uri_discovery = { .uri = "/", .method = HTTP_GET, .handler = api_get_discovery }; |
| 367 | static const httpd_uri_t uri_payment = { .uri = "/", .method = HTTP_POST, .handler = api_post_payment }; | 491 | static const httpd_uri_t uri_payment = { .uri = "/", .method = HTTP_POST, .handler = api_post_payment }; |
| 368 | static const httpd_uri_t uri_usage = { .uri = "/usage", .method = HTTP_GET, .handler = api_get_usage }; | 492 | static const httpd_uri_t uri_usage = { .uri = "/usage", .method = HTTP_GET, .handler = api_get_usage }; |
| 369 | static const httpd_uri_t uri_whoami = { .uri = "/whoami", .method = HTTP_GET, .handler = api_get_whoami }; | 493 | static const httpd_uri_t uri_whoami = { .uri = "/whoami", .method = HTTP_GET, .handler = api_get_whoami }; |
| 494 | static const httpd_uri_t uri_wallet = { .uri = "/wallet", .method = HTTP_GET, .handler = api_get_wallet }; | ||
| 495 | static const httpd_uri_t uri_wallet_swap = { .uri = "/wallet/swap", .method = HTTP_POST, .handler = api_post_wallet_swap }; | ||
| 496 | static const httpd_uri_t uri_wallet_send = { .uri = "/wallet/send", .method = HTTP_POST, .handler = api_post_wallet_send }; | ||
| 370 | 497 | ||
| 371 | esp_err_t tollgate_api_start(void) | 498 | esp_err_t tollgate_api_start(void) |
| 372 | { | 499 | { |
| @@ -388,6 +515,9 @@ esp_err_t tollgate_api_start(void) | |||
| 388 | httpd_register_uri_handler(s_api_server, &uri_payment); | 515 | httpd_register_uri_handler(s_api_server, &uri_payment); |
| 389 | httpd_register_uri_handler(s_api_server, &uri_usage); | 516 | httpd_register_uri_handler(s_api_server, &uri_usage); |
| 390 | httpd_register_uri_handler(s_api_server, &uri_whoami); | 517 | httpd_register_uri_handler(s_api_server, &uri_whoami); |
| 518 | httpd_register_uri_handler(s_api_server, &uri_wallet); | ||
| 519 | httpd_register_uri_handler(s_api_server, &uri_wallet_swap); | ||
| 520 | httpd_register_uri_handler(s_api_server, &uri_wallet_send); | ||
| 391 | 521 | ||
| 392 | ESP_LOGI(TAG, "TollGate API started on port 2121"); | 522 | ESP_LOGI(TAG, "TollGate API started on port 2121"); |
| 393 | return ESP_OK; | 523 | return ESP_OK; |