Fork me on GitHub
#clojurescript
<
2021-09-05
>
zendevil.eth10:09:15

I’m trying to resolve a promise with <p! in a go block, but it seems like the promise isn’t resolved and nothing after the promise resolution is executed either. There’s no error about why the promise isn’t resolved. The execution just stops there

p-himik10:09:27

<p! does not resolve a promise. It parks the go block till the promise is resolved. Resolving a promise must be done in some different place.

zendevil.eth11:09:20

I mean yes the promise is supposed to be resolved by the library whose function I’m calling

zendevil.eth11:09:02

but while earlier it was resolving just fine, now it doesn’t resolve

zendevil.eth11:09:35

nor does anything else after the go block get executed

p-himik11:09:59

With the amount of information you provide, it is impossible to give you any answer more useful than "there's something wrong with your code". Maybe you're doing something that blocks or deadlocks, maybe there's some other bug in your code, maybe there's some bug in that library, maybe some precondition somewhere is not met - and so on, and so forth.

zendevil.eth11:09:26

This is the relevant section of the let bindings:

contract-deploy
          (.. contract
              (deploy (clj->js 
                         {:arguments [ipfs 
                                      (.toString
                                        (* (js/parseFloat (:income-to-sell db)) 
                                           1000000000000000000)) 
                                      (:amount-to-raise db)
                                      (nth (:timeframe-raising db) 0) 
                                      (nth (:timeframe-raising db) 1) 
                                      (nth (:timeframe-payments db) 0)
                                      (nth (:timeframe-payments db) 1)
                                      (:payment-interval db)]
                          :data (.-bytecode (js/JSON.parse resp))})))


          
          contract-send 
          (.. contract-deploy
              (send (clj->js {:from ego}) 
                    (fn [err tx-hash] 
                      (prn "err is " err
                           "tx hash is " tx-hash))))
           
          _ (prn "after contract send") 

          contract-instance
          (<p!
            (.. contract-send
                (on "error" (fn [obj] (js/console.log "error " obj)))
                (on "sending" (fn [obj] (prn "sending " obj)))
                (on "receipt" (fn [receipt] 
                                 (prn "contract address is")
                                 (.-contractAddress receipt)))
                (on "confirmation" (fn [confirmation-number receipt]
                                      (dispatch [:stop-loading])    
                                      (prn "confirmation number"
                                           confirmation-number)
                                      (prn "receipt"
                                           receipt)))))
Nothing after contract-instance executes including everything after the go block that contract-instance is in and contract-instance doesn’t give an error either.

Vlad Kryvokoniev13:09:20

Hi, I have problem adjusted to shadow-cljs env variables As the https://shadow-cljs.github.io/docs/UsersGuide.html#shadow-env "not clearly" says I can read a variable via `#shadow/env "TWITCH_AUTHORIZATION_TOKEN"` but instead i get an error `No reader function for tag shadow/env.` my version of shadow-cljs is "2.15.2" here is my shadow-cljs.edn:

