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:
-
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.
-
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.
-
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.
-
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.
-
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.
-
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.
-
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.
-
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.
-
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.
-
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.
-
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.
-
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
-
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.
-
Add a trustline-existence check (query the buyer's account balances via Horizon/RPC) before attempting any transfer to that account.
-
Add explicit detection and a clear error/response for op_no_trust failures on submitted transfer transactions.
-
Add configuration for default trustline limits per supported asset code.
-
Add a TrustlineClient (or extend the existing Client interface in stellar_client.go) with a BuildTrustlineTransaction method and a mock implementation for tests.
-
Add a re-check of trustline status immediately before executing a transfer, not just at onboarding time.
-
Add issuer-side AllowTrust/SetTrustLineFlags support if any supported asset uses AUTH_REQUIRED_FLAG.
-
Add buyer account existence/funding checks before returning a trustline transaction for signing.
-
Add unit tests for trustline-missing, trustline-established, and trustline-removed transfer scenarios.
-
Add integration between this trustline flow and the existing IsStellarProvider/NormalizeAssetCode helpers in stellar_payments.go.
-
Document the buyer-side trustline signing requirement in onboarding/API docs.
-
Add structured logging when a transfer fails specifically due to a missing trustline, distinct from other failure types.
Acceptance Criteria
- An endpoint returns an unsigned
ChangeTrust transaction XDR for a buyer to establish a trustline.
- Transfers to a buyer without a trustline return a specific, actionable error instead of a generic failure.
- Trustline existence is verified immediately before a transfer is attempted.
- Trustline limits are configurable per asset code.
- Issuer-required-authorization assets are supported via
AllowTrust/SetTrustLineFlags.
- Buyer account existence is verified before trustline setup is offered.
- Unit tests cover missing, established, and removed trustline scenarios.
op_no_trust failures are distinguishable from other transfer failures in logs and API responses.
- Documentation describes the buyer-side trustline signing step.
- No transfer is attempted against a known trustline-missing account.
Directory to Work on:
project-portal/project-portal-backend/
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.goandproject-portal/project-portal-backend/internal/financing/payments/stellar_payments.go:No trustline operation anywhere in the module:
stellar_client.goonly buildstxnbuild.InvokeHostFunctionoperations formint— there is notxnbuild.ChangeTrustoperation constructed anywhere ininternal/financing.RealStellarClient.Mintassumes the recipient can already hold the asset:Mintsends tokens toowner(req.AssetIssueror the authority address) without any prior check that the destination account has established a trustline for the carbon asset code.payments.NormalizeAssetCodeproduces asset codes with no corresponding trustline flow:NormalizeAssetCodeinstellar_payments.gomaps currencies to asset codes likeUSDC, but nothing in the payments package establishes a trustline for that asset on the buyer's account before a transfer is attempted.No buyer account existence check: There is no call to
LoadAccountfor the buyer's address (only the authority's account is loaded inMint) to confirm the account exists and is funded before attempting a transfer.No trustline-limit configuration:
txnbuild.ChangeTrustrequires an asset and optional limit; no configuration or default limit strategy exists for carbon asset or stablecoin trustlines.No detection of
op_no_trustfailures: Since trustlines are never set up client-side, submitted transfer transactions that fail with Horizon'sop_no_trusterror have no specific handling or user-facing message distinguishing this from a generic failure.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.IsStellarProviderhas no accompanying trustline-readiness check:stellar_payments.goonly classifies whether a provider string is"stellar"/"stellar_network"— it does not verify the buyer's account is trustline-ready for that provider path.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.
No support for the authorization-required asset flag: If the carbon asset or stablecoin requires issuer authorization (
AUTH_REQUIRED_FLAG), there is noAllowTrust/SetTrustLineFlagscounterpart operation for the issuer side.No tests for trustline scenarios:
stellar_client_test.goandworkflow_test.goininternal/financing/tokenizationdo not cover trustline-missing, trustline-established, or trustline-removed cases.No documentation for buyers on the trustline requirement: There is no operator or buyer-facing guidance in the repo describing that a
ChangeTrusttransaction must be signed before a purchase can be finalized.Required Changes
Add an endpoint that builds and returns an unsigned
txnbuild.ChangeTrusttransaction XDR for a given buyer public key and asset code/issuer, for the buyer's wallet to sign.Add a trustline-existence check (query the buyer's account balances via Horizon/RPC) before attempting any transfer to that account.
Add explicit detection and a clear error/response for
op_no_trustfailures on submitted transfer transactions.Add configuration for default trustline limits per supported asset code.
Add a
TrustlineClient(or extend the existingClientinterface instellar_client.go) with aBuildTrustlineTransactionmethod and a mock implementation for tests.Add a re-check of trustline status immediately before executing a transfer, not just at onboarding time.
Add issuer-side
AllowTrust/SetTrustLineFlagssupport if any supported asset usesAUTH_REQUIRED_FLAG.Add buyer account existence/funding checks before returning a trustline transaction for signing.
Add unit tests for trustline-missing, trustline-established, and trustline-removed transfer scenarios.
Add integration between this trustline flow and the existing
IsStellarProvider/NormalizeAssetCodehelpers instellar_payments.go.Document the buyer-side trustline signing requirement in onboarding/API docs.
Add structured logging when a transfer fails specifically due to a missing trustline, distinct from other failure types.
Acceptance Criteria
ChangeTrusttransaction XDR for a buyer to establish a trustline.AllowTrust/SetTrustLineFlags.op_no_trustfailures are distinguishable from other transfer failures in logs and API responses.Directory to Work on:
project-portal/project-portal-backend/