on master help sign in
threads - update fetch-json example to get btc price from coingecko api
2f35894Tinnus Napbus
content/docs/userspace/threads/examples/get-json.md+73−86
@@ -6,122 +6,109 @@ template = "doc.html"
6
6
7Grabbing JSON from some url is very easy.
7Grabbing JSON from some url is very easy.
8
8
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`.
10
10
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.
12
14
13−- grab JSON of the latest base-hash from https://www.whatsthelatestbasehash.com/latesthash.json
15+#### `btc-price.hoon`
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`
20
16
21```hoon
17```hoon
22/- spider
18/- spider
23/+ *strandio
19/+ *strandio
24=, strand=strand:spider
20=, 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
21+=, dejs-soft:format
42− =, dejs:format
22+=, strand-fail=strand-fail:libstrand:spider
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−--
59^- thread:spider
23^- thread:spider
60|= arg=vase
24|= arg=vase
61=/ m (strand ,vase)
25=/ m (strand ,vase)
62^- form:m
26^- form:m
63−;< js-latest=json bind:m (fetch-json url-1)
27+=/ url
64−;< js-all=json bind:m (fetch-json url-2)
28+ "https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies="
65−=/ latest `latest-sur`(latest-format js-latest)
29+=/ cur !<((unit @tas) arg)
66−=/ all `(list all-sur)`(all-format js-all)
30+?~ cur (strand-fail %no-arg ~)
67−=/ res (skim all |=(a=all-sur =(hash.a hash.latest)))
31+=. u.cur (crip (cass (trip u.cur)))
68−?~ res
32+?. ((sane %tas) u.cur) (strand-fail %bad-currency-format ~)
69− %- (slog leaf+"Not Found" ~) (pure:m !>(~))
33+;< =json bind:m (fetch-json (weld url (trip u.cur)))
70−%- (slog leaf+"Hash: {(trip hash.i.res)}" ~)
34+=/ price=(unit @ta) ((ot ~[bitcoin+(ot [u.cur no]~)]) json)
71−%- (slog leaf+"Pill? {?:(pill.i.res "Yes" "No")}" ~)
35+?~ price ((slog 'Currency not found.' ~) (pure:m !>(~)))
72−%- (slog leaf+"Version: {(trip version.i.res)}" ~)
36+%- (slog leaf+"{(trip u.price)} {(cuss (trip u.cur))}" ~)
73−%- (slog leaf+"Published: {(trip published.i.res)}" ~)
74−%- (slog leaf+"Release: {(trip release.i.res)}" ~)
75(pure:m !>(~))
37(pure:m !>(~))
76```
38```
77
39
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:
79
48
80```
49```
81−> -latest-hash
50+> -btc-price %nzd
82−Hash: 0vj.dqqil.77m3k.a7v8d.mvrmi.8mavk.0a2nl.te6i6.cstfa.1ko6e.872gd
51+72455 NZD
83−Pill? No
52+> -btc-price %aud
84−Version: v2.39
53+68866 AUD
85−Published: ~2021.3.10..02.20.48
54+> -btc-price %gbp
86−Release: https://github.com/urbit/urbit/releases/tag/urbit-os-v2.39
55+37319 GBP
87−~
88```
56```
89
57
90### Analysis
58### Analysis
91
59
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:
93
61
94```hoon
62```hoon
95−=>
63+=/ cur !<((unit @tas) arg)
96−|%
64+?~ cur (strand-fail %no-arg ~)
97−++ url-1 "https://www.whatsthelatestbasehash.com/latesthash.json"
98−++ url-2 "https://www.whatsthelatestbasehash.com/all.json"
99−...
100```
65```
101
66
102−...then just called `fetch-json` like:
67+We then convert it to lowercase and check it's a valid `@tas`:
103
68
104```hoon
69```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 ~)
106```
72```
107
73
108−We've added formatting and structure arms like:
74+Next, we use the `fetch-json` function in `strandio` like so:
109
75
110```hoon
76```hoon
111−++ latest-format
77+;< =json bind:m (fetch-json (weld url (trip u.cur)))
112− =, dejs:format
78+```
113− %- ot
79+
114− :~ ['hash' so]
80+We convert the currency to a `tape` and `weld` it to the end of the `url`, which
115− ['timestamp' so]
81+we give as an argument to `fetch-json`. The `fetch-json` function will make the
116− ['last_five' so]
82+request to the URL, receive the result, parse the JSON and produce the result as
117− ==
83+a `json` structure.
118−++ latest-sur
84+
119− $: hash=@t
85+The JSON the API produces looks like:
120− timestamp=@t
86+
121− last-five=@t
87+```json
122− ==
88+{
89+ "bitcoin": {
90+ "usd": 49477
91+ }
92+}
123```
93```
124
94
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+```
126
112
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).