Created
December 26, 2025 01:26
-
-
Save mazz/7235130052a4ebda1f235c56f9db0abc to your computer and use it in GitHub Desktop.
This file contains hidden or 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
| defp build_configure_transaction( | |
| {escrow_public_key, escrow_secret_seed}, | |
| depositor_public_key, | |
| recipient_public_key, | |
| asset_code, | |
| asset_issuer, | |
| network_passphrase, | |
| sequence | |
| ) do | |
| # Validate issuer public key | |
| case StrKey.decode(asset_issuer, :ed25519_public_key) do | |
| {:ok, _decoded_issuer} -> | |
| server = horizon_server() | |
| unless issuer_exists?(asset_issuer, server) do | |
| Logger.error("Asset issuer #{asset_issuer} does not exist on network") | |
| throw({:invalid_asset, "Asset issuer account does not exist"}) | |
| end | |
| # Look up and normalize asset | |
| normalized_code = | |
| case Assets.all(server, asset_issuer: asset_issuer) do | |
| {:ok, %Stellar.Horizon.Collection{records: assets}} -> | |
| case Enum.find(assets, fn asset -> asset.asset_code == asset_code end) do | |
| nil -> | |
| Logger.error("Asset #{asset_code} not found for issuer #{asset_issuer}") | |
| throw({:invalid_asset, "Asset not found for issuer"}) | |
| horizon_asset -> | |
| code = String.trim(horizon_asset.asset_code) | |
| unless code =~ ~r/^[A-Za-z0-9]{1,12}$/ do | |
| Logger.error("Invalid asset code: #{code}") | |
| throw({:invalid_asset, "Invalid asset code format"}) | |
| end | |
| code | |
| end | |
| {:error, reason} -> | |
| Logger.error("Failed to fetch assets for issuer #{asset_issuer}: #{inspect(reason)}") | |
| throw({:invalid_asset, "Failed to fetch assets"}) | |
| end | |
| escrow_account = Account.new(escrow_public_key) | |
| trust_op = | |
| ChangeTrust.new(asset: {normalized_code, asset_issuer}, limit: "922337203685.4775807") | |
| Logger.debug("Trustline operation: #{inspect(trust_op, pretty: true)}") | |
| # Decode signer keys to binary format | |
| Logger.info("[TX 2 Build] Decoding signer public keys to binary format.") | |
| {:ok, depositor_binary_key} = StrKey.decode(depositor_public_key, :ed25519_public_key) | |
| {:ok, recipient_binary_key} = StrKey.decode(recipient_public_key, :ed25519_public_key) | |
| Logger.debug("[TX 2 Build] Depositor Binary Key: #{inspect(depositor_binary_key)}") | |
| Logger.debug("[TX 2 Build] Recipient Binary Key: #{inspect(recipient_binary_key)}") | |
| # Build Signer structs directly with binary keys | |
| depositor_signer = Signer.new(ed25519_public_key: depositor_binary_key, weight: 1) | |
| recipient_signer = Signer.new(ed25519_public_key: recipient_binary_key, weight: 1) | |
| Logger.debug("Depositor Signer struct: #{inspect(depositor_signer, pretty: true)}") | |
| Logger.debug("Recipient Signer struct: #{inspect(recipient_signer, pretty: true)}") | |
| # First SetOptions: thresholds + master weight only | |
| set_options_master = | |
| SetOptions.new( | |
| master_weight: 0, | |
| low_threshold: 0, | |
| medium_threshold: 2, | |
| high_threshold: 2 | |
| ) | |
| Logger.debug("SetOptions (master/thresholds) operation: #{inspect(set_options_master, pretty: true)}") | |
| # Second SetOptions: add depositor as signer | |
| set_options_depositor = | |
| SetOptions.new( | |
| signer: depositor_signer | |
| ) | |
| Logger.debug("SetOptions (depositor signer) operation: #{inspect(set_options_depositor, pretty: true)}") | |
| # Third SetOptions: add recipient as signer | |
| set_options_recipient = | |
| SetOptions.new( | |
| signer: recipient_signer | |
| ) | |
| Logger.debug("SetOptions (recipient signer) operation: #{inspect(set_options_recipient, pretty: true)}") | |
| # Build transaction with 4 ops: trustline + 3 set-options | |
| unsigned_tx = | |
| Stellar.TxBuild.new( | |
| escrow_account, | |
| fee: @base_fee * 4, | |
| network_passphrase: network_passphrase, | |
| sequence_number: sequence | |
| ) | |
| |> Stellar.TxBuild.add_operation(trust_op) | |
| |> Stellar.TxBuild.add_operation(set_options_master) | |
| |> Stellar.TxBuild.add_operation(set_options_depositor) | |
| |> Stellar.TxBuild.add_operation(set_options_recipient) | |
| Logger.debug("Unsigned transaction (TX 2): #{inspect(unsigned_tx, pretty: true)}") | |
| signature = Signature.new(ed25519: escrow_secret_seed) | |
| signed_tx = Stellar.TxBuild.sign(unsigned_tx, signature) | |
| Logger.debug("Signed transaction (TX 2): #{inspect(signed_tx, pretty: true)}") | |
| {:ok, signed_tx} | |
| {:error, reason} -> | |
| Logger.error("Invalid asset issuer public key: #{asset_issuer}, reason: #{inspect(reason)}") | |
| {:error, {:invalid_asset, "Invalid asset issuer public key"}} | |
| end | |
| catch | |
| {:invalid_asset, reason} -> | |
| Logger.error("[TX 2 Build] Invalid asset: #{inspect(reason)}") | |
| {:error, {:invalid_asset, reason}} | |
| {:invalid_signer, reason} -> | |
| Logger.error("[TX 2 Build] Invalid signer: #{inspect(reason)}") | |
| {:error, {:invalid_signer, reason}} | |
| end | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment