Skip to content

Commit

Permalink
Merge pull request #215 from kommitters/v0.9
Browse files Browse the repository at this point in the history
Release v0.9.2
  • Loading branch information
CristhianRodriguezMolina authored Aug 9, 2022
2 parents b65e7a0 + 134ba96 commit 205c1bd
Show file tree
Hide file tree
Showing 7 changed files with 253 additions and 19 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## 0.9.2 (09.08.2022)
* Fix preconditions to allow minimum sequence number field to be optional.
* Add stellar protocol 19 documentation.

## 0.9.1 (08.08.2022)
* Add scorecards actions

Expand Down
72 changes: 66 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ The **Stellar SDK** enables the construction, signing and encoding of Stellar [t

This library is aimed at developers building Elixir applications that interact with the [**Stellar network**][stellar].

#### Protocol Version Support
| Protocol | Version |
| --------- | ------------ |
| 18 | >= v0.8 |
| 19 | >= v0.9 |

## Documentation
The **Stellar SDK** is composed of two complementary components: **`TxBuild`** + **`Horizon`**.
* **`TxBuild`** - used for [**building transactions.**](#building-transactions)
Expand All @@ -21,7 +27,7 @@ The **Stellar SDK** is composed of two complementary components: **`TxBuild`** +
```elixir
def deps do
[
{:stellar_sdk, "~> 0.9.1"}
{:stellar_sdk, "~> 0.9.2"}
]
end
```
Expand Down Expand Up @@ -102,7 +108,7 @@ source_account = Stellar.TxBuild.Account.new("GDC3W2X5KUTZRTQIKXM5D2I5WG5JYSEJQW
Stellar.TxBuild.new(source_account)

# initialize a transaction with options
# allowed options: memo, sequence_number, base_fee, time_bounds
# allowed options: memo, sequence_number, base_fee, preconditions
Stellar.TxBuild.new(source_account, memo: memo, sequence_number: sequence_number)
```

Expand Down Expand Up @@ -169,13 +175,27 @@ base_fee = Stellar.TxBuild.BaseFee.new(1_000)
|> Stellar.TxBuild.set_base_fee(base_fee)
```

#### Time bounds
[TimeBounds][stellar-docs-time-bounds] are optional UNIX timestamps (in seconds), determined by ledger time. A lower and upper bound of when this transaction will be valid.
#### Preconditions
Proposed on the [Stellar protocol-19][stellar-protocol-19] implementation, [Preconditions][stellar-docs-preconditions] are conditions that determines if a transaction is valid or not, and implements the following conditions:

- **Time bounds**: [TimeBounds][stellar-docs-time-bounds] are optional UNIX timestamps (in seconds), determined by ledger time. A lower and upper bound of when this transaction will be valid.

- **Ledger bounds**: [LedgerBounds][stellar-docs-ledger-bounds] are like Time Bounds, except they apply to ledger numbers. With them set, a transaction will only be valid for ledger numbers that fall into the range you set.

- **Minimum Sequence Number**: [Minimum sequence number][stellar-docs-min-seq-num] if is set, the transaction will only be valid when `S` (the minimum sequence number) satisfies `minSeqNum <= S < tx.seqNum`. If is not set, the default behavior applies (the transaction’s sequence number must be exactly one greater than the account’s sequence number)

- **Minimum Sequence Age**: [Minimum sequence age][stellar-docs-min-seq-age] is based on the account's [sequence number age][stellar-docs-account-seq-num-age]. When is set, the transaction is only valid after a particular duration (in seconds) elapses since the account’s sequence number age.

- **Minimum Sequence Ledger Gap**: [Minimum sequence ledger gap][stellar-docs-min-seq-ledger-gap] is based on the account's [sequence number age][stellar-docs-account-seq-num-age], this is similar to the minimum sequence age, except it’s expressed as a number of ledgers rather than a duration of time.

- **Extra Signers**: A transaction can specify up to two [Extra signers][stellar-docs-extra-signers] (of any type) even if those signatures would not otherwise be required to authorize the transaction.

```elixir
# set the source account (this accound should exist in the ledger)
source_account = Stellar.TxBuild.Account.new("GDC3W2X5KUTZRTQIKXM5D2I5WG5JYSEJQWEELVPQ5YMWZR6CA2JJ35RW")

# TimeBounds ---------------------------------------------------------------------------

# no time bounds for a transaction
time_bounds = Stellar.TxBuild.TimeBounds.new(:none)

Expand All @@ -194,11 +214,43 @@ time_bounds = Stellar.TxBuild.TimeBounds.new(
# timeout
time_bounds = Stellar.TxBuild.TimeBounds.set_timeout(1_643_990_815)

# set the time bounds for the transaction
# LedgerBounds -------------------------------------------------------------------------

# no ledger bounds for a transaction
ledger_bounds = Stellar.TxBuild.LedgerBounds.new(:none)

# ledger bounds with ledger numbers
ledger_bounds = Stellar.TxBuild.LedgerBounds.new(min_ledger: 0, max_ledger: 1_234_567_890)

# SequenceNumber -----------------------------------------------------------------------

# minimum sequence number for a transaction with value 0
min_seq_num = Stellar.TxBuild.SequenceNumber.new()

# minimum sequence number
min_seq_num = Stellar.TxBuild.SequenceNumber.new(1_000_000)

# ExtraSigners

extra_signers = ["GA2YG3YULNTUEMMLN4HUQVL7B37GJTYSRZYH6HZUFLXFDCCGKLXIXMDT"]

# Preconditions ------------------------------------------------------------------------

preconditions =
Stellar.TxBuild.Preconditions.new(
time_bounds: time_bounds,
ledger_bounds: ledger_bounds,
min_seq_num: min_seq_num,
min_seq_age: 30,
min_seq_ledger_gap: 5,
extra_signers: extra_signers
)

# set the preconditions for the transaction
{:ok, tx_build} =
source_account
|> Stellar.TxBuild.new()
|> Stellar.TxBuild.set_time_bounds(time_bounds)
|> Stellar.TxBuild.set_preconditions(preconditions)
```

#### Operations
Expand Down Expand Up @@ -785,8 +837,16 @@ Made with 💙 by [kommitters Open Source](https://kommit.co)
[stellar-docs-sequence-number]: https://developers.stellar.org/docs/glossary/transactions/#sequence-number
[stellar-docs-fee]: https://developers.stellar.org/docs/glossary/transactions/#fee
[stellar-docs-memo]: https://developers.stellar.org/docs/glossary/transactions/#memo
[stellar-docs-preconditions]: https://developers.stellar.org/docs/glossary/transactions/#validity-conditions
[stellar-docs-time-bounds]: https://developers.stellar.org/docs/glossary/transactions/#time-bounds
[stellar-docs-ledger-bounds]: https://developers.stellar.org/docs/glossary/transactions/#ledger-bounds
[stellar-docs-min-seq-num]: https://developers.stellar.org/docs/glossary/transactions/#minimum-sequence-number
[stellar-docs-min-seq-age]: https://developers.stellar.org/docs/glossary/transactions/#minimum-sequence-age
[stellar-docs-min-seq-ledger-gap]: https://developers.stellar.org/docs/glossary/transactions/#minimum-sequence-ledger-gap
[stellar-docs-extra-signers]: https://developers.stellar.org/docs/glossary/transactions/#extra-signers
[stellar-docs-tx-envelope]: https://developers.stellar.org/docs/glossary/transactions/#transaction-envelopes
[stellar-docs-list-operations]: https://developers.stellar.org/docs/start/list-of-operations
[stellar-docs-tx-signatures]: https://developers.stellar.org/docs/glossary/multisig/#transaction-signatures
[stellar-cap-27]: https://stellar.org/protocol/cap-27
[stellar-protocol-19]: https://stellar.org/blog/announcing-protocol-19
[stellar-docs-account-seq-num-age]: https://developers.stellar.org/docs/glossary/accounts/#sequence-time-and-ledger
33 changes: 33 additions & 0 deletions lib/tx_build/optional_sequence_number.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
defmodule Stellar.TxBuild.OptionalSequenceNumber do
@moduledoc """
`OptionalSequenceNumber` struct definition.
"""
alias StellarBase.XDR.OptionalSequenceNumber
alias Stellar.TxBuild.SequenceNumber

@behaviour Stellar.TxBuild.XDR

@type sequence_number :: SequenceNumber.t() | nil

@type t :: %__MODULE__{sequence_number: sequence_number()}

defstruct [:sequence_number]

@impl true
def new(sequence_number \\ nil, opts \\ [])

def new(%SequenceNumber{} = sequence_number, _opts) do
%__MODULE__{sequence_number: sequence_number}
end

def new(nil, _opts), do: %__MODULE__{sequence_number: nil}

@impl true
def to_xdr(%__MODULE__{sequence_number: nil}), do: OptionalSequenceNumber.new()

def to_xdr(%__MODULE__{sequence_number: sequence_number}) do
sequence_number
|> SequenceNumber.to_xdr()
|> OptionalSequenceNumber.new()
end
end
24 changes: 15 additions & 9 deletions lib/tx_build/preconditions.ex
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ defmodule Stellar.TxBuild.Preconditions do
TimeBounds,
LedgerBounds,
SequenceNumber,
SignerKey
SignerKey,
OptionalSequenceNumber
}

alias StellarBase.XDR.TimeBounds, as: TimeBoundsXDR
Expand All @@ -16,7 +17,6 @@ defmodule Stellar.TxBuild.Preconditions do
PreconditionsV2,
PreconditionType,
Duration,
OptionalSequenceNumber,
SignerKeyList,
TimePoint,
UInt32,
Expand All @@ -28,7 +28,7 @@ defmodule Stellar.TxBuild.Preconditions do
@type precond_v2 :: [
time_bounds: TimeBounds.t(),
ledger_bounds: LedgerBounds.t(),
min_seq_num: SequenceNumber.t(),
min_seq_num: OptionalSequenceNumber.t(),
min_seq_age: non_neg_integer(),
min_seq_ledger_gap: non_neg_integer(),
extra_signers: list(SignerKey.t())
Expand Down Expand Up @@ -63,7 +63,7 @@ defmodule Stellar.TxBuild.Preconditions do

with {:ok, time_bounds} <- validate_time_bounds(time_bounds),
{:ok, ledger_bounds} <- validate_ledger_bounds(ledger_bounds),
{:ok, min_seq_num} <- validate_min_seq_num(min_seq_num),
{:ok, min_seq_num} <- validate_optional_min_seq_num(min_seq_num),
{:ok, min_seq_age} <- validate_min_seq_age(min_seq_age),
{:ok, min_seq_ledger_gap} <- validate_min_seq_ledger_gap(min_seq_ledger_gap),
{:ok, extra_signers} <- validate_extra_signers([], extra_signers) do
Expand Down Expand Up @@ -117,7 +117,7 @@ defmodule Stellar.TxBuild.Preconditions do

time_bounds = TimeBounds.to_xdr(time_bounds)
ledger_bounds = LedgerBounds.to_xdr(ledger_bounds)
min_seq_num = min_seq_num |> SequenceNumber.to_xdr() |> OptionalSequenceNumber.new()
min_seq_num = OptionalSequenceNumber.to_xdr(min_seq_num)
min_seq_age = Duration.new(min_seq_age)
min_seq_ledger_gap = UInt32.new(min_seq_ledger_gap)
extra_signers_list = get_extra_signers_list(extra_signers)
Expand Down Expand Up @@ -150,11 +150,17 @@ defmodule Stellar.TxBuild.Preconditions do

defp validate_ledger_bounds(_ledger_bounds), do: {:error, :invalid_ledger_bounds}

@spec validate_min_seq_num(min_seq_num :: SequenceNumber.t()) :: validation()
defp validate_min_seq_num(%SequenceNumber{} = min_seq_num),
do: {:ok, min_seq_num}
@spec validate_optional_min_seq_num(min_seq_num :: SequenceNumber.t() | nil) :: validation()
defp validate_optional_min_seq_num(nil),
do: {:ok, OptionalSequenceNumber.new()}

defp validate_min_seq_num(_min_seq_num), do: {:error, :invalid_min_seq_num}
defp validate_optional_min_seq_num(%SequenceNumber{} = min_seq_num),
do:
min_seq_num
|> OptionalSequenceNumber.new()
|> (&{:ok, &1}).()

defp validate_optional_min_seq_num(_min_seq_num), do: {:error, :invalid_min_seq_num}

@spec validate_min_seq_age(min_seq_age :: non_neg_integer()) :: validation()
defp validate_min_seq_age(min_seq_age)
Expand Down
2 changes: 1 addition & 1 deletion mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ defmodule Stellar.MixProject do
use Mix.Project

@github_url "https://github.com/kommitters/stellar_sdk"
@version "0.9.1"
@version "0.9.2"

def project do
[
Expand Down
36 changes: 36 additions & 0 deletions test/tx_build/optional_sequence_number_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
defmodule Stellar.TxBuild.OptionalSequenceNumberTest do
use ExUnit.Case

alias Stellar.TxBuild.{SequenceNumber, OptionalSequenceNumber}
alias StellarBase.XDR.SequenceNumber, as: SequenceNumberXDR
alias StellarBase.XDR.OptionalSequenceNumber, as: OptionalSequenceNumberXDR

setup do
%{sequence_number: SequenceNumber.new(4_130_487_228_432_385)}
end

test "new/2", %{sequence_number: sequence_number} do
%OptionalSequenceNumber{sequence_number: ^sequence_number} =
OptionalSequenceNumber.new(sequence_number)
end

test "new/2 without_sequence_number" do
%OptionalSequenceNumber{sequence_number: nil} = OptionalSequenceNumber.new()
end

test "to_xdr/1", %{sequence_number: sequence_number} do
%OptionalSequenceNumberXDR{
sequence_number: %SequenceNumberXDR{sequence_number: 4_130_487_228_432_385}
} =
sequence_number
|> OptionalSequenceNumber.new()
|> OptionalSequenceNumber.to_xdr()
end

test "to_xdr/1 without_sequence_number" do
%OptionalSequenceNumberXDR{sequence_number: nil} =
nil
|> OptionalSequenceNumber.new()
|> OptionalSequenceNumber.to_xdr()
end
end
Loading

0 comments on commit 205c1bd

Please sign in to comment.