Skip to content

Implement Stellar asset trustline setup for new buyers #562

Description

@Oluwaseyi89

Summary

Implement Stellar asset trustline setup for new buyers — No endpoint creates a trustline on a buyer's Stellar account before attempting a carbon credit transfer, which will always fail.

Social Media Link

Let's collaborate on Discord. And ensure to star our repo.

Problem Statement

Confirmed in project-portal/project-portal-backend/internal/financing/tokenization/stellar_client.go and project-portal/project-portal-backend/internal/financing/payments/stellar_payments.go:

  1. No trustline operation anywhere in the module: stellar_client.go only builds txnbuild.InvokeHostFunction operations for mint — there is no txnbuild.ChangeTrust operation constructed anywhere in internal/financing.

  2. RealStellarClient.Mint assumes the recipient can already hold the asset: Mint sends tokens to owner (req.AssetIssuer or the authority address) without any prior check that the destination account has established a trustline for the carbon asset code.

  3. payments.NormalizeAssetCode produces asset codes with no corresponding trustline flow: NormalizeAssetCode in stellar_payments.go maps currencies to asset codes like USDC, but nothing in the payments package establishes a trustline for that asset on the buyer's account before a transfer is attempted.

  4. No buyer account existence check: There is no call to LoadAccount for the buyer's address (only the authority's account is loaded in Mint) to confirm the account exists and is funded before attempting a transfer.

  5. No trustline-limit configuration: txnbuild.ChangeTrust requires an asset and optional limit; no configuration or default limit strategy exists for carbon asset or stablecoin trustlines.

  6. No detection of op_no_trust failures: Since trustlines are never set up client-side, submitted transfer transactions that fail with Horizon's op_no_trust error have no specific handling or user-facing message distinguishing this from a generic failure.

  7. No endpoint for a buyer to initiate trustline setup: There is no handler in internal/financing (or elsewhere) that returns a trustline transaction XDR for the buyer's wallet to sign, which is required since the platform cannot sign on behalf of buyer-controlled accounts.

  8. IsStellarProvider has no accompanying trustline-readiness check: stellar_payments.go only classifies whether a provider string is "stellar"/"stellar_network" — it does not verify the buyer's account is trustline-ready for that provider path.

  9. No re-check before transfer: Even if a trustline were established once, nothing re-verifies it still exists (a trustline can be removed by the account holder) immediately before a transfer attempt.

  10. No support for the authorization-required asset flag: If the carbon asset or stablecoin requires issuer authorization (AUTH_REQUIRED_FLAG), there is no AllowTrust/SetTrustLineFlags counterpart operation for the issuer side.

  11. No tests for trustline scenarios: stellar_client_test.go and workflow_test.go in internal/financing/tokenization do not cover trustline-missing, trustline-established, or trustline-removed cases.

  12. No documentation for buyers on the trustline requirement: There is no operator or buyer-facing guidance in the repo describing that a ChangeTrust transaction must be signed before a purchase can be finalized.

Required Changes

  1. Add an endpoint that builds and returns an unsigned txnbuild.ChangeTrust transaction XDR for a given buyer public key and asset code/issuer, for the buyer's wallet to sign.

  2. Add a trustline-existence check (query the buyer's account balances via Horizon/RPC) before attempting any transfer to that account.

  3. Add explicit detection and a clear error/response for op_no_trust failures on submitted transfer transactions.

  4. Add configuration for default trustline limits per supported asset code.

  5. Add a TrustlineClient (or extend the existing Client interface in stellar_client.go) with a BuildTrustlineTransaction method and a mock implementation for tests.

  6. Add a re-check of trustline status immediately before executing a transfer, not just at onboarding time.

  7. Add issuer-side AllowTrust/SetTrustLineFlags support if any supported asset uses AUTH_REQUIRED_FLAG.

  8. Add buyer account existence/funding checks before returning a trustline transaction for signing.

  9. Add unit tests for trustline-missing, trustline-established, and trustline-removed transfer scenarios.

  10. Add integration between this trustline flow and the existing IsStellarProvider/NormalizeAssetCode helpers in stellar_payments.go.

  11. Document the buyer-side trustline signing requirement in onboarding/API docs.

  12. Add structured logging when a transfer fails specifically due to a missing trustline, distinct from other failure types.

Acceptance Criteria

  1. An endpoint returns an unsigned ChangeTrust transaction XDR for a buyer to establish a trustline.
  2. Transfers to a buyer without a trustline return a specific, actionable error instead of a generic failure.
  3. Trustline existence is verified immediately before a transfer is attempted.
  4. Trustline limits are configurable per asset code.
  5. Issuer-required-authorization assets are supported via AllowTrust/SetTrustLineFlags.
  6. Buyer account existence is verified before trustline setup is offered.
  7. Unit tests cover missing, established, and removed trustline scenarios.
  8. op_no_trust failures are distinguishable from other transfer failures in logs and API responses.
  9. Documentation describes the buyer-side trustline signing step.
  10. No transfer is attempted against a known trustline-missing account.

Directory to Work on:

project-portal/project-portal-backend/

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    backendThis issue is about building backend API services.ginThis issue is to be implemented with the `golang` `gin` framework for backend APIs.golangThis issue is to be implemented with `golang` programming language.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions