on master help sign in
threads - update fetch-json example to get btc price from coingecko api
commit2f358943723143c0d32255bcb4cb4f1886ec5735 authorTinnus Napbus <admin@tinnus-napbus.xyz> dateFri 10 Dec 2021, 01:02 (5 years ago) parent6761da4
1 file changed+73−86
content/docs/userspace/threads/examples/get-json.md+73−86
content/docs/userspace/threads/examples/get-json.md+73−86
@@ -6,122 +6,109 @@ template = "doc.html"
66
77Grabbing JSON from some url is very easy.
88
9−`strandio` includes the `fetch-json` function which will handle the http request and response parsing and just return unformatted json data.
9+`strandio` includes the `fetch-json` function which will handle the HTTP request, response, and parsing, producing `json`.
1010
11−Here's a simple thread that will:
11+The following thread fetches the current Bitcoin price from the [CoinGecko
12+API](https://www.coingecko.com/en/api) in the specified currency and prints it
13+to the terminal.
1214
13−- grab JSON of the latest base-hash from https://www.whatsthelatestbasehash.com/latesthash.json
14−- grab JSON of a list of all base-hashes with version info from https://www.whatsthelatestbasehash.com/all.json
15−- format and cast them
16−- check `all.json` includes the latest base-hash
17−- print the details of the latest base-hash to the dojo
18−
19−#### `latest-hash.hoon`
15+#### `btc-price.hoon`
2016
2117```hoon
2218/- spider
2319/+ *strandio
2420=, strand=strand:spider
25−=>
26−|%
27−++ url-1 "https://www.whatsthelatestbasehash.com/latesthash.json"
28−++ url-2 "https://www.whatsthelatestbasehash.com/all.json"
29−++ latest-format
30− =, dejs:format
31− %- ot
32− :~ ['hash' so]
33− ['timestamp' so]
34− ['last_five' so]
35− ==
36−++ latest-sur
37− $: hash=@t
38− timestamp=@t
39− last-five=@t
40− ==
41−++ all-format
42− =, dejs:format
43− %- ar
44− %- ot
45− :~ ['hash' so]
46− ['pill' bo]
47− ['version' so]
48− ['published' so]
49− ['release' so]
50− ==
51−++ all-sur
52− $: hash=@t
53− pill=?
54− version=@t
55− published=@t
56− release=@t
57− ==
58−--
21+=, dejs-soft:format
22+=, strand-fail=strand-fail:libstrand:spider
5923^- thread:spider
6024|= arg=vase
6125=/ m (strand ,vase)
6226^- form:m
63−;< js-latest=json bind:m (fetch-json url-1)
64−;< js-all=json bind:m (fetch-json url-2)
65−=/ latest `latest-sur`(latest-format js-latest)
66−=/ all `(list all-sur)`(all-format js-all)
67−=/ res (skim all |=(a=all-sur =(hash.a hash.latest)))
68−?~ res
69− %- (slog leaf+"Not Found" ~) (pure:m !>(~))
70−%- (slog leaf+"Hash: {(trip hash.i.res)}" ~)
71−%- (slog leaf+"Pill? {?:(pill.i.res "Yes" "No")}" ~)
72−%- (slog leaf+"Version: {(trip version.i.res)}" ~)
73−%- (slog leaf+"Published: {(trip published.i.res)}" ~)
74−%- (slog leaf+"Release: {(trip release.i.res)}" ~)
27+=/ url
28+ "https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies="
29+=/ cur !<((unit @tas) arg)
30+?~ cur (strand-fail %no-arg ~)
31+=. u.cur (crip (cass (trip u.cur)))
32+?. ((sane %tas) u.cur) (strand-fail %bad-currency-format ~)
33+;< =json bind:m (fetch-json (weld url (trip u.cur)))
34+=/ price=(unit @ta) ((ot ~[bitcoin+(ot [u.cur no]~)]) json)
35+?~ price ((slog 'Currency not found.' ~) (pure:m !>(~)))
36+%- (slog leaf+"{(trip u.price)} {(cuss (trip u.cur))}" ~)
7537(pure:m !>(~))
7638```
7739
78−Save it as `/ted/latest-hash.hoon` of the `%base` desk, `|commit %base` and run it with `-latest-hash`. You should see something like:
40+Save it as `/ted/btc-price.hoon` in the `%base` desk of a fake ship, `|commit %base` and run it with `-btc-price %usd`. You should see something like:
41+
42+```
43+> -btc-price %usd
44+49168 USD
45+```
46+
47+You can try with other currencies as well:
7948
8049```
81−> -latest-hash
82−Hash: 0vj.dqqil.77m3k.a7v8d.mvrmi.8mavk.0a2nl.te6i6.cstfa.1ko6e.872gd
83−Pill? No
84−Version: v2.39
85−Published: ~2021.3.10..02.20.48
86−Release: https://github.com/urbit/urbit/releases/tag/urbit-os-v2.39
87−~
50+> -btc-price %nzd
51+72455 NZD
52+> -btc-price %aud
53+68866 AUD
54+> -btc-price %gbp
55+37319 GBP
8856```
8957
9058### Analysis
9159
92−`fetch-json` takes a url as a tape, so we've added a core with the urls like:
60+The thread takes an `@tas` as its argument, which the dojo wraps in a `unit`. We extract the `vase` and check it's not empty:
9361
9462```hoon
95−=>
96−|%
97−++ url-1 "https://www.whatsthelatestbasehash.com/latesthash.json"
98−++ url-2 "https://www.whatsthelatestbasehash.com/all.json"
99−...
63+=/ cur !<((unit @tas) arg)
64+?~ cur (strand-fail %no-arg ~)
10065```
10166
102−...then just called `fetch-json` like:
67+We then convert it to lowercase and check it's a valid `@tas`:
10368
10469```hoon
105−;< js-latest=json bind:m (fetch-json url-1)
70+=. u.cur (crip (cass (trip u.cur)))
71+?. ((sane %tas) u.cur) (strand-fail %bad-currency-format ~)
10672```
10773
108−We've added formatting and structure arms like:
74+Next, we use the `fetch-json` function in `strandio` like so:
10975
11076```hoon
111−++ latest-format
112− =, dejs:format
113− %- ot
114− :~ ['hash' so]
115− ['timestamp' so]
116− ['last_five' so]
117− ==
118−++ latest-sur
119− $: hash=@t
120− timestamp=@t
121− last-five=@t
122− ==
77+;< =json bind:m (fetch-json (weld url (trip u.cur)))
78+```
79+
80+We convert the currency to a `tape` and `weld` it to the end of the `url`, which
81+we give as an argument to `fetch-json`. The `fetch-json` function will make the
82+request to the URL, receive the result, parse the JSON and produce the result as
83+a `json` structure.
84+
85+The JSON the API produces looks like:
86+
87+```json
88+{
89+ "bitcoin": {
90+ "usd": 49477
91+ }
92+}
12393```
12494
125−...to turn it from `json` to a noun with faces. You can have a look at the JSON formatting functions under `dejs:format` in `zuse.hoon` for how to deal with the various json types.
95+Since it's an object in an object, we decode them using nested
96+[`ot:dejs-soft:format`](/docs/hoon/reference/zuse/2d_7#otdejs-softformat)
97+functions, and the price itself using
98+[`no:dejs-soft:format`](/docs/hoon/reference/zuse/2d_7#nodejs-softformat) to
99+produce a `(unit @ta)`:
100+
101+```hoon
102+=/ price=(unit @ta) ((ot ~[bitcoin+(ot [u.cur no]~)]) json)
103+```
104+
105+Finally, we check if the `unit` is null and either print an error or print the price to the terminal with `slog` functions (the thread itself produces `~`):
106+
107+```hoon
108+?~ price ((slog 'Currency not found.' ~) (pure:m !>(~)))
109+%- (slog leaf+"{(trip u.price)} {(cuss (trip u.cur))}" ~)
110+(pure:m !>(~))
111+```
126112
127−After that it's just some ordinary list logic and printing.
113+For more information about working with `json`, see the [JSON
114+Guide](/docs/hoon/guides/json-guide).