| 1256 | } |
| 1257 | |
| 1258 | static struct command_result *currency_done(struct command *cmd, |
| 1259 | const char *method, |
| 1260 | const char *buf, |
| 1261 | const jsmntok_t *result, |
| 1262 | struct currency_time *ctime) |
| 1263 | { |
| 1264 | struct bkpr *bkpr = bkpr_of(cmd->plugin); |
| 1265 | double rate; |
| 1266 | const char *err; |
| 1267 | |
| 1268 | err = json_scan(cmd, buf, result, "{rate:%}", |
| 1269 | JSON_SCAN(json_to_double, &rate)); |
| 1270 | if (err) { |
| 1271 | plugin_log(cmd->plugin, LOG_BROKEN, |
| 1272 | "Invalid currencyrate return '%.*s': %s", |
| 1273 | json_tok_full_len(result), |
| 1274 | json_tok_full(buf, result), err); |
| 1275 | /* Make sure they didn't change currency while we were out! */ |
| 1276 | } else if (bkpr->currency == ctime->currency) { |
| 1277 | char *val; |
| 1278 | const char **key; |
| 1279 | u64 raw_rate = (u64)(rate * ratefactor(bkpr->currency)); |
| 1280 | /* Can we extend previous entry */ |
| 1281 | u64 ts = ctime->timestamp + 1; |
| 1282 | struct currencyrate *crate |
| 1283 | = uintmap_before(bkpr->currency_rates, &ts); |
| 1284 | |
| 1285 | if (crate) { |
| 1286 | u64 crate_end = ts + crate->duration; |
| 1287 | /* If we raced, it might already be there! */ |
| 1288 | if (crate_end > ctime->timestamp) |
| 1289 | goto out; |
| 1290 | |
| 1291 | /* Reuse if it's recent, and the same rate. |
| 1292 | * (Recent check avoid glossing over failures, if we |
| 1293 | * couldn't get reliable data). */ |
| 1294 | if (raw_rate == crate->raw_rate |
| 1295 | && crate_end + CURRENCYRATE_TOLERANCE_SECONDS > ctime->timestamp) { |
| 1296 | uintmap_del(bkpr->currency_rates, ts); |
| 1297 | crate->duration = ctime->timestamp - ts + 1; |
| 1298 | } else { |
| 1299 | crate = NULL; |
| 1300 | } |
| 1301 | } |
| 1302 | |
| 1303 | if (!crate) { |
| 1304 | ts = ctime->timestamp; |
| 1305 | crate = tal(bkpr->currency_rates, struct currencyrate); |
| 1306 | crate->raw_rate = raw_rate; |
| 1307 | crate->duration = 1; |
| 1308 | } |
| 1309 | uintmap_add(bkpr->currency_rates, ts, crate); |
| 1310 | val = tal_fmt(tmpctx, "%"PRIu64":%u", |
| 1311 | crate->raw_rate, crate->duration); |
| 1312 | key = mkdatastorekey(tmpctx, |
| 1313 | "bookkeeper", |
| 1314 | "currencyrate", |
| 1315 | ctime->currency->name, |
nothing calls this directly
no test coverage detected