[Solved] Testing BTP websockets for block and event subscriptions

Hey! I have a question regarding the BTP extension. I’d like to experiment with the BTP websockets and I’d like to know if https://btp.net.solidwallet.io/ is a good node to use for that. I was trying to establish a websocket connection with curl and I get a 404.

First Attempt

$ curl --include \
     --no-buffer \
     --header "Connection: Upgrade" \
     --header "Upgrade: websocket" \
     --header "Host: btp.net.solidwallet.io:80" \
     --header "Origin: http://btp.net.solidwallet.io:80" \
     "https://btp.net.solidwallet.io/api/v3/895821fc-0f3b-45f7-91e1-e9d83cc9eaf4/block?height=9995235"
HTTP/2 404 
date: Fri, 28 Jan 2022 13:39:21 GMT
content-length: 0
access-control-allow-origin: *
vary: Origin
server: ProSexy

My assumptions are:

  • The :channel variable in /api/v3/:channel/block should be a unique string, so I’ve used a UUID.
  • The height could be either an integer or an integer in ICON representation e.g. 9995235 or 0x9883e3 (I’ve tried both and none of them work).

I want to test this out with curl first before I start implementing this in the SDK I’ve written in Elixir.

Update Jan 31st 2022

Reading the docs here I realized the request must be a JSON (though it’s a GET request), so I did the following but got the same result:

$ curl --include \
     --no-buffer \
     --request GET \
     --header "Accept: application/json" \
     --header "Content-type: application/json" \
     --header "Connection: Upgrade" \
     --header "Upgrade: websocket" \
     --header "Host: btp.net.solidwallet.io:80" \
     --header "Origin: http://btp.net.solidwallet.io:80" \
     --data '{"height":"0x9883e3"}' \
     'https://btp.net.solidwallet.io/api/v3/b01169f7-604c-4df6-8702-13a3793b6e36/block'
HTTP/2 404 
date: Mon, 31 Jan 2022 15:26:06 GMT
content-length: 0
access-control-allow-origin: *
vary: Origin
server: ProSexy

Update Feb 1st 2022

I’ve opened an (https://github.com/icon-project/goloop/issues/87) in goloop repository asking the same question. So far, my channel should be a UUID assumption was wrong. By default, nodes create a channel called icon_dex (unless the node administrator changes the configuration). Still, I cannot establish a WebSocket connection with curl :disappointed::

$ curl --include \
     --no-buffer \
     --request GET \
     --header "Accept: application/json" \
     --header "Content-type: application/json" \
     --header "Connection: Upgrade" \
     --header "Upgrade: websocket" \
     --header "Host: btp.net.solidwallet.io:80" \
     --header "Origin: http://btp.net.solidwallet.io:80" \
     --data '{"height":"0x9883e3"}' \
     'https://btp.net.solidwallet.io/api/v3/icon_dex/block'
HTTP/2 400 
date: Thu, 03 Feb 2022 06:47:13 GMT
content-type: text/plain; charset=utf-8
content-length: 118
access-control-allow-origin: *
sec-websocket-version: 13
vary: Origin
x-content-type-options: nosniff
server: ProSexy
access-control-allow-origin: *

Bad Request
websocket: the client is not using the websocket protocol: 'websocket' token not found in 'Upgrade' header

Update Feb 5th 2022

curl didn’t seem like a good fit for the test, so I decided to write a small script in Elixir to open the actual WebSocket and it works :slight_smile: This is the script:

#!/usr/bin/env elixir

Mix.install(
  mint: "~> 1.4",
  mint_web_socket: "~> 0.1",
  castore: "~> 0.1"
)

# Bootstrap
{:ok, conn} = Mint.HTTP.connect(:https, "btp.net.solidwallet.io", 443, protocols: [:http1])
{:ok, conn, ref} = Mint.WebSocket.upgrade(conn, "/api/v3/icon_dex/block", [])
http_reply_message = receive(do: (message -> message))
{:ok, conn, [{:status, ^ref, status}, {:headers, ^ref, resp_headers}, {:done, ^ref}]} =
  Mint.HTTP.stream(conn, http_reply_message)
{:ok, conn, websocket} = Mint.WebSocket.new(conn, ref, status, resp_headers)

# Send data
{:ok, websocket, data} = Mint.WebSocket.encode(websocket, {:text, ~s({"height":"0x9883e3"})})
{:ok, conn} = Mint.HTTP.stream_request_body(conn, ref, data)

# Receive reply
waiter = fn conn, websocket, waiter ->
  receive do
    message ->
      {:ok, conn, [{:data, ^ref, data}]} = Mint.HTTP.stream(conn, message)
      {:ok, websocket, responses} = Mint.WebSocket.decode(websocket, data)
      IO.inspect(responses) # This line prints the notifications coming from the websocket
      waiter.(conn, websocket, waiter)
  end
end

waiter.(conn, websocket, waiter)
1 Like