Skip to content

Commit

Permalink
Merge pull request #58 from kommitters/v0.6
Browse files Browse the repository at this point in the history
Release v0.6.0
  • Loading branch information
Odraxs authored May 11, 2023
2 parents 5cb5742 + 39d5cc7 commit bfaa6c0
Show file tree
Hide file tree
Showing 20 changed files with 729 additions and 5 deletions.
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
# Changelog

## 0.4.0 (09.05.2023)
## 0.6.0 (11.05.2023)

- [Soroban compound types](https://github.com/kommitters/soroban.ex/issues/43)

## 0.5.0 (09.05.2023)

- [Invoke Contract Function](https://github.com/kommitters/soroban.ex/issues/23)

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Add `soroban` to your list of dependencies in `mix.exs`:
```elixir
def deps do
[
{:soroban, "~> 0.5.0"}
{:soroban, "~> 0.6.0"}
]
end
```
Expand Down
49 changes: 49 additions & 0 deletions lib/types/enum.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
defmodule Soroban.Types.Enum do
@moduledoc """
`Enum` struct definition.
"""

@behaviour Soroban.Types.Spec

alias Soroban.Types.Symbol
alias Stellar.TxBuild.SCVal

defstruct [:key, :value]

@type sc_val :: SCVal.t()
@type t :: %__MODULE__{key: String.t(), value: struct()}

@impl true
def new(key) when is_binary(key),
do: %__MODULE__{key: key}

def new({key, value}) when is_binary(key) and is_struct(value),
do: %__MODULE__{key: key, value: value}

def new(_args), do: {:error, :invalid}

@impl true
def to_sc_val(%__MODULE__{key: key, value: nil}) do
key
|> Symbol.new()
|> Symbol.to_sc_val()
|> (&SCVal.new(vec: [&1])).()
end

def to_sc_val(%__MODULE__{key: key, value: value}) do
value = param_to_sc_val(value)

key
|> Symbol.new()
|> Symbol.to_sc_val()
|> (&SCVal.new(vec: [&1, value])).()
end

def to_sc_val(_error), do: {:error, :invalid_struct_enum}

@spec param_to_sc_val(param :: struct()) :: sc_val()
defp param_to_sc_val(param) do
struct = param.__struct__
struct.to_sc_val(param)
end
end
42 changes: 42 additions & 0 deletions lib/types/map.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
defmodule Soroban.Types.Map do
@moduledoc """
`Map` struct definition.
"""

@behaviour Soroban.Types.Spec

alias Soroban.Types.MapEntry
alias Stellar.TxBuild.SCVal

defstruct [:values]

@type errors :: atom()
@type values :: list(MapEntry.t())
@type validation :: {:ok, values()} | {:error, errors()}
@type t :: %__MODULE__{values: values}

@impl true
def new(values) when is_list(values) do
with {:ok, values} <- validate_map_entry_values(values) do
%__MODULE__{values: values}
end
end

def new(_values), do: {:error, :invalid}

@impl true
def to_sc_val(%__MODULE__{values: values}) do
values
|> Enum.map(&MapEntry.to_sc_map_entry/1)
|> (&SCVal.new(map: &1)).()
end

def to_sc_val(_error), do: {:error, :invalid_struct_map}

@spec validate_map_entry_values(values :: values()) :: validation()
def validate_map_entry_values(values) do
if Enum.all?(values, &is_struct(&1, MapEntry)),
do: {:ok, values},
else: {:error, :invalid_values}
end
end
36 changes: 36 additions & 0 deletions lib/types/map_entry.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
defmodule Soroban.Types.MapEntry do
@moduledoc """
`MapEntry` struct definition.
"""

@behaviour Soroban.Types.Spec

alias Stellar.TxBuild.{SCMapEntry, SCVal}

defstruct [:key, :value]

@type sc_val :: SCVal.t()
@type t :: %__MODULE__{key: struct(), value: struct()}

@impl true
def new({key, value}) when is_struct(key) and is_struct(value),
do: %__MODULE__{key: key, value: value}

def new(_args), do: {:error, :invalid}

@impl true
def to_sc_map_entry(%__MODULE__{key: key, value: value}) do
key = param_to_sc_val(key)
value = param_to_sc_val(value)

SCMapEntry.new(key, value)
end

def to_sc_map_entry(_error), do: {:error, :invalid_struct_map_entry}

@spec param_to_sc_val(param :: struct()) :: sc_val()
defp param_to_sc_val(param) do
struct = param.__struct__
struct.to_sc_val(param)
end
end
32 changes: 32 additions & 0 deletions lib/types/option.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
defmodule Soroban.Types.Option do
@moduledoc """
`Option` struct definition.
"""

@behaviour Soroban.Types.Spec

alias Stellar.TxBuild.SCVal

defstruct [:value]

@type sc_val :: SCVal.t()
@type value :: struct() | nil
@type t :: %__MODULE__{value: value()}

@impl true
def new(value \\ nil)
def new(nil), do: %__MODULE__{}
def new(value) when is_struct(value), do: %__MODULE__{value: value}
def new(_value), do: {:error, :invalid_option}

@impl true
def to_sc_val(%__MODULE__{value: nil}), do: SCVal.new(void: nil)
def to_sc_val(%__MODULE__{value: value}), do: param_to_sc_val(value)
def to_sc_val(_error), do: {:error, :invalid_struct_bool}

@spec param_to_sc_val(param :: struct()) :: sc_val()
defp param_to_sc_val(param) do
struct = param.__struct__
struct.to_sc_val(param)
end
end
6 changes: 5 additions & 1 deletion lib/types/spec.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,15 @@ defmodule Soroban.Types.Spec do
@moduledoc """
Defines base types constructions.
"""
alias Stellar.TxBuild.SCVal
alias Stellar.TxBuild.{SCMapEntry, SCVal}

@type error :: {:error, atom()}
@type sc_val :: SCVal.t()
@type map_entry :: SCMapEntry.t()

@callback new(any()) :: struct() | error()
@callback to_sc_val(struct()) :: sc_val()
@callback to_sc_map_entry(struct()) :: map_entry()

@optional_callbacks to_sc_val: 1, to_sc_map_entry: 1
end
42 changes: 42 additions & 0 deletions lib/types/struct.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
defmodule Soroban.Types.Struct do
@moduledoc """
`Struct` struct definition.
"""

@behaviour Soroban.Types.Spec

alias Soroban.Types.StructField
alias Stellar.TxBuild.SCVal

defstruct [:values]

@type errors :: atom()
@type values :: list(StructField.t())
@type validation :: {:ok, values()} | {:error, errors()}
@type t :: %__MODULE__{values: values}

@impl true
def new(values) when is_list(values) do
with {:ok, values} <- validate_struct_field_values(values) do
%__MODULE__{values: values}
end
end

def new(_values), do: {:error, :invalid}

@impl true
def to_sc_val(%__MODULE__{values: values}) do
values
|> Enum.map(&StructField.to_sc_map_entry/1)
|> (&SCVal.new(map: &1)).()
end

def to_sc_val(_error), do: {:error, :invalid_struct}

@spec validate_struct_field_values(values :: values()) :: validation()
def validate_struct_field_values(values) do
if Enum.all?(values, &is_struct(&1, StructField)),
do: {:ok, values},
else: {:error, :invalid_values}
end
end
40 changes: 40 additions & 0 deletions lib/types/struct_field.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
defmodule Soroban.Types.StructField do
@moduledoc """
`StructField` struct definition.
"""

@behaviour Soroban.Types.Spec

alias Soroban.Types.Symbol
alias Stellar.TxBuild.{SCMapEntry, SCVal}

defstruct [:key, :value]

@type key :: String.t()
@type sc_val :: SCVal.t()
@type t :: %__MODULE__{key: key(), value: struct()}

@impl true
def new({key, value}) when is_binary(key) and is_struct(value),
do: %__MODULE__{key: key, value: value}

def new(_args), do: {:error, :invalid}

@impl true
def to_sc_map_entry(%__MODULE__{key: key, value: value}) do
value = param_to_sc_val(value)

key
|> Symbol.new()
|> Symbol.to_sc_val()
|> SCMapEntry.new(value)
end

def to_sc_map_entry(_error), do: {:error, :invalid_struct_field}

@spec param_to_sc_val(param :: struct()) :: sc_val()
defp param_to_sc_val(param) do
struct = param.__struct__
struct.to_sc_val(param)
end
end
29 changes: 29 additions & 0 deletions lib/types/tuple.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
defmodule Soroban.Types.Tuple do
@moduledoc """
`Tuple` struct definition.
"""

@behaviour Soroban.Types.Spec

alias Stellar.TxBuild.SCVal

defstruct [:values]

@type values :: list(struct())
@type errors :: atom()
@type t :: %__MODULE__{values: values()}

@impl true
def new(values) when is_list(values), do: %__MODULE__{values: values}

def new(_values), do: {:error, :invalid}

@impl true
def to_sc_val(%__MODULE__{values: values}) do
values
|> Enum.map(fn %{__struct__: struct} = arg -> struct.to_sc_val(arg) end)
|> (&SCVal.new(vec: &1)).()
end

def to_sc_val(_error), do: {:error, :invalid_struct_tuple}
end
41 changes: 41 additions & 0 deletions lib/types/vec.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
defmodule Soroban.Types.Vec do
@moduledoc """
`Vec` struct definition.
"""

@behaviour Soroban.Types.Spec

alias Stellar.TxBuild.SCVal

defstruct [:values]

@type values :: list(struct())
@type errors :: atom()
@type validation :: {:ok, values()} | {:error, errors()}
@type t :: %__MODULE__{values: values()}

@impl true
def new(values) when is_list(values) do
with {:ok, values} <- validate_vec_values(values) do
%__MODULE__{values: values}
end
end

def new(_values), do: {:error, :invalid}

@impl true
def to_sc_val(%__MODULE__{values: values}) do
values
|> Enum.map(fn %{__struct__: struct} = arg -> struct.to_sc_val(arg) end)
|> (&SCVal.new(vec: &1)).()
end

def to_sc_val(_error), do: {:error, :invalid_struct_vec}

@spec validate_vec_values(values :: values()) :: validation()
defp validate_vec_values([value | _] = values) do
if Enum.any?(values, fn val -> val.__struct__ != value.__struct__ end),
do: {:error, :invalid_args},
else: {:ok, values}
end
end
12 changes: 10 additions & 2 deletions mix.exs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
defmodule Soroban.MixProject do
use Mix.Project

@version "0.5.0"
@version "0.6.0"
@github_url "https://github.com/kommitters/soroban.ex"

def project do
Expand Down Expand Up @@ -113,7 +113,15 @@ defmodule Soroban.MixProject do
Soroban.Types.UInt32,
Soroban.Types.UInt64,
Soroban.Types.UInt128,
Soroban.Types.UInt256
Soroban.Types.UInt256,
Soroban.Types.Vec,
Soroban.Types.Tuple,
Soroban.Types.MapEntry,
Soroban.Types.Map,
Soroban.Types.Enum,
Soroban.Types.StructField,
Soroban.Types.Struct,
Soroban.Types.Option
]
]
end
Expand Down
Loading

0 comments on commit bfaa6c0

Please sign in to comment.