Skip to content

Token-Gated Invoice Access Controller #548

Description

@Kingsman-99

Description

Some invoice workflows should be readable only by accounts holding a minimum balance of a specific Stellar asset (e.g. a governance or membership token). The SDK has no access control primitive tied to on-chain token ownership. A token-gated access controller should verify a caller's token balance before returning invoice data, integrating with Server.loadAccount() to read balances on demand without requiring off-chain authentication.

Technical Context

Add src/tokenGateController.ts. Reads BalanceLineAsset from @stellar/stellar-sdk account data. Accepts TokenGatePolicy (asset, minimum balance) added to src/types.ts. Integrates with src/client.ts getInvoice() and src/accessControl.ts. Throws TokenGateAccessDeniedError from src/errors.ts when the caller's balance is below the minimum. Caches balance checks via src/cache.ts with a short TTL.

Acceptance Criteria

  • TokenGateController.verify(callerAccountId: string, policy: TokenGatePolicy): Promise<void> resolves when the caller meets the balance requirement and throws TokenGateAccessDeniedError otherwise
  • Balance check result is cached for cacheTtlMs (configurable, default 15 000 ms) to reduce Horizon calls
  • src/client.ts getInvoice() calls TokenGateController.verify() when invoice.accessPolicy is set
  • TokenGatePolicy supports { asset: Asset, minBalance: string, strict: boolean } where strict: false only warns without blocking
  • Unit tests mock loadAccount() for two scenarios: balance above minimum (resolves) and balance below minimum (throws)
  • All CI checks (npm test, npm run build, ESLint/TypeScript) pass and the branch has no merge conflicts

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions