21 cJSON *root = cJSON_Parse(resp);
25 const cJSON *result = cJSON_GetObjectItemCaseSensitive(root,
"result");
26 if (cJSON_IsString(result) && (result->valuestring != NULL)) {
27 size_t len = strlen(result->valuestring);
28 if ((len + 1U) <= out_size) {
29 ok = CW_Utils::safe_memcpy(
30 reinterpret_cast<uint8_t *
>(out), out_size,
31 reinterpret_cast<const uint8_t *
>(result->valuestring),
41 if ((out == NULL) || (out_size == 0U)) {
return false; }
44 cJSON *root = cJSON_Parse(resp);
48 const cJSON *err = cJSON_GetObjectItemCaseSensitive(root,
"error");
49 if (cJSON_IsObject(err)) {
50 const cJSON *msg = cJSON_GetObjectItemCaseSensitive(err,
"message");
51 if (cJSON_IsString(msg) && (msg->valuestring != NULL) &&
52 (msg->valuestring[0] !=
'\0')) {
57 size_t len = strlen(msg->valuestring);
58 if (len > (out_size - 1U)) { len = out_size - 1U; }
59 ok = CW_Utils::safe_memcpy(
60 reinterpret_cast<uint8_t *
>(out), out_size,
61 reinterpret_cast<const uint8_t *
>(msg->valuestring), len);
62 if (
ok) { out[len] =
'\0'; }
72 cJSON *root = cJSON_Parse(resp);
76 const cJSON *result = cJSON_GetObjectItemCaseSensitive(root,
"result");
77 if (cJSON_IsNull(result)) {
79 }
else if (cJSON_IsObject(result)) {
81 cJSON_GetObjectItemCaseSensitive(result,
"status");
82 if (cJSON_IsString(status) && (status->valuestring != NULL)) {
83 verdict = (strcmp(status->valuestring,
"0x1") == 0)
94 "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef";
98 return ((c >=
'A') && (c <=
'Z')) ?
static_cast<char>(c + (
'a' -
'A')) : c;
102static bool str_is(
const cJSON *j,
const char *want)
104 if (!cJSON_IsString(j) || (j->valuestring == NULL)) {
return false; }
105 const char *v = j->valuestring;
107 for (; (v[i] !=
'\0') && (want[i] !=
'\0'); i++) {
108 if (
lc(v[i]) !=
lc(want[i])) {
return false; }
110 return (v[i] ==
'\0') && (want[i] ==
'\0');
114static void addr_hex(
const uint8_t a[20],
bool word,
char *out)
116 static const char H[] =
"0123456789abcdef";
120 if (word) {
for (
size_t i = 0U; i < 24U; i++) { out[p++] =
'0'; } }
121 for (
size_t i = 0U; i < 20U; i++) {
122 out[p++] = H[a[i] >> 4];
123 out[p++] = H[a[i] & 0x0FU];
131 static const char H[] =
"0123456789abcdef";
135 for (
size_t i = 0U; i < 48U; i++) { out[p++] =
'0'; }
136 for (
int sh = 60; sh >= 0; sh -= 4) {
137 out[p++] = H[(v >> sh) & 0x0FULL];
144 const char *payee_word,
const char *amount_word)
146 const cJSON *log = NULL;
147 cJSON_ArrayForEach(log, logs) {
148 const cJSON *topics = cJSON_GetObjectItemCaseSensitive(log,
"topics");
149 if (!
str_is(cJSON_GetObjectItemCaseSensitive(log,
"address"), token) ||
150 !cJSON_IsArray(topics) || (cJSON_GetArraySize(topics) != 3)) {
154 str_is(cJSON_GetArrayItem(topics, 2), payee_word) &&
155 str_is(cJSON_GetObjectItemCaseSensitive(log,
"data"), amount_word)) {
165 if ((want == NULL) || (want->
tx_hash == NULL) || (want->
to == NULL)) {
174 cJSON *root = cJSON_Parse(resp);
176 const cJSON *r = cJSON_GetObjectItemCaseSensitive(root,
"result");
180 bool match =
str_is(cJSON_GetObjectItemCaseSensitive(r,
"transactionHash"),
182 str_is(cJSON_GetObjectItemCaseSensitive(r,
"to"), to_hex);
188 char amount_word[67];
191 match =
has_transfer(cJSON_GetObjectItemCaseSensitive(r,
"logs"),
192 to_hex, payee_word, amount_word);
bool eth_json_error_message(const char *resp, char *out, size_t out_size)
Extract the JSON-RPC error.message from a response body.
static const char TRANSFER_TOPIC[]
eth_json_receipt_t eth_json_receipt_status(const char *resp)
Classify an eth_getTransactionReceipt response body.
static bool str_is(const cJSON *j, const char *want)
true if a JSON string equals want, ignoring hex case.
static bool has_transfer(const cJSON *logs, const char *token, const char *payee_word, const char *amount_word)
true if logs holds a Transfer(*, payee, amount) from token.
static void addr_hex(const uint8_t a[20], bool word, char *out)
"0x" + the 20 bytes as hex, or left-padded to a 32-byte word.
bool eth_json_result_string(const char *resp, char *out, size_t out_size)
Extract the top-level "result" string from a JSON-RPC response.
static void word_hex(uint64_t v, char *out)
"0x" + v as a 32-byte big-endian word.
eth_json_receipt_t eth_json_receipt_check(const char *resp, const eth_receipt_expect_t *want)
Classify a receipt AND check it is the payment that was asked for.
JSON-RPC response parsing helpers โ kept in their own unit (cJSON + CW_Utils only,...
eth_json_receipt_t
Verdict for an eth_getTransactionReceipt response body.
@ ETH_JSON_RECEIPT_REVERTED
@ ETH_JSON_RECEIPT_PENDING
@ ETH_JSON_RECEIPT_SUCCESS
@ ETH_JSON_RECEIPT_MISMATCH
static esp_err_t ok(httpd_req_t *req, const char *msg)
200 with a plain-text message.
What a receipt must show for the payment to count โ see eth_json_receipt_check.