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
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. ReadsBalanceLineAssetfrom@stellar/stellar-sdkaccount data. AcceptsTokenGatePolicy(asset, minimum balance) added tosrc/types.ts. Integrates withsrc/client.tsgetInvoice()andsrc/accessControl.ts. ThrowsTokenGateAccessDeniedErrorfromsrc/errors.tswhen the caller's balance is below the minimum. Caches balance checks viasrc/cache.tswith a short TTL.Acceptance Criteria
TokenGateController.verify(callerAccountId: string, policy: TokenGatePolicy): Promise<void>resolves when the caller meets the balance requirement and throwsTokenGateAccessDeniedErrorotherwisecacheTtlMs(configurable, default 15 000 ms) to reduce Horizon callssrc/client.tsgetInvoice()callsTokenGateController.verify()wheninvoice.accessPolicyis setTokenGatePolicysupports{ asset: Asset, minBalance: string, strict: boolean }wherestrict: falseonly warns without blockingloadAccount()for two scenarios: balance above minimum (resolves) and balance below minimum (throws)