Skip to content

Commit

Permalink
Merge pull request #11 from wowica/add-sync-from-option
Browse files Browse the repository at this point in the history
- Add sync_from option
- Fix client disconnection bug.
  • Loading branch information
caike authored Jan 24, 2024
2 parents a63dc5c + c12a607 commit a851d98
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 5 deletions.
11 changes: 11 additions & 0 deletions examples/chain_sync_client.ex
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,17 @@ defmodule ChainSyncClient do

def start_link(opts) do
initial_state = [counter: 3]
### See examples below on how to sync
### from different points of the chain:
# initial_state = [sync_from: :babbage]
# initial_state = [
# sync_from: %{
# point: %{
# slot: 114_127_654,
# id: "b0ff1e2bfc326a7f7378694b1f2693233058032bfb2798be2992a0db8b143099"
# }
# }
# ]
opts = Keyword.merge(opts, initial_state)
Xogmios.start_chain_sync_link(__MODULE__, opts)
end
Expand Down
26 changes: 22 additions & 4 deletions lib/xogmios/chain_sync.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ defmodule Xogmios.ChainSync do
{:ok, :next_block, map()} | {:ok, map()} | {:ok, :close, map()}

def start_link(client, opts) do
url = Keyword.fetch!(opts, :url)
state = Keyword.merge(opts, handler: client)
:websocket_client.start_link(url, client, state)
{url, opts} = Keyword.pop(opts, :url)
initial_state = Keyword.merge(opts, handler: client)
:websocket_client.start_link(url, client, initial_state)
end

defmacro __using__(_opts) do
Expand All @@ -28,7 +28,25 @@ defmodule Xogmios.ChainSync do
"result" => %{"direction" => "backward", "tip" => tip}
} = message

message = Messages.find_intersection(tip["slot"], tip["id"])
message =
case state[:sync_from] do
nil ->
# No option passed, sync with current tip
Messages.find_intersection(tip["slot"], tip["id"])

%{point: point} ->
# Sync with a specific point
Messages.find_intersection(point.slot, point.id)

cardano_era when cardano_era in [:origin, :byron] ->
# Sync with origin
Messages.find_origin()

cardano_era when is_atom(cardano_era) ->
# Sync with a particular era bound
Messages.last_block_from(cardano_era)
end

{:reply, {:text, message}, state}
end

Expand Down
2 changes: 1 addition & 1 deletion lib/xogmios/chain_sync/connection.ex
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ defmodule Xogmios.ChainSync.Connection do
|> Enum.into(%{})
|> Map.merge(%{handler: __MODULE__})

{:once, initial_state}
{:reconnect, initial_state}
end

@impl true
Expand Down
41 changes: 41 additions & 0 deletions lib/xogmios/chain_sync/messages.ex
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,47 @@ defmodule Xogmios.ChainSync.Messages do
json
end

def find_origin do
# For finding origin, any value can be passed as a point as long as "origin"
# is the first value.
json = ~S"""
{
"jsonrpc": "2.0",
"method": "findIntersection",
"params": {
"points": [
"origin",
{
"slot": 4492799,
"id": "f8084c61b6a238acec985b59310b6ecec49c0ab8352249afd7268da5cff2a457"
}
]
}
}
"""

validate_json!(json)
json
end

# The following are the last points (absolute slot and block id) of
# the previous era of each entry. The sync is done against the last
# point, so that the next block received is the first of the following era.
@era_bounds %{
shelley: {4_492_799, "f8084c61b6a238acec985b59310b6ecec49c0ab8352249afd7268da5cff2a457"},
allegra: {16_588_737, "4e9bbbb67e3ae262133d94c3da5bffce7b1127fc436e7433b87668dba34c354a"},
mary: {23_068_793, "4e9bbbb67e3ae262133d94c3da5bffce7b1127fc436e7433b87668dba34c354a"},
alonzo: {39_916_796, "e72579ff89dc9ed325b723a33624b596c08141c7bd573ecfff56a1f7229e4d09"},
babbage: {72_316_796, "c58a24ba8203e7629422a24d9dc68ce2ed495420bf40d9dab124373655161a20"}
}

def last_block_from(era_name) when is_atom(era_name) do
case @era_bounds[era_name] do
{last_slot, last_block_id} -> find_intersection(last_slot, last_block_id)
nil -> {:error, :unknown_block}
end
end

defp validate_json!(json) do
case Jason.decode(json) do
{:ok, _decoded} -> :ok
Expand Down

0 comments on commit a851d98

Please sign in to comment.