From 1355d040aada90c539d7848dacccf533ce13058f Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Mon, 14 Oct 2024 13:17:54 -0500 Subject: [PATCH] feat: add recent blocks --- CHANGELOG.md | 4 + dev/app.js | 385 ++++++++++++++++++++++++++++---------------- src/Exblo/API.purs | 5 + src/Exblo/Home.purs | 130 ++++++++++----- 4 files changed, 343 insertions(+), 181 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 87698f5..2a0f299 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.3.1.0] + +- Display recent blocks in home page + ## [0.3.0.0] ### Added diff --git a/dev/app.js b/dev/app.js index 2a8e4aa..8aa90b5 100644 --- a/dev/app.js +++ b/dev/app.js @@ -159,19 +159,19 @@ }; var applyFirst = function(dictApply) { var apply12 = apply(dictApply); - var map44 = map(dictApply.Functor0()); + var map45 = map(dictApply.Functor0()); return function(a2) { return function(b2) { - return apply12(map44($$const)(a2))(b2); + return apply12(map45($$const)(a2))(b2); }; }; }; var applySecond = function(dictApply) { var apply12 = apply(dictApply); - var map44 = map(dictApply.Functor0()); + var map45 = map(dictApply.Functor0()); return function(a2) { return function(b2) { - return apply12(map44($$const(identity2))(a2))(b2); + return apply12(map45($$const(identity2))(a2))(b2); }; }; }; @@ -411,11 +411,11 @@ // output/Data.Ord/foreign.js var unsafeCompareImpl = function(lt) { - return function(eq4) { + return function(eq5) { return function(gt) { return function(x) { return function(y) { - return x < y ? lt : x === y ? eq4 : gt; + return x < y ? lt : x === y ? eq5 : gt; }; }; }; @@ -796,7 +796,7 @@ }; }; var eqMaybe = function(dictEq) { - var eq4 = eq(dictEq); + var eq5 = eq(dictEq); return { eq: function(x) { return function(y) { @@ -805,7 +805,7 @@ } ; if (x instanceof Just && y instanceof Just) { - return eq4(x.value0)(y.value0); + return eq5(x.value0)(y.value0); } ; return false; @@ -1138,13 +1138,13 @@ return v.value0; }; var eqTuple = function(dictEq) { - var eq4 = eq(dictEq); + var eq5 = eq(dictEq); return function(dictEq1) { var eq12 = eq(dictEq1); return { eq: function(x) { return function(y) { - return eq4(x.value0)(y.value0) && eq12(x.value1)(y.value1); + return eq5(x.value0)(y.value0) && eq12(x.value1)(y.value1); }; } }; @@ -1337,7 +1337,7 @@ var intercalate = function(dictFoldable) { var foldl22 = foldl(dictFoldable); return function(dictMonoid) { - var append9 = append(dictMonoid.Semigroup0()); + var append10 = append(dictMonoid.Semigroup0()); var mempty3 = mempty(dictMonoid); return function(sep) { return function(xs) { @@ -1352,7 +1352,7 @@ ; return { init: false, - acc: append9(v.acc)(append9(sep)(v1)) + acc: append10(v.acc)(append10(sep)(v1)) }; }; }; @@ -1463,12 +1463,12 @@ var foldMapDefaultR = function(dictFoldable) { var foldr22 = foldr(dictFoldable); return function(dictMonoid) { - var append9 = append(dictMonoid.Semigroup0()); + var append10 = append(dictMonoid.Semigroup0()); var mempty3 = mempty(dictMonoid); return function(f) { return foldr22(function(x) { return function(acc) { - return append9(f(x))(acc); + return append10(f(x))(acc); }; })(mempty3); }; @@ -2536,10 +2536,10 @@ var $$try2 = function(dictMonadError) { var catchError1 = catchError(dictMonadError); var Monad0 = dictMonadError.MonadThrow0().Monad0(); - var map44 = map(Monad0.Bind1().Apply0().Functor0()); + var map45 = map(Monad0.Bind1().Apply0().Functor0()); var pure23 = pure(Monad0.Applicative0()); return function(a2) { - return catchError1(map44(Right.create)(a2))(function($52) { + return catchError1(map45(Right.create)(a2))(function($52) { return pure23(Left.create($52)); }); }; @@ -2912,7 +2912,7 @@ }; }; var altExceptT = function(dictSemigroup) { - var append9 = append(dictSemigroup); + var append10 = append(dictSemigroup); return function(dictMonad) { var Bind1 = dictMonad.Bind1(); var bind19 = bind(Bind1); @@ -2933,7 +2933,7 @@ } ; if (rn instanceof Left) { - return pure23(new Left(append9(rm.value0)(rn.value0))); + return pure23(new Left(append10(rm.value0)(rn.value0))); } ; throw new Error("Failed pattern match at Control.Monad.Except.Trans (line 86, column 9 - line 88, column 49): " + [rn.constructor.name]); @@ -3106,7 +3106,7 @@ }; } return function(apply6) { - return function(map44) { + return function(map45) { return function(pure23) { return function(f) { return function(array) { @@ -3115,14 +3115,14 @@ case 0: return pure23([]); case 1: - return map44(array1)(f(array[bot])); + return map45(array1)(f(array[bot])); case 2: - return apply6(map44(array2)(f(array[bot])))(f(array[bot + 1])); + return apply6(map45(array2)(f(array[bot])))(f(array[bot + 1])); case 3: - return apply6(apply6(map44(array3)(f(array[bot])))(f(array[bot + 1])))(f(array[bot + 2])); + return apply6(apply6(map45(array3)(f(array[bot])))(f(array[bot + 1])))(f(array[bot + 2])); default: var pivot = bot + Math.floor((top3 - bot) / 4) * 2; - return apply6(map44(concat2)(go2(bot, pivot)))(go2(pivot, top3)); + return apply6(map45(concat2)(go2(bot, pivot)))(go2(pivot, top3)); } } return go2(0, array.length); @@ -3141,7 +3141,7 @@ var traversableMaybe = { traverse: function(dictApplicative) { var pure23 = pure(dictApplicative); - var map44 = map(dictApplicative.Apply0().Functor0()); + var map45 = map(dictApplicative.Apply0().Functor0()); return function(v) { return function(v1) { if (v1 instanceof Nothing) { @@ -3149,7 +3149,7 @@ } ; if (v1 instanceof Just) { - return map44(Just.create)(v(v1.value0)); + return map45(Just.create)(v(v1.value0)); } ; throw new Error("Failed pattern match at Data.Traversable (line 115, column 1 - line 119, column 33): " + [v.constructor.name, v1.constructor.name]); @@ -3158,14 +3158,14 @@ }, sequence: function(dictApplicative) { var pure23 = pure(dictApplicative); - var map44 = map(dictApplicative.Apply0().Functor0()); + var map45 = map(dictApplicative.Apply0().Functor0()); return function(v) { if (v instanceof Nothing) { return pure23(Nothing.value); } ; if (v instanceof Just) { - return map44(Just.create)(v.value0); + return map45(Just.create)(v.value0); } ; throw new Error("Failed pattern match at Data.Traversable (line 115, column 1 - line 119, column 33): " + [v.constructor.name]); @@ -3986,13 +3986,13 @@ var foldMapWithIndexDefaultR = function(dictFoldableWithIndex) { var foldrWithIndex1 = foldrWithIndex(dictFoldableWithIndex); return function(dictMonoid) { - var append9 = append(dictMonoid.Semigroup0()); + var append10 = append(dictMonoid.Semigroup0()); var mempty3 = mempty(dictMonoid); return function(f) { return foldrWithIndex1(function(i2) { return function(x) { return function(acc) { - return append9(f(i2)(x))(acc); + return append10(f(i2)(x))(acc); }; }; })(mempty3); @@ -4183,14 +4183,14 @@ traverseWithIndex: function(dictApplicative) { var Apply0 = dictApplicative.Apply0(); var apply6 = apply(Apply0); - var map44 = map(Apply0.Functor0()); + var map45 = map(Apply0.Functor0()); var pure111 = pure(dictApplicative); return function(f) { return function(ms) { return fold2(function(acc) { return function(k) { return function(v) { - return apply6(map44(flip(insert(k)))(acc))(f(k)(v)); + return apply6(map45(flip(insert(k)))(acc))(f(k)(v)); }; }; })(pure111(empty2))(ms); @@ -6944,7 +6944,7 @@ return unsafeReadTagged(dictMonad)("Number"); }; var readInt = function(dictMonad) { - var map44 = map(dictMonad.Bind1().Apply0().Functor0()); + var map45 = map(dictMonad.Bind1().Apply0().Functor0()); var readNumber1 = readNumber(dictMonad); return function(value15) { var error4 = new Left(singleton6(new TypeMismatch2("Int", tagOf(value15)))); @@ -6954,7 +6954,7 @@ return $155(fromNumber($156)); }; }(); - return mapExceptT(map44(either($$const(error4))(fromNumber2)))(readNumber1(value15)); + return mapExceptT(map45(either($$const(error4))(fromNumber2)))(readNumber1(value15)); }; }; var readString = function(dictMonad) { @@ -8445,11 +8445,11 @@ // output/Data.Bifoldable/index.js var bifoldableTuple = { bifoldMap: function(dictMonoid) { - var append9 = append(dictMonoid.Semigroup0()); + var append10 = append(dictMonoid.Semigroup0()); return function(f) { return function(g) { return function(v) { - return append9(f(v.value0))(g(v.value1)); + return append10(f(v.value0))(g(v.value1)); }; }; }; @@ -8492,11 +8492,11 @@ bitraverse: function(dictApplicative) { var Apply0 = dictApplicative.Apply0(); var apply6 = apply(Apply0); - var map44 = map(Apply0.Functor0()); + var map45 = map(Apply0.Functor0()); return function(f) { return function(g) { return function(v) { - return apply6(map44(Tuple.create)(f(v.value0)))(g(v.value1)); + return apply6(map45(Tuple.create)(f(v.value0)))(g(v.value1)); }; }; }; @@ -8504,9 +8504,9 @@ bisequence: function(dictApplicative) { var Apply0 = dictApplicative.Apply0(); var apply6 = apply(Apply0); - var map44 = map(Apply0.Functor0()); + var map45 = map(Apply0.Functor0()); return function(v) { - return apply6(map44(Tuple.create)(v.value0))(v.value1); + return apply6(map45(Tuple.create)(v.value0))(v.value1); }; }, Bifunctor0: function() { @@ -9878,11 +9878,11 @@ return x; }; var selectEq = function(dictEq) { - var eq4 = eq(dictEq); + var eq5 = eq(dictEq); return function($14) { return Selector(/* @__PURE__ */ function(v) { return { - eq: eq4, + eq: eq5, select: v }; }($14)); @@ -12651,7 +12651,7 @@ }; var runParserT$prime = function(dictMonadRec) { var Monad0 = dictMonadRec.Monad0(); - var map44 = map(Monad0.Bind1().Apply0().Functor0()); + var map45 = map(Monad0.Bind1().Apply0().Functor0()); var pure111 = pure(Monad0.Applicative0()); var tailRecM4 = tailRecM(dictMonadRec); return function(state1) { @@ -12668,7 +12668,7 @@ ; if (v1 instanceof Lift3) { $tco_done = true; - return map44(Loop.create)(v1.value0); + return map45(Loop.create)(v1.value0); } ; if (v1 instanceof Stop) { @@ -12710,12 +12710,12 @@ column: 1 }; var runParserT = function(dictMonadRec) { - var map44 = map(dictMonadRec.Monad0().Bind1().Apply0().Functor0()); + var map45 = map(dictMonadRec.Monad0().Bind1().Apply0().Functor0()); var runParserT$prime1 = runParserT$prime(dictMonadRec); return function(s) { return function(p2) { var initialState = new ParseState(s, initialPos, false); - return map44(fst)(runParserT$prime1(initialState)(p2)); + return map45(fst)(runParserT$prime1(initialState)(p2)); }; }; }; @@ -12986,13 +12986,13 @@ }; }; var oneOfAs = function(dictFunctor) { - var map44 = map(dictFunctor); + var map45 = map(dictFunctor); return function(dictFoldable) { var choice2 = choice(dictFoldable); return function(dictMonad) { return function(p2) { return function(xs) { - return choice2(map44(function(v) { + return choice2(map45(function(v) { return voidLeft3(p2(v.value0))(v.value1); })(xs)); }; @@ -14036,10 +14036,10 @@ return function(dictApplicative) { var Apply0 = dictApplicative.Apply0(); var apply6 = apply(Apply0); - var map44 = map(Apply0.Functor0()); + var map45 = map(Apply0.Functor0()); return function(fun) { return function(a2) { - return apply6(map44(applyEither1)(runExceptT(fun)))(runExceptT(a2)); + return apply6(map45(applyEither1)(runExceptT(fun)))(runExceptT(a2)); }; }; }; @@ -14327,6 +14327,15 @@ }; }; + // output/Affjax.StatusCode/index.js + var eqStatusCode = { + eq: function(x) { + return function(y) { + return x === y; + }; + } + }; + // output/Exblo.Home/index.js var forever2 = /* @__PURE__ */ forever(monadRecAff); var discard4 = /* @__PURE__ */ discard(discardUnit); @@ -14335,13 +14344,30 @@ var show7 = /* @__PURE__ */ show(showInt); var value14 = /* @__PURE__ */ value(isPropString); var type_19 = /* @__PURE__ */ type_(isPropButtonType); - var show17 = /* @__PURE__ */ show(showZcashNet); + var show17 = /* @__PURE__ */ show(showString); + var append9 = /* @__PURE__ */ append(semigroupArray); + var map38 = /* @__PURE__ */ map(functorArray); + var show23 = /* @__PURE__ */ show(showZcashNet); var bind9 = /* @__PURE__ */ bind(bindHalogenM); var bindFlipped8 = /* @__PURE__ */ bindFlipped(bindHalogenM); var discard22 = /* @__PURE__ */ discard4(bindHalogenM); var modify_5 = /* @__PURE__ */ modify_2(monadStateHalogenM); var readJSON3 = /* @__PURE__ */ readJSON(readInt2); - var show23 = /* @__PURE__ */ show(/* @__PURE__ */ showNonEmptyList(showForeignError)); + var show32 = /* @__PURE__ */ show(/* @__PURE__ */ showNonEmptyList(showForeignError)); + var eq4 = /* @__PURE__ */ eq(eqStatusCode); + var readJSON1 = /* @__PURE__ */ readJSON(/* @__PURE__ */ readArray2(/* @__PURE__ */ readRecord()(/* @__PURE__ */ readFieldsCons({ + reflectSymbol: function() { + return "hash"; + } + })(readString3)(/* @__PURE__ */ readFieldsCons({ + reflectSymbol: function() { + return "height"; + } + })(readInt2)(/* @__PURE__ */ readFieldsCons({ + reflectSymbol: function() { + return "time"; + } + })(readInt2)(readFieldsNil)()())()())()()))); var gets4 = /* @__PURE__ */ gets(monadStateHalogenM); var Initialize4 = /* @__PURE__ */ function() { function Initialize7() { @@ -14422,12 +14448,32 @@ return show7(state3.block.value0); } ; - throw new Error("Failed pattern match at Exblo.Home (line 68, column 17 - line 72, column 38): " + [state3.block.constructor.name]); + throw new Error("Failed pattern match at Exblo.Home (line 70, column 17 - line 74, column 38): " + [state3.block.constructor.name]); }())])]), form([onSubmit(function(ev) { return new Search(ev); })])([p_([input([css("input"), value14(state3.term), placeholder("TX ID/Block height..."), onValueInput(function(str) { return new SetTerm(str); - })]), button([css("btn-primary raised"), type_19(ButtonSubmit.value)])([i([css("ri-search-line ri-xl")])([])])])]), table([css("footer")])([tr_([td([css("footer")])([p_([text("Made with "), a([href("https://www.purescript.org/")])([text("PureScript")])])]), td([css("footer")])([p_([i([css("ri-copyright-line")])([]), text("2024 Vergara Technologies LLC")])]), td([css("footer")])([p([])([text("Network: "), text(show17(state3.network)), br_, text("Server: "), text(state3.version), br_, text("UI: 0.3.0.0"), br_, text("Zebra Node: "), text(state3.zebra)])])])])]); + })]), button([css("btn-primary raised"), type_19(ButtonSubmit.value)])([i([css("ri-search-line ri-xl")])([])])])]), function() { + if (state3.recents instanceof NotAsked) { + return div_([]); + } + ; + if (state3.recents instanceof Loading2) { + return div3([css("card")])([text("Processing data...")]); + } + ; + if (state3.recents instanceof Failure) { + return div3([css("card")])([text(show17(state3.recents.value0))]); + } + ; + if (state3.recents instanceof Success2) { + return div3([css("card")])([h3_([text("recent blocks")]), table_(append9([tr_([th_([text("mined")]), th_([text("hash")])])])(map38(function(b2) { + return tr_([td_([text(convertToDate(b2.time))]), td_([a([safeHref(new Blk(show7(b2.height)))])([text(b2.hash)])])]); + })(state3.recents.value0)))]); + } + ; + throw new Error("Failed pattern match at Exblo.Home (line 93, column 7 - line 121, column 14): " + [state3.recents.constructor.name]); + }(), table([css("footer")])([tr_([td([css("footer")])([p_([text("Made with "), a([href("https://www.purescript.org/")])([text("PureScript")])])]), td([css("footer")])([p_([i([css("ri-copyright-line")])([]), text("2024 Vergara Technologies LLC")])]), td([css("footer")])([p([])([text("Network: "), text(show23(state3.network)), br_, text("Server: "), text(state3.version), br_, text("UI: 0.3.0.0"), br_, text("Zebra Node: "), text(state3.zebra)])])])])]); }; var handleAction2 = function(dictMonadAff) { var monadAffHalogenM2 = monadAffHalogenM(dictMonadAff); @@ -14445,18 +14491,18 @@ return bind9(bindFlipped8(subscribe2)(timer1(Refresh.value)))(function() { return bind9(getStore2)(function(st) { return discard22(modify_5(function(v1) { - var $70 = {}; - for (var $71 in v1) { - if ({}.hasOwnProperty.call(v1, $71)) { - $70[$71] = v1[$71]; + var $103 = {}; + for (var $104 in v1) { + if ({}.hasOwnProperty.call(v1, $104)) { + $103[$104] = v1[$104]; } ; } ; - $70.network = st.network; - $70.zebra = st.zebraVersion; - $70.version = st.version; - return $70; + $103.network = st.network; + $103.zebra = st.zebraVersion; + $103.version = st.version; + return $103; }))(function() { return handleAction2(dictMonadAff)(dictNavigate)(dictMonadStore)(Refresh.value); }); @@ -14466,93 +14512,157 @@ ; if (v instanceof Refresh) { return discard22(modify_5(function(v1) { - var $73 = {}; - for (var $74 in v1) { - if ({}.hasOwnProperty.call(v1, $74)) { - $73[$74] = v1[$74]; + var $106 = {}; + for (var $107 in v1) { + if ({}.hasOwnProperty.call(v1, $107)) { + $106[$107] = v1[$107]; } ; } ; - $73.block = Loading2.value; - return $73; + $106.block = Loading2.value; + $106.recents = Loading2.value; + return $106; }))(function() { return bind9(liftAff2(get4(string)("https://api.exblo.app/getblock")))(function(res) { - if (res instanceof Left) { - return log4("/block response failed to decode: " + printError(res.value0)); - } - ; - if (res instanceof Right) { - var v1 = readJSON3(res.value0.body); - if (v1 instanceof Right) { - return modify_5(function(v2) { - var $79 = {}; - for (var $80 in v2) { - if ({}.hasOwnProperty.call(v2, $80)) { - $79[$80] = v2[$80]; - } - ; + return bind9(liftAff2(get4(string)("https://api.exblo.app/getrecentblocks")))(function(resList) { + return discard22(function() { + if (res instanceof Left) { + return log4("/block response failed to decode: " + printError(res.value0)); + } + ; + if (res instanceof Right) { + var v1 = readJSON3(res.value0.body); + if (v1 instanceof Right) { + return modify_5(function(v2) { + var $112 = {}; + for (var $113 in v2) { + if ({}.hasOwnProperty.call(v2, $113)) { + $112[$113] = v2[$113]; + } + ; + } + ; + $112.block = new Success2(v1.value0); + return $112; + }); } ; - $79.block = new Success2(v1.value0); - return $79; - }); - } - ; - if (v1 instanceof Left) { - return discard22(log4("Can't parse JSON. " + show23(v1.value0)))(function() { - return modify_5(function(v2) { - var $83 = {}; - for (var $84 in v2) { - if ({}.hasOwnProperty.call(v2, $84)) { - $83[$84] = v2[$84]; + if (v1 instanceof Left) { + return discard22(log4("Can't parse JSON. " + show32(v1.value0)))(function() { + return modify_5(function(v2) { + var $116 = {}; + for (var $117 in v2) { + if ({}.hasOwnProperty.call(v2, $117)) { + $116[$117] = v2[$117]; + } + ; + } + ; + $116.block = new Failure("Failed to parse response"); + return $116; + }); + }); + } + ; + throw new Error("Failed pattern match at Exblo.Home (line 176, column 9 - line 184, column 61): " + [v1.constructor.name]); + } + ; + throw new Error("Failed pattern match at Exblo.Home (line 172, column 5 - line 184, column 61): " + [res.constructor.name]); + }())(function() { + if (resList instanceof Left) { + return log4("/getrecentblocks response failed to decode: " + printError(resList.value0)); + } + ; + if (resList instanceof Right) { + var $123 = eq4(resList.value0.status)(200); + if ($123) { + var v1 = readJSON1(resList.value0.body); + if (v1 instanceof Right) { + return modify_5(function(v2) { + var $125 = {}; + for (var $126 in v2) { + if ({}.hasOwnProperty.call(v2, $126)) { + $125[$126] = v2[$126]; + } + ; + } + ; + $125.recents = new Success2(v1.value0); + return $125; + }); + } + ; + if (v1 instanceof Left) { + return discard22(log4("Can't parse JSON. " + show32(v1.value0)))(function() { + return modify_5(function(v2) { + var $129 = {}; + for (var $130 in v2) { + if ({}.hasOwnProperty.call(v2, $130)) { + $129[$130] = v2[$130]; + } + ; + } + ; + $129.recents = new Failure("Failed to parse response"); + return $129; + }); + }); + } + ; + throw new Error("Failed pattern match at Exblo.Home (line 189, column 55 - line 194, column 73): " + [v1.constructor.name]); + } + ; + return modify_5(function(v12) { + var $133 = {}; + for (var $134 in v12) { + if ({}.hasOwnProperty.call(v12, $134)) { + $133[$134] = v12[$134]; } ; } ; - $83.block = new Failure("Failed to parse response"); - return $83; + $133.recents = new Failure("Error in API server"); + return $133; }); - }); - } - ; - throw new Error("Failed pattern match at Exblo.Home (line 144, column 9 - line 152, column 61): " + [v1.constructor.name]); - } - ; - throw new Error("Failed pattern match at Exblo.Home (line 140, column 5 - line 152, column 61): " + [res.constructor.name]); + } + ; + throw new Error("Failed pattern match at Exblo.Home (line 185, column 5 - line 195, column 69): " + [resList.constructor.name]); + }); + }); }); }); } ; if (v instanceof SetTerm) { return modify_5(function(v1) { - var $88 = {}; - for (var $89 in v1) { - if ({}.hasOwnProperty.call(v1, $89)) { - $88[$89] = v1[$89]; + var $137 = {}; + for (var $138 in v1) { + if ({}.hasOwnProperty.call(v1, $138)) { + $137[$138] = v1[$138]; } ; } ; - $88.term = v.value0; - return $88; + $137.term = v.value0; + return $137; }); } ; if (v instanceof Receive4) { return modify_5(function(v1) { - var $92 = {}; - for (var $93 in v1) { - if ({}.hasOwnProperty.call(v1, $93)) { - $92[$93] = v1[$93]; + var $141 = {}; + for (var $142 in v1) { + if ({}.hasOwnProperty.call(v1, $142)) { + $141[$142] = v1[$142]; } ; } ; - $92.network = v.value0.context.network; - $92.zebra = v.value0.context.zebraVersion; - $92.version = v.value0.context.version; - return $92; + $141.network = v.value0.context.network; + $141.zebra = v.value0.context.zebraVersion; + $141.version = v.value0.context.version; + return $141; }); } ; @@ -14561,8 +14671,8 @@ return bind9(gets4(function(v1) { return v1.term; }))(function(term) { - var $98 = length3(term) !== 64; - if ($98) { + var $147 = length3(term) !== 64; + if ($147) { return navigate2(new Blk(term)); } ; @@ -14571,7 +14681,7 @@ }); } ; - throw new Error("Failed pattern match at Exblo.Home (line 131, column 16 - line 162, column 30): " + [v.constructor.name]); + throw new Error("Failed pattern match at Exblo.Home (line 162, column 16 - line 204, column 28): " + [v.constructor.name]); }; }; }; @@ -14589,7 +14699,8 @@ term: "", network: TestNet.value, zebra: "", - version: "" + version: "", + recents: NotAsked.value }; }, render: render2, @@ -14597,8 +14708,8 @@ handleQuery: defaultEval.handleQuery, finalize: defaultEval.finalize, handleAction: handleAction1(dictNavigate)(dictMonadStore), - receive: function($100) { - return Just.create(Receive4.create($100)); + receive: function($149) { + return Just.create(Receive4.create($149)); }, initialize: new Just(Initialize4.value) }) @@ -15048,7 +15159,7 @@ var bindFlipped9 = /* @__PURE__ */ bindFlipped(bindEither); var decodeJson3 = /* @__PURE__ */ decodeJson(decodeJsonExbloInfo); var show9 = /* @__PURE__ */ show(showJsonDecodeError); - var map38 = /* @__PURE__ */ map(functorHalogenM); + var map39 = /* @__PURE__ */ map(functorHalogenM); var Navigate = /* @__PURE__ */ function() { function Navigate2(value0, value1) { this.value0 = value0; @@ -15170,7 +15281,7 @@ ; throw new Error("Failed pattern match at Exblo.Router (line 73, column 5 - line 80, column 69): " + [res.constructor.name]); }())(function() { - return bind11(map38(function() { + return bind11(map39(function() { var $97 = parse(routeCodec); return function($98) { return hush($97($98)); @@ -15229,7 +15340,7 @@ var pure16 = /* @__PURE__ */ pure(applicativeAff); var bindFlipped1 = /* @__PURE__ */ bindFlipped(bindMaybe); var pure17 = /* @__PURE__ */ pure(applicativeEffect); - var map39 = /* @__PURE__ */ map(functorEffect); + var map40 = /* @__PURE__ */ map(functorEffect); var discard7 = /* @__PURE__ */ discard(discardUnit); var throwError3 = /* @__PURE__ */ throwError(monadThrowAff); var selectElement = function(query3) { @@ -15247,7 +15358,7 @@ return function __do2() { var rs = bindFlipped10(readyState)(bindFlipped10(document)(windowImpl))(); if (rs instanceof Loading) { - var et = map39(toEventTarget)(windowImpl)(); + var et = map40(toEventTarget)(windowImpl)(); var listener = eventListener(function(v) { return callback(new Right(unit)); })(); @@ -15344,7 +15455,7 @@ var fork3 = /* @__PURE__ */ fork(monadForkAff); var parSequence_2 = /* @__PURE__ */ parSequence_(parallelAff)(applicativeParAff)(foldableList); var pure18 = /* @__PURE__ */ pure(applicativeAff); - var map40 = /* @__PURE__ */ map(functorCoyoneda); + var map41 = /* @__PURE__ */ map(functorCoyoneda); var parallel3 = /* @__PURE__ */ parallel(parallelAff); var map115 = /* @__PURE__ */ map(functorAff); var sequential2 = /* @__PURE__ */ sequential(parallelAff); @@ -15418,7 +15529,7 @@ return function(ref2) { return function(q2) { return bind14(liftEffect6(read(ref2)))(function(v) { - return evalM(render5)(ref2)(v["component"]["eval"](new Query(map40(Just.create)(liftCoyoneda(q2)), $$const(Nothing.value)))); + return evalM(render5)(ref2)(v["component"]["eval"](new Query(map41(Just.create)(liftCoyoneda(q2)), $$const(Nothing.value)))); }); }; }; @@ -15628,7 +15739,7 @@ var parSequence_3 = /* @__PURE__ */ parSequence_(parallelAff)(applicativeParAff)(foldableList); var liftEffect7 = /* @__PURE__ */ liftEffect(monadEffectAff); var pure19 = /* @__PURE__ */ pure(applicativeEffect); - var map41 = /* @__PURE__ */ map(functorEffect); + var map42 = /* @__PURE__ */ map(functorEffect); var pure110 = /* @__PURE__ */ pure(applicativeAff); var when3 = /* @__PURE__ */ when(applicativeEffect); var renderStateX2 = /* @__PURE__ */ renderStateX(functorEffect); @@ -15726,7 +15837,7 @@ return function(childrenOutRef) { return unComponentSlot(function(slot3) { return function __do2() { - var childrenIn = map41(slot3.pop)(read(childrenInRef))(); + var childrenIn = map42(slot3.pop)(read(childrenInRef))(); var $$var2 = function() { if (childrenIn instanceof Just) { write(childrenIn.value0.value1)(childrenInRef)(); @@ -15756,7 +15867,7 @@ ; throw new Error("Failed pattern match at Halogen.Aff.Driver (line 213, column 14 - line 222, column 98): " + [childrenIn.constructor.name]); }(); - var isDuplicate = map41(function($69) { + var isDuplicate = map42(function($69) { return isJust(slot3.get($69)); })(read(childrenOutRef))(); when3(isDuplicate)(warn("Halogen: Duplicate slot address was detected during rendering, unexpected results may occur"))(); @@ -15782,7 +15893,7 @@ return function($$var2) { return function __do2() { var v = read($$var2)(); - var shouldProcessHandlers = map41(isNothing)(read(v.pendingHandlers))(); + var shouldProcessHandlers = map42(isNothing)(read(v.pendingHandlers))(); when3(shouldProcessHandlers)(write(new Just(Nil.value))(v.pendingHandlers))(); write(empty6)(v.childrenOut)(); write(v.children)(v.childrenIn)(); @@ -15975,15 +16086,15 @@ } // output/Web.DOM.Node/index.js - var map42 = /* @__PURE__ */ map(functorEffect); + var map43 = /* @__PURE__ */ map(functorEffect); var parentNode2 = /* @__PURE__ */ function() { - var $6 = map42(toMaybe); + var $6 = map43(toMaybe); return function($7) { return $6(_parentNode($7)); }; }(); var nextSibling = /* @__PURE__ */ function() { - var $15 = map42(toMaybe); + var $15 = map43(toMaybe); return function($16) { return $15(_nextSibling($16)); }; @@ -16013,7 +16124,7 @@ var identity15 = /* @__PURE__ */ identity(categoryFn); var bind17 = /* @__PURE__ */ bind(bindAff); var liftEffect8 = /* @__PURE__ */ liftEffect(monadEffectAff); - var map43 = /* @__PURE__ */ map(functorEffect); + var map44 = /* @__PURE__ */ map(functorEffect); var bindFlipped13 = /* @__PURE__ */ bindFlipped(bindEffect); var substInParent = function(v) { return function(v1) { @@ -16161,7 +16272,7 @@ var runUI2 = function(component6) { return function(i2) { return function(element3) { - return bind17(liftEffect8(map43(toDocument)(bindFlipped13(document)(windowImpl))))(function(document2) { + return bind17(liftEffect8(map44(toDocument)(bindFlipped13(document)(windowImpl))))(function(document2) { return runUI(renderSpec(document2)(element3))(component6)(i2); }); }; diff --git a/src/Exblo/API.purs b/src/Exblo/API.purs index 516df49..4adc437 100644 --- a/src/Exblo/API.purs +++ b/src/Exblo/API.purs @@ -142,3 +142,8 @@ type Block = , tx :: Array String } +type ShortBlock = + { hash :: String + , height :: Int + , time :: Int + } diff --git a/src/Exblo/Home.purs b/src/Exblo/Home.purs index cf80605..2be8f21 100644 --- a/src/Exblo/Home.purs +++ b/src/Exblo/Home.purs @@ -3,6 +3,7 @@ module Exblo.Home where import Prelude import Control.Monad.Rec.Class (forever) import Simple.JSON (readJSON) +import Affjax.StatusCode (StatusCode(..)) import Affjax.Web as AX import Affjax.ResponseFormat as AXRF import Data.Maybe (Maybe(..)) @@ -12,9 +13,9 @@ import Effect.Aff as Aff import Effect.Aff.Class (class MonadAff) import Effect.Class.Console (log) import Effect.Aff (Milliseconds(..)) -import Exblo.API (ZcashNet(..)) +import Exblo.API (ZcashNet(..), ShortBlock) import Exblo.Navigate (class Navigate, navigate, Route(..)) -import Exblo.Utils (css) +import Exblo.Utils (css, convertToDate, safeHref) import Exblo.Store as S import Halogen as H import Halogen.HTML as HH @@ -36,6 +37,7 @@ type State = , network :: ZcashNet , zebra :: String , version :: String + , recents :: RemoteData String (Array ShortBlock) } data Action @@ -48,7 +50,7 @@ data Action component :: forall q o m. MonadAff m => MonadStore S.Action S.Store m => Navigate m => H.Component q Input o m component = connect selectAll $ H.mkComponent - { initialState: \_ -> { block: NotAsked, term: "", network: TestNet, zebra: "", version: "" } + { initialState: \_ -> { block: NotAsked, term: "", network: TestNet, zebra: "", version: "", recents: NotAsked } , render , eval: H.mkEval H.defaultEval { handleAction = handleAction, receive = Just <<< Receive, initialize = Just Initialize } } @@ -88,43 +90,72 @@ render state = [ HH.i [ css "ri-search-line ri-xl" ] [] ] ] ] + , case state.recents of + NotAsked -> HH.div_ [] + Loading -> + HH.div + [ css "card" ] + [ HH.text "Processing data..." + ] + Failure e -> + HH.div + [ css "card" ] + [ HH.text $ show e + ] + Success blks -> + HH.div + [ css "card" ] + [ HH.h3_ [ HH.text "recent blocks" ] + , HH.table_ + ( [ HH.tr_ [ HH.th_ [ HH.text "mined" ], HH.th_ [ HH.text "hash" ] ] ] <> + ( map + ( \b -> + HH.tr_ + [ HH.td_ [ HH.text $ convertToDate b.time ] + , HH.td_ [ HH.a [ safeHref $ Blk $ show b.height ] [ HH.text b.hash ] ] + ] + ) + blks + ) + ) + ] , HH.table - [ css "footer" ] - [ HH.tr_ - [ HH.td - [ css "footer" ] - [ HH.p_ - [ HH.text "Made with " - , HH.a - [ HP.href "https://www.purescript.org/"] - [ HH.text "PureScript" ] + [ css "footer" ] + [ HH.tr_ + [ HH.td + [ css "footer" ] + [ HH.p_ + [ HH.text "Made with " + , HH.a + [ HP.href "https://www.purescript.org/" ] + [ HH.text "PureScript" ] + ] + ] + , HH.td + [ css "footer" ] + [ HH.p_ + [ HH.i [ css "ri-copyright-line" ] [] + , HH.text "2024 Vergara Technologies LLC" + ] + ] + , HH.td + [ css "footer" ] + [ HH.p + [] + [ HH.text "Network: " + , HH.text $ show state.network + , HH.br_ + , HH.text "Server: " + , HH.text state.version + , HH.br_ + , HH.text "UI: 0.3.1.0" + , HH.br_ + , HH.text "Zebra Node: " + , HH.text state.zebra + ] + ] ] - ] - , HH.td - [ css "footer" ] - [ HH.p_ - [ HH.i [ css "ri-copyright-line" ] [] - , HH.text "2024 Vergara Technologies LLC" - ] - ] - , HH.td - [ css "footer" ] - [ HH.p - [] - [ HH.text "Network: " - , HH.text $ show state.network - , HH.br_ - , HH.text "Server: " - , HH.text state.version - , HH.br_ - , HH.text "UI: 0.3.0.0" - , HH.br_ - , HH.text "Zebra Node: " - , HH.text state.zebra - ] - ] ] - ] ] handleAction :: forall cs o m. MonadAff m => Navigate m => MonadStore S.Action S.Store m => Action -> H.HalogenM State Action cs o m Unit @@ -132,11 +163,12 @@ handleAction = case _ of Initialize -> do _ <- H.subscribe =<< timer Refresh st <- getStore - H.modify_ _ {network = st.network, zebra = st.zebraVersion, version = st.version } + H.modify_ _ { network = st.network, zebra = st.zebraVersion, version = st.version } handleAction Refresh Refresh -> do - H.modify_ _ { block = Loading } + H.modify_ _ { block = Loading, recents = Loading } res <- H.liftAff $ AX.get AXRF.string ("https://api.exblo.app/getblock") + resList <- H.liftAff $ AX.get AXRF.string ("https://api.exblo.app/getrecentblocks") case res of Left err -> do log $ "/block response failed to decode: " <> AX.printError err @@ -150,16 +182,26 @@ handleAction = case _ of log $ "Can't parse JSON. " <> show e H.modify_ _ { block = Failure "Failed to parse response" } + case resList of + Left err -> do + log $ "/getrecentblocks response failed to decode: " <> AX.printError err + Right listResponse -> do + if listResponse.status == StatusCode 200 then case readJSON listResponse.body of + Right (rb :: Array ShortBlock) -> + H.modify_ _ { recents = Success rb } + Left e -> do + log $ "Can't parse JSON. " <> show e + H.modify_ _ { recents = Failure "Failed to parse response" } + else H.modify_ _ { recents = Failure "Error in API server" } SetTerm s -> do H.modify_ _ { term = s } - Receive {context: store, input: inp } -> do - H.modify_ _ { network = store.network, zebra = store.zebraVersion, version = store.version } + Receive { context: store, input: inp } -> do + H.modify_ _ { network = store.network, zebra = store.zebraVersion, version = store.version } Search event -> do H.liftEffect $ Event.preventDefault event term <- H.gets _.term - if (SC.length term /= 64) - then navigate $ Blk term - else navigate $ Tx term + if (SC.length term /= 64) then navigate $ Blk term + else navigate $ Tx term timer :: forall m a. MonadAff m => a -> m (HS.Emitter a) timer val = do