Elm Json request not working? - json

In Elm, you can use the Json.decode and Http package to request json data. My attempt was to work out a periodic lookup for emails ( from this url ). The timer operation does work (i tried it with with a simple counter).
I have used this example and this SO question as reference.
Now the types:
type alias Email = { title: String, ... }
type Action =
NoAction
| TickCounter -- TODO rem
| AddEmails (List Email)
Then the main + state + actions ...
main: Signal Html
main = Signal.map (view actions.address) state
state: Signal Model
state = Signal.foldp update makeEmptyModel input
-- handle inputs (merging signals)
input : Signal Action
input =
Signal.mergeMany
[ actions.signal
-- , other actions
, Signal.map checkForNewMails (Time.every (Time.minute / 6.0) ) -- TODO precise timer (quick test)
]
actions: Signal.Mailbox Action
actions = Signal.mailbox NoAction
update: Action -> Model -> Model
update action model =
case action of
NoAction -> model
TickCounter -> { model | count = model.count + 1 }
AddEmails newMails -> { model | emails = newMails }
checkForNewMails: Time -> Action
checkForNewMails t =
let mails = startGettingEmailData
in TickCounter -- TODO replace with AddEmails using mails
The TickCounter is an Action, which i have used to test my timing operation. But the problem is startGettingEmailData. It uses the next snippet, but it doesn't fire any JSON request (i have checked it through the console). Once that has been resolved, i can convert mails to an action so that i can add the emails in the model.
-- url to json
jsonUrl = "https://dl.dropboxusercontent.com/u/14070433/temp.json"
-- get emails
startGettingEmailData: Task Http.Error (List Email)
startGettingEmailData = Http.get emailJsonDecoder jsonUrl
emailJsonDecoder: Json.Decoder (List Email)
emailJsonDecoder =
let makeEmail = Json.object4
(\ti fr da bo -> makeNewEmail -1 ti fr da bo )
("title" := Json.string)
("from" := Json.string)
("date" := Json.string)
("body" := Json.string)
in
"emails" := Json.list makeEmail
Is there a problem with my code ? If not, then is there a way to check the Http.Error content ? (Maybe the problem lies not in my code, but in the network, but i can access the dropbox file by browser...)

Your code for checkForNewMails doesn't actually do anything with mails, so it never gets invoked. The let statement doesn't make any calls, it only lets you define one-off functions within the body of a larger function. Since the in portion merely returns TickCounter, then it means this function only ever returns TickCounter and does nothing else.
Furthermore, startGettingEmailData is returning a Task, which means it only gets invoked when in a port. You can't use it in a function that only returns an Action, because it would never get run.
You'll instead want to write a port that triggers on a timer, then creates a Task which polls your url, then maps the response of that GET request to an Action, calling the actions mailbox. You can use Task.onError to write a simple error handler, which could forward an error message to your view by creating an Error String constructor on your Action type.
Here's an example:
getEmailData _ =
let
request =
Http.get emailJsonDecoder jsonUrl
|> Task.map AddEmails
in
request
`Task.onError` (\err -> Task.succeed (Error (toString err)))
`Task.andThen` (\action -> Signal.send actions.address action)
port getEmails : Signal (Task a ())
port getEmails =
Signal.map getEmailData (Time.every (Time.minute / 6.0) )
The above code will cause the URL to be retrieved, parsed, then, on success, it will trigger you actions mailbox and cause an update of the view. If there is an error, it will send the new action of Error with a message, which you should handle in the view. (You'll have to add Error String to the Action union type and handle it in the model, update, and view functions).

Related

yubihsm2 signatures are invalid when signing ETH transactions

I am trying to figure out how to get this yubihsm2 to work with signing eth transactions. I have been using the python lib and so far i have had some basic setup. Below is an abbreviation of what i have
web3_endpoint = ''
web3 = Web3(HTTPProvider(web3_endpoint))
hsm = YubiHsm.connect("http://localhost:12345")
session = hsm.create_session_derived(1, "password")
key = session.get_object(1,OBJECT.ASYMMETRIC_KEY)
#key = AsymmetricKey.generate(session, 1, "EC Key", 1, CAPABILITY.SIGN_ECDSA, ALGORITHM.EC_K256)
pub_key = key.get_public_key()
#raw_pub = pub_key.public_bytes(
# encoding=serialization.Encoding.DER,
# format=serialization.PublicFormat.SubjectPublicKeyInfo
# )
raw_pub = pub_key.public_bytes(
encoding=serialization.Encoding.X962,
format=serialization.PublicFormat.UncompressedPoint
)
print ("Public key (Uncompressed):\n",binascii.b2a_hex(raw_pub))
unindexPub = raw_pub[1:]
public_key_hash = Web3.keccak(unindexPub)
address_bytes = public_key_hash[-20:]
address = address_bytes.hex()
print(address)
Now so far i can consistently get the same public key and it looks correct. I then get the same public key each time. When i say correct, the formatting looks correct and is the correct number of bytes.
1). should i be using the commented out public key formatting or the uncompressed X962 encoding that i have above.
From there, this is where things get a bit weird
transaction = {
'to': Web3.toChecksumAddress('0x785AB1daE1b0Ee3f2412aCF55e4153A9517b07e1'),
'gas': 21000,
'gasPrice': Web3.toWei(5, 'gwei'),
'value': 1,
'nonce': 1,
'chainId': 4,
}
serializable_transaction = serializable_unsigned_transaction_from_dict(transaction)
transaction_hash = serializable_transaction.hash()
print(transaction_hash.hex())
# sign the transaction hash and calculate v value
signature = key.sign_ecdsa(transaction_hash,hashes.SHA3_256())
r, s = ecdsa.util.sigdecode_der(signature, ecdsa.SECP256k1.generator.order())
print("r: "+str(r)+"\ns: "+str(s))
v = 28
# encode the transaction along with the full signature and send it
encoded_transaction = encode_transaction(serializable_transaction, vrs=(v, r, s))
web3.eth.sendRawTransaction(encoded_transaction)
I am settings v to 28.. i also test it with 27.. I could use the correct amount with the chainid.. but it's not necessary right from the perspective of trying to get a valid signature (recoverable to get the same public key each time). Sometimes i am getting the error "invalid sender" and other times i am getting the error "insufficient gas." If i take the signature output and use a javascript lib to try to find the public key, each time i am getting a different public key. But i keep consistently generating the same public key from the yubihsm2 in this python app.
I have also commented out in sign_ecdsa the hashing function as i am passing in the data already hashed (in order to use keccak256).
Is there something i am missing? Why are these transactions not signing correctly for eth?
i am getting some of those serialization helpers from enter link description here
helper serialization functions
Thanks

Azure eventhub sending several float array messages in python

I have three float arrays of data (A,B,C) that I want to send it to event hub.
The issue here is that the classes are nested and I can't figure out how to shape the data to be able to send successfully.
Here is the code that I am trying
logger = logging.getLogger("azure")
ADDRESS = ""
USER = ""
KEY = ""
try:
if not ADDRESS:
raise ValueError("No EventHubs URL supplied.")
# Create Event Hubs client
client = EventHubClient(ADDRESS, debug=False, username=USER, password=KEY)
sender = client.add_sender(partition="0")
client.run()
x_value = np.arange(100)
try:
start_time = time.time()
for i in range(100000):
A = np.asarray([1,2,3,4])
B = np.asarray([2,3,4,5])
C = np.asarray([3,4,5,6])
message = [A, B, C]
sender.send(EventData(body = message))
time.sleep(1)
except:
raise
finally:
end_time = time.time()
client.stop()
run_time = end_time - start_time
logger.info("Runtime: {} seconds".format(run_time))
except KeyboardInterrupt:
pass
In this way, I am seeing the error 'ValueBody' object has no attribute 'append'
I think by types, the class encodes the message differently.
Instead of sending a single message with a serial string, I want to send the message in a parallel way, and receive them something like this:
Receive one eventdata with the form of the list [A,B,C]
Receive three eventdata A, B, C separately, like calling three different objects basis.
For the second way, I am not sure if it would work since I am using only one partition and that may have the three eventdata A, B, C mixed when I receive them and I do not want that.
I have confirmed with ms support, the feedback is that: it only works for a list of string or bytes, but does not work for a list of int.
And also you should note that, even it sends a list of string, when receive the list, it will concatenate the all elements of the list to compose a single message. For example, if there is a list ["a","b","c","d"] for sending, when receive it, it will show this "abcd" as a whole string.
I have tested it by myself, the above information is correct.
So for your case, you should consider change the list to a string or json string. when receiving it, you can format the data to what you need.
Hope it helps.

