Heyo. Trying to figure out the best way to use websockex to stream Kraken trades. Their API requires a payload to define the subscription, possibly including an auth token for private data. I’m able to connect and get a basic status event back but am not sure how to send the payload from the start_link function.
Any ideas? TIA.
defmodule Streamer.Kraken do
use WebSockex
require Logger
@stream_endpoint "wss://beta-ws.kraken.com"
def start_link(symbol) do
## Get Kraken Websocket Token only needed for private endpoints
## {:ok, %{"expires" => expires, "token" => token}} = Krakex.websockets_token()}
lowercased_symbol = String.downcase(symbol)
WebSockex.start_link(
"#{@stream_endpoint}",
__MODULE__,
nil,
name: :"#{__MODULE__}-#{lowercased_symbol}"
)
end
def subscribe(client, symbol) do
json = """
{"event": "subscribe", "pair": ["#{symbol}"], "subscription": {"name": "trade"}}
"""
Logger.info("Sending message: #{json}")
WebSockex.send_frame(client, {:text, json})
end
def handle_connect(_conn, state) do
Logger.info("Kraken WS Connected!")
subscribe(self(), "ADA/USDT")
{:ok, state}
end
def handle_frame({_type, msg}, state) do
IO.inspect msg
case Jason.decode(msg) do
{:ok, event} -> process_event(event)
{:error, _} -> Logger.error("Unable to parse msg: #{msg}")
end
{:ok, state}
end
And when I run this I get:
** (MatchError) no match of right hand side value: {:error, %WebSockex.CallingSelfError{function: :send_frame}}
I’m using a DynamicSupervisor
to run the worker - so was looking for a way to get all the way through the subscribe from the start_link flow.
If I don’t use the supervisor and run it manually in two steps it works.
WebSockex.send_frame
has specific “nope” code for that calling pattern:
The message for this case suggests a fix:
def message(%__MODULE__{function: :send_frame}) do
"""
Process attempted to call itself.
The function send_frame/2 cannot be used inside of a callback. Instead try returning {:reply, frame, state} from the callback.
"""
end
1 Like