Packages
stellar_sdk
0.15.0
0.23.0
0.22.0
0.21.2
0.21.1
0.21.0
0.20.0
0.19.0
0.18.1
0.18.0
0.17.1
0.17.0
0.16.1
0.16.0
0.15.1
0.15.0
0.14.0
0.13.1
0.13.0
0.12.0
0.11.8
0.11.7
0.11.6
0.11.5
0.11.4
0.11.3
0.11.2
0.11.1
0.11.0
0.10.2
0.10.1
0.10.0
0.9.3
0.9.2
0.9.1
0.9.0
0.8.1
0.8.0
0.7.1
0.7.0
0.6.0
0.5.0
0.4.0
0.3.0
0.2.0
0.1.0
Elixir SDK for the Stellar network.
Current section
Files
Jump to
Current section
Files
lib/tx_build/account.ex
defmodule Stellar.TxBuild.Account do
@moduledoc """
`Account` struct definition.
"""
alias Stellar.KeyPair
alias StellarBase.XDR.{CryptoKeyType, MuxedAccount, MuxedAccountMed25519, UInt64, UInt256}
@behaviour Stellar.TxBuild.XDR
@type address :: String.t()
@type account_id :: String.t()
@type muxed_id :: integer() | nil
@type type :: :ed25519_public_key | :ed25519_muxed_account
@type error :: {:error, atom()}
@type validation :: {:ok, any()} | error()
@type t :: %__MODULE__{
address: address(),
account_id: account_id(),
muxed_id: muxed_id(),
type: type()
}
defstruct [:address, :account_id, :muxed_id, :type]
@impl true
def new(address, opts \\ [])
def new(address, _opts) when byte_size(address) == 69 do
with {:ok, address} <- validate_muxed_address(address),
{:ok, {account_id, muxed_id}} <- parse_muxed_address(address) do
%__MODULE__{
address: address,
account_id: account_id,
muxed_id: muxed_id,
type: :ed25519_muxed_account
}
end
end
def new(address, _opts) when byte_size(address) == 56 do
case validate_public_key(address) do
{:ok, account_id} ->
%__MODULE__{
address: account_id,
account_id: account_id,
type: :ed25519_public_key
}
error ->
error
end
end
def new(_address, _opts), do: {:error, :invalid_ed25519_public_key}
@impl true
def to_xdr(%__MODULE__{account_id: account_id, muxed_id: muxed_id, type: :ed25519_muxed_account}) do
type = CryptoKeyType.new(:KEY_TYPE_MUXED_ED25519)
ed25519_public_key_xdr = ed25519_public_key_xdr(account_id)
muxed_id
|> UInt64.new()
|> MuxedAccountMed25519.new(ed25519_public_key_xdr)
|> MuxedAccount.new(type)
end
def to_xdr(%__MODULE__{account_id: account_id}) do
type = CryptoKeyType.new(:KEY_TYPE_ED25519)
ed25519_public_key_xdr = ed25519_public_key_xdr(account_id)
MuxedAccount.new(ed25519_public_key_xdr, type)
end
@spec create_muxed(account_id :: account_id(), muxed_id :: muxed_id()) :: t()
def create_muxed(account_id, muxed_id)
when byte_size(account_id) == 56 and is_integer(muxed_id) do
account_id
|> KeyPair.raw_public_key()
|> Kernel.<>(<<muxed_id::big-unsigned-integer-size(64)>>)
|> KeyPair.from_raw_muxed_account()
|> new()
end
def create_muxed(_account_id, _id), do: {:error, :invalid_muxed_account}
@spec validate_muxed_address(address :: address()) :: validation()
defp validate_muxed_address(address) do
case KeyPair.validate_muxed_account(address) do
:ok -> {:ok, address}
error -> error
end
end
@spec validate_public_key(address :: address()) :: validation()
defp validate_public_key(address) do
case KeyPair.validate_public_key(address) do
:ok -> {:ok, address}
error -> error
end
end
@spec parse_muxed_address(address :: address()) :: {:ok, {account_id(), muxed_id()}} | error()
defp parse_muxed_address(address) do
address
|> KeyPair.raw_muxed_account()
|> encode_muxed_address()
end
@spec encode_muxed_address(decoded_address :: binary()) ::
{:ok, {account_id(), muxed_id()}} | error()
defp encode_muxed_address(<<decoded::binary-size(32), muxed_id::big-unsigned-integer-size(64)>>) do
ed25519_key = KeyPair.from_raw_public_key(decoded)
{:ok, {ed25519_key, muxed_id}}
end
defp encode_muxed_address(_muxed_account), do: {:error, :invalid_muxed_address}
@spec ed25519_public_key_xdr(account_id :: account_id()) :: UInt256.t()
defp ed25519_public_key_xdr(account_id) do
account_id
|> KeyPair.raw_public_key()
|> UInt256.new()
end
end