Using Dict.update with nested update functions in Elm

I'm writing an Elm app where a major part of the state is in a Dict with Records as values. I have an update function for the main state model, and an update function for the individual records in the Dict. Is there a way to use Dict.update with the record state update function?
The issue I'm having is that the state update function for the records returns what update functions usually return: a tuple with the updated object and any commands to trigger (e.g. (newRecord, Cmd.none)). But the Dict.update function needs to take in a record and return a record (e.g. just newRecord), not a tuple with a record and a command object.
Is there a way around this? Right now I've got it working using a combination of Dict.get and Dict.insert, but this seems clumsy.
If update function for record always return Cmd.none, you can simplify it and return only the updated model.
Child modules do not have to follow ( Model, Cmd Msg ) convention if your application architecture does not require that.
If you do need to pass Commands from the lower level, it is also possible to re-structure your child module's update function to simplify those updates.
Example based on example/http
Here is an example of how you can split the update so that you could re-use the same logic in the top-level update without additional trickery.
update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
(updateModel msg model, updateCmd msg model)
updateCmd: Msg -> Model -> Cmd Msg
updateCmd msg model =
case msg of
MorePlease ->
getRandomGif model.topic
_ ->
Cmd.none
updateModel: Msg -> Model -> Model
updateModel msg model =
case msg of
NewGif (Ok newUrl) ->
Model model.topic newUrl
_ ->
model
If you need the updated model in updateCmd, then just pass it instead of current model or even pass both if you desire.
As a bonus, you can entirely omit unused branches of the case expression.
Using Dict.update
It will also be possible to use updateModel in Dict.update without retrieving the record and writing it back.
Dict.update childKey (Maybe.map (updateModel childMsg)) model
Not sure if this is what you are looking for, but if you have a nested Dict structure in your model, like this:
type alias Model =
{ parentsAndChildren : Dict String (Dict String Int) }
Then it is not necessary to make the child update output a Cmd. Your update could look something like this:
update : Msg -> Model -> Model
update msg model =
case msg of
NewChild parentName childName age ->
let
newModel =
{ model
| parentsAndChildren =
model.parentsAndChildren
|> Dict.update
parentName
(Maybe.map insertChild)
}
in
(newModel, Cmd.none)
-- helper function to update a child Dict
insertChild: String -> Int -> Dict (String Int) -> Dict (String Int)
insertChild name age childDict =
Dict.insert name age childDict
The only update function that NEEDS to output a Cmd is the update function in your top component.
So your child update function doesn't have to output a Cmd.
Not that I know of. I have this helper function in my one of my projects
updateDict : comparable -> msg -> Dict comparable b -> (msg -> b -> ( b, Cmd msg )) -> (comparable -> msg -> c) -> ( Dict comparable b, Cmd c )
updateDict uid act dict fn wrapper =
case Dict.get uid dict |> Maybe.map (fn act) of
Just ( m, e ) ->
( Dict.insert uid m dict
, Cmd.map (wrapper uid) e
)
Nothing ->
( dict, Cmd.none )

Elm updating model from json response

I am having an issue with updating a model from a JSON response through one of my actions.
Here is the setup:
I have models that looks like this:
type alias Model =
{ totals: Totals.Total // all values are initialized as 0 or 0.0
}
-- In other module
type alias Total =
{ days : Int
, avgPerDay: Float
, reports : Int
, people : Int
, locations : Int
, totalCoffees : Int
, coffeesPerDay: Float
}
A decoder for said model:
decodeTotal : Json.Decoder Total
decodeTotal =
object7 Total
("days" := Json.int)
("avgPerDay" := Json.float)
("reports" := Json.int)
("people" := Json.int)
("locations" := Json.int)
("totalCoffees" := Json.int)
("coffeesPerDay" := Json.float)
To update the model, the following Http request is called:
getTotals : Effects Action
getTotals =
Http.get Totals.decodeTotal ("/reports/totals")
|> Task.toMaybe
|> Task.map TotalsFetched
|> Effects.task
The response from the server is 200 OK with this body: {"days":347,"reports":1793,"avgPerDay":5.167147,"people":205,"locations":332,"coffees":146,"coffeesPerDay":0.42074928}
However, in the TotalsFetched Action:
update : Action -> Model -> (Model, Effects Action)
update action model =
case action of
TotalsFetched totals ->
log (toString totals) -- logs Nothing
( { model | totals = Maybe.withDefault model.totals totals }
, Effects.none
)
I am assuming that since totals is Nothing my model just stays as is described in the Maybe.withDefault
I don't understand why totals is Nothing instead of the Decoded response from the server. This is my first elm project, so I wouldn't be surprised if I am missing something really obvious to the trained eye.
Your json is returning a field called coffees while your decoder is looking for totalCoffees.
You may want to consider using Task.toResult instead of Task.toMaybe because that way you'll get an error message returned when something goes wrong.

How to call Stored Procedures and defined functions in MySQL with Slick 3.0

I have defined in my db something like this
CREATE FUNCTION fun_totalInvestorsFor(issuer varchar(30)) RETURNS INT
NOT DETERMINISTIC
BEGIN
RETURN (SELECT COUNT(DISTINCT LOYAL3_SHARED_HOLDER_ID)
FROM stocks_x_hldr
WHERE STOCK_TICKER_SIMBOL = issuer AND
QUANT_PURCHASES > QUANT_SALES);
END;
Now I have received an answer from Stefan Zeiger (Slick lead) redirecting me here: User defined functions in Slick
I have tried (having the following object in scope):
lazy val db = Database.forURL("jdbc:mysql://localhost:3306/mydb",
driver = "com.mysql.jdbc.Driver", user = "dev", password = "root")
val totalInvestorsFor = SimpleFunction.unary[String, Int]("fun_totalInvestorsFor")
totalInvestorsFor("APPLE") should be (23)
Result: Rep(slick.lifted.SimpleFunction$$anon$2#13fd2ccd fun_totalInvestorsFor, false) was not equal to 23
I have also tried while having an application.conf in src/main/resources like this:
tsql = {
driver = "slick.driver.MySQLDriver$"
db {
connectionPool = disabled
driver = "com.mysql.jdbc.Driver"
url = "jdbc:mysql://localhost/mydb"
}
}
Then in my code with #StaticDatabaseConfig("file:src/main/resources/application.conf#tsql")
tsql"select fun_totalInvestorsFor('APPLE')" should be (23)
Result: Error:(24, 9) Cannot load #StaticDatabaseConfig("file:src/main/resources/application.conf#tsql"): No configuration setting found for key 'tsql'
tsql"select fun_totalInvestorsFor('APPLE')" should be (23)
^
I am also planning to call stored procedures that return one tuple of three values, via sql"call myProc(v1).as[(Int, Int, Int)]
Any ideas?
EDIT: When making
sql""""SELECT COUNT(DISTINCT LOYAL3_SHARED_HOLDER_ID)
FROM stocks_x_hldr
WHERE STOCK_TICKER_SIMBOL = issuer AND
QUANT_PURCHASES > QUANT_SALES""".as[(Int)]
results in SqlStreamingAction[Vector[Int], Int, Effect] instead of the suggested DBIO[Int] (from what I infer) suggested by the documentation
I've been running into exactly the same problem for the past week. After some extensive research (see my post here, I'll be adding a complete description of what I've done as a solution), I decided it can't be done in Slick... not strictly speaking.
But, I'm resistant to adding pure JDBC or Anorm into our solution stack, so I did find an "acceptable" fix, IMHO.
The solution is to get the session object from Slick, and then use common JDBC to manage the stored function / stored procedure calls. At that point you can use any third party library that makes it easier... although in my case I wrote my own function to set up the call and return a result set.
val db = Database.forDataSource(DB.getDataSource)
var response: Option[GPInviteResponse] = None
db.withSession {
implicit session => {
// Set up your call here... (See my other post for a more detailed
// answer with an example:
// procedure is eg., "{?=call myfunction(?,?,?,?)}"
val cs = session.conn.prepareCall(procedure.toString)
// Set up your in and out parameters here
// eg. cs.setLong(index, value)
val result = cs.execute()
val rc = result.head.asInstanceOf[Int]
response = rc match {
// Package up the response to the caller
}
}
}
db.close()
I know that's pretty terse, but as I said, see the other thread for a more complete posting. I'm putting it together right now and will post the answer shortly.