{:source-paths
 ["src/main"]


 :dependencies
 [[reagent "1.1.0"]
  [cljs-ajax "0.8.4"]]

 :dev-http {8080 "public"}
 :builds
 {:frontend
  {:target :browser
   :modules {:main {:init-fn app/start}}
   :closure-defines {events.async/TWITCH_AUTHORIZATION_TOKEN #shadow/env "TWITCH_AUTHORIZATION_TOKEN"}}}} 
also my .env:
TWITCH_AUTHORIZATION_TOKEN="blalbbllba"
i duplicate this question in #beginners channel so that I can get any response faster) so my question is how to read a env variable then?

thheller14:09:39

@vladkryvokoniev when/where do you get that error? which command did you run? looks correct and should work. FWIW there is also a #shadow-cljs channel for these kinds of questions 😉

Vlad Kryvokoniev15:09:44

It doesnt compiles when i run it with the error above

thheller15:09:36

*what* doesn't compile? the configuration file is never compiled? like literally which command do you run? some kind of log helps to narrow down what the actual issue is

Vlad Kryvokoniev15:09:11

where I try to read the env variable

Vlad Kryvokoniev15:09:23

i ran shadow-cljs watch frontend

p-himik16:09:41

@vladkryvokoniev I'm pretty sure that reader tag is supported only within the configuration. You can't use it in the CLJS files - you have to use goog-define for it: https://shadow-cljs.github.io/docs/UsersGuide.html#closure-defines

Vlad Kryvokoniev16:09:19

i tried it (goog-define TWITCH_AUTHORIZATION_TOKEN "") but it doesn't seem to work

Vlad Kryvokoniev16:09:06

it didn't take variable from my env

p-himik16:09:06

How exactly did you try it? Please post the relevant part of your config and the usage in CLJS.

p-himik16:09:01

It doesn't show the usage.

p-himik16:09:46

LGTM. Now are you sure you don't have any other shadow-cljs process running? Are you sure you have restarted its processes after you set the environment variable? Are you sure the shadow-cljs server itself picks up that variable?

p-himik16:09:57

BTW this amount of moving parts is the main reason (IMO) why the documentation recommends using -config-merge instead.

thheller16:09:54

@vladkryvokoniev is the env variable actually set? it must have been set at the time shadow-cljs is started.

thheller16:09:59

otherwise looks fine

thheller16:09:29

shadow-cljs makes no attempt at reading .env so dunno how you get it to be an actual env var?

thheller16:09:17

you can try shadow-cljs clj-repl and (System/getenv) to get all env variables available

thheller16:09:51

or (System/getenv "TWITCH_AUTHORIZATION_TOKEN")

Vlad Kryvokoniev16:09:24

how can I say the config where to look up env variables?

thheller16:09:07

the environment variable is not set

thheller16:09:12

you should figure out why not

thheller16:09:20

can't look up env variables that aren't set

thheller16:09:47

they are never looked up anywhere except the actual environment

Vlad Kryvokoniev16:09:11

where exactly in the documentation can I see all the way along of setting environment variables? Coz I have no clue what's wrong

p-himik16:09:28

That depends on your OS and how you run things - it's not shadow-cljs-specific at all.

thheller16:09:47

yeah environment stuff is OS specific. shadow-cljs never sets any for you

zendevil.eth15:09:20

I have the following macro:

(defmacro with-contract-deploy [contract-name contract-json args & body]
  `(~'go
    (let [~'web3 (Web3. (.-givenProvider ~'Web3))
          ~'ego
          (->
            (~'<p!
              (.. ~'web3 -eth (getAccounts)))  
            (nth 0))
          contract#
          (new (.. ~'web3 -eth -Contract)
               (.-abi (js/JSON.parse ~contract-json)))
          ~contract-name
          (.. contract#
              (deploy (~'clj->js 
                         {:arguments ~args
                          :data (.-bytecode (js/JSON.parse ~contract-json))})))]
            
      ~@body)))

zendevil.eth15:09:51

And I’m using it like so:

(with-contract-deploy contract-deploy
    contract-json
    [ipfs 
     (.toString
       (* (js/parseFloat (:income-to-sell db)) 
          1000000000000000000)) 
     (:amount-to-raise db)
     (nth (:timeframe-raising db) 0) 
     (nth (:timeframe-raising db) 1) 
     (nth (:timeframe-payments db) 0)
     (nth (:timeframe-payments db) 1)
     (:payment-interval db)]

    (let [contract-send
          (.. contract-deploy
              (send (clj->js {:from ego}) 
                    (fn [err tx-hash] 
                      (prn "err is " err
                           "tx hash is " tx-hash))))
           
          _ (prn "contract send is " contract-send)
          _ (prn "after contract send") 
          _ (prn "after after. contract send ")

          contract-instance
          (.. contract-send
              (on "error" (fn [obj] (js/console.log "error " obj)))
              (on "sending" (fn [obj] (prn "sending " obj)))
              (on "receipt" (fn [receipt] 
                               (prn "contract address is")
                               (.-contractAddress receipt)))
              (on "confirmation" (fn [confirmation-number receipt]
                                    (dispatch [:stop-loading])    
                                    (prn "confirmation number"
                                         confirmation-number)
                                    (prn "receipt"
                                         receipt)))
              (then (fn [contract-instance]
                      (dispatch [:issue-nfts contract-instance contract-json ego]))))

          _ (prn "contract instance is " contract-instance)]))

zendevil.eth15:09:06

But it’s giving me a strange error:

Uncaught TypeError: Cannot read property 'macros' of undefined

thheller15:09:03

how did you setup the macro? I'm guessing that you have this in a .macros ns only required via :require-macros somewhere else?

thheller15:09:17

FWIW I think this shouldn't be a macro at all. you make make it a regular function if you just take a callback function

thheller15:09:23

the macro is also kinda bad in the way of all the symbols it forces via ~'. you should really avoid that

zendevil.eth15:09:13

I put the macro in a clj file. Then required that file in the same named cljs file

zendevil.eth15:09:35

Then require-macro in where I use it

thheller15:09:54

that likely is the mistake

thheller15:09:35

if you follow https://code.thheller.com/blog/shadow-cljs/2019/10/12/clojurescript-macros.html then ONLY the namespace with the same name as the macro namespace uses :require-macros. everything else just uses :require

thheller15:09:32

I'm guessing thats also why you have ~'go and so on?

zendevil.eth15:09:26

okay I put that in require but get the same error. I also changed ~’go to cljs.core.async/go cljs.core.async.interop/<p! and cljs.core/clj->js etc.

zendevil.eth15:09:12

Here’s the complete stacktrace:

ioc_helpers.cljs:50 Uncaught TypeError: Cannot read property 'macros' of undefined
    at switch__60950__auto__ (events.cljs:173)
    at eval (events.cljs:173)
    at Function.humboi$events$state_machine__60951__auto____1 [as cljs$core$IFn$_invoke$arity$1] (events.cljs:173)
    at Object.cljs$core$async$impl$ioc_helpers$run_state_machine [as run_state_machine] (ioc_helpers.cljs:43)
    at Object.cljs$core$async$impl$ioc_helpers$run_state_machine_wrapped [as run_state_machine_wrapped] (ioc_helpers.cljs:47)
    at eval (events.cljs:173)
    at cljs$core$async$impl$dispatch$process_messages (dispatch.cljs:27)
    at MessagePort.channel.port1.onmessage (nexttick.js:214)
switch__60950__auto__	@	events.cljs:173
eval	@	events.cljs:173
humboi$events$state_machine__60951__auto____1	@	events.cljs:173
cljs$core$async$impl$ioc_helpers$run_state_machine	@	ioc_helpers.cljs:43
cljs$core$async$impl$ioc_helpers$run_state_machine_wrapped	@	ioc_helpers.cljs:47
eval	@	events.cljs:173
cljs$core$async$impl$dispatch$process_messages	@	dispatch.cljs:27
channel.port1.onmessage	@	nexttick.js:214

thheller16:09:01

no compiler warnings? would help to see actual code

thheller16:09:46

FWIW this is what it could look like without a macro entirely

(defn with-contract-deploy [contract-json args callback]
  (go (let [web3
            (Web3. (.-givenProvider Web3))

            ego
            (-> (<p! (.. web3 -eth (getAccounts)))
                (nth 0))

            contract
            (new (.. web3 -eth -Contract)
              (.-abi (js/JSON.parse ~contract-json)))

            contract
            (.. contract
                (deploy (clj->js
                          {:arguments ~args
                           :data (.-bytecode (js/JSON.parse ~contract-json))})))]

        (callback contract))))

(with-contract-deploy
  contract-json
  [ipfs
   (.toString
     (* (js/parseFloat (:income-to-sell db))
       1000000000000000000))
   (:amount-to-raise db)
   (nth (:timeframe-raising db) 0)
   (nth (:timeframe-raising db) 1)
   (nth (:timeframe-payments db) 0)
   (nth (:timeframe-payments db) 1)
   (:payment-interval db)]

  (fn [contract-deploy]
    (let [contract-send
          (.. contract-deploy
              (send (clj->js {:from ego})
                (fn [err tx-hash]
                  (prn "err is " err
                    "tx hash is " tx-hash))))

          _ (prn "contract send is " contract-send)
          _ (prn "after contract send")
          _ (prn "after after. contract send ")

          contract-instance
          (.. contract-send
              (on "error" (fn [obj] (js/console.log "error " obj)))
              (on "sending" (fn [obj] (prn "sending " obj)))
              (on "receipt" (fn [receipt]
                              (prn "contract address is")
                              (.-contractAddress receipt)))
              (on "confirmation" (fn [confirmation-number receipt]
                                   (dispatch [:stop-loading])
                                   (prn "confirmation number"
                                     confirmation-number)
                                   (prn "receipt"
                                     receipt)))
              (then (fn [contract-instance]
                      (dispatch [:issue-nfts contract-instance contract-json ego]))))

          _ (prn "contract instance is " contract-instance)])))

zendevil.eth17:09:32

@U05224H0W the callback contains the variable “ego” but it would be nil in the way you’ve written this and not have the value that you bound to in the function

thheller17:09:53

then pass a second argument to the callback?

thheller17:09:39

I didn't test this code, just wanted to show that the macro really isn't needed imho

Bryce Tichit15:09:51

Hello, I'm trying to use a SaaS boilerplate written in JS with CLJS, thanks to the advices of the members of Clojurians I made good progress on this. 🙂 Shadow-cljs is incredible and allow me to use my existing JS code into my CLJS project very easily. The only thing would be that shadow-cljs does not understand JSX expression (my SaaS boilerplate contains JSX), is there an option to pass or something so shadow-cljs can understand it or do I need to translate the JSX using babel? I'd prefer to not have to translate the JSX and keep original source code but if needed I will do it. Any idea? Thanks a lot for the help !

Bryce Tichit16:09:17

Ok amazing thanks, sorry I already read the doc but didn't remember this one 🙃

👍 2
john17:09:12

Wow, I'm seeing really good gains for Clojurescript transducers. For this particular thread, I'm seeing between a 5 and 6 times speedup:

(x>> (range 1000000)
     (map inc)
     (filter odd?)
     (mapcat #(do [% (dec %)]))
     (partition-by #(= 0 (mod % 5)))
     (map (partial apply +))
    ;;  (mapv dec)
     (map (partial + 10))
     (map #(do {:temp-value %}))
     (map :temp-value)
     (filter even?)
     (apply +)
     time)
;=> "Elapsed time: 574.145888 msecs"
;=> 50005499994

(->> (range 1000000)
     (map inc)
     (filter odd?)
     (mapcat #(do [% (dec %)]))
     (partition-by #(= 0 (mod % 5)))
     (map (partial apply +))
    ;;  (mapv dec)
     (map (partial + 10))
     (map #(do {:temp-value %}))
     (map :temp-value)
     (filter even?)
     (apply +)
     time)
;=> "Elapsed time: 3523.186678 msecs"
;=> 50005499994

(float (/ 3523 574))
;= 6.137630662020906

Bryce Tichit18:09:41

Hello, I'm trying to import React from my JS code, while everything being compiled via shadow-cljs. When compiling I get an error about the fact I'd like to import React. Feels pretty advanced to me and don't really understand what's happening but looks like I'm close to my goal. Does anyone has an idea? I attach full debug log in thread, thanks a lot in advance for the help 🙂

unexpected qualified name: com.google.javascript.rhino.QualifiedName$GetpropQname@425979db
  Node(SCRIPT): divjoy/util/router.js:6:0
import React from "goog:module$node_modules$react$index";

thheller19:09:33

what are you actually doing in the code? I assume thats import React from "react"?

thheller19:09:42

would need some code to reproduce to comment more

thheller19:09:05

ESM code is sometimes a little finicky. might work better if you switch to commonjs require instead of import

thheller19:09:33

(or have babel rewrite it prior, if you doing this for JSX anyways)

Bryce Tichit19:09:57

Hello @U05224H0W thanks a lot for your answer. 1) Yes 2) I send you a tgz archive of the code in a few dozens of minutes if that's what you ask

Bryce Tichit19:09:08

3) Ok thanks will try require 4) Good idea, I need to search for a babel plugin that converts all import in require?

Bryce Tichit20:09:16

Everything works good after rewriting import to commonjs require, I just added the following babel plugin: "@babel/plugin-transform-modules-commonjs"

Bryce Tichit20:09:22

Thanks a lot @U05224H0W for the help !

Bryce Tichit20:09:42

I had to use this babel config to make it work in the end,

"babel": {
    "presets": [
      "@babel/preset-react"
    ],
    "plugins": [
      "babel-plugin-transform-scss",
      "@babel/plugin-transform-modules-commonjs"
    ]
  }

Bryce Tichit20:09:21

@babel.preset-react : transform JSX (and other things as well I think) babel-plugin-transform-css : compile sass to css @babel/plugin-transform-modules-commonjs: transform import to commonjs require