-
-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #286 from kommitters/v0.12
Release v0.12.0
- Loading branch information
Showing
53 changed files
with
5,274 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -28,3 +28,5 @@ stellar_sdk-*.tar | |
|
||
# DS_Store | ||
.DS_Store | ||
|
||
.elixir_ls/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,3 @@ | ||
use Mix.Config | ||
|
||
config :stellar_sdk, | ||
network: :test | ||
config :stellar_sdk, network: :test |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
defmodule Stellar.TxBuild.AddressWithNonce do | ||
@moduledoc """ | ||
`AddressWithNonce` struct definition. | ||
""" | ||
|
||
import Stellar.TxBuild.Validations, | ||
only: [ | ||
validate_pos_integer: 1 | ||
] | ||
|
||
alias Stellar.TxBuild.SCAddress | ||
alias StellarBase.XDR.{AddressWithNonce, UInt64} | ||
|
||
@behaviour Stellar.TxBuild.XDR | ||
|
||
defstruct [:address, :nonce] | ||
|
||
@type validation :: {:ok, any()} | {:error, atom()} | ||
|
||
@type t :: %__MODULE__{address: SCAddress.t(), nonce: non_neg_integer()} | ||
@impl true | ||
def new(args, opts \\ nil) | ||
|
||
## change functions to keyword list | ||
def new(args, _opts) when is_list(args) do | ||
address = Keyword.get(args, :address) | ||
nonce = Keyword.get(args, :nonce) | ||
|
||
with {:ok, address} <- validate_address({:address, address}), | ||
{:ok, nonce} <- validate_pos_integer({:nonce, nonce}) do | ||
%__MODULE__{ | ||
address: address, | ||
nonce: nonce | ||
} | ||
end | ||
end | ||
|
||
def new(_args, _opts), do: {:error, :invalid_address_with_nonce} | ||
|
||
@impl true | ||
def to_xdr(%__MODULE__{ | ||
address: address, | ||
nonce: nonce | ||
}) do | ||
address = SCAddress.to_xdr(address) | ||
nonce = UInt64.new(nonce) | ||
|
||
AddressWithNonce.new(address, nonce) | ||
end | ||
|
||
def to_xdr(_error), do: {:error, :invalid_struct_address_with_nonce} | ||
|
||
@spec validate_address(tuple()) :: validation() | ||
defp validate_address({_field, %SCAddress{} = value}), do: {:ok, value} | ||
defp validate_address({field, _value}), do: {:error, :"invalid_#{field}"} | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
defmodule Stellar.TxBuild.AuthorizedInvocation do | ||
@moduledoc """ | ||
`AuthorizedInvocation` struct definition. | ||
""" | ||
import Stellar.TxBuild.Validations, | ||
only: [ | ||
validate_sc_vals: 1, | ||
validate_contract_id: 1, | ||
validate_string: 1, | ||
is_struct?: 2 | ||
] | ||
|
||
alias StellarBase.XDR.{AuthorizedInvocation, AuthorizedInvocationList, Hash, SCSymbol, SCVec} | ||
alias Stellar.TxBuild.SCVal | ||
|
||
@type error :: Keyword.t() | atom() | ||
@type validation :: {:ok, any()} | {:error, error()} | ||
@type authorized_invocation_list :: AuthorizedInvocationList.t() | ||
@type t :: %__MODULE__{ | ||
contract_id: binary(), | ||
function_name: String.t(), | ||
args: list(SCVal.t()), | ||
sub_invocations: list(t()) | ||
} | ||
|
||
@behaviour Stellar.TxBuild.XDR | ||
|
||
defstruct [:contract_id, :function_name, :args, :sub_invocations] | ||
|
||
@impl true | ||
def new(args, opts \\ nil) | ||
|
||
def new(args, _opts) when is_list(args) do | ||
contract_id = Keyword.get(args, :contract_id) | ||
function_name = Keyword.get(args, :function_name) | ||
sub_invocations = Keyword.get(args, :sub_invocations) | ||
args = Keyword.get(args, :args) | ||
|
||
with {:ok, contract_id} <- validate_contract_id({:contract_id, contract_id}), | ||
{:ok, function_name} <- validate_string({:function_name, function_name}), | ||
{:ok, args} <- validate_sc_vals({:args, args}), | ||
{:ok, sub_invocations} <- validate_sub_invocations({:sub_invocations, sub_invocations}) do | ||
%__MODULE__{ | ||
contract_id: contract_id, | ||
function_name: function_name, | ||
args: args, | ||
sub_invocations: sub_invocations | ||
} | ||
end | ||
end | ||
|
||
def new(_args, _opts), do: {:error, :invalid_authorized_invocation} | ||
|
||
@impl true | ||
def to_xdr(%__MODULE__{ | ||
contract_id: contract_id, | ||
function_name: function_name, | ||
args: args, | ||
sub_invocations: sub_invocations | ||
}) do | ||
contract_id = | ||
contract_id | ||
|> Base.decode16!(case: :lower) | ||
|> Hash.new() | ||
|
||
function_name = SCSymbol.new(function_name) | ||
args = args |> Enum.map(&SCVal.to_xdr/1) |> SCVec.new() | ||
|
||
sub_invocations = sub_invocations |> Enum.map(&to_xdr/1) |> AuthorizedInvocationList.new() | ||
|
||
AuthorizedInvocation.new(contract_id, function_name, args, sub_invocations) | ||
end | ||
|
||
def to_xdr(_error), do: {:error, :invalid_struct_authorized_invocation} | ||
|
||
@spec validate_sub_invocations(tuple :: tuple()) :: validation() | ||
defp validate_sub_invocations({field, args}) when is_list(args) do | ||
if Enum.all?(args, &is_struct?(&1, __MODULE__)), | ||
do: {:ok, args}, | ||
else: {:error, :"invalid_#{field}"} | ||
end | ||
|
||
defp validate_sub_invocations({field, _args}), do: {:error, :"invalid_#{field}"} | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,149 @@ | ||
defmodule Stellar.TxBuild.ContractAuth do | ||
@moduledoc """ | ||
`ContractAuth` struct definition. | ||
""" | ||
|
||
import Stellar.TxBuild.Validations, | ||
only: [ | ||
validate_sc_vals: 1, | ||
validate_optional_address_with_nonce: 1 | ||
] | ||
|
||
alias Stellar.TxBuild.{ | ||
AuthorizedInvocation, | ||
OptionalAddressWithNonce, | ||
SCObject, | ||
SCMapEntry, | ||
HashIDPreimage | ||
} | ||
|
||
alias Stellar.{KeyPair, Network} | ||
alias StellarBase.XDR.{ContractAuth, SCVec} | ||
alias StellarBase.XDR.HashIDPreimage, as: HashIDPreimageXDR | ||
|
||
alias Stellar.TxBuild.{ | ||
AddressWithNonce, | ||
SCVal, | ||
HashIDPreimageContractAuth | ||
} | ||
|
||
@type error :: Keyword.t() | atom() | ||
@type validation :: {:ok, any()} | {:error, error()} | ||
|
||
@type t :: %__MODULE__{ | ||
address_with_nonce: OptionalAddressWithNonce.t(), | ||
authorized_invocation: AuthorizedInvocation.t(), | ||
signature_args: list(SCVal.t()) | ||
} | ||
|
||
@behaviour Stellar.TxBuild.XDR | ||
|
||
defstruct [:address_with_nonce, :authorized_invocation, :signature_args] | ||
|
||
@impl true | ||
def new(args, opts \\ nil) | ||
|
||
def new(args, _opts) when is_list(args) do | ||
address_with_nonce = Keyword.get(args, :address_with_nonce) | ||
authorized_invocation = Keyword.get(args, :authorized_invocation) | ||
signature_args = Keyword.get(args, :signature_args, []) | ||
|
||
with {:ok, opt_address_with_nonce} <- | ||
validate_optional_address_with_nonce({:address_with_nonce, address_with_nonce}), | ||
{:ok, authorized_invocation} <- | ||
validate_authorized_invocation({:authorized_invocation, authorized_invocation}), | ||
{:ok, signature_args} <- | ||
validate_sc_vals({:signature_args, signature_args}) do | ||
%__MODULE__{ | ||
address_with_nonce: opt_address_with_nonce, | ||
authorized_invocation: authorized_invocation, | ||
signature_args: signature_args | ||
} | ||
end | ||
end | ||
|
||
def new(_args, _opts), do: {:error, :invalid_contract_auth} | ||
|
||
@impl true | ||
def to_xdr(%__MODULE__{ | ||
address_with_nonce: address_with_nonce, | ||
authorized_invocation: authorized_invocation, | ||
signature_args: signature_args | ||
}) do | ||
address_with_nonce = OptionalAddressWithNonce.to_xdr(address_with_nonce) | ||
|
||
authorized_invocation = AuthorizedInvocation.to_xdr(authorized_invocation) | ||
|
||
signature_args = | ||
[vec: signature_args] | ||
|> SCObject.new() | ||
|> SCVal.new() | ||
|> SCVal.to_xdr() | ||
|> (&SCVec.new([&1])).() | ||
|
||
ContractAuth.new(address_with_nonce, authorized_invocation, signature_args) | ||
end | ||
|
||
def to_xdr(_struct), do: {:error, :invalid_struct_contract_auth} | ||
|
||
@spec sign(contract_auth :: t(), secret_key :: binary) :: t() | ||
def sign( | ||
%__MODULE__{ | ||
address_with_nonce: %OptionalAddressWithNonce{ | ||
address_with_nonce: %AddressWithNonce{nonce: nonce} | ||
}, | ||
authorized_invocation: authorized_invocation, | ||
signature_args: signature_args | ||
} = contract_auth, | ||
secret_key | ||
) | ||
when is_binary(secret_key) do | ||
{public_key, _secret_key} = KeyPair.from_secret_seed(secret_key) | ||
raw_public_key = KeyPair.raw_public_key(public_key) | ||
network_id = network_id_xdr() | ||
|
||
signature = | ||
[ | ||
network_id: network_id, | ||
nonce: nonce, | ||
invocation: authorized_invocation | ||
] | ||
|> HashIDPreimageContractAuth.new() | ||
|> (&HashIDPreimage.new(contract_auth: &1)).() | ||
|> HashIDPreimage.to_xdr() | ||
|> HashIDPreimageXDR.encode_xdr!() | ||
|> hash() | ||
|> KeyPair.sign(secret_key) | ||
|
||
public_key_map_entry = | ||
SCMapEntry.new( | ||
SCVal.new(symbol: "public_key"), | ||
SCVal.new(object: SCObject.new(bytes: raw_public_key)) | ||
) | ||
|
||
signature_map_entry = | ||
SCMapEntry.new( | ||
SCVal.new(symbol: "signature"), | ||
SCVal.new(object: SCObject.new(bytes: signature)) | ||
) | ||
|
||
signature_sc_val = | ||
SCVal.new(object: SCObject.new(map: [public_key_map_entry, signature_map_entry])) | ||
|
||
%{contract_auth | signature_args: signature_args ++ [signature_sc_val]} | ||
end | ||
|
||
def sign(_args, _val), do: {:error, :invalid_secret_key} | ||
|
||
@spec network_id_xdr :: binary() | ||
defp network_id_xdr, do: hash(Network.passphrase()) | ||
|
||
@spec hash(data :: binary()) :: binary() | ||
defp hash(data), do: :crypto.hash(:sha256, data) | ||
|
||
@spec validate_authorized_invocation(tuple :: tuple()) :: validation() | ||
defp validate_authorized_invocation({_field, %AuthorizedInvocation{} = value}), | ||
do: {:ok, value} | ||
|
||
defp validate_authorized_invocation({field, _}), do: {:error, :"invalid_#{field}"} | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
defmodule Stellar.TxBuild.Ed25519ContractID do | ||
@moduledoc """ | ||
`Ed25519ContractID` struct definition. | ||
""" | ||
|
||
import Stellar.TxBuild.Validations, | ||
only: [ | ||
validate_pos_integer: 1, | ||
validate_string: 1 | ||
] | ||
|
||
alias StellarBase.XDR.{Ed25519ContractID, Hash, UInt256} | ||
|
||
@type t :: %__MODULE__{ | ||
network_id: binary(), | ||
ed25519: non_neg_integer(), | ||
salt: non_neg_integer() | ||
} | ||
|
||
@behaviour Stellar.TxBuild.XDR | ||
|
||
defstruct [:network_id, :ed25519, :salt] | ||
|
||
@impl true | ||
def new(args, opts \\ nil) | ||
|
||
def new(args, _opts) when is_list(args) do | ||
network_id = Keyword.get(args, :network_id) | ||
ed25519 = Keyword.get(args, :ed25519) | ||
salt = Keyword.get(args, :salt) | ||
|
||
with {:ok, network_id} <- validate_string({:network_id, network_id}), | ||
{:ok, ed25519} <- validate_pos_integer({:ed25519, ed25519}), | ||
{:ok, salt} <- validate_pos_integer({:salt, salt}) do | ||
%__MODULE__{ | ||
network_id: network_id, | ||
ed25519: ed25519, | ||
salt: salt | ||
} | ||
end | ||
end | ||
|
||
def new(_args, _opts), do: {:error, :invalid_ed25519_contract_id} | ||
|
||
@impl true | ||
def to_xdr(%__MODULE__{ | ||
network_id: network_id, | ||
ed25519: ed25519, | ||
salt: salt | ||
}) do | ||
network_id = Hash.new(network_id) | ||
ed25519 = UInt256.new(ed25519) | ||
salt = UInt256.new(salt) | ||
|
||
Ed25519ContractID.new(network_id, ed25519, salt) | ||
end | ||
|
||
def to_xdr(_error), do: {:error, :invalid_struct_ed25519_contract_id} | ||
end |
Oops, something went wrong.