@plasius/economy 0.3.1 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/amount.ts","../src/canonical-order.ts","../src/contracts.ts","../src/acquisition.ts","../src/allocations.ts","../src/early-backers.ts","../src/ledger.ts","../src/integrity.ts","../src/lots.ts","../src/operations.ts","../src/ports/persistence.ts","../src/wallets.ts","../src/projection.ts","../src/ports/query.ts","../src/recurrence.ts","../src/spend-requests.ts"],"sourcesContent":["export * from \"./acquisition.js\";\nexport * from \"./allocations.js\";\nexport * from \"./amount.js\";\nexport * from \"./contracts.js\";\nexport * from \"./early-backers.js\";\nexport * from \"./errors.js\";\nexport * from \"./integrity.js\";\nexport * from \"./ledger.js\";\nexport * from \"./lots.js\";\nexport * from \"./operations.js\";\nexport * from \"./ports/persistence.js\";\nexport * from \"./ports/query.js\";\nexport * from \"./projection.js\";\nexport * from \"./recurrence.js\";\nexport * from \"./spend-requests.js\";\nexport * from \"./wallets.js\";\n","/** Stable machine-readable failures exposed by the economy domain. */\nexport type EconomyErrorCode =\n | \"INVALID_AMOUNT\"\n | \"AMOUNT_OUT_OF_RANGE\"\n | \"AMOUNT_NOT_WHOLE_TOKEN\"\n | \"INVALID_CONTRACT\"\n | \"UNBALANCED_TRANSACTION\"\n | \"DUPLICATE_IDENTIFIER\"\n | \"DUPLICATE_TRANSACTION\"\n | \"INSUFFICIENT_BALANCE\"\n | \"INSUFFICIENT_ELIGIBLE_LOTS\"\n | \"SOURCE_LOT_RESTRICTED\"\n | \"REVERSAL_ALREADY_EXISTS\"\n | \"NEGATIVE_PROJECTION\"\n | \"INVALID_TIME_WINDOW\";\n\nexport interface EconomyErrorEnvelopeV1 {\n readonly schemaVersion: \"1\";\n readonly error: {\n readonly code: EconomyErrorCode;\n readonly message: string;\n readonly requestId?: string;\n };\n}\n\n/**\n * Domain error with a stable code and deliberately non-sensitive message.\n * Provider evidence, identities, and payment details must not be included.\n */\nexport class EconomyError extends Error {\n readonly code: EconomyErrorCode;\n\n constructor(code: EconomyErrorCode, message: string) {\n super(message);\n this.name = \"EconomyError\";\n this.code = code;\n }\n}\n\n/** Throws a stable economy error when a domain assertion fails. */\nexport function economyAssert(\n condition: unknown,\n code: EconomyErrorCode,\n message: string,\n): asserts condition {\n if (!condition) {\n throw new EconomyError(code, message);\n }\n}\n\n/** Creates a bounded, non-sensitive error contract for an HTTP adapter. */\nexport function toEconomyErrorEnvelope(\n error: EconomyError,\n requestId?: string,\n): EconomyErrorEnvelopeV1 {\n return {\n schemaVersion: \"1\",\n error: {\n code: error.code,\n message: error.message.slice(0, 256),\n ...(requestId === undefined ? {} : { requestId }),\n },\n };\n}\n","import { EconomyError, economyAssert } from \"./errors.js\";\n\n/** Number of indivisible subunits in one public Token. */\nexport const TOKEN_SUBUNITS_PER_TOKEN = 1_000n;\n\n/** PostgreSQL-compatible signed bigint bounds. */\nexport const TOKEN_SUBUNITS_MIN = -(2n ** 63n);\nexport const TOKEN_SUBUNITS_MAX = 2n ** 63n - 1n;\n\ndeclare const tokenSubunitStringBrand: unique symbol;\n\n/** Canonical base-10 representation used at JSON and persistence boundaries. */\nexport type TokenSubunitString = string & {\n readonly [tokenSubunitStringBrand]: \"TokenSubunitString\";\n};\n\nconst CANONICAL_INTEGER = /^(?:0|-?[1-9][0-9]*)$/u;\n\nfunction assertInRange(amount: bigint): void {\n economyAssert(\n amount >= TOKEN_SUBUNITS_MIN && amount <= TOKEN_SUBUNITS_MAX,\n \"AMOUNT_OUT_OF_RANGE\",\n \"TokenSubunit amount is outside the signed 64-bit range\",\n );\n}\n\n/** Parses a canonical base-10 TokenSubunit string without floating point. */\nexport function parseTokenSubunits(value: string): bigint {\n economyAssert(\n typeof value === \"string\" && CANONICAL_INTEGER.test(value),\n \"INVALID_AMOUNT\",\n \"TokenSubunit amount must be a canonical base-10 integer string\",\n );\n\n try {\n const amount = BigInt(value);\n assertInRange(amount);\n return amount;\n } catch (error) {\n if (error instanceof EconomyError) {\n throw error;\n }\n throw new EconomyError(\"INVALID_AMOUNT\", \"TokenSubunit amount is invalid\");\n }\n}\n\n/** Serializes a signed 64-bit TokenSubunit amount to canonical base-10. */\nexport function serializeTokenSubunits(amount: bigint): TokenSubunitString {\n assertInRange(amount);\n return amount.toString(10) as TokenSubunitString;\n}\n\n/** Converts an exact whole-Token integer into TokenSubunits. */\nexport function wholeTokensToSubunits(tokens: bigint): bigint {\n const amount = tokens * TOKEN_SUBUNITS_PER_TOKEN;\n assertInRange(amount);\n return amount;\n}\n\n/** Returns true when a subunit amount represents an exact whole Token. */\nexport function isWholeTokenAmount(amount: bigint): boolean {\n return amount % TOKEN_SUBUNITS_PER_TOKEN === 0n;\n}\n\n/** Converts TokenSubunits to whole Tokens, rejecting fractional progress. */\nexport function subunitsToWholeTokens(amount: bigint): bigint {\n economyAssert(\n isWholeTokenAmount(amount),\n \"AMOUNT_NOT_WHOLE_TOKEN\",\n \"Amount must contain whole Tokens\",\n );\n return amount / TOKEN_SUBUNITS_PER_TOKEN;\n}\n\n/** Sums amount strings with signed 64-bit overflow protection. */\nexport function sumTokenSubunits(values: readonly string[]): bigint {\n let total = 0n;\n for (const value of values) {\n total += parseTokenSubunits(value);\n assertInRange(total);\n }\n return total;\n}\n","/**\n * Compares strings using locale-independent ECMAScript UTF-16 code-unit order.\n *\n * Canonical transaction identifiers and metadata keys use a validated ASCII\n * alphabet, so this ordering is byte-for-byte equivalent to PostgreSQL\n * `COLLATE \"C\"` for those fields.\n */\nexport function compareUnicodeCodeUnits(left: string, right: string): number {\n if (left === right) {\n return 0;\n }\n return left < right ? -1 : 1;\n}\n","import { compareUnicodeCodeUnits } from \"./canonical-order.js\";\nimport { economyAssert } from \"./errors.js\";\n\nexport const ECONOMY_CONTRACT_VERSION = \"1\" as const;\nexport type EconomyContractVersion = typeof ECONOMY_CONTRACT_VERSION;\n\nexport type AccountId = string;\nexport type AllocationId = string;\nexport type HouseholdId = string;\nexport type LotId = string;\nexport type PostingId = string;\nexport type ProviderEventId = string;\nexport type TransactionId = string;\nexport type WalletId = string;\nexport type IsoTimestamp = string;\n\nconst IDENTIFIER = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/u;\n\n/** Validates opaque pseudonymous domain identifiers. */\nexport function assertEconomyIdentifier(\n value: string,\n label = \"identifier\",\n): void {\n economyAssert(\n typeof value === \"string\" && IDENTIFIER.test(value),\n \"INVALID_CONTRACT\",\n `${label} must be a non-empty opaque identifier`,\n );\n}\n\n/** Parses a bounded ISO timestamp and returns milliseconds since epoch. */\nexport function parseIsoTimestamp(value: IsoTimestamp): number {\n economyAssert(\n typeof value === \"string\",\n \"INVALID_CONTRACT\",\n \"Timestamp must be an ISO-8601 UTC value\",\n );\n const match = /^(\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2})(?:\\.(\\d{3}))?Z$/u.exec(\n value,\n );\n economyAssert(\n match !== null,\n \"INVALID_CONTRACT\",\n \"Timestamp must be an ISO-8601 UTC value\",\n );\n const milliseconds = Date.parse(value);\n const base = match[1];\n const fraction = match[2] ?? \"000\";\n economyAssert(\n Number.isFinite(milliseconds) &&\n base !== undefined &&\n new Date(milliseconds).toISOString() === `${base}.${fraction}Z`,\n \"INVALID_CONTRACT\",\n \"Timestamp must be valid\",\n );\n return milliseconds;\n}\n\n/** Returns a new record with keys sorted by locale-independent code units. */\nexport function sortStringRecord(\n value: Readonly<Record<string, string>>,\n): Readonly<Record<string, string>> {\n return Object.fromEntries(\n Object.entries(value).sort(([left], [right]) =>\n compareUnicodeCodeUnits(left, right),\n ),\n );\n}\n","import {\n TOKEN_SUBUNITS_PER_TOKEN,\n isWholeTokenAmount,\n parseTokenSubunits,\n serializeTokenSubunits,\n type TokenSubunitString,\n} from \"./amount.js\";\nimport {\n ECONOMY_CONTRACT_VERSION,\n assertEconomyIdentifier,\n parseIsoTimestamp,\n type AccountId,\n type EconomyContractVersion,\n type HouseholdId,\n type IsoTimestamp,\n type ProviderEventId,\n type WalletId,\n} from \"./contracts.js\";\nimport { economyAssert } from \"./errors.js\";\nimport type { ActivityStatus, ActivityType } from \"./ledger.js\";\n\nexport interface TokenPackV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly packId: string;\n readonly catalogVersion: string;\n readonly currency: \"GBP\";\n readonly priceMinorUnits: string;\n readonly grantAmount: TokenSubunitString;\n readonly active: boolean;\n}\n\n/** Product-copy reference only; it is not a redemption or exchange promise. */\nexport interface TokenReferenceRateV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly rateVersion: string;\n readonly currency: \"GBP\";\n readonly referenceMinorUnitsPerToken: string;\n readonly tokenSubunitsPerToken: string;\n readonly cashRedemptionAllowed: false;\n}\n\nexport const BASELINE_GBP_REFERENCE_RATE: TokenReferenceRateV1 = Object.freeze({\n schemaVersion: ECONOMY_CONTRACT_VERSION,\n rateVersion: \"gbp-reference-v1\",\n currency: \"GBP\",\n referenceMinorUnitsPerToken: \"10\",\n tokenSubunitsPerToken: TOKEN_SUBUNITS_PER_TOKEN.toString(10),\n cashRedemptionAllowed: false,\n});\n\nexport const BASELINE_GBP_CATALOG_VERSION = \"gbp-v1\" as const;\n\n/** Initial flat-price public catalog. Changes require a new catalog version. */\nexport const BASELINE_GBP_TOKEN_PACKS: readonly TokenPackV1[] = Object.freeze([\n Object.freeze({\n schemaVersion: ECONOMY_CONTRACT_VERSION,\n packId: \"gbp_5_50_v1\",\n catalogVersion: BASELINE_GBP_CATALOG_VERSION,\n currency: \"GBP\",\n priceMinorUnits: \"500\",\n grantAmount: serializeTokenSubunits(50_000n),\n active: true,\n }),\n Object.freeze({\n schemaVersion: ECONOMY_CONTRACT_VERSION,\n packId: \"gbp_10_100_v1\",\n catalogVersion: BASELINE_GBP_CATALOG_VERSION,\n currency: \"GBP\",\n priceMinorUnits: \"1000\",\n grantAmount: serializeTokenSubunits(100_000n),\n active: true,\n }),\n Object.freeze({\n schemaVersion: ECONOMY_CONTRACT_VERSION,\n packId: \"gbp_25_250_v1\",\n catalogVersion: BASELINE_GBP_CATALOG_VERSION,\n currency: \"GBP\",\n priceMinorUnits: \"2500\",\n grantAmount: serializeTokenSubunits(250_000n),\n active: true,\n }),\n Object.freeze({\n schemaVersion: ECONOMY_CONTRACT_VERSION,\n packId: \"gbp_50_500_v1\",\n catalogVersion: BASELINE_GBP_CATALOG_VERSION,\n currency: \"GBP\",\n priceMinorUnits: \"5000\",\n grantAmount: serializeTokenSubunits(500_000n),\n active: true,\n }),\n]);\n\nexport interface PurchaseLimitPolicyV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly maxOrderPriceMinorUnits: string;\n readonly rollingPayerPriceMinorUnits: string;\n readonly rollingHouseholdPriceMinorUnits: string;\n readonly rollingDays: number;\n}\n\n/** Default server limits; household controls may only lower these values. */\nexport const BASELINE_PURCHASE_LIMIT_POLICY: PurchaseLimitPolicyV1 =\n Object.freeze({\n schemaVersion: ECONOMY_CONTRACT_VERSION,\n maxOrderPriceMinorUnits: \"5000\",\n rollingPayerPriceMinorUnits: \"10000\",\n rollingHouseholdPriceMinorUnits: \"10000\",\n rollingDays: 30,\n });\n\nexport type PurchaseIntentStatus =\n | \"created\"\n | \"checkout-created\"\n | \"paid-unreconciled\"\n | \"credited\"\n | \"expired\"\n | \"cancelled\"\n | \"disputed\";\n\n/** Short-lived server authority binding checkout facts to a payer/household. */\nexport interface PurchaseIntentV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly intentId: string;\n readonly payerAccountId: AccountId;\n readonly receivingHouseholdId: HouseholdId;\n readonly receivingWalletId: WalletId;\n readonly packId: string;\n readonly catalogVersion: string;\n readonly expectedCurrency: \"GBP\";\n readonly expectedPriceMinorUnits: string;\n readonly grantAmount: TokenSubunitString;\n readonly status: PurchaseIntentStatus;\n readonly createdAt: IsoTimestamp;\n readonly expiresAt: IsoTimestamp;\n readonly providerCheckoutReferenceHash?: string;\n}\n\nexport interface RewardRateV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly rateVersion: string;\n readonly provider: \"ayet\" | \"bitlabs\";\n /** TokenSubunits granted per denominator of authoritative GBP minor units. */\n readonly tokenSubunitsNumerator: string;\n readonly gbpMinorUnitsDenominator: string;\n readonly effectiveFrom: IsoTimestamp;\n readonly effectiveUntil?: IsoTimestamp;\n}\n\nexport interface FxSnapshotV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly snapshotId: string;\n readonly sourceCurrency: string;\n readonly quoteCurrency: \"GBP\";\n /** Exact rational conversion to GBP minor units. */\n readonly gbpMinorUnitsNumerator: string;\n readonly sourceMinorUnitsDenominator: string;\n readonly capturedAt: IsoTimestamp;\n}\n\nexport type RewardConversionStatus =\n | \"pending\"\n | \"completed\"\n | \"reconciled\";\n\nexport type BitLabsConversionState =\n | \"PENDING\"\n | \"COMPLETED\"\n | \"RECONCILED\";\n\nexport interface RewardActivityTransitionV1 {\n readonly conversionStatus: RewardConversionStatus;\n readonly activityType: ActivityType;\n readonly activityStatus: ActivityStatus;\n}\n\nexport interface RewardConversionV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly provider: \"ayet\" | \"bitlabs\";\n readonly providerEventId: ProviderEventId;\n readonly beneficiaryAccountId: AccountId;\n readonly walletId: WalletId;\n readonly status: RewardConversionStatus;\n readonly providerPayoutMinorUnits: string;\n readonly providerCurrency: string;\n readonly gbpMinorUnits: string;\n readonly tokenSubunits: TokenSubunitString;\n readonly rateVersion: string;\n readonly fxSnapshotId: string;\n readonly occurredAt: IsoTimestamp;\n}\n\n/** Validates a minimized, signed-provider conversion record before journaling. */\nexport function assertRewardConversion(\n conversion: RewardConversionV1,\n): void {\n economyAssert(\n conversion.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported reward-conversion contract version\",\n );\n economyAssert(\n conversion.provider === \"ayet\" || conversion.provider === \"bitlabs\",\n \"INVALID_CONTRACT\",\n \"Unsupported reward-conversion provider\",\n );\n assertEconomyIdentifier(conversion.providerEventId, \"providerEventId\");\n assertEconomyIdentifier(\n conversion.beneficiaryAccountId,\n \"beneficiaryAccountId\",\n );\n assertEconomyIdentifier(conversion.walletId, \"walletId\");\n economyAssert(\n [\"pending\", \"completed\", \"reconciled\"].includes(conversion.status),\n \"INVALID_CONTRACT\",\n \"Unsupported reward-conversion status\",\n );\n economyAssert(\n /^[A-Z]{3}$/u.test(conversion.providerCurrency),\n \"INVALID_CONTRACT\",\n \"Reward payout currency must use an uppercase ISO code\",\n );\n economyAssert(\n parseNonNegativeInteger(\n conversion.providerPayoutMinorUnits,\n \"Provider payout\",\n ) > 0n &&\n parseNonNegativeInteger(conversion.gbpMinorUnits, \"GBP payout\") >= 0n &&\n parseTokenSubunits(conversion.tokenSubunits) > 0n,\n \"INVALID_AMOUNT\",\n \"Reward conversion must carry positive payout and Token values\",\n );\n assertEconomyIdentifier(conversion.rateVersion, \"rateVersion\");\n assertEconomyIdentifier(conversion.fxSnapshotId, \"fxSnapshotId\");\n parseIsoTimestamp(conversion.occurredAt);\n}\n\nfunction parseNonNegativeInteger(value: string, label: string): bigint {\n economyAssert(\n /^(?:0|[1-9][0-9]*)$/u.test(value),\n \"INVALID_AMOUNT\",\n `${label} must be a non-negative integer string`,\n );\n return BigInt(value);\n}\n\n/** Validates a paid pack; pack grants are whole Tokens in the baseline. */\nexport function assertTokenPack(pack: TokenPackV1): void {\n economyAssert(\n pack.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported Token pack contract version\",\n );\n assertEconomyIdentifier(pack.packId, \"packId\");\n assertEconomyIdentifier(pack.catalogVersion, \"catalogVersion\");\n economyAssert(\n pack.currency === \"GBP\" && typeof pack.active === \"boolean\",\n \"INVALID_CONTRACT\",\n \"Token packs must use GBP and declare whether they are active\",\n );\n economyAssert(\n parseNonNegativeInteger(pack.priceMinorUnits, \"Pack price\") > 0n,\n \"INVALID_AMOUNT\",\n \"Pack price must be positive\",\n );\n const grant = parseTokenSubunits(pack.grantAmount);\n economyAssert(\n grant > 0n && isWholeTokenAmount(grant),\n \"AMOUNT_NOT_WHOLE_TOKEN\",\n \"Paid pack grants must contain whole Tokens\",\n );\n}\n\n/** Validates nominal reference metadata without creating redemption rights. */\nexport function assertTokenReferenceRate(\n rate: TokenReferenceRateV1,\n): void {\n economyAssert(\n rate.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported Token reference-rate contract version\",\n );\n assertEconomyIdentifier(rate.rateVersion, \"rateVersion\");\n const referenceMinorUnits = parseNonNegativeInteger(\n rate.referenceMinorUnitsPerToken,\n \"Reference minor units per Token\",\n );\n const subunitsPerToken = parseNonNegativeInteger(\n rate.tokenSubunitsPerToken,\n \"TokenSubunits per Token\",\n );\n economyAssert(\n rate.currency === \"GBP\" &&\n referenceMinorUnits > 0n &&\n subunitsPerToken === TOKEN_SUBUNITS_PER_TOKEN &&\n rate.cashRedemptionAllowed === false,\n \"INVALID_CONTRACT\",\n \"Token reference rate must preserve the GBP nominal, subunit, and no-redemption boundary\",\n );\n}\n\n/** Proves that every pack in one catalog uses the same flat nominal ratio. */\nexport function assertFlatTokenCatalog(\n packs: readonly TokenPackV1[],\n referenceRate: TokenReferenceRateV1,\n): void {\n assertTokenReferenceRate(referenceRate);\n economyAssert(\n packs.length > 0,\n \"INVALID_CONTRACT\",\n \"Token catalog must contain at least one pack\",\n );\n const packIds = new Set<string>();\n const catalogVersion = packs[0]?.catalogVersion;\n const referenceMinorUnits = BigInt(\n referenceRate.referenceMinorUnitsPerToken,\n );\n const subunitsPerToken = BigInt(referenceRate.tokenSubunitsPerToken);\n for (const pack of packs) {\n assertTokenPack(pack);\n economyAssert(\n !packIds.has(pack.packId),\n \"DUPLICATE_IDENTIFIER\",\n \"Token catalog pack IDs must be unique\",\n );\n economyAssert(\n pack.catalogVersion === catalogVersion,\n \"INVALID_CONTRACT\",\n \"Token catalog packs must share one catalog version\",\n );\n packIds.add(pack.packId);\n const scaledReference =\n parseTokenSubunits(pack.grantAmount) * referenceMinorUnits;\n economyAssert(\n scaledReference % subunitsPerToken === 0n &&\n scaledReference / subunitsPerToken === BigInt(pack.priceMinorUnits),\n \"INVALID_CONTRACT\",\n \"Token catalog must use the declared flat nominal reference ratio\",\n );\n }\n}\n\n/** Validates server-side order and rolling acquisition ceilings. */\nexport function assertPurchaseLimitPolicy(\n policy: PurchaseLimitPolicyV1,\n): void {\n economyAssert(\n policy.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported purchase-limit contract version\",\n );\n const maxOrder = parseNonNegativeInteger(\n policy.maxOrderPriceMinorUnits,\n \"Maximum order\",\n );\n const payer = parseNonNegativeInteger(\n policy.rollingPayerPriceMinorUnits,\n \"Rolling payer limit\",\n );\n const household = parseNonNegativeInteger(\n policy.rollingHouseholdPriceMinorUnits,\n \"Rolling household limit\",\n );\n economyAssert(\n maxOrder > 0n && payer >= maxOrder && household >= maxOrder,\n \"INVALID_AMOUNT\",\n \"Rolling purchase limits must cover at least one maximum order\",\n );\n economyAssert(\n Number.isSafeInteger(policy.rollingDays) &&\n policy.rollingDays >= 1 &&\n policy.rollingDays <= 365,\n \"INVALID_CONTRACT\",\n \"Purchase-limit rolling window must be a bounded whole-day count\",\n );\n}\n\n/** Validates the immutable server-side facts bound into a purchase intent. */\nexport function assertPurchaseIntentBinding(\n intent: PurchaseIntentV1,\n pack: TokenPackV1,\n): void {\n assertTokenPack(pack);\n economyAssert(\n intent.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported purchase-intent contract version\",\n );\n assertEconomyIdentifier(intent.intentId, \"intentId\");\n assertEconomyIdentifier(intent.payerAccountId, \"payerAccountId\");\n assertEconomyIdentifier(intent.receivingHouseholdId, \"receivingHouseholdId\");\n assertEconomyIdentifier(intent.receivingWalletId, \"receivingWalletId\");\n assertEconomyIdentifier(intent.packId, \"packId\");\n assertEconomyIdentifier(intent.catalogVersion, \"catalogVersion\");\n\n const createdAt = parseIsoTimestamp(intent.createdAt);\n const expiresAt = parseIsoTimestamp(intent.expiresAt);\n economyAssert(\n expiresAt > createdAt,\n \"INVALID_TIME_WINDOW\",\n \"Purchase intent expiry must follow its creation time\",\n );\n economyAssert(\n intent.expectedCurrency === \"GBP\" &&\n intent.packId === pack.packId &&\n intent.catalogVersion === pack.catalogVersion &&\n intent.expectedCurrency === pack.currency &&\n intent.expectedPriceMinorUnits === pack.priceMinorUnits &&\n intent.grantAmount === pack.grantAmount,\n \"INVALID_CONTRACT\",\n \"Purchase intent does not match its authoritative catalog pack\",\n );\n parseNonNegativeInteger(intent.expectedPriceMinorUnits, \"Expected price\");\n parseTokenSubunits(intent.grantAmount);\n economyAssert(\n [\n \"created\",\n \"checkout-created\",\n \"paid-unreconciled\",\n \"credited\",\n \"expired\",\n \"cancelled\",\n \"disputed\",\n ].includes(intent.status),\n \"INVALID_CONTRACT\",\n \"Purchase intent has an unsupported status\",\n );\n if (intent.providerCheckoutReferenceHash !== undefined) {\n economyAssert(\n /^sha256:[a-f0-9]{64}$/u.test(intent.providerCheckoutReferenceHash),\n \"INVALID_CONTRACT\",\n \"Checkout references must be stored as sanitized SHA-256 hashes\",\n );\n }\n}\n\n/** Rejects stale, inactive, or already-consumed intents before checkout creation. */\nexport function assertOpenPurchaseIntent(\n intent: PurchaseIntentV1,\n pack: TokenPackV1,\n checkedAt: IsoTimestamp,\n): void {\n assertPurchaseIntentBinding(intent, pack);\n const checkedAtValue = parseIsoTimestamp(checkedAt);\n economyAssert(\n pack.active &&\n (intent.status === \"created\" || intent.status === \"checkout-created\") &&\n checkedAtValue >= parseIsoTimestamp(intent.createdAt) &&\n checkedAtValue < parseIsoTimestamp(intent.expiresAt),\n \"INVALID_TIME_WINDOW\",\n \"Purchase intent is inactive, expired, or not open for checkout\",\n );\n}\n\nexport function assertRewardRate(rate: RewardRateV1): void {\n economyAssert(\n rate.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported reward-rate contract version\",\n );\n assertEconomyIdentifier(rate.rateVersion, \"rateVersion\");\n economyAssert(\n rate.provider === \"ayet\" || rate.provider === \"bitlabs\",\n \"INVALID_CONTRACT\",\n \"Unsupported reward provider\",\n );\n const effectiveFrom = parseIsoTimestamp(rate.effectiveFrom);\n if (rate.effectiveUntil !== undefined) {\n economyAssert(\n parseIsoTimestamp(rate.effectiveUntil) > effectiveFrom,\n \"INVALID_TIME_WINDOW\",\n \"Reward-rate expiry must follow its effective time\",\n );\n }\n}\n\nexport function assertFxSnapshot(fx: FxSnapshotV1): void {\n economyAssert(\n fx.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported FX snapshot contract version\",\n );\n assertEconomyIdentifier(fx.snapshotId, \"snapshotId\");\n economyAssert(\n /^[A-Z]{3}$/u.test(fx.sourceCurrency) && fx.quoteCurrency === \"GBP\",\n \"INVALID_CONTRACT\",\n \"FX snapshots must convert an ISO currency into GBP\",\n );\n parseIsoTimestamp(fx.capturedAt);\n}\n\n/** Converts provider payout using exact rational FX and rate snapshots. */\nexport function convertRewardPayout(\n providerPayoutMinorUnits: string,\n rate: RewardRateV1,\n fx: FxSnapshotV1,\n): { readonly gbpMinorUnits: string; readonly tokenSubunits: TokenSubunitString } {\n assertRewardRate(rate);\n assertFxSnapshot(fx);\n const payout = parseNonNegativeInteger(\n providerPayoutMinorUnits,\n \"Provider payout\",\n );\n const fxNumerator = parseNonNegativeInteger(\n fx.gbpMinorUnitsNumerator,\n \"FX numerator\",\n );\n const fxDenominator = parseNonNegativeInteger(\n fx.sourceMinorUnitsDenominator,\n \"FX denominator\",\n );\n const tokenNumerator = parseNonNegativeInteger(\n rate.tokenSubunitsNumerator,\n \"Rate numerator\",\n );\n const tokenDenominator = parseNonNegativeInteger(\n rate.gbpMinorUnitsDenominator,\n \"Rate denominator\",\n );\n economyAssert(\n fxDenominator > 0n && tokenDenominator > 0n,\n \"INVALID_AMOUNT\",\n \"FX and reward-rate denominators must be positive\",\n );\n economyAssert(\n fxNumerator > 0n && tokenNumerator > 0n,\n \"INVALID_AMOUNT\",\n \"FX and reward-rate numerators must be positive\",\n );\n\n const gbpMinorUnits = (payout * fxNumerator) / fxDenominator;\n const tokenSubunits = (gbpMinorUnits * tokenNumerator) / tokenDenominator;\n return {\n gbpMinorUnits: gbpMinorUnits.toString(10),\n tokenSubunits: serializeTokenSubunits(tokenSubunits),\n };\n}\n\n/** Maps BitLabs' signed callback state into an immutable journal transition. */\nexport function mapBitLabsConversionState(\n state: string,\n): RewardActivityTransitionV1 {\n const transitions: Readonly<\n Record<BitLabsConversionState, RewardActivityTransitionV1>\n > = {\n PENDING: {\n conversionStatus: \"pending\",\n activityType: \"hold\",\n activityStatus: \"held\",\n },\n COMPLETED: {\n conversionStatus: \"completed\",\n activityType: \"offerwall\",\n activityStatus: \"settled\",\n },\n RECONCILED: {\n conversionStatus: \"reconciled\",\n activityType: \"reversal\",\n activityStatus: \"reversed\",\n },\n };\n const transition = transitions[state as BitLabsConversionState];\n economyAssert(\n transition !== undefined,\n \"INVALID_CONTRACT\",\n \"Unsupported BitLabs conversion state\",\n );\n return transition;\n}\n","import {\n isWholeTokenAmount,\n parseTokenSubunits,\n serializeTokenSubunits,\n sumTokenSubunits,\n type TokenSubunitString,\n} from \"./amount.js\";\nimport {\n ECONOMY_CONTRACT_VERSION,\n assertEconomyIdentifier,\n parseIsoTimestamp,\n type AccountId,\n type AllocationId,\n type EconomyContractVersion,\n type HouseholdId,\n type IsoTimestamp,\n type WalletId,\n} from \"./contracts.js\";\nimport { economyAssert } from \"./errors.js\";\nimport type { SourceLotSliceV1 } from \"./lots.js\";\n\nexport type AllocationStatus = \"active\" | \"closed\";\nexport type PeriodicLimitWindow = \"daily\" | \"weekly\" | \"monthly\";\n\nexport interface GameplayLimitsV1 {\n readonly perTransaction: TokenSubunitString;\n readonly periodic: TokenSubunitString;\n readonly periodicWindow: PeriodicLimitWindow;\n}\n\n/** Guardian-funded, child-visible reservation. This is not a gameplay ledger. */\nexport interface GameplayAllocationV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly allocationId: AllocationId;\n readonly householdId: HouseholdId;\n readonly hostWalletId: WalletId;\n readonly childWalletId: WalletId;\n readonly childAccountId: AccountId;\n readonly status: AllocationStatus;\n readonly reservedAmount: TokenSubunitString;\n readonly remainingAmount: TokenSubunitString;\n readonly reclaimedAmount: TokenSubunitString;\n readonly fundingSlices: readonly SourceLotSliceV1[];\n readonly reclaimedSlices: readonly SourceLotSliceV1[];\n readonly limits: GameplayLimitsV1;\n readonly version: number;\n readonly createdAt: IsoTimestamp;\n readonly updatedAt: IsoTimestamp;\n}\n\nfunction assertWholePositive(amount: TokenSubunitString, label: string): bigint {\n const parsed = parseTokenSubunits(amount);\n economyAssert(parsed > 0n, \"INVALID_AMOUNT\", `${label} must be positive`);\n economyAssert(\n isWholeTokenAmount(parsed),\n \"AMOUNT_NOT_WHOLE_TOKEN\",\n `${label} must contain whole Tokens`,\n );\n return parsed;\n}\n\nfunction assertSlices(\n slices: readonly SourceLotSliceV1[],\n expectedAmount: bigint,\n label: string,\n): void {\n economyAssert(slices.length > 0, \"INVALID_CONTRACT\", `${label} are required`);\n const lotIds = new Set<string>();\n for (const slice of slices) {\n assertEconomyIdentifier(slice.lotId, \"lotId\");\n economyAssert(\n !lotIds.has(slice.lotId),\n \"DUPLICATE_IDENTIFIER\",\n `${label} must not repeat a lot`,\n );\n lotIds.add(slice.lotId);\n economyAssert(\n parseTokenSubunits(slice.amount) > 0n,\n \"INVALID_AMOUNT\",\n `${label} amounts must be positive`,\n );\n }\n economyAssert(\n sumTokenSubunits(slices.map((slice) => slice.amount)) === expectedAmount,\n \"INVALID_CONTRACT\",\n `${label} must sum to the command amount`,\n );\n}\n\n/** Validates allocation arithmetic and whole-Token reservation policy. */\nexport function assertGameplayAllocation(\n allocation: GameplayAllocationV1,\n): void {\n economyAssert(\n allocation.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported allocation contract version\",\n );\n assertEconomyIdentifier(allocation.allocationId, \"allocationId\");\n assertEconomyIdentifier(allocation.householdId, \"householdId\");\n assertEconomyIdentifier(allocation.hostWalletId, \"hostWalletId\");\n assertEconomyIdentifier(allocation.childWalletId, \"childWalletId\");\n assertEconomyIdentifier(allocation.childAccountId, \"childAccountId\");\n const createdAt = parseIsoTimestamp(allocation.createdAt);\n const updatedAt = parseIsoTimestamp(allocation.updatedAt);\n economyAssert(\n updatedAt >= createdAt,\n \"INVALID_TIME_WINDOW\",\n \"Allocation update time cannot precede its creation time\",\n );\n economyAssert(\n allocation.status === \"active\" || allocation.status === \"closed\",\n \"INVALID_CONTRACT\",\n \"Allocation has an unsupported status\",\n );\n\n const reserved = parseTokenSubunits(allocation.reservedAmount);\n const remaining = parseTokenSubunits(allocation.remainingAmount);\n const reclaimed = parseTokenSubunits(allocation.reclaimedAmount);\n economyAssert(\n reserved > 0n &&\n remaining >= 0n &&\n reclaimed >= 0n &&\n isWholeTokenAmount(reserved) &&\n isWholeTokenAmount(remaining) &&\n isWholeTokenAmount(reclaimed),\n \"AMOUNT_NOT_WHOLE_TOKEN\",\n \"Allocation reservations and reclaims must contain whole Tokens\",\n );\n economyAssert(\n remaining + reclaimed <= reserved,\n \"INVALID_CONTRACT\",\n \"Allocation remaining and reclaimed amounts exceed its reservation\",\n );\n\n const fundingByLot = new Map<string, bigint>();\n let funded = 0n;\n for (const slice of allocation.fundingSlices) {\n assertEconomyIdentifier(slice.lotId, \"lotId\");\n const amount = parseTokenSubunits(slice.amount);\n economyAssert(\n amount > 0n,\n \"INVALID_AMOUNT\",\n \"Allocation funding slices must be positive\",\n );\n funded += amount;\n fundingByLot.set(\n slice.lotId,\n (fundingByLot.get(slice.lotId) ?? 0n) + amount,\n );\n }\n economyAssert(\n funded === reserved,\n \"INVALID_CONTRACT\",\n \"Allocation funding provenance must equal its total reservation\",\n );\n\n const reclaimedByLot = new Map<string, bigint>();\n let reclaimedFromSlices = 0n;\n for (const slice of allocation.reclaimedSlices) {\n assertEconomyIdentifier(slice.lotId, \"lotId\");\n const amount = parseTokenSubunits(slice.amount);\n economyAssert(\n amount > 0n,\n \"INVALID_AMOUNT\",\n \"Allocation reclaim slices must be positive\",\n );\n reclaimedFromSlices += amount;\n reclaimedByLot.set(\n slice.lotId,\n (reclaimedByLot.get(slice.lotId) ?? 0n) + amount,\n );\n }\n economyAssert(\n reclaimedFromSlices === reclaimed,\n \"INVALID_CONTRACT\",\n \"Allocation reclaim provenance must equal its reclaimed amount\",\n );\n for (const [lotId, amount] of reclaimedByLot) {\n economyAssert(\n amount <= (fundingByLot.get(lotId) ?? 0n),\n \"SOURCE_LOT_RESTRICTED\",\n \"Reclaimed provenance cannot exceed allocation funding\",\n );\n }\n economyAssert(\n allocation.version >= 1 && Number.isSafeInteger(allocation.version),\n \"INVALID_CONTRACT\",\n \"Allocation version must be a positive safe integer\",\n );\n\n const perTransaction = parseTokenSubunits(allocation.limits.perTransaction);\n const periodic = parseTokenSubunits(allocation.limits.periodic);\n economyAssert(\n [\"daily\", \"weekly\", \"monthly\"].includes(allocation.limits.periodicWindow),\n \"INVALID_CONTRACT\",\n \"Gameplay limit has an unsupported period\",\n );\n economyAssert(\n perTransaction >= 0n &&\n periodic >= 0n &&\n isWholeTokenAmount(perTransaction) &&\n isWholeTokenAmount(periodic),\n \"AMOUNT_NOT_WHOLE_TOKEN\",\n \"Gameplay limits must contain whole Tokens\",\n );\n economyAssert(\n perTransaction <= periodic || periodic === 0n,\n \"INVALID_CONTRACT\",\n \"Per-transaction limit cannot exceed an enabled periodic limit\",\n );\n}\n\nexport interface CreateGameplayAllocationInputV1 {\n readonly allocationId: AllocationId;\n readonly householdId: HouseholdId;\n readonly hostWalletId: WalletId;\n readonly childWalletId: WalletId;\n readonly childAccountId: AccountId;\n readonly amount: TokenSubunitString;\n readonly fundingSlices: readonly SourceLotSliceV1[];\n readonly limits: GameplayLimitsV1;\n readonly occurredAt: IsoTimestamp;\n}\n\n/** Creates a new whole-Token reservation from already-selected source lots. */\nexport function createGameplayAllocation(\n input: CreateGameplayAllocationInputV1,\n): GameplayAllocationV1 {\n const amount = assertWholePositive(input.amount, \"Allocation amount\");\n assertSlices(input.fundingSlices, amount, \"Allocation funding slices\");\n const allocation: GameplayAllocationV1 = {\n schemaVersion: ECONOMY_CONTRACT_VERSION,\n allocationId: input.allocationId,\n householdId: input.householdId,\n hostWalletId: input.hostWalletId,\n childWalletId: input.childWalletId,\n childAccountId: input.childAccountId,\n status: \"active\",\n reservedAmount: input.amount,\n remainingAmount: input.amount,\n reclaimedAmount: serializeTokenSubunits(0n),\n fundingSlices: input.fundingSlices,\n reclaimedSlices: [],\n limits: input.limits,\n version: 1,\n createdAt: input.occurredAt,\n updatedAt: input.occurredAt,\n };\n assertGameplayAllocation(allocation);\n return allocation;\n}\n\nexport interface BoostGameplayAllocationInputV1 {\n readonly amount: TokenSubunitString;\n readonly fundingSlices: readonly SourceLotSliceV1[];\n readonly expectedVersion: number;\n readonly occurredAt: IsoTimestamp;\n}\n\n/** Returns the next immutable allocation state after a whole-Token boost. */\nexport function boostGameplayAllocation(\n allocation: GameplayAllocationV1,\n input: BoostGameplayAllocationInputV1,\n): GameplayAllocationV1 {\n assertGameplayAllocation(allocation);\n economyAssert(\n allocation.status === \"active\" && allocation.version === input.expectedVersion,\n \"INVALID_CONTRACT\",\n \"Allocation is closed or its optimistic version is stale\",\n );\n const amount = assertWholePositive(input.amount, \"Boost amount\");\n assertSlices(input.fundingSlices, amount, \"Boost funding slices\");\n\n const next: GameplayAllocationV1 = {\n ...allocation,\n reservedAmount: serializeTokenSubunits(\n parseTokenSubunits(allocation.reservedAmount) + amount,\n ),\n remainingAmount: serializeTokenSubunits(\n parseTokenSubunits(allocation.remainingAmount) + amount,\n ),\n fundingSlices: [...allocation.fundingSlices, ...input.fundingSlices],\n version: allocation.version + 1,\n updatedAt: input.occurredAt,\n };\n assertGameplayAllocation(next);\n return next;\n}\n\nexport interface ReclaimGameplayAllocationInputV1 {\n readonly amount: TokenSubunitString;\n readonly sourceSlices: readonly SourceLotSliceV1[];\n readonly expectedVersion: number;\n readonly occurredAt: IsoTimestamp;\n}\n\n/** Reclaims unused whole Tokens without changing spent history. */\nexport function reclaimGameplayAllocation(\n allocation: GameplayAllocationV1,\n input: ReclaimGameplayAllocationInputV1,\n): GameplayAllocationV1 {\n assertGameplayAllocation(allocation);\n economyAssert(\n allocation.status === \"active\" && allocation.version === input.expectedVersion,\n \"INVALID_CONTRACT\",\n \"Allocation is closed or its optimistic version is stale\",\n );\n const amount = assertWholePositive(input.amount, \"Reclaim amount\");\n economyAssert(\n amount <= parseTokenSubunits(allocation.remainingAmount),\n \"INSUFFICIENT_BALANCE\",\n \"Cannot reclaim more than the unused allocation\",\n );\n assertSlices(input.sourceSlices, amount, \"Reclaim source slices\");\n const fundedLotIds = new Set(\n allocation.fundingSlices.map((slice) => slice.lotId),\n );\n economyAssert(\n input.sourceSlices.every((slice) => fundedLotIds.has(slice.lotId)),\n \"SOURCE_LOT_RESTRICTED\",\n \"Reclaim slices must originate from the allocation\",\n );\n\n const remaining = parseTokenSubunits(allocation.remainingAmount) - amount;\n const next: GameplayAllocationV1 = {\n ...allocation,\n remainingAmount: serializeTokenSubunits(remaining),\n reclaimedAmount: serializeTokenSubunits(\n parseTokenSubunits(allocation.reclaimedAmount) + amount,\n ),\n reclaimedSlices: [...allocation.reclaimedSlices, ...input.sourceSlices],\n status: remaining === 0n ? \"closed\" : allocation.status,\n version: allocation.version + 1,\n updatedAt: input.occurredAt,\n };\n assertGameplayAllocation(next);\n return next;\n}\n","import {\n parseTokenSubunits,\n serializeTokenSubunits,\n type TokenSubunitString,\n} from \"./amount.js\";\nimport {\n ECONOMY_CONTRACT_VERSION,\n assertEconomyIdentifier,\n parseIsoTimestamp,\n type AccountId,\n type EconomyContractVersion,\n type HouseholdId,\n type IsoTimestamp,\n type LotId,\n} from \"./contracts.js\";\nimport { economyAssert } from \"./errors.js\";\n\nexport const PRE_UTILITY_BACKER_COHORT = \"pre_utility_backer_v1\" as const;\n\nexport interface EarlyBackerWindowV1 {\n readonly publicTokensLaunchAt: IsoTimestamp;\n readonly firstPublicSpendLiveAt?: IsoTimestamp;\n}\n\n/** Paid-lot facts required to recalculate retained early-backer basis. */\nexport interface PaidLotRetentionV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly lotId: LotId;\n readonly payerAccountId: AccountId;\n readonly receivingHouseholdId: HouseholdId;\n readonly purchaseId: string;\n readonly catalogVersion: string;\n readonly purchasedAt: IsoTimestamp;\n readonly settledAt: IsoTimestamp;\n readonly creditedAt: IsoTimestamp;\n readonly retainedAmount: TokenSubunitString;\n}\n\nexport interface EarlyBackerEvaluationV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly cohortKey: typeof PRE_UTILITY_BACKER_COHORT;\n readonly status: \"not-qualified\" | \"provisional\";\n readonly payerAccountId: AccountId;\n readonly receivingHouseholdId: HouseholdId;\n readonly netRetainedAmount: TokenSubunitString;\n readonly contributingLotIds: readonly LotId[];\n readonly evaluatedAt: IsoTimestamp;\n}\n\nexport const EARLY_BACKER_SETTLEMENT_POLICY_V2 =\n \"settlement-window-v2\" as const;\n\n/**\n * Additive evaluation result using settlement as the sole qualification event.\n * Purchase and credit times remain provenance/order facts.\n */\nexport interface EarlyBackerEvaluationV2 {\n readonly schemaVersion: EconomyContractVersion;\n readonly policyVersion: typeof EARLY_BACKER_SETTLEMENT_POLICY_V2;\n readonly qualificationEvent: \"settled-at\";\n readonly cohortKey: typeof PRE_UTILITY_BACKER_COHORT;\n readonly status: \"not-qualified\" | \"provisional\";\n readonly payerAccountId: AccountId;\n readonly receivingHouseholdId: HouseholdId;\n readonly netRetainedAmount: TokenSubunitString;\n readonly contributingLotIds: readonly LotId[];\n readonly evaluatedAt: IsoTimestamp;\n}\n\nfunction isWithinWindow(\n timestamp: IsoTimestamp,\n launch: number,\n cutoff: number | undefined,\n): boolean {\n const value = parseIsoTimestamp(timestamp);\n return value >= launch && (cutoff === undefined || value < cutoff);\n}\n\n/**\n * Recalculates provisional cohort basis from retained paid lots. It promises no\n * future reward and deliberately has no permanent entitled state.\n */\nexport function evaluateEarlyBacker(\n payerAccountId: AccountId,\n receivingHouseholdId: HouseholdId,\n paidLots: readonly PaidLotRetentionV1[],\n window: EarlyBackerWindowV1,\n evaluatedAt: IsoTimestamp,\n): EarlyBackerEvaluationV1 {\n assertEconomyIdentifier(payerAccountId, \"payerAccountId\");\n assertEconomyIdentifier(receivingHouseholdId, \"receivingHouseholdId\");\n const launch = parseIsoTimestamp(window.publicTokensLaunchAt);\n const cutoff =\n window.firstPublicSpendLiveAt === undefined\n ? undefined\n : parseIsoTimestamp(window.firstPublicSpendLiveAt);\n economyAssert(\n cutoff === undefined || cutoff > launch,\n \"INVALID_TIME_WINDOW\",\n \"First public spend must occur after public Token launch\",\n );\n parseIsoTimestamp(evaluatedAt);\n\n let retained = 0n;\n const contributingLotIds: LotId[] = [];\n const seenLotIds = new Set<string>();\n for (const lot of paidLots) {\n economyAssert(\n lot.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported paid-lot retention contract version\",\n );\n assertEconomyIdentifier(lot.lotId, \"lotId\");\n economyAssert(\n !seenLotIds.has(lot.lotId),\n \"DUPLICATE_IDENTIFIER\",\n \"Paid-lot retention input must not repeat a source lot\",\n );\n seenLotIds.add(lot.lotId);\n assertEconomyIdentifier(lot.payerAccountId, \"payerAccountId\");\n assertEconomyIdentifier(lot.receivingHouseholdId, \"receivingHouseholdId\");\n assertEconomyIdentifier(lot.purchaseId, \"purchaseId\");\n assertEconomyIdentifier(lot.catalogVersion, \"catalogVersion\");\n const purchasedAt = parseIsoTimestamp(lot.purchasedAt);\n const settledAt = parseIsoTimestamp(lot.settledAt);\n const creditedAt = parseIsoTimestamp(lot.creditedAt);\n economyAssert(\n purchasedAt <= settledAt && settledAt <= creditedAt,\n \"INVALID_TIME_WINDOW\",\n \"Paid-lot timestamps must follow purchase, settlement, then credit order\",\n );\n if (\n lot.payerAccountId !== payerAccountId ||\n lot.receivingHouseholdId !== receivingHouseholdId\n ) {\n continue;\n }\n const inWindow =\n isWithinWindow(lot.purchasedAt, launch, cutoff) &&\n isWithinWindow(lot.settledAt, launch, cutoff) &&\n isWithinWindow(lot.creditedAt, launch, cutoff);\n const amount = parseTokenSubunits(lot.retainedAmount);\n economyAssert(\n amount >= 0n,\n \"INVALID_AMOUNT\",\n \"Retained paid-lot basis cannot be negative\",\n );\n if (inWindow && amount > 0n) {\n retained += amount;\n contributingLotIds.push(lot.lotId);\n }\n }\n\n return {\n schemaVersion: ECONOMY_CONTRACT_VERSION,\n cohortKey: PRE_UTILITY_BACKER_COHORT,\n status: retained > 0n ? \"provisional\" : \"not-qualified\",\n payerAccountId,\n receivingHouseholdId,\n netRetainedAmount: serializeTokenSubunits(retained),\n contributingLotIds: contributingLotIds.sort((left, right) =>\n left.localeCompare(right),\n ),\n evaluatedAt,\n };\n}\n\n/**\n * Evaluates the approved settlement-window policy. The caller owns environment\n * and rollout classification: `publicTokensLaunchAt` and\n * `firstPublicSpendLiveAt` must be derived from the entire public cohort, so\n * staff, test, and closed-beta availability cannot open or close this window.\n * The caller must also exclude non-production/test lots before evaluation.\n */\nexport function evaluateEarlyBackerBySettlementV2(\n payerAccountId: AccountId,\n receivingHouseholdId: HouseholdId,\n paidLots: readonly PaidLotRetentionV1[],\n window: EarlyBackerWindowV1,\n evaluatedAt: IsoTimestamp,\n): EarlyBackerEvaluationV2 {\n assertEconomyIdentifier(payerAccountId, \"payerAccountId\");\n assertEconomyIdentifier(receivingHouseholdId, \"receivingHouseholdId\");\n const launch = parseIsoTimestamp(window.publicTokensLaunchAt);\n const cutoff =\n window.firstPublicSpendLiveAt === undefined\n ? undefined\n : parseIsoTimestamp(window.firstPublicSpendLiveAt);\n economyAssert(\n cutoff === undefined || cutoff > launch,\n \"INVALID_TIME_WINDOW\",\n \"First public spend must occur after public Token launch\",\n );\n const evaluationTime = parseIsoTimestamp(evaluatedAt);\n\n let retained = 0n;\n const contributingLotIds: LotId[] = [];\n const seenLotIds = new Set<string>();\n for (const lot of paidLots) {\n economyAssert(\n lot.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported paid-lot retention contract version\",\n );\n assertEconomyIdentifier(lot.lotId, \"lotId\");\n economyAssert(\n !seenLotIds.has(lot.lotId),\n \"DUPLICATE_IDENTIFIER\",\n \"Paid-lot retention input must not repeat a source lot\",\n );\n seenLotIds.add(lot.lotId);\n assertEconomyIdentifier(lot.payerAccountId, \"payerAccountId\");\n assertEconomyIdentifier(lot.receivingHouseholdId, \"receivingHouseholdId\");\n assertEconomyIdentifier(lot.purchaseId, \"purchaseId\");\n assertEconomyIdentifier(lot.catalogVersion, \"catalogVersion\");\n const purchasedAt = parseIsoTimestamp(lot.purchasedAt);\n const settledAt = parseIsoTimestamp(lot.settledAt);\n const creditedAt = parseIsoTimestamp(lot.creditedAt);\n economyAssert(\n purchasedAt <= settledAt && settledAt <= creditedAt,\n \"INVALID_TIME_WINDOW\",\n \"Paid-lot timestamps must follow purchase, settlement, then credit order\",\n );\n const amount = parseTokenSubunits(lot.retainedAmount);\n economyAssert(\n amount >= 0n,\n \"INVALID_AMOUNT\",\n \"Retained paid-lot basis cannot be negative\",\n );\n if (\n lot.payerAccountId === payerAccountId &&\n lot.receivingHouseholdId === receivingHouseholdId &&\n settledAt >= launch &&\n (cutoff === undefined || settledAt < cutoff) &&\n settledAt <= evaluationTime &&\n amount > 0n\n ) {\n retained += amount;\n contributingLotIds.push(lot.lotId);\n }\n }\n\n return {\n schemaVersion: ECONOMY_CONTRACT_VERSION,\n policyVersion: EARLY_BACKER_SETTLEMENT_POLICY_V2,\n qualificationEvent: \"settled-at\",\n cohortKey: PRE_UTILITY_BACKER_COHORT,\n status: retained > 0n ? \"provisional\" : \"not-qualified\",\n payerAccountId,\n receivingHouseholdId,\n netRetainedAmount: serializeTokenSubunits(retained),\n contributingLotIds: contributingLotIds.sort((left, right) =>\n left.localeCompare(right),\n ),\n evaluatedAt,\n };\n}\n","import {\n parseTokenSubunits,\n serializeTokenSubunits,\n sumTokenSubunits,\n type TokenSubunitString,\n} from \"./amount.js\";\nimport { compareUnicodeCodeUnits } from \"./canonical-order.js\";\nimport {\n ECONOMY_CONTRACT_VERSION,\n assertEconomyIdentifier,\n parseIsoTimestamp,\n sortStringRecord,\n type AccountId,\n type EconomyContractVersion,\n type IsoTimestamp,\n type LotId,\n type PostingId,\n type ProviderEventId,\n type TransactionId,\n type WalletId,\n} from \"./contracts.js\";\nimport { economyAssert } from \"./errors.js\";\nimport type { TokenSource } from \"./lots.js\";\n\nexport type ActivityType =\n | \"purchase\"\n | \"subscription\"\n | \"rewarded-ad\"\n | \"offerwall\"\n | \"allocation\"\n | \"boost\"\n | \"reclaim\"\n | \"spend\"\n | \"hold\"\n | \"refund\"\n | \"chargeback\"\n | \"adjustment\"\n | \"reversal\"\n | \"event\"\n | \"competition\";\n\nexport type ActivityStatus =\n | \"pending\"\n | \"held\"\n | \"settled\"\n | \"reversed\"\n | \"failed\";\n\n/**\n * States permitted on an immutable transaction accepted by the V2\n * persistence boundary. Pending and failed work belongs to the command\n * workflow, while a reversed presentation state is derived from an immutable\n * compensating transaction rather than written back to the original journal\n * row.\n */\nexport type EconomicJournalStatus = \"held\" | \"settled\";\n\n/** A journal transaction that has an immediate economic effect. */\nexport type EconomicJournalTransactionV1 = Omit<\n LedgerTransactionV1,\n \"status\"\n> & {\n readonly status: EconomicJournalStatus;\n};\n\nconst ACTIVITY_TYPES = new Set<ActivityType>([\n \"purchase\",\n \"subscription\",\n \"rewarded-ad\",\n \"offerwall\",\n \"allocation\",\n \"boost\",\n \"reclaim\",\n \"spend\",\n \"hold\",\n \"refund\",\n \"chargeback\",\n \"adjustment\",\n \"reversal\",\n \"event\",\n \"competition\",\n]);\n\nconst ACTIVITY_STATUSES = new Set<ActivityStatus>([\n \"pending\",\n \"held\",\n \"settled\",\n \"reversed\",\n \"failed\",\n]);\n\nconst ACTIVITY_SOURCES = new Set<TokenSource>([\n \"shopify\",\n \"ayet\",\n \"bitlabs\",\n \"subscription\",\n \"event\",\n \"competition\",\n \"adjustment\",\n]);\n\nfunction assertCanonicalHash(value: string, label: string): void {\n economyAssert(\n /^sha256:[a-f0-9]{64}$/u.test(value),\n \"INVALID_CONTRACT\",\n `${label} must be a canonical SHA-256 reference`,\n );\n}\n\nfunction hasControlCharacters(value: string): boolean {\n return [...value].some((character) => {\n const code = character.charCodeAt(0);\n return code <= 31 || code === 127;\n });\n}\n\n/** One signed side of an immutable double-entry transaction. */\nexport interface LedgerPostingV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly postingId: PostingId;\n readonly transactionId: TransactionId;\n readonly accountId: AccountId;\n readonly walletId?: WalletId;\n readonly lotId?: LotId;\n readonly amount: TokenSubunitString;\n}\n\n/** Immutable transaction envelope. Posting amounts must sum to exactly zero. */\nexport interface LedgerTransactionV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly transactionId: TransactionId;\n readonly activityType: ActivityType;\n readonly status: ActivityStatus;\n readonly idempotencyKey: string;\n readonly providerEventId?: ProviderEventId;\n readonly reversesTransactionId?: TransactionId;\n readonly effectiveAt: IsoTimestamp;\n readonly recordedAt: IsoTimestamp;\n readonly previousCanonicalHash?: string;\n readonly canonicalHash?: string;\n readonly metadata: Readonly<Record<string, string>>;\n readonly postings: readonly LedgerPostingV1[];\n}\n\n/** Privacy-safe, display-oriented journal entry returned by an API adapter. */\nexport interface ActivityEntryV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly transactionId: TransactionId;\n readonly activityType: ActivityType;\n readonly status: ActivityStatus;\n readonly occurredAt: IsoTimestamp;\n readonly amount: TokenSubunitString;\n /** Stable source identity used for filtering and provenance presentation. */\n readonly source: TokenSource;\n readonly beneficiaryAccountId?: AccountId;\n readonly maskedReference?: string;\n readonly sourceLabel: string;\n}\n\n/** Validates one privacy-safe activity row returned by an HTTP adapter. */\nexport function assertActivityEntry(entry: ActivityEntryV1): void {\n economyAssert(\n entry.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported activity-entry contract version\",\n );\n assertEconomyIdentifier(entry.transactionId, \"transactionId\");\n economyAssert(\n ACTIVITY_TYPES.has(entry.activityType) &&\n ACTIVITY_STATUSES.has(entry.status) &&\n ACTIVITY_SOURCES.has(entry.source),\n \"INVALID_CONTRACT\",\n \"Activity type, status, or source is unsupported\",\n );\n parseIsoTimestamp(entry.occurredAt);\n economyAssert(\n parseTokenSubunits(entry.amount) !== 0n,\n \"INVALID_AMOUNT\",\n \"Activity entries cannot contain a zero amount\",\n );\n if (entry.beneficiaryAccountId !== undefined) {\n assertEconomyIdentifier(\n entry.beneficiaryAccountId,\n \"beneficiaryAccountId\",\n );\n }\n if (entry.maskedReference !== undefined) {\n economyAssert(\n typeof entry.maskedReference === \"string\" &&\n entry.maskedReference.length > 0 &&\n entry.maskedReference.length <= 128 &&\n !hasControlCharacters(entry.maskedReference),\n \"INVALID_CONTRACT\",\n \"Masked activity references must be bounded and safe for display\",\n );\n }\n economyAssert(\n typeof entry.sourceLabel === \"string\" &&\n entry.sourceLabel.trim().length > 0 &&\n entry.sourceLabel.length <= 128 &&\n !hasControlCharacters(entry.sourceLabel),\n \"INVALID_CONTRACT\",\n \"Activity source labels must be bounded and safe for display\",\n );\n}\n\n/** Proves the structural and arithmetic invariants of one transaction. */\nexport function assertBalancedTransaction(\n transaction: LedgerTransactionV1,\n): void {\n economyAssert(\n transaction.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported ledger contract version\",\n );\n assertEconomyIdentifier(transaction.transactionId, \"transactionId\");\n assertEconomyIdentifier(transaction.idempotencyKey, \"idempotencyKey\");\n economyAssert(\n ACTIVITY_TYPES.has(transaction.activityType) &&\n ACTIVITY_STATUSES.has(transaction.status),\n \"INVALID_CONTRACT\",\n \"Transaction activity type or status is unsupported\",\n );\n if (transaction.providerEventId !== undefined) {\n assertEconomyIdentifier(transaction.providerEventId, \"providerEventId\");\n }\n if (transaction.reversesTransactionId !== undefined) {\n assertEconomyIdentifier(\n transaction.reversesTransactionId,\n \"reversesTransactionId\",\n );\n }\n economyAssert(\n (transaction.activityType === \"reversal\") ===\n (transaction.reversesTransactionId !== undefined),\n \"INVALID_CONTRACT\",\n \"Reversal transactions must identify exactly one original transaction\",\n );\n const effectiveAt = parseIsoTimestamp(transaction.effectiveAt);\n const recordedAt = parseIsoTimestamp(transaction.recordedAt);\n economyAssert(\n recordedAt >= effectiveAt,\n \"INVALID_TIME_WINDOW\",\n \"Transaction recording time cannot precede its effective time\",\n );\n if (transaction.previousCanonicalHash !== undefined) {\n assertCanonicalHash(\n transaction.previousCanonicalHash,\n \"Previous canonical hash\",\n );\n }\n if (transaction.canonicalHash !== undefined) {\n assertCanonicalHash(transaction.canonicalHash, \"Canonical hash\");\n }\n const metadataEntries = Object.entries(transaction.metadata);\n economyAssert(\n metadataEntries.length <= 32 &&\n metadataEntries.every(\n ([key, value]) =>\n /^[A-Za-z][A-Za-z0-9_.-]{0,63}$/u.test(key) &&\n value.length <= 512 &&\n !hasControlCharacters(value),\n ),\n \"INVALID_CONTRACT\",\n \"Transaction metadata must be bounded and free of control characters\",\n );\n economyAssert(\n transaction.postings.length >= 2,\n \"UNBALANCED_TRANSACTION\",\n \"A ledger transaction needs at least two postings\",\n );\n\n const postingIds = new Set<string>();\n for (const posting of transaction.postings) {\n economyAssert(\n posting.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported posting contract version\",\n );\n assertEconomyIdentifier(posting.postingId, \"postingId\");\n assertEconomyIdentifier(posting.accountId, \"accountId\");\n if (posting.walletId !== undefined) {\n assertEconomyIdentifier(posting.walletId, \"walletId\");\n }\n if (posting.lotId !== undefined) {\n assertEconomyIdentifier(posting.lotId, \"lotId\");\n }\n economyAssert(\n posting.transactionId === transaction.transactionId,\n \"INVALID_CONTRACT\",\n \"Posting transactionId must match its transaction\",\n );\n economyAssert(\n !postingIds.has(posting.postingId),\n \"DUPLICATE_IDENTIFIER\",\n \"Posting identifiers must be unique within a transaction\",\n );\n postingIds.add(posting.postingId);\n economyAssert(\n parseTokenSubunits(posting.amount) !== 0n,\n \"INVALID_AMOUNT\",\n \"Zero-value postings are not permitted\",\n );\n }\n\n economyAssert(\n sumTokenSubunits(transaction.postings.map((posting) => posting.amount)) ===\n 0n,\n \"UNBALANCED_TRANSACTION\",\n \"Ledger postings must sum to zero TokenSubunits\",\n );\n}\n\n/**\n * Narrows a balanced V1 transaction to the states accepted by the V2 journal.\n * This is additive: legacy V1 validators retain their existing status union.\n */\nexport function assertEconomicJournalTransaction(\n transaction: LedgerTransactionV1,\n): asserts transaction is EconomicJournalTransactionV1 {\n assertBalancedTransaction(transaction);\n economyAssert(\n transaction.status === \"held\" || transaction.status === \"settled\",\n \"INVALID_CONTRACT\",\n \"Pending, failed, and derived reversed activity cannot be journal transactions\",\n );\n}\n\n/**\n * Produces deterministic UTF-8 JSON for an approved SHA-256/HSM adapter.\n * Hashing itself deliberately remains outside this provider-neutral package.\n */\nexport function canonicalTransactionPayload(\n transaction: LedgerTransactionV1,\n): string {\n assertBalancedTransaction(transaction);\n const postings = [...transaction.postings]\n .sort((left, right) =>\n compareUnicodeCodeUnits(left.postingId, right.postingId),\n )\n .map((posting) => ({\n schemaVersion: posting.schemaVersion,\n postingId: posting.postingId,\n transactionId: posting.transactionId,\n accountId: posting.accountId,\n ...(posting.walletId === undefined ? {} : { walletId: posting.walletId }),\n ...(posting.lotId === undefined ? {} : { lotId: posting.lotId }),\n amount: posting.amount,\n }));\n\n return JSON.stringify({\n schemaVersion: transaction.schemaVersion,\n transactionId: transaction.transactionId,\n activityType: transaction.activityType,\n status: transaction.status,\n idempotencyKey: transaction.idempotencyKey,\n ...(transaction.providerEventId === undefined\n ? {}\n : { providerEventId: transaction.providerEventId }),\n ...(transaction.reversesTransactionId === undefined\n ? {}\n : { reversesTransactionId: transaction.reversesTransactionId }),\n effectiveAt: transaction.effectiveAt,\n recordedAt: transaction.recordedAt,\n ...(transaction.previousCanonicalHash === undefined\n ? {}\n : { previousCanonicalHash: transaction.previousCanonicalHash }),\n metadata: sortStringRecord(transaction.metadata),\n postings,\n });\n}\n\nexport interface ReversalInputV1 {\n readonly transactionId: TransactionId;\n readonly postingIds: readonly PostingId[];\n readonly idempotencyKey: string;\n readonly effectiveAt: IsoTimestamp;\n readonly recordedAt: IsoTimestamp;\n readonly metadata?: Readonly<Record<string, string>>;\n readonly previousCanonicalHash?: string;\n}\n\n/** Creates an immutable compensating transaction; it never edits the original. */\nexport function createReversalTransaction(\n original: LedgerTransactionV1,\n input: ReversalInputV1,\n): LedgerTransactionV1 {\n assertBalancedTransaction(original);\n economyAssert(\n original.reversesTransactionId === undefined,\n \"INVALID_CONTRACT\",\n \"A reversal cannot itself be reversed by this helper\",\n );\n economyAssert(\n input.postingIds.length === original.postings.length,\n \"INVALID_CONTRACT\",\n \"A reversal needs one new posting identifier per original posting\",\n );\n\n const postings = original.postings.map((posting, index) => {\n const postingId = input.postingIds[index];\n economyAssert(\n postingId !== undefined,\n \"INVALID_CONTRACT\",\n \"Missing reversal posting identifier\",\n );\n return {\n ...posting,\n postingId,\n transactionId: input.transactionId,\n amount: serializeTokenSubunits(-parseTokenSubunits(posting.amount)),\n } satisfies LedgerPostingV1;\n });\n\n const transaction: LedgerTransactionV1 = {\n schemaVersion: ECONOMY_CONTRACT_VERSION,\n transactionId: input.transactionId,\n activityType: \"reversal\",\n status: \"settled\",\n idempotencyKey: input.idempotencyKey,\n reversesTransactionId: original.transactionId,\n effectiveAt: input.effectiveAt,\n recordedAt: input.recordedAt,\n ...(input.previousCanonicalHash === undefined\n ? {}\n : { previousCanonicalHash: input.previousCanonicalHash }),\n metadata: input.metadata ?? {},\n postings,\n };\n assertBalancedTransaction(transaction);\n return transaction;\n}\n\n/** Rejects a second effective reversal for the same original transaction. */\nexport function assertReversalAvailable(\n originalTransactionId: TransactionId,\n existingTransactions: readonly LedgerTransactionV1[],\n): void {\n assertEconomyIdentifier(originalTransactionId, \"originalTransactionId\");\n economyAssert(\n !existingTransactions.some(\n (transaction) =>\n transaction.reversesTransactionId === originalTransactionId &&\n transaction.status !== \"failed\",\n ),\n \"REVERSAL_ALREADY_EXISTS\",\n \"The transaction already has an effective reversal\",\n );\n}\n","import {\n ECONOMY_CONTRACT_VERSION,\n assertEconomyIdentifier,\n parseIsoTimestamp,\n type EconomyContractVersion,\n type IsoTimestamp,\n type TransactionId,\n} from \"./contracts.js\";\nimport { economyAssert } from \"./errors.js\";\nimport {\n assertEconomicJournalTransaction,\n type EconomicJournalTransactionV1,\n} from \"./ledger.js\";\n\nexport type JournalChainId = string;\n\n/** Locked head of one canonical transaction hash chain. */\nexport interface JournalChainHeadV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly chainId: JournalChainId;\n readonly version: number;\n readonly lastTransactionId?: TransactionId;\n readonly canonicalHash?: string;\n readonly updatedAt: IsoTimestamp;\n}\n\n/** An effective economic transaction carrying its approved canonical hash. */\nexport type ChainedEconomicJournalTransactionV1 =\n EconomicJournalTransactionV1 & {\n readonly canonicalHash: string;\n };\n\nfunction assertCanonicalHash(value: string, label: string): void {\n economyAssert(\n typeof value === \"string\" && /^sha256:[a-f0-9]{64}$/u.test(value),\n \"INVALID_CONTRACT\",\n `${label} must be a canonical SHA-256 reference`,\n );\n}\n\n/** Validates an empty or populated journal-chain head. */\nexport function assertJournalChainHead(head: JournalChainHeadV1): void {\n economyAssert(\n head.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported journal-chain-head contract version\",\n );\n assertEconomyIdentifier(head.chainId, \"chainId\");\n economyAssert(\n Number.isSafeInteger(head.version) && head.version >= 0,\n \"INVALID_CONTRACT\",\n \"Journal-chain-head version must be a non-negative safe integer\",\n );\n parseIsoTimestamp(head.updatedAt);\n const hasTransaction = head.lastTransactionId !== undefined;\n const hasHash = head.canonicalHash !== undefined;\n economyAssert(\n hasTransaction === hasHash && (head.version > 0) === hasTransaction,\n \"INVALID_CONTRACT\",\n \"Journal-chain head identity, hash, and version must describe the same state\",\n );\n if (head.lastTransactionId !== undefined) {\n assertEconomyIdentifier(head.lastTransactionId, \"lastTransactionId\");\n }\n if (head.canonicalHash !== undefined) {\n assertCanonicalHash(head.canonicalHash, \"Journal-chain-head hash\");\n }\n}\n\n/**\n * Proves that a hashed transaction extends the locked head and returns the\n * exact next head. The persistence adapter must compare-and-swap the old\n * version inside the same serializable transaction that appends the journal.\n */\nexport function advanceJournalChainHead(\n head: JournalChainHeadV1,\n transaction: ChainedEconomicJournalTransactionV1,\n): JournalChainHeadV1 {\n assertJournalChainHead(head);\n assertEconomicJournalTransaction(transaction);\n assertCanonicalHash(transaction.canonicalHash, \"Transaction hash\");\n economyAssert(\n transaction.previousCanonicalHash === head.canonicalHash,\n \"INVALID_CONTRACT\",\n \"Transaction previous hash must match the locked journal-chain head\",\n );\n economyAssert(\n transaction.canonicalHash !== head.canonicalHash,\n \"DUPLICATE_TRANSACTION\",\n \"Transaction hash must advance the journal chain\",\n );\n const recordedAt = parseIsoTimestamp(transaction.recordedAt);\n economyAssert(\n recordedAt >= parseIsoTimestamp(head.updatedAt),\n \"INVALID_TIME_WINDOW\",\n \"Journal-chain update cannot precede its locked head\",\n );\n\n return {\n schemaVersion: ECONOMY_CONTRACT_VERSION,\n chainId: head.chainId,\n version: head.version + 1,\n lastTransactionId: transaction.transactionId,\n canonicalHash: transaction.canonicalHash,\n updatedAt: transaction.recordedAt,\n };\n}\n","import {\n parseTokenSubunits,\n serializeTokenSubunits,\n type TokenSubunitString,\n} from \"./amount.js\";\nimport {\n ECONOMY_CONTRACT_VERSION,\n assertEconomyIdentifier,\n parseIsoTimestamp,\n type AccountId,\n type EconomyContractVersion,\n type HouseholdId,\n type IsoTimestamp,\n type LotId,\n type ProviderEventId,\n type TransactionId,\n type WalletId,\n} from \"./contracts.js\";\nimport { EconomyError, economyAssert } from \"./errors.js\";\n\nexport type TokenSource =\n | \"shopify\"\n | \"ayet\"\n | \"bitlabs\"\n | \"subscription\"\n | \"event\"\n | \"competition\"\n | \"adjustment\";\n\nexport type LotTransferPolicy =\n | \"household-allocatable\"\n | \"same-user-only\"\n | \"non-transferable\";\n\nexport type LotRefundState =\n | \"none\"\n | \"partial\"\n | \"refunded\"\n | \"disputed\"\n | \"chargeback-lost\";\n\nexport interface SourceLotV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly lotId: LotId;\n readonly walletId: WalletId;\n readonly beneficiaryAccountId: AccountId;\n readonly householdId?: HouseholdId;\n readonly payerAccountId?: AccountId;\n readonly source: TokenSource;\n readonly providerEventId?: ProviderEventId;\n readonly rateVersion: string;\n readonly settlementEvidenceHash: string;\n readonly transferPolicy: LotTransferPolicy;\n readonly refundState: LotRefundState;\n readonly originalAmount: TokenSubunitString;\n readonly remainingAmount: TokenSubunitString;\n readonly heldAmount: TokenSubunitString;\n readonly reversedAmount: TokenSubunitString;\n readonly settledAt: IsoTimestamp;\n readonly creditedAt: IsoTimestamp;\n readonly cohortKey?: string;\n}\n\nexport type LotUseOperation = \"allocate\" | \"spend\" | \"reclaim\" | \"refund\";\n\nexport interface LotUseContextV1 {\n readonly operation: LotUseOperation;\n readonly beneficiaryAccountId: AccountId;\n readonly householdId?: HouseholdId;\n}\n\nexport interface SourceLotSliceV1 {\n readonly lotId: LotId;\n readonly amount: TokenSubunitString;\n}\n\n/** Versioned mutable projection around immutable V1 source-lot provenance. */\nexport interface VersionedSourceLotV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly lot: SourceLotV1;\n readonly version: number;\n readonly updatedAt: IsoTimestamp;\n}\n\nexport type SourceLotMovementType =\n | \"allocate\"\n | \"boost\"\n | \"reclaim\"\n | \"spend\"\n | \"hold\"\n | \"release-hold\"\n | \"refund\"\n | \"chargeback\"\n | \"reversal\";\n\n/**\n * Immutable movement applied to one source-lot projection by compare-and-swap.\n * Signed deltas are authoritative; `resultingRefundState` is part of the same\n * atomic version transition.\n */\nexport interface SourceLotMovementV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly movementId: string;\n readonly transactionId: TransactionId;\n readonly lotId: LotId;\n readonly movementType: SourceLotMovementType;\n readonly remainingDelta: TokenSubunitString;\n readonly heldDelta: TokenSubunitString;\n readonly reversedDelta: TokenSubunitString;\n readonly expectedVersion: number;\n readonly resultingVersion: number;\n readonly expectedRefundState: LotRefundState;\n readonly resultingRefundState: LotRefundState;\n readonly occurredAt: IsoTimestamp;\n}\n\n/** Validates source-lot arithmetic, evidence, and immutable provenance fields. */\nexport function assertSourceLot(lot: SourceLotV1): void {\n economyAssert(\n lot.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported source-lot contract version\",\n );\n assertEconomyIdentifier(lot.lotId, \"lotId\");\n assertEconomyIdentifier(lot.walletId, \"walletId\");\n assertEconomyIdentifier(lot.beneficiaryAccountId, \"beneficiaryAccountId\");\n if (lot.householdId !== undefined) {\n assertEconomyIdentifier(lot.householdId, \"householdId\");\n }\n if (lot.payerAccountId !== undefined) {\n assertEconomyIdentifier(lot.payerAccountId, \"payerAccountId\");\n }\n if (lot.providerEventId !== undefined) {\n assertEconomyIdentifier(lot.providerEventId, \"providerEventId\");\n }\n assertEconomyIdentifier(lot.rateVersion, \"rateVersion\");\n economyAssert(\n [\n \"shopify\",\n \"ayet\",\n \"bitlabs\",\n \"subscription\",\n \"event\",\n \"competition\",\n \"adjustment\",\n ].includes(lot.source),\n \"INVALID_CONTRACT\",\n \"Source lot has an unsupported source\",\n );\n economyAssert(\n [\"household-allocatable\", \"same-user-only\", \"non-transferable\"].includes(\n lot.transferPolicy,\n ),\n \"INVALID_CONTRACT\",\n \"Source lot has an unsupported transfer policy\",\n );\n economyAssert(\n [\"none\", \"partial\", \"refunded\", \"disputed\", \"chargeback-lost\"].includes(\n lot.refundState,\n ),\n \"INVALID_CONTRACT\",\n \"Source lot has an unsupported refund state\",\n );\n if (lot.source === \"ayet\" || lot.source === \"bitlabs\") {\n economyAssert(\n lot.transferPolicy === \"same-user-only\" &&\n lot.providerEventId !== undefined,\n \"SOURCE_LOT_RESTRICTED\",\n \"Reward-provider lots must remain with the earning account\",\n );\n }\n if (lot.source === \"shopify\") {\n economyAssert(\n lot.transferPolicy === \"household-allocatable\" &&\n lot.householdId !== undefined &&\n lot.payerAccountId !== undefined,\n \"INVALID_CONTRACT\",\n \"Shopify lots must retain payer and receiving-household provenance\",\n );\n }\n economyAssert(\n /^sha256:[a-f0-9]{64}$/u.test(lot.settlementEvidenceHash),\n \"INVALID_CONTRACT\",\n \"Settlement evidence must be a sanitized SHA-256 reference\",\n );\n const settledAt = parseIsoTimestamp(lot.settledAt);\n const creditedAt = parseIsoTimestamp(lot.creditedAt);\n economyAssert(\n creditedAt >= settledAt,\n \"INVALID_TIME_WINDOW\",\n \"Source-lot credit time cannot precede settlement\",\n );\n if (lot.cohortKey !== undefined) {\n assertEconomyIdentifier(lot.cohortKey, \"cohortKey\");\n }\n\n const original = parseTokenSubunits(lot.originalAmount);\n const remaining = parseTokenSubunits(lot.remainingAmount);\n const held = parseTokenSubunits(lot.heldAmount);\n const reversed = parseTokenSubunits(lot.reversedAmount);\n economyAssert(\n original > 0n && remaining >= 0n && held >= 0n && reversed >= 0n,\n \"INVALID_AMOUNT\",\n \"Source-lot amounts must be non-negative and original must be positive\",\n );\n economyAssert(\n remaining <= original && held <= remaining && reversed <= original,\n \"INVALID_CONTRACT\",\n \"Source-lot amount components exceed the original or remaining amount\",\n );\n economyAssert(\n remaining + reversed <= original,\n \"INVALID_CONTRACT\",\n \"Remaining and reversed source-lot amounts exceed the original\",\n );\n}\n\n/** Validates the optimistic projection wrapper used by V2 persistence. */\nexport function assertVersionedSourceLot(\n snapshot: VersionedSourceLotV1,\n): void {\n economyAssert(\n snapshot.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported versioned source-lot contract version\",\n );\n assertSourceLot(snapshot.lot);\n economyAssert(\n Number.isSafeInteger(snapshot.version) && snapshot.version >= 1,\n \"INVALID_CONTRACT\",\n \"Source-lot version must be a positive safe integer\",\n );\n economyAssert(\n parseIsoTimestamp(snapshot.updatedAt) >=\n parseIsoTimestamp(snapshot.lot.creditedAt),\n \"INVALID_TIME_WINDOW\",\n \"Source-lot update time cannot precede its credit\",\n );\n}\n\n/** Creates the only state accepted by the V2 append-source-lot operation. */\nexport function createInitialSourceLotSnapshot(\n lot: SourceLotV1,\n): VersionedSourceLotV1 {\n assertSourceLot(lot);\n economyAssert(\n lot.refundState === \"none\" &&\n lot.originalAmount === lot.remainingAmount &&\n parseTokenSubunits(lot.heldAmount) === 0n &&\n parseTokenSubunits(lot.reversedAmount) === 0n,\n \"INVALID_CONTRACT\",\n \"A new source lot must start fully remaining, clear, and unreversed\",\n );\n return {\n schemaVersion: ECONOMY_CONTRACT_VERSION,\n lot,\n version: 1,\n updatedAt: lot.creditedAt,\n };\n}\n\nfunction assertRefundState(value: LotRefundState): void {\n economyAssert(\n [\n \"none\",\n \"partial\",\n \"refunded\",\n \"disputed\",\n \"chargeback-lost\",\n ].includes(value),\n \"INVALID_CONTRACT\",\n \"Source-lot movement has an unsupported refund state\",\n );\n}\n\n/** Validates movement shape and operation-specific delta direction. */\nexport function assertSourceLotMovement(\n movement: SourceLotMovementV1,\n): void {\n economyAssert(\n movement.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported source-lot-movement contract version\",\n );\n assertEconomyIdentifier(movement.movementId, \"movementId\");\n assertEconomyIdentifier(movement.transactionId, \"transactionId\");\n assertEconomyIdentifier(movement.lotId, \"lotId\");\n economyAssert(\n [\n \"allocate\",\n \"boost\",\n \"reclaim\",\n \"spend\",\n \"hold\",\n \"release-hold\",\n \"refund\",\n \"chargeback\",\n \"reversal\",\n ].includes(movement.movementType),\n \"INVALID_CONTRACT\",\n \"Source-lot movement has an unsupported type\",\n );\n const remaining = parseTokenSubunits(movement.remainingDelta);\n const held = parseTokenSubunits(movement.heldDelta);\n const reversed = parseTokenSubunits(movement.reversedDelta);\n economyAssert(\n remaining !== 0n || held !== 0n || reversed !== 0n,\n \"INVALID_AMOUNT\",\n \"Source-lot movement must change at least one amount\",\n );\n economyAssert(\n Number.isSafeInteger(movement.expectedVersion) &&\n movement.expectedVersion >= 1 &&\n movement.resultingVersion === movement.expectedVersion + 1,\n \"INVALID_CONTRACT\",\n \"Source-lot movement must advance its optimistic version exactly once\",\n );\n assertRefundState(movement.expectedRefundState);\n assertRefundState(movement.resultingRefundState);\n parseIsoTimestamp(movement.occurredAt);\n\n if (\n movement.movementType === \"allocate\" ||\n movement.movementType === \"boost\" ||\n movement.movementType === \"spend\"\n ) {\n economyAssert(\n remaining < 0n &&\n held === 0n &&\n reversed === 0n &&\n movement.resultingRefundState === movement.expectedRefundState,\n \"INVALID_CONTRACT\",\n \"Allocation, boost, and spend movements only consume remaining lot value\",\n );\n } else if (movement.movementType === \"reclaim\") {\n economyAssert(\n remaining > 0n &&\n held === 0n &&\n reversed === 0n &&\n movement.resultingRefundState === movement.expectedRefundState,\n \"INVALID_CONTRACT\",\n \"Reclaim movements only restore remaining lot value\",\n );\n } else if (movement.movementType === \"hold\") {\n economyAssert(\n remaining === 0n &&\n held > 0n &&\n reversed === 0n &&\n movement.resultingRefundState === \"disputed\",\n \"INVALID_CONTRACT\",\n \"Hold movements must enter disputed state and increase held value\",\n );\n } else if (movement.movementType === \"release-hold\") {\n economyAssert(\n remaining === 0n &&\n held < 0n &&\n reversed === 0n &&\n movement.expectedRefundState === \"disputed\" &&\n movement.resultingRefundState !== \"disputed\" &&\n movement.resultingRefundState !== \"refunded\" &&\n movement.resultingRefundState !== \"chargeback-lost\",\n \"INVALID_CONTRACT\",\n \"Released holds must leave disputed state without reversing value\",\n );\n } else {\n economyAssert(\n remaining < 0n &&\n reversed === -remaining &&\n held <= 0n &&\n (movement.resultingRefundState === \"partial\" ||\n movement.resultingRefundState === \"refunded\" ||\n movement.resultingRefundState === \"chargeback-lost\"),\n \"INVALID_CONTRACT\",\n \"Refund, chargeback, and reversal movements must compensate remaining value exactly\",\n );\n if (movement.movementType === \"chargeback\") {\n economyAssert(\n movement.resultingRefundState === \"chargeback-lost\",\n \"INVALID_CONTRACT\",\n \"Chargeback movements must enter chargeback-lost state\",\n );\n } else {\n economyAssert(\n movement.resultingRefundState !== \"chargeback-lost\",\n \"INVALID_CONTRACT\",\n \"Only a chargeback movement may enter chargeback-lost state\",\n );\n }\n }\n}\n\n/**\n * Applies one immutable movement to a locked source-lot snapshot. Persistence\n * must append the movement and compare-and-swap this result atomically.\n */\nexport function applySourceLotMovement(\n snapshot: VersionedSourceLotV1,\n movement: SourceLotMovementV1,\n): VersionedSourceLotV1 {\n assertVersionedSourceLot(snapshot);\n assertSourceLotMovement(movement);\n economyAssert(\n movement.lotId === snapshot.lot.lotId &&\n movement.expectedVersion === snapshot.version &&\n movement.expectedRefundState === snapshot.lot.refundState,\n \"INVALID_CONTRACT\",\n \"Source-lot movement does not match the locked lot version and refund state\",\n );\n economyAssert(\n parseIsoTimestamp(movement.occurredAt) >=\n parseIsoTimestamp(snapshot.updatedAt),\n \"INVALID_TIME_WINDOW\",\n \"Source-lot movement cannot precede its current projection\",\n );\n\n const lot: SourceLotV1 = {\n ...snapshot.lot,\n remainingAmount: serializeTokenSubunits(\n parseTokenSubunits(snapshot.lot.remainingAmount) +\n parseTokenSubunits(movement.remainingDelta),\n ),\n heldAmount: serializeTokenSubunits(\n parseTokenSubunits(snapshot.lot.heldAmount) +\n parseTokenSubunits(movement.heldDelta),\n ),\n reversedAmount: serializeTokenSubunits(\n parseTokenSubunits(snapshot.lot.reversedAmount) +\n parseTokenSubunits(movement.reversedDelta),\n ),\n refundState: movement.resultingRefundState,\n };\n assertSourceLot(lot);\n\n const remaining = parseTokenSubunits(lot.remainingAmount);\n const held = parseTokenSubunits(lot.heldAmount);\n const reversed = parseTokenSubunits(lot.reversedAmount);\n const original = parseTokenSubunits(lot.originalAmount);\n if (lot.refundState === \"none\") {\n economyAssert(\n reversed === 0n && held === 0n,\n \"INVALID_CONTRACT\",\n \"A clear lot cannot retain held or reversed value\",\n );\n } else if (lot.refundState === \"partial\") {\n economyAssert(\n reversed > 0n && remaining > 0n && held === 0n,\n \"INVALID_CONTRACT\",\n \"A partial refund requires retained/reversed value and no active hold\",\n );\n } else if (lot.refundState === \"disputed\") {\n economyAssert(\n held > 0n,\n \"INVALID_CONTRACT\",\n \"A disputed lot must hold affected value\",\n );\n } else {\n economyAssert(\n remaining === 0n && held === 0n && reversed === original,\n \"INVALID_CONTRACT\",\n \"Final refund and lost-chargeback states must reverse the full lot\",\n );\n }\n\n return {\n schemaVersion: ECONOMY_CONTRACT_VERSION,\n lot,\n version: movement.resultingVersion,\n updatedAt: movement.occurredAt,\n };\n}\n\n/** Returns unheld, unconsumed TokenSubunits in a source lot. */\nexport function availableSourceLotAmount(lot: SourceLotV1): bigint {\n assertSourceLot(lot);\n return (\n parseTokenSubunits(lot.remainingAmount) - parseTokenSubunits(lot.heldAmount)\n );\n}\n\n/** Evaluates provider/source restrictions without trusting a browser claim. */\nexport function canUseSourceLot(\n lot: SourceLotV1,\n context: LotUseContextV1,\n): boolean {\n if (context.operation === \"refund\") {\n return true;\n }\n\n if (context.operation === \"allocate\" || context.operation === \"reclaim\") {\n return (\n lot.transferPolicy === \"household-allocatable\" &&\n lot.householdId !== undefined &&\n lot.householdId === context.householdId\n );\n }\n\n if (lot.transferPolicy === \"household-allocatable\") {\n return (\n lot.householdId !== undefined && lot.householdId === context.householdId\n );\n }\n\n return lot.beneficiaryAccountId === context.beneficiaryAccountId;\n}\n\n/**\n * Selects eligible lots deterministically in credited-time/lot-id order.\n * The returned slices are a proposal; persistence must consume them atomically.\n */\nexport function selectSourceLots(\n lots: readonly SourceLotV1[],\n requestedAmount: TokenSubunitString,\n context: LotUseContextV1,\n): readonly SourceLotSliceV1[] {\n const requested = parseTokenSubunits(requestedAmount);\n economyAssert(\n requested > 0n,\n \"INVALID_AMOUNT\",\n \"Requested source-lot amount must be positive\",\n );\n assertEconomyIdentifier(context.beneficiaryAccountId, \"beneficiaryAccountId\");\n\n const ordered = [...lots].sort((left, right) => {\n const timeDifference =\n parseIsoTimestamp(left.creditedAt) - parseIsoTimestamp(right.creditedAt);\n return timeDifference === 0\n ? left.lotId.localeCompare(right.lotId)\n : timeDifference;\n });\n\n let allAvailable = 0n;\n let remaining = requested;\n const slices: SourceLotSliceV1[] = [];\n\n for (const lot of ordered) {\n const available = availableSourceLotAmount(lot);\n allAvailable += available;\n if (available === 0n || !canUseSourceLot(lot, context)) {\n continue;\n }\n const selected = available < remaining ? available : remaining;\n slices.push({ lotId: lot.lotId, amount: serializeTokenSubunits(selected) });\n remaining -= selected;\n if (remaining === 0n) {\n return slices;\n }\n }\n\n if (allAvailable >= requested) {\n throw new EconomyError(\n \"SOURCE_LOT_RESTRICTED\",\n \"Available source lots do not permit this operation\",\n );\n }\n throw new EconomyError(\n \"INSUFFICIENT_ELIGIBLE_LOTS\",\n \"Insufficient eligible source-lot balance\",\n );\n}\n","import { parseTokenSubunits, type TokenSubunitString } from \"./amount.js\";\nimport {\n ECONOMY_CONTRACT_VERSION,\n assertEconomyIdentifier,\n parseIsoTimestamp,\n type AccountId,\n type EconomyContractVersion,\n type IsoTimestamp,\n type TransactionId,\n type WalletId,\n} from \"./contracts.js\";\nimport { economyAssert } from \"./errors.js\";\n\nexport type AdjustmentStatus =\n | \"draft\"\n | \"pending-approval\"\n | \"approved\"\n | \"rejected\"\n | \"executed\"\n | \"expired\";\n\n/** Dual-control request; the resulting change is always a ledger transaction. */\nexport interface AdjustmentRequestV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly adjustmentId: string;\n readonly walletId: WalletId;\n readonly amount: TokenSubunitString;\n readonly reason: string;\n readonly ticketReference: string;\n readonly status: AdjustmentStatus;\n readonly initiatedByAccountId: AccountId;\n readonly initiatedAt: IsoTimestamp;\n readonly approvedByAccountId?: AccountId;\n readonly approvedAt?: IsoTimestamp;\n readonly resultingTransactionId?: TransactionId;\n}\n\n/** Proves that production adjustment approval was performed by another actor. */\nexport function assertDistinctAdjustmentApproval(\n request: AdjustmentRequestV1,\n): void {\n economyAssert(\n request.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported adjustment contract version\",\n );\n assertEconomyIdentifier(request.adjustmentId, \"adjustmentId\");\n assertEconomyIdentifier(request.walletId, \"walletId\");\n assertEconomyIdentifier(request.initiatedByAccountId, \"initiatedByAccountId\");\n economyAssert(\n parseTokenSubunits(request.amount) !== 0n,\n \"INVALID_AMOUNT\",\n \"Adjustment amount cannot be zero\",\n );\n economyAssert(\n request.reason.trim().length > 0 && request.reason.length <= 512,\n \"INVALID_CONTRACT\",\n \"Adjustment reason is required and must be bounded\",\n );\n assertEconomyIdentifier(request.ticketReference, \"ticketReference\");\n const initiatedAt = parseIsoTimestamp(request.initiatedAt);\n economyAssert(\n request.approvedByAccountId !== undefined &&\n request.approvedByAccountId !== request.initiatedByAccountId,\n \"INVALID_CONTRACT\",\n \"Adjustment approval requires a distinct authorized operator\",\n );\n assertEconomyIdentifier(request.approvedByAccountId, \"approvedByAccountId\");\n economyAssert(\n request.approvedAt !== undefined &&\n parseIsoTimestamp(request.approvedAt) >= initiatedAt,\n \"INVALID_TIME_WINDOW\",\n \"Adjustment approval time must follow initiation\",\n );\n economyAssert(\n request.status === \"approved\" || request.status === \"executed\",\n \"INVALID_CONTRACT\",\n \"Only approved adjustments satisfy dual-control approval\",\n );\n if (request.resultingTransactionId !== undefined) {\n assertEconomyIdentifier(\n request.resultingTransactionId,\n \"resultingTransactionId\",\n );\n }\n}\n","import type { TokenSubunitString } from \"../amount.js\";\nimport type { GameplayAllocationV1 } from \"../allocations.js\";\nimport {\n ECONOMY_CONTRACT_VERSION,\n assertEconomyIdentifier,\n parseIsoTimestamp,\n type AccountId,\n type AllocationId,\n type EconomyContractVersion,\n type HouseholdId,\n type IsoTimestamp,\n type LotId,\n type TransactionId,\n type WalletId,\n} from \"../contracts.js\";\nimport { economyAssert } from \"../errors.js\";\nimport type {\n ChainedEconomicJournalTransactionV1,\n JournalChainHeadV1,\n} from \"../integrity.js\";\nimport type { LedgerTransactionV1 } from \"../ledger.js\";\nimport type {\n SourceLotMovementV1,\n SourceLotV1,\n VersionedSourceLotV1,\n} from \"../lots.js\";\nimport type {\n BalanceProjection,\n BalanceProjectionSnapshotV1,\n WalletBalanceDeltaV1,\n WalletBalanceProjectionV1,\n WalletLifetimeDeltaV1,\n} from \"../projection.js\";\nimport type {\n WalletOwnerReferenceV1,\n WalletV1,\n} from \"../wallets.js\";\n\nexport type EconomyCommandType =\n | \"credit-purchase\"\n | \"credit-subscription\"\n | \"credit-reward\"\n | \"credit-event\"\n | \"credit-competition\"\n | \"allocate\"\n | \"boost\"\n | \"reclaim\"\n | \"spend\"\n | \"hold\"\n | \"release-hold\"\n | \"refund\"\n | \"chargeback\"\n | \"reverse\"\n | \"adjust\";\n\nexport interface EconomyCommandEnvelopeV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly commandId: string;\n readonly commandType: EconomyCommandType;\n readonly idempotencyKey: string;\n readonly actorAccountId: AccountId;\n readonly subjectAccountId: AccountId;\n readonly relationshipId?: string;\n readonly authorizationVersion?: number;\n readonly payloadHash: string;\n readonly acceptedAt: IsoTimestamp;\n readonly acceptedRegion: string;\n readonly writerFencingToken: string;\n}\n\nexport type EconomyCommandWorkflowStateV1 =\n | \"accepted\"\n | \"processing\"\n | \"failed\"\n | \"completed\";\n\n/** Immutable workflow evidence; it is never an economic journal transaction. */\nexport interface EconomyCommandWorkflowEventV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly workflowEventId: string;\n readonly commandId: string;\n readonly state: EconomyCommandWorkflowStateV1;\n /** Stable non-sensitive classifier; detailed failure data stays operational. */\n readonly failureCode?: string;\n readonly occurredAt: IsoTimestamp;\n}\n\nexport interface EconomyOutboxEventV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly eventId: string;\n readonly transactionId: TransactionId;\n readonly eventType: string;\n readonly payloadHash: string;\n readonly occurredAt: IsoTimestamp;\n}\n\nexport interface PersistedIdempotencyResultV1 {\n readonly transactionId: TransactionId;\n readonly responseHash: string;\n readonly recordedAt: IsoTimestamp;\n}\n\n/** Exact actor/subject/operation namespace for a caller-owned idempotency key. */\nexport interface EconomyIdempotencyScopeV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly idempotencyKey: string;\n readonly commandType: EconomyCommandType;\n readonly actorAccountId: AccountId;\n readonly subjectAccountId: AccountId;\n}\n\n/** V2 replay evidence bound to one accepted command and exact scope. */\nexport interface ScopedPersistedIdempotencyResultV1\n extends PersistedIdempotencyResultV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly commandId: string;\n}\n\n/** Validates replay evidence before it is returned across a command boundary. */\nexport function assertScopedPersistedIdempotencyResult(\n result: ScopedPersistedIdempotencyResultV1,\n): void {\n economyAssert(\n result.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported scoped idempotency-result contract version\",\n );\n assertEconomyIdentifier(result.commandId, \"commandId\");\n assertEconomyIdentifier(result.transactionId, \"transactionId\");\n economyAssert(\n /^sha256:[a-f0-9]{64}$/u.test(result.responseHash),\n \"INVALID_CONTRACT\",\n \"Idempotency response hash must be a canonical SHA-256 reference\",\n );\n parseIsoTimestamp(result.recordedAt);\n}\n\nconst ECONOMY_COMMAND_TYPES = new Set<EconomyCommandType>([\n \"credit-purchase\",\n \"credit-subscription\",\n \"credit-reward\",\n \"credit-event\",\n \"credit-competition\",\n \"allocate\",\n \"boost\",\n \"reclaim\",\n \"spend\",\n \"hold\",\n \"release-hold\",\n \"refund\",\n \"chargeback\",\n \"reverse\",\n \"adjust\",\n]);\n\n/** Validates the namespace that prevents cross-principal replay collisions. */\nexport function assertEconomyIdempotencyScope(\n scope: EconomyIdempotencyScopeV1,\n): void {\n economyAssert(\n scope.schemaVersion === ECONOMY_CONTRACT_VERSION &&\n ECONOMY_COMMAND_TYPES.has(scope.commandType),\n \"INVALID_CONTRACT\",\n \"Unsupported economy idempotency scope\",\n );\n assertEconomyIdentifier(scope.idempotencyKey, \"idempotencyKey\");\n assertEconomyIdentifier(scope.actorAccountId, \"actorAccountId\");\n assertEconomyIdentifier(scope.subjectAccountId, \"subjectAccountId\");\n}\n\n/** Validates minimized accepted-command evidence before durable append. */\nexport function assertEconomyCommandEnvelope(\n envelope: EconomyCommandEnvelopeV1,\n): void {\n economyAssert(\n envelope.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported economy-command-envelope contract version\",\n );\n assertEconomyIdentifier(envelope.commandId, \"commandId\");\n economyAssert(\n ECONOMY_COMMAND_TYPES.has(envelope.commandType),\n \"INVALID_CONTRACT\",\n \"Economy command has an unsupported type\",\n );\n assertEconomyIdentifier(envelope.idempotencyKey, \"idempotencyKey\");\n assertEconomyIdentifier(envelope.actorAccountId, \"actorAccountId\");\n assertEconomyIdentifier(envelope.subjectAccountId, \"subjectAccountId\");\n if (envelope.relationshipId !== undefined) {\n assertEconomyIdentifier(envelope.relationshipId, \"relationshipId\");\n }\n if (envelope.authorizationVersion !== undefined) {\n economyAssert(\n Number.isSafeInteger(envelope.authorizationVersion) &&\n envelope.authorizationVersion >= 1,\n \"INVALID_CONTRACT\",\n \"Command authorization version must be a positive safe integer\",\n );\n }\n economyAssert(\n (envelope.relationshipId === undefined) ===\n (envelope.authorizationVersion === undefined),\n \"INVALID_CONTRACT\",\n \"Relationship identity and authorization version must be supplied together\",\n );\n economyAssert(\n /^sha256:[a-f0-9]{64}$/u.test(envelope.payloadHash),\n \"INVALID_CONTRACT\",\n \"Command payload hash must be a canonical SHA-256 reference\",\n );\n parseIsoTimestamp(envelope.acceptedAt);\n assertEconomyIdentifier(envelope.acceptedRegion, \"acceptedRegion\");\n assertEconomyIdentifier(\n envelope.writerFencingToken,\n \"writerFencingToken\",\n );\n}\n\n/** Validates one immutable command-workflow state event. */\nexport function assertEconomyCommandWorkflowEvent(\n event: EconomyCommandWorkflowEventV1,\n): void {\n economyAssert(\n event.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported command-workflow-event contract version\",\n );\n assertEconomyIdentifier(event.workflowEventId, \"workflowEventId\");\n assertEconomyIdentifier(event.commandId, \"commandId\");\n economyAssert(\n [\"accepted\", \"processing\", \"failed\", \"completed\"].includes(event.state),\n \"INVALID_CONTRACT\",\n \"Command workflow has an unsupported state\",\n );\n economyAssert(\n (event.state === \"failed\") === (event.failureCode !== undefined),\n \"INVALID_CONTRACT\",\n \"Only failed command workflows require a failure code\",\n );\n if (event.failureCode !== undefined) {\n assertEconomyIdentifier(event.failureCode, \"failureCode\");\n }\n parseIsoTimestamp(event.occurredAt);\n}\n\n/** Operations available only inside one serializable database transaction. */\nexport interface EconomyUnitOfWork {\n getWalletForUpdate(walletId: WalletId): Promise<WalletV1 | null>;\n listSpendableLotsForUpdate(walletId: WalletId): Promise<readonly SourceLotV1[]>;\n findLotForUpdate(lotId: LotId): Promise<SourceLotV1 | null>;\n findIdempotencyResult(\n idempotencyKey: string,\n ): Promise<PersistedIdempotencyResultV1 | null>;\n appendTransaction(transaction: LedgerTransactionV1): Promise<void>;\n appendSourceLot(lot: SourceLotV1): Promise<void>;\n updateSourceLotProjection(\n lotId: LotId,\n remainingAmount: TokenSubunitString,\n heldAmount: TokenSubunitString,\n reversedAmount: TokenSubunitString,\n ): Promise<void>;\n saveBalanceProjection(\n projection: BalanceProjection,\n transactionId: TransactionId,\n ): Promise<void>;\n saveIdempotencyResult(\n idempotencyKey: string,\n result: PersistedIdempotencyResultV1,\n ): Promise<void>;\n appendOutboxEvent(event: EconomyOutboxEventV1): Promise<void>;\n}\n\n/** Adapter boundary for serializable, ACID economy mutations. */\nexport interface EconomyPersistencePort {\n runSerializable<T>(\n operation: (unitOfWork: EconomyUnitOfWork) => Promise<T>,\n ): Promise<T>;\n getWallet(walletId: WalletId): Promise<WalletV1 | null>;\n getBalanceProjection(walletId: WalletId): Promise<BalanceProjectionSnapshotV1 | null>;\n getTransaction(transactionId: TransactionId): Promise<LedgerTransactionV1 | null>;\n rebuildProjection(): Promise<BalanceProjection>;\n}\n\n/**\n * V2 mutation surface. Unlike `EconomyUnitOfWork`, it has no absolute balance\n * overwrite: journal, source-lot movement, allocation state, balance/lifetime\n * deltas, idempotency, chain head, and outbox are committed atomically.\n */\nexport interface EconomyUnitOfWorkV2 {\n getWalletForOwnerForUpdate(\n walletId: WalletId,\n owner: WalletOwnerReferenceV1,\n ): Promise<WalletV1 | null>;\n listSpendableLotsForUpdate(\n walletId: WalletId,\n ): Promise<readonly VersionedSourceLotV1[]>;\n findLotForUpdate(lotId: LotId): Promise<VersionedSourceLotV1 | null>;\n getGameplayAllocationForUpdate(\n allocationId: AllocationId,\n householdId: HouseholdId,\n childAccountId: AccountId,\n ): Promise<GameplayAllocationV1 | null>;\n findIdempotencyResult(\n scope: EconomyIdempotencyScopeV1,\n ): Promise<ScopedPersistedIdempotencyResultV1 | null>;\n /** Locks and rejects any stale/non-active regional writer lease. */\n lockActiveWriterFence(\n acceptedRegion: string,\n writerFencingToken: string,\n ): Promise<void>;\n lockJournalChainHead(chainId: string): Promise<JournalChainHeadV1>;\n\n appendCommandEnvelope(envelope: EconomyCommandEnvelopeV1): Promise<void>;\n appendCommandWorkflowEvent(\n event: EconomyCommandWorkflowEventV1,\n ): Promise<void>;\n appendTransaction(\n transaction: ChainedEconomicJournalTransactionV1,\n ): Promise<void>;\n /** Appends `createInitialSourceLotSnapshot()` output; later changes are movements. */\n appendSourceLot(snapshot: VersionedSourceLotV1): Promise<void>;\n /** Appends movement evidence and applies its lot CAS as one operation. */\n applySourceLotMovement(movement: SourceLotMovementV1): Promise<void>;\n appendGameplayAllocation(allocation: GameplayAllocationV1): Promise<void>;\n /**\n * Compares `expectedVersion`, requires `allocation.version` to be exactly the\n * next value, and never overwrites a stale row.\n */\n saveGameplayAllocation(\n allocation: GameplayAllocationV1,\n expectedVersion: number,\n ): Promise<void>;\n /**\n * Atomically adds deltas, verifies them against the appended postings and\n * account bindings, and records transaction-scoped application keys.\n */\n applyWalletBalanceDeltas(\n transactionId: TransactionId,\n deltas: readonly WalletBalanceDeltaV1[],\n ): Promise<void>;\n /**\n * Atomically increments monotonic lifetime counters after verifying the\n * deltas against the appended transaction's deterministic classification.\n */\n applyWalletLifetimeDeltas(\n transactionId: TransactionId,\n deltas: readonly WalletLifetimeDeltaV1[],\n ): Promise<void>;\n saveIdempotencyResult(\n scope: EconomyIdempotencyScopeV1,\n result: ScopedPersistedIdempotencyResultV1,\n ): Promise<void>;\n appendOutboxEvent(event: EconomyOutboxEventV1): Promise<void>;\n /** Compare-and-swaps the full locked head, including its canonical hash. */\n advanceJournalChainHead(\n expected: JournalChainHeadV1,\n next: JournalChainHeadV1,\n ): Promise<void>;\n}\n\n/**\n * Additive authoritative persistence boundary for new consumers. V1 remains\n * exported for compatibility but must not be adapted by delegating its\n * absolute `saveBalanceProjection` operation to this interface.\n */\nexport interface EconomyPersistencePortV2 {\n runSerializable<T>(\n operation: (unitOfWork: EconomyUnitOfWorkV2) => Promise<T>,\n ): Promise<T>;\n getWallet(walletId: WalletId): Promise<WalletV1 | null>;\n listWalletsByOwner(\n owner: WalletOwnerReferenceV1,\n ): Promise<readonly WalletV1[]>;\n getGameplayAllocation(\n allocationId: AllocationId,\n householdId: HouseholdId,\n childAccountId: AccountId,\n ): Promise<GameplayAllocationV1 | null>;\n getCommandEnvelope(\n commandId: string,\n ): Promise<EconomyCommandEnvelopeV1 | null>;\n getTransaction(\n transactionId: TransactionId,\n ): Promise<ChainedEconomicJournalTransactionV1 | null>;\n rebuildWalletBalanceProjections(): Promise<\n readonly WalletBalanceProjectionV1[]\n >;\n}\n\nexport interface EconomyClockPort {\n now(): IsoTimestamp;\n}\n\nexport interface EconomyIdPort {\n nextId(namespace: string): string;\n}\n","import {\n ECONOMY_CONTRACT_VERSION,\n assertEconomyIdentifier,\n parseIsoTimestamp,\n type AccountId,\n type EconomyContractVersion,\n type HouseholdId,\n type IsoTimestamp,\n type WalletId,\n} from \"./contracts.js\";\nimport {\n parseTokenSubunits,\n type TokenSubunitString,\n} from \"./amount.js\";\nimport { economyAssert } from \"./errors.js\";\n\nexport type WalletKind =\n | \"household-treasury\"\n | \"personal\"\n | \"gameplay-allocation\"\n | \"hold\"\n | \"purchase-clearing\"\n | \"provider-clearing\"\n | \"system\";\n\nexport type WalletStatus = \"active\" | \"restricted\" | \"closed\";\nexport type WalletOwnerType = \"account\" | \"household\" | \"system\";\n\n/** Exact owner identity used by persistence lookups and IDOR-safe locking. */\nexport interface WalletOwnerReferenceV1 {\n readonly ownerType: WalletOwnerType;\n readonly ownerId: AccountId | HouseholdId | \"system\";\n}\n\n/** Versioned authoritative wallet descriptor. */\nexport interface WalletV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly walletId: WalletId;\n readonly accountId: AccountId;\n readonly kind: WalletKind;\n readonly ownerType: WalletOwnerType;\n readonly ownerId: AccountId | HouseholdId | \"system\";\n readonly householdId?: HouseholdId;\n readonly status: WalletStatus;\n readonly version: number;\n readonly createdAt: IsoTimestamp;\n readonly closedAt?: IsoTimestamp;\n}\n\n/** Server-computed wallet totals. Clients must never derive authority from it. */\nexport interface WalletBalanceSummaryV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly walletId: WalletId;\n readonly available: TokenSubunitString;\n readonly reserved: TokenSubunitString;\n readonly held: TokenSubunitString;\n readonly rewardProgress: TokenSubunitString;\n readonly version: number;\n readonly asOf: IsoTimestamp;\n}\n\n/** Lifetime aggregates used by the Token profile. */\nexport interface WalletLifetimeTotalsV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly bought: TokenSubunitString;\n readonly earned: TokenSubunitString;\n readonly allocated: TokenSubunitString;\n readonly reclaimed: TokenSubunitString;\n readonly spent: TokenSubunitString;\n readonly reversed: TokenSubunitString;\n}\n\n/** Validates an exact wallet owner without accepting a browser-derived role. */\nexport function assertWalletOwnerReference(\n owner: WalletOwnerReferenceV1,\n): void {\n economyAssert(\n [\"account\", \"household\", \"system\"].includes(owner.ownerType),\n \"INVALID_CONTRACT\",\n \"Wallet owner reference has an unsupported type\",\n );\n if (owner.ownerType === \"system\") {\n economyAssert(\n owner.ownerId === \"system\",\n \"INVALID_CONTRACT\",\n \"System wallet lookups must use the system owner\",\n );\n } else {\n assertEconomyIdentifier(owner.ownerId, \"ownerId\");\n economyAssert(\n owner.ownerId !== \"system\",\n \"INVALID_CONTRACT\",\n \"Account and household wallets cannot use the system owner\",\n );\n }\n}\n\n/** Validates wallet ownership, lifecycle, and optimistic-version facts. */\nexport function assertWallet(wallet: WalletV1): void {\n economyAssert(\n wallet.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported wallet contract version\",\n );\n assertEconomyIdentifier(wallet.walletId, \"walletId\");\n assertEconomyIdentifier(wallet.accountId, \"accountId\");\n economyAssert(\n [\n \"household-treasury\",\n \"personal\",\n \"gameplay-allocation\",\n \"hold\",\n \"purchase-clearing\",\n \"provider-clearing\",\n \"system\",\n ].includes(wallet.kind),\n \"INVALID_CONTRACT\",\n \"Wallet has an unsupported kind\",\n );\n economyAssert(\n [\"account\", \"household\", \"system\"].includes(wallet.ownerType),\n \"INVALID_CONTRACT\",\n \"Wallet has an unsupported owner type\",\n );\n economyAssert(\n [\"active\", \"restricted\", \"closed\"].includes(wallet.status),\n \"INVALID_CONTRACT\",\n \"Wallet has an unsupported status\",\n );\n if (wallet.ownerType === \"system\") {\n economyAssert(\n wallet.ownerId === \"system\",\n \"INVALID_CONTRACT\",\n \"System wallets must be owned by the system\",\n );\n } else {\n assertEconomyIdentifier(wallet.ownerId, \"ownerId\");\n }\n if (wallet.householdId !== undefined) {\n assertEconomyIdentifier(wallet.householdId, \"householdId\");\n }\n if (wallet.ownerType === \"household\") {\n economyAssert(\n wallet.householdId === wallet.ownerId,\n \"INVALID_CONTRACT\",\n \"Household wallets must identify the same household owner\",\n );\n }\n if (wallet.kind === \"household-treasury\") {\n economyAssert(\n wallet.ownerType === \"household\" && wallet.householdId !== undefined,\n \"INVALID_CONTRACT\",\n \"Household treasuries must be owned by their household\",\n );\n }\n if (wallet.kind === \"personal\" || wallet.kind === \"gameplay-allocation\") {\n economyAssert(\n wallet.ownerType === \"account\",\n \"INVALID_CONTRACT\",\n \"Personal and gameplay-allocation wallets must be account-owned\",\n );\n }\n if (wallet.kind === \"gameplay-allocation\") {\n economyAssert(\n wallet.householdId !== undefined,\n \"INVALID_CONTRACT\",\n \"Gameplay-allocation wallets must retain household provenance\",\n );\n }\n if (\n wallet.kind === \"purchase-clearing\" ||\n wallet.kind === \"provider-clearing\" ||\n wallet.kind === \"system\"\n ) {\n economyAssert(\n wallet.ownerType === \"system\" && wallet.householdId === undefined,\n \"INVALID_CONTRACT\",\n \"Clearing and system wallets must be system-owned\",\n );\n }\n economyAssert(\n Number.isSafeInteger(wallet.version) && wallet.version >= 1,\n \"INVALID_CONTRACT\",\n \"Wallet version must be a positive safe integer\",\n );\n const createdAt = parseIsoTimestamp(wallet.createdAt);\n if (wallet.closedAt !== undefined) {\n economyAssert(\n parseIsoTimestamp(wallet.closedAt) >= createdAt &&\n wallet.status === \"closed\",\n \"INVALID_TIME_WINDOW\",\n \"Only closed wallets may have a valid closure time\",\n );\n } else {\n economyAssert(\n wallet.status !== \"closed\",\n \"INVALID_CONTRACT\",\n \"Closed wallets require a closure time\",\n );\n }\n}\n\n/** Validates non-negative server-computed wallet balance categories. */\nexport function assertWalletBalanceSummary(\n summary: WalletBalanceSummaryV1,\n): void {\n economyAssert(\n summary.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported wallet summary contract version\",\n );\n assertEconomyIdentifier(summary.walletId, \"walletId\");\n for (const amount of [\n summary.available,\n summary.reserved,\n summary.held,\n summary.rewardProgress,\n ]) {\n economyAssert(\n parseTokenSubunits(amount) >= 0n,\n \"INVALID_AMOUNT\",\n \"Wallet summary categories cannot be negative\",\n );\n }\n economyAssert(\n Number.isSafeInteger(summary.version) && summary.version >= 1,\n \"INVALID_CONTRACT\",\n \"Wallet summary version must be a positive safe integer\",\n );\n parseIsoTimestamp(summary.asOf);\n}\n\n/** Validates non-negative lifetime aggregates exposed by the profile API. */\nexport function assertWalletLifetimeTotals(\n totals: WalletLifetimeTotalsV1,\n): void {\n economyAssert(\n totals.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported wallet lifetime-total contract version\",\n );\n for (const amount of [\n totals.bought,\n totals.earned,\n totals.allocated,\n totals.reclaimed,\n totals.spent,\n totals.reversed,\n ]) {\n economyAssert(\n parseTokenSubunits(amount) >= 0n,\n \"INVALID_AMOUNT\",\n \"Wallet lifetime totals cannot be negative\",\n );\n }\n}\n","import {\n parseTokenSubunits,\n serializeTokenSubunits,\n type TokenSubunitString,\n} from \"./amount.js\";\nimport {\n ECONOMY_CONTRACT_VERSION,\n assertEconomyIdentifier,\n parseIsoTimestamp,\n type AccountId,\n type EconomyContractVersion,\n type IsoTimestamp,\n type TransactionId,\n type WalletId,\n} from \"./contracts.js\";\nimport { economyAssert } from \"./errors.js\";\nimport {\n assertBalancedTransaction,\n assertEconomicJournalTransaction,\n type ActivityType,\n type EconomicJournalTransactionV1,\n type LedgerTransactionV1,\n} from \"./ledger.js\";\nimport {\n assertWalletBalanceSummary,\n assertWalletLifetimeTotals,\n type WalletBalanceSummaryV1,\n type WalletLifetimeTotalsV1,\n} from \"./wallets.js\";\n\nexport type BalanceProjection = Readonly<Record<AccountId, TokenSubunitString>>;\n\nexport interface BalanceProjectionSnapshotV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly balances: BalanceProjection;\n readonly lastTransactionId?: TransactionId;\n readonly rebuiltAt: IsoTimestamp;\n}\n\nexport type WalletProjectionBucket = \"spendable\" | \"reserved\" | \"held\";\n\n/** Exclusive stored buckets for one wallet; reward progress is derived. */\nexport interface WalletBalanceProjectionV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly walletId: WalletId;\n readonly spendable: TokenSubunitString;\n readonly reserved: TokenSubunitString;\n readonly held: TokenSubunitString;\n readonly version: number;\n readonly lastTransactionId?: TransactionId;\n readonly asOf: IsoTimestamp;\n}\n\n/** One atomic add operation against all exclusive buckets of a wallet. */\nexport interface WalletBalanceDeltaV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly walletId: WalletId;\n readonly spendableDelta: TokenSubunitString;\n readonly reservedDelta: TokenSubunitString;\n readonly heldDelta: TokenSubunitString;\n}\n\n/** Authoritative mapping from a ledger account to one wallet bucket. */\nexport interface WalletPostingAccountBindingV1 {\n readonly accountId: AccountId;\n readonly walletId: WalletId;\n readonly bucket: WalletProjectionBucket;\n}\n\nexport type WalletLifetimeBucket =\n | \"bought\"\n | \"earned\"\n | \"allocated\"\n | \"reclaimed\"\n | \"spent\"\n | \"reversed\";\n\n/** Positive monotonic contribution to one wallet lifetime counter. */\nexport interface WalletLifetimeDeltaV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly walletId: WalletId;\n readonly bucket: WalletLifetimeBucket;\n readonly amount: TokenSubunitString;\n}\n\n/** Validates one exclusive-bucket projection. */\nexport function assertWalletBalanceProjection(\n projection: WalletBalanceProjectionV1,\n): void {\n economyAssert(\n projection.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported wallet-balance-projection contract version\",\n );\n assertEconomyIdentifier(projection.walletId, \"walletId\");\n for (const amount of [\n projection.spendable,\n projection.reserved,\n projection.held,\n ]) {\n economyAssert(\n parseTokenSubunits(amount) >= 0n,\n \"NEGATIVE_PROJECTION\",\n \"Wallet projection buckets cannot be negative\",\n );\n }\n economyAssert(\n Number.isSafeInteger(projection.version) && projection.version >= 1,\n \"INVALID_CONTRACT\",\n \"Wallet projection version must be a positive safe integer\",\n );\n if (projection.lastTransactionId !== undefined) {\n assertEconomyIdentifier(\n projection.lastTransactionId,\n \"lastTransactionId\",\n );\n }\n parseIsoTimestamp(projection.asOf);\n}\n\n/** Validates one non-zero atomic wallet delta. */\nexport function assertWalletBalanceDelta(delta: WalletBalanceDeltaV1): void {\n economyAssert(\n delta.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported wallet-balance-delta contract version\",\n );\n assertEconomyIdentifier(delta.walletId, \"walletId\");\n const values = [\n parseTokenSubunits(delta.spendableDelta),\n parseTokenSubunits(delta.reservedDelta),\n parseTokenSubunits(delta.heldDelta),\n ];\n economyAssert(\n values.some((value) => value !== 0n),\n \"INVALID_AMOUNT\",\n \"Wallet balance delta must change at least one bucket\",\n );\n}\n\n/** Rejects duplicate wallet updates before one atomic persistence call. */\nexport function assertWalletBalanceDeltaBatch(\n transactionId: TransactionId,\n deltas: readonly WalletBalanceDeltaV1[],\n): void {\n assertEconomyIdentifier(transactionId, \"transactionId\");\n economyAssert(\n deltas.length > 0,\n \"INVALID_CONTRACT\",\n \"An economic transaction must update at least one wallet projection\",\n );\n const walletIds = new Set<string>();\n for (const delta of deltas) {\n assertWalletBalanceDelta(delta);\n economyAssert(\n !walletIds.has(delta.walletId),\n \"DUPLICATE_IDENTIFIER\",\n \"A balance-delta batch must update each wallet once\",\n );\n walletIds.add(delta.walletId);\n }\n}\n\n/** Applies an atomic add locally for deterministic tests and rebuilds. */\nexport function applyWalletBalanceDelta(\n projection: WalletBalanceProjectionV1,\n delta: WalletBalanceDeltaV1,\n transactionId: TransactionId,\n asOf: IsoTimestamp,\n): WalletBalanceProjectionV1 {\n assertWalletBalanceProjection(projection);\n assertWalletBalanceDelta(delta);\n assertEconomyIdentifier(transactionId, \"transactionId\");\n economyAssert(\n projection.walletId === delta.walletId,\n \"INVALID_CONTRACT\",\n \"Wallet balance delta must target its projection wallet\",\n );\n economyAssert(\n parseIsoTimestamp(asOf) >= parseIsoTimestamp(projection.asOf),\n \"INVALID_TIME_WINDOW\",\n \"Wallet balance update cannot precede its projection\",\n );\n const next: WalletBalanceProjectionV1 = {\n ...projection,\n spendable: serializeTokenSubunits(\n parseTokenSubunits(projection.spendable) +\n parseTokenSubunits(delta.spendableDelta),\n ),\n reserved: serializeTokenSubunits(\n parseTokenSubunits(projection.reserved) +\n parseTokenSubunits(delta.reservedDelta),\n ),\n held: serializeTokenSubunits(\n parseTokenSubunits(projection.held) +\n parseTokenSubunits(delta.heldDelta),\n ),\n version: projection.version + 1,\n lastTransactionId: transactionId,\n asOf,\n };\n assertWalletBalanceProjection(next);\n return next;\n}\n\n/**\n * Converts exclusive storage buckets to the legacy display DTO. Available is\n * independently usable whole Tokens in this wallet; rewardProgress is this\n * wallet's sub-Token remainder and is never netted with another wallet.\n */\nexport function createWalletBalanceSummary(\n projection: WalletBalanceProjectionV1,\n): WalletBalanceSummaryV1 {\n assertWalletBalanceProjection(projection);\n const spendable = parseTokenSubunits(projection.spendable);\n const rewardProgress = spendable % 1_000n;\n const summary: WalletBalanceSummaryV1 = {\n schemaVersion: ECONOMY_CONTRACT_VERSION,\n walletId: projection.walletId,\n available: serializeTokenSubunits(spendable - rewardProgress),\n reserved: projection.reserved,\n held: projection.held,\n rewardProgress: serializeTokenSubunits(rewardProgress),\n version: projection.version,\n asOf: projection.asOf,\n };\n assertDeterministicWalletBalanceSummary(summary);\n return summary;\n}\n\n/** Enforces the stronger per-wallet semantics required by V1 query adapters. */\nexport function assertDeterministicWalletBalanceSummary(\n summary: WalletBalanceSummaryV1,\n): void {\n assertWalletBalanceSummary(summary);\n economyAssert(\n parseTokenSubunits(summary.available) % 1_000n === 0n &&\n parseTokenSubunits(summary.rewardProgress) < 1_000n,\n \"INVALID_CONTRACT\",\n \"Per-wallet availability must be whole Tokens with sub-Token progress below one Token\",\n );\n}\n\n/**\n * Derives a single delta per wallet from wallet-linked postings and an\n * authoritative account-to-bucket mapping. Unlinked system postings are not\n * wallet projections.\n */\nexport function deriveWalletBalanceDeltas(\n transaction: EconomicJournalTransactionV1,\n bindings: readonly WalletPostingAccountBindingV1[],\n): readonly WalletBalanceDeltaV1[] {\n assertEconomicJournalTransaction(transaction);\n const byAccount = new Map<AccountId, WalletPostingAccountBindingV1>();\n for (const binding of bindings) {\n assertEconomyIdentifier(binding.accountId, \"accountId\");\n assertEconomyIdentifier(binding.walletId, \"walletId\");\n economyAssert(\n [\"spendable\", \"reserved\", \"held\"].includes(binding.bucket),\n \"INVALID_CONTRACT\",\n \"Wallet account binding has an unsupported bucket\",\n );\n economyAssert(\n !byAccount.has(binding.accountId),\n \"DUPLICATE_IDENTIFIER\",\n \"A ledger account may bind to only one wallet bucket\",\n );\n byAccount.set(binding.accountId, binding);\n }\n\n const byWallet = new Map<WalletId, [bigint, bigint, bigint]>();\n for (const posting of transaction.postings) {\n if (posting.walletId === undefined) {\n continue;\n }\n const binding = byAccount.get(posting.accountId);\n economyAssert(\n binding !== undefined && binding.walletId === posting.walletId,\n \"INVALID_CONTRACT\",\n \"Every wallet-linked posting must match an authoritative account binding\",\n );\n const values = byWallet.get(binding.walletId) ?? [0n, 0n, 0n];\n const amount = parseTokenSubunits(posting.amount);\n if (binding.bucket === \"spendable\") {\n values[0] += amount;\n } else if (binding.bucket === \"reserved\") {\n values[1] += amount;\n } else {\n values[2] += amount;\n }\n byWallet.set(binding.walletId, values);\n }\n\n const deltas = [...byWallet.entries()]\n .map(([walletId, values]) => ({\n schemaVersion: ECONOMY_CONTRACT_VERSION,\n walletId,\n spendableDelta: serializeTokenSubunits(values[0]),\n reservedDelta: serializeTokenSubunits(values[1]),\n heldDelta: serializeTokenSubunits(values[2]),\n }))\n .filter(\n (delta) =>\n delta.spendableDelta !== \"0\" ||\n delta.reservedDelta !== \"0\" ||\n delta.heldDelta !== \"0\",\n )\n .sort((left, right) => left.walletId.localeCompare(right.walletId));\n assertWalletBalanceDeltaBatch(transaction.transactionId, deltas);\n return deltas;\n}\n\nconst EARNED_ACTIVITY_TYPES = new Set<ActivityType>([\n \"rewarded-ad\",\n \"offerwall\",\n \"event\",\n \"competition\",\n]);\n\n/**\n * Rebuilds monotonic gross lifetime contributions from a settled transaction.\n * Earlier bought/earned counters are never reduced by a later compensating\n * transaction; removals accrue separately in `reversed`.\n */\nexport function deriveWalletLifetimeDeltas(\n transaction: EconomicJournalTransactionV1,\n): readonly WalletLifetimeDeltaV1[] {\n assertEconomicJournalTransaction(transaction);\n if (transaction.status !== \"settled\") {\n return [];\n }\n const netByWallet = new Map<WalletId, bigint>();\n for (const posting of transaction.postings) {\n if (posting.walletId !== undefined) {\n netByWallet.set(\n posting.walletId,\n (netByWallet.get(posting.walletId) ?? 0n) +\n parseTokenSubunits(posting.amount),\n );\n }\n }\n\n const deltas: WalletLifetimeDeltaV1[] = [];\n for (const [walletId, net] of [...netByWallet.entries()].sort(([left], [right]) =>\n left.localeCompare(right),\n )) {\n let bucket: WalletLifetimeBucket | undefined;\n let amount = 0n;\n if (\n net > 0n &&\n (transaction.activityType === \"purchase\" ||\n transaction.activityType === \"subscription\")\n ) {\n bucket = \"bought\";\n amount = net;\n } else if (net > 0n && EARNED_ACTIVITY_TYPES.has(transaction.activityType)) {\n bucket = \"earned\";\n amount = net;\n } else if (\n net < 0n &&\n (transaction.activityType === \"allocation\" ||\n transaction.activityType === \"boost\")\n ) {\n bucket = \"allocated\";\n amount = -net;\n } else if (net > 0n && transaction.activityType === \"reclaim\") {\n bucket = \"reclaimed\";\n amount = net;\n } else if (net < 0n && transaction.activityType === \"spend\") {\n bucket = \"spent\";\n amount = -net;\n } else if (\n net < 0n &&\n (transaction.activityType === \"refund\" ||\n transaction.activityType === \"chargeback\" ||\n transaction.activityType === \"reversal\")\n ) {\n bucket = \"reversed\";\n amount = -net;\n }\n if (bucket !== undefined) {\n deltas.push({\n schemaVersion: ECONOMY_CONTRACT_VERSION,\n walletId,\n bucket,\n amount: serializeTokenSubunits(amount),\n });\n }\n }\n return deltas;\n}\n\n/** Applies positive lifetime deltas for one wallet without rewriting history. */\nexport function applyWalletLifetimeDeltas(\n current: WalletLifetimeTotalsV1,\n walletId: WalletId,\n deltas: readonly WalletLifetimeDeltaV1[],\n): WalletLifetimeTotalsV1 {\n assertWalletLifetimeTotals(current);\n assertEconomyIdentifier(walletId, \"walletId\");\n const next: Record<WalletLifetimeBucket, bigint> = {\n bought: parseTokenSubunits(current.bought),\n earned: parseTokenSubunits(current.earned),\n allocated: parseTokenSubunits(current.allocated),\n reclaimed: parseTokenSubunits(current.reclaimed),\n spent: parseTokenSubunits(current.spent),\n reversed: parseTokenSubunits(current.reversed),\n };\n for (const delta of deltas) {\n economyAssert(\n delta.schemaVersion === ECONOMY_CONTRACT_VERSION &&\n delta.walletId === walletId &&\n [\n \"bought\",\n \"earned\",\n \"allocated\",\n \"reclaimed\",\n \"spent\",\n \"reversed\",\n ].includes(delta.bucket),\n \"INVALID_CONTRACT\",\n \"Lifetime delta must target the requested wallet and a known bucket\",\n );\n const amount = parseTokenSubunits(delta.amount);\n economyAssert(\n amount > 0n,\n \"INVALID_AMOUNT\",\n \"Lifetime deltas must be positive\",\n );\n next[delta.bucket] += amount;\n }\n const totals: WalletLifetimeTotalsV1 = {\n schemaVersion: ECONOMY_CONTRACT_VERSION,\n bought: serializeTokenSubunits(next.bought),\n earned: serializeTokenSubunits(next.earned),\n allocated: serializeTokenSubunits(next.allocated),\n reclaimed: serializeTokenSubunits(next.reclaimed),\n spent: serializeTokenSubunits(next.spent),\n reversed: serializeTokenSubunits(next.reversed),\n };\n assertWalletLifetimeTotals(totals);\n return totals;\n}\n\n/** Applies one balanced transaction without mutating the existing projection. */\nexport function applyTransactionToProjection(\n current: BalanceProjection,\n transaction: LedgerTransactionV1,\n): BalanceProjection {\n assertBalancedTransaction(transaction);\n const next: Record<AccountId, TokenSubunitString> = { ...current };\n for (const posting of transaction.postings) {\n const prior = parseTokenSubunits(next[posting.accountId] ?? \"0\");\n next[posting.accountId] = serializeTokenSubunits(\n prior + parseTokenSubunits(posting.amount),\n );\n }\n return next;\n}\n\n/**\n * Rebuilds balances deterministically and rejects duplicate economic envelopes.\n */\nexport function rebuildBalanceProjection(\n transactions: readonly LedgerTransactionV1[],\n): BalanceProjection {\n let projection: BalanceProjection = {};\n const transactionIds = new Set<string>();\n const idempotencyKeys = new Set<string>();\n const providerEvents = new Set<string>();\n\n for (const transaction of transactions) {\n economyAssert(\n !transactionIds.has(transaction.transactionId),\n \"DUPLICATE_TRANSACTION\",\n \"Transaction identifiers must be unique\",\n );\n economyAssert(\n !idempotencyKeys.has(transaction.idempotencyKey),\n \"DUPLICATE_TRANSACTION\",\n \"Idempotency keys must be unique\",\n );\n if (transaction.providerEventId !== undefined) {\n economyAssert(\n !providerEvents.has(transaction.providerEventId),\n \"DUPLICATE_TRANSACTION\",\n \"Provider event identifiers must be unique\",\n );\n providerEvents.add(transaction.providerEventId);\n }\n transactionIds.add(transaction.transactionId);\n idempotencyKeys.add(transaction.idempotencyKey);\n projection = applyTransactionToProjection(projection, transaction);\n }\n\n return projection;\n}\n\n/** Enforces non-negative balances only for spendable/reservable accounts. */\nexport function assertNonNegativeAccounts(\n projection: BalanceProjection,\n protectedAccountIds: readonly AccountId[],\n): void {\n for (const accountId of protectedAccountIds) {\n economyAssert(\n parseTokenSubunits(projection[accountId] ?? \"0\") >= 0n,\n \"NEGATIVE_PROJECTION\",\n \"A protected economy account would become negative\",\n );\n }\n}\n\n/** Creates a versioned snapshot after a deterministic rebuild. */\nexport function createProjectionSnapshot(\n transactions: readonly LedgerTransactionV1[],\n rebuiltAt: IsoTimestamp,\n): BalanceProjectionSnapshotV1 {\n parseIsoTimestamp(rebuiltAt);\n const last = transactions.at(-1);\n return {\n schemaVersion: ECONOMY_CONTRACT_VERSION,\n balances: rebuildBalanceProjection(transactions),\n ...(last === undefined ? {} : { lastTransactionId: last.transactionId }),\n rebuiltAt,\n };\n}\n","import {\n parseTokenSubunits,\n serializeTokenSubunits,\n type TokenSubunitString,\n} from \"../amount.js\";\nimport {\n ECONOMY_CONTRACT_VERSION,\n assertEconomyIdentifier,\n parseIsoTimestamp,\n type AccountId,\n type EconomyContractVersion,\n type IsoTimestamp,\n type TransactionId,\n type WalletId,\n} from \"../contracts.js\";\nimport { economyAssert } from \"../errors.js\";\nimport type { ActivityType } from \"../ledger.js\";\nimport type { TokenSource } from \"../lots.js\";\nimport { assertDeterministicWalletBalanceSummary } from \"../projection.js\";\nimport {\n assertWalletLifetimeTotals,\n type WalletBalanceSummaryV1,\n type WalletLifetimeTotalsV1,\n} from \"../wallets.js\";\n\nexport type WalletPortfolioComponentRole =\n | \"household-treasury\"\n | \"personal\"\n | \"gameplay-allocation\"\n | \"hold\";\n\n/** One server-authorized component of a portfolio read. */\nexport interface WalletPortfolioComponentScopeV1 {\n readonly walletId: WalletId;\n readonly role: WalletPortfolioComponentRole;\n readonly beneficiaryAccountId?: AccountId;\n}\n\n/**\n * Explicit portfolio scope assembled after authorization. It prevents a host's\n * household treasury and same-user-only personal wallet from being silently\n * represented as one wallet.\n */\nexport interface WalletPortfolioReadScopeV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly portfolioId: string;\n readonly subjectAccountId: AccountId;\n readonly components: readonly WalletPortfolioComponentScopeV1[];\n}\n\nexport interface WalletBalanceTotalsV1 {\n readonly available: TokenSubunitString;\n readonly reserved: TokenSubunitString;\n readonly held: TokenSubunitString;\n readonly rewardProgress: TokenSubunitString;\n}\n\nexport interface WalletPortfolioBalanceComponentV1\n extends WalletPortfolioComponentScopeV1 {\n readonly summary: WalletBalanceSummaryV1;\n}\n\nexport interface WalletPortfolioSummaryV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly portfolioId: string;\n readonly subjectAccountId: AccountId;\n readonly components: readonly WalletPortfolioBalanceComponentV1[];\n /**\n * Exact column sums for display only. Progress is intentionally not promoted\n * across wallets because their source/transfer policies may differ.\n */\n readonly totals: WalletBalanceTotalsV1;\n readonly asOf: IsoTimestamp;\n}\n\n/** Self-identifying lifetime read for one wallet. */\nexport interface WalletLifetimeSnapshotV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly walletId: WalletId;\n readonly totals: WalletLifetimeTotalsV1;\n readonly version: number;\n readonly asOf: IsoTimestamp;\n}\n\nexport interface WalletPortfolioLifetimeComponentV1\n extends WalletPortfolioComponentScopeV1 {\n readonly snapshot: WalletLifetimeSnapshotV1;\n}\n\nexport interface WalletPortfolioLifetimeV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly portfolioId: string;\n readonly subjectAccountId: AccountId;\n readonly components: readonly WalletPortfolioLifetimeComponentV1[];\n readonly totals: WalletLifetimeTotalsV1;\n readonly asOf: IsoTimestamp;\n}\n\nexport type EconomicActivityStatusV1 = \"held\" | \"settled\" | \"reversed\";\nexport type WorkflowActivityStatusV1 = \"pending\" | \"failed\";\nexport type WalletActivityStatusV1 =\n | EconomicActivityStatusV1\n | WorkflowActivityStatusV1;\n\ninterface WalletActivityBaseV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly activityId: string;\n /** Component wallet whose signed display amount this row represents. */\n readonly walletId: WalletId;\n readonly activityType: ActivityType;\n readonly occurredAt: IsoTimestamp;\n readonly amount: TokenSubunitString;\n readonly source: TokenSource;\n readonly beneficiaryAccountId?: AccountId;\n readonly maskedReference?: string;\n readonly sourceLabel: string;\n}\n\n/** Economically effective or read-model-derived reversal activity. */\nexport interface EconomicWalletActivityEntryV1 extends WalletActivityBaseV1 {\n readonly entryKind: \"economic\";\n readonly transactionId: TransactionId;\n readonly status: EconomicActivityStatusV1;\n}\n\n/**\n * Non-economic accepted/failed work. Its amount is display context only and is\n * excluded from balances and lifetime aggregates.\n */\nexport interface WorkflowWalletActivityEntryV1 extends WalletActivityBaseV1 {\n readonly entryKind: \"workflow\";\n readonly commandId: string;\n readonly status: WorkflowActivityStatusV1;\n}\n\nexport type WalletActivityEntryV1 =\n | EconomicWalletActivityEntryV1\n | WorkflowWalletActivityEntryV1;\n\nexport interface WalletActivityFilterV1 {\n readonly activityTypes?: readonly ActivityType[];\n readonly statuses?: readonly WalletActivityStatusV1[];\n readonly sources?: readonly TokenSource[];\n readonly beneficiaryAccountId?: AccountId;\n readonly fromInclusive?: IsoTimestamp;\n readonly toExclusive?: IsoTimestamp;\n}\n\nexport interface WalletActivityPageRequestV1 {\n readonly limit: number;\n readonly cursor?: string;\n readonly filter?: WalletActivityFilterV1;\n}\n\nexport interface WalletActivityPageV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly entries: readonly WalletActivityEntryV1[];\n readonly hasMore: boolean;\n readonly nextCursor?: string;\n}\n\nconst ACTIVITY_TYPES = new Set<ActivityType>([\n \"purchase\",\n \"subscription\",\n \"rewarded-ad\",\n \"offerwall\",\n \"allocation\",\n \"boost\",\n \"reclaim\",\n \"spend\",\n \"hold\",\n \"refund\",\n \"chargeback\",\n \"adjustment\",\n \"reversal\",\n \"event\",\n \"competition\",\n]);\nconst ACTIVITY_STATUSES = new Set<WalletActivityStatusV1>([\n \"pending\",\n \"held\",\n \"settled\",\n \"reversed\",\n \"failed\",\n]);\nconst ACTIVITY_SOURCES = new Set<TokenSource>([\n \"shopify\",\n \"ayet\",\n \"bitlabs\",\n \"subscription\",\n \"event\",\n \"competition\",\n \"adjustment\",\n]);\nconst PORTFOLIO_ROLES = new Set<WalletPortfolioComponentRole>([\n \"household-treasury\",\n \"personal\",\n \"gameplay-allocation\",\n \"hold\",\n]);\n\nfunction hasControlCharacters(value: string): boolean {\n return [...value].some((character) => {\n const code = character.charCodeAt(0);\n return code <= 31 || code === 127;\n });\n}\n\nfunction assertSafeDisplayString(value: string, label: string): void {\n economyAssert(\n typeof value === \"string\" &&\n value.trim().length > 0 &&\n value.length <= 128 &&\n !hasControlCharacters(value),\n \"INVALID_CONTRACT\",\n `${label} must be bounded and safe for display`,\n );\n}\n\nfunction assertOpaqueCursor(value: string): void {\n economyAssert(\n typeof value === \"string\" &&\n value.length > 0 &&\n value.length <= 512 &&\n !hasControlCharacters(value),\n \"INVALID_CONTRACT\",\n \"Activity cursor must be a bounded opaque value\",\n );\n}\n\nfunction assertUniqueValues<T extends string>(\n values: readonly T[],\n allowed: ReadonlySet<T>,\n label: string,\n): void {\n const unique = new Set(values);\n economyAssert(\n values.length > 0 &&\n values.length === unique.size &&\n values.every((value) => allowed.has(value)),\n \"INVALID_CONTRACT\",\n `${label} must contain unique supported values`,\n );\n}\n\n/** Validates a server-created, bounded portfolio scope. */\nexport function assertWalletPortfolioReadScope(\n scope: WalletPortfolioReadScopeV1,\n): void {\n economyAssert(\n scope.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported wallet-portfolio scope contract version\",\n );\n assertEconomyIdentifier(scope.portfolioId, \"portfolioId\");\n assertEconomyIdentifier(scope.subjectAccountId, \"subjectAccountId\");\n economyAssert(\n scope.components.length > 0 && scope.components.length <= 100,\n \"INVALID_CONTRACT\",\n \"Wallet portfolio must contain between one and 100 components\",\n );\n const walletIds = new Set<string>();\n for (const component of scope.components) {\n assertEconomyIdentifier(component.walletId, \"walletId\");\n economyAssert(\n PORTFOLIO_ROLES.has(component.role),\n \"INVALID_CONTRACT\",\n \"Wallet portfolio component has an unsupported role\",\n );\n economyAssert(\n !walletIds.has(component.walletId),\n \"DUPLICATE_IDENTIFIER\",\n \"Wallet portfolio cannot repeat a wallet\",\n );\n walletIds.add(component.walletId);\n if (component.beneficiaryAccountId !== undefined) {\n assertEconomyIdentifier(\n component.beneficiaryAccountId,\n \"beneficiaryAccountId\",\n );\n }\n economyAssert(\n component.role !== \"gameplay-allocation\" ||\n component.beneficiaryAccountId !== undefined,\n \"INVALID_CONTRACT\",\n \"Gameplay-allocation portfolio components require a beneficiary\",\n );\n }\n}\n\n/** Validates a self-identifying wallet lifetime read. */\nexport function assertWalletLifetimeSnapshot(\n snapshot: WalletLifetimeSnapshotV1,\n): void {\n economyAssert(\n snapshot.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported wallet-lifetime-snapshot contract version\",\n );\n assertEconomyIdentifier(snapshot.walletId, \"walletId\");\n assertWalletLifetimeTotals(snapshot.totals);\n economyAssert(\n Number.isSafeInteger(snapshot.version) && snapshot.version >= 1,\n \"INVALID_CONTRACT\",\n \"Wallet lifetime version must be a positive safe integer\",\n );\n parseIsoTimestamp(snapshot.asOf);\n}\n\nfunction assertPortfolioComponentMatch(\n expected: WalletPortfolioComponentScopeV1,\n actual: WalletPortfolioComponentScopeV1,\n): void {\n economyAssert(\n expected.walletId === actual.walletId &&\n expected.role === actual.role &&\n expected.beneficiaryAccountId === actual.beneficiaryAccountId,\n \"INVALID_CONTRACT\",\n \"Portfolio result component does not match its authorized read scope\",\n );\n}\n\n/**\n * Constructs a portfolio balance without merging wallet identities or\n * promoting sub-Token progress across policy boundaries.\n */\nexport function createWalletPortfolioSummary(\n scope: WalletPortfolioReadScopeV1,\n components: readonly WalletPortfolioBalanceComponentV1[],\n asOf: IsoTimestamp,\n): WalletPortfolioSummaryV1 {\n assertWalletPortfolioReadScope(scope);\n parseIsoTimestamp(asOf);\n economyAssert(\n components.length === scope.components.length,\n \"INVALID_CONTRACT\",\n \"Portfolio balance must include every authorized component exactly once\",\n );\n const byWallet = new Map(components.map((item) => [item.walletId, item]));\n economyAssert(\n byWallet.size === components.length,\n \"DUPLICATE_IDENTIFIER\",\n \"Portfolio balance cannot repeat a wallet\",\n );\n\n const ordered = scope.components.map((expected) => {\n const actual = byWallet.get(expected.walletId);\n economyAssert(\n actual !== undefined,\n \"INVALID_CONTRACT\",\n \"Portfolio balance is missing an authorized wallet\",\n );\n assertPortfolioComponentMatch(expected, actual);\n assertDeterministicWalletBalanceSummary(actual.summary);\n economyAssert(\n actual.summary.walletId === actual.walletId &&\n actual.summary.asOf === asOf,\n \"INVALID_CONTRACT\",\n \"Portfolio component summary must identify its wallet and shared snapshot time\",\n );\n return actual;\n });\n\n const totals: WalletBalanceTotalsV1 = {\n available: serializeTokenSubunits(\n ordered.reduce(\n (sum, item) => sum + parseTokenSubunits(item.summary.available),\n 0n,\n ),\n ),\n reserved: serializeTokenSubunits(\n ordered.reduce(\n (sum, item) => sum + parseTokenSubunits(item.summary.reserved),\n 0n,\n ),\n ),\n held: serializeTokenSubunits(\n ordered.reduce(\n (sum, item) => sum + parseTokenSubunits(item.summary.held),\n 0n,\n ),\n ),\n rewardProgress: serializeTokenSubunits(\n ordered.reduce(\n (sum, item) => sum + parseTokenSubunits(item.summary.rewardProgress),\n 0n,\n ),\n ),\n };\n return {\n schemaVersion: ECONOMY_CONTRACT_VERSION,\n portfolioId: scope.portfolioId,\n subjectAccountId: scope.subjectAccountId,\n components: ordered,\n totals,\n asOf,\n };\n}\n\n/** Validates a portfolio balance read independently of its producing adapter. */\nexport function assertWalletPortfolioSummary(\n summary: WalletPortfolioSummaryV1,\n): void {\n const scope: WalletPortfolioReadScopeV1 = {\n schemaVersion: summary.schemaVersion,\n portfolioId: summary.portfolioId,\n subjectAccountId: summary.subjectAccountId,\n components: summary.components.map(\n ({ walletId, role, beneficiaryAccountId }) => ({\n walletId,\n role,\n ...(beneficiaryAccountId === undefined\n ? {}\n : { beneficiaryAccountId }),\n }),\n ),\n };\n const rebuilt = createWalletPortfolioSummary(\n scope,\n summary.components,\n summary.asOf,\n );\n for (const field of [\n \"available\",\n \"reserved\",\n \"held\",\n \"rewardProgress\",\n ] as const) {\n economyAssert(\n summary.totals[field] === rebuilt.totals[field],\n \"INVALID_CONTRACT\",\n \"Portfolio balance totals must equal their component column sums\",\n );\n }\n}\n\n/** Builds monotonic lifetime totals while retaining per-wallet components. */\nexport function createWalletPortfolioLifetime(\n scope: WalletPortfolioReadScopeV1,\n components: readonly WalletPortfolioLifetimeComponentV1[],\n asOf: IsoTimestamp,\n): WalletPortfolioLifetimeV1 {\n assertWalletPortfolioReadScope(scope);\n parseIsoTimestamp(asOf);\n economyAssert(\n components.length === scope.components.length,\n \"INVALID_CONTRACT\",\n \"Portfolio lifetime must include every authorized component exactly once\",\n );\n const byWallet = new Map(components.map((item) => [item.walletId, item]));\n economyAssert(\n byWallet.size === components.length,\n \"DUPLICATE_IDENTIFIER\",\n \"Portfolio lifetime cannot repeat a wallet\",\n );\n const ordered = scope.components.map((expected) => {\n const actual = byWallet.get(expected.walletId);\n economyAssert(\n actual !== undefined,\n \"INVALID_CONTRACT\",\n \"Portfolio lifetime is missing an authorized wallet\",\n );\n assertPortfolioComponentMatch(expected, actual);\n assertWalletLifetimeSnapshot(actual.snapshot);\n economyAssert(\n actual.snapshot.walletId === actual.walletId &&\n actual.snapshot.asOf === asOf,\n \"INVALID_CONTRACT\",\n \"Portfolio lifetime component must identify its wallet and shared snapshot time\",\n );\n return actual;\n });\n const sumField = (\n field: Exclude<keyof WalletLifetimeTotalsV1, \"schemaVersion\">,\n ): TokenSubunitString =>\n serializeTokenSubunits(\n ordered.reduce(\n (sum, item) => sum + parseTokenSubunits(item.snapshot.totals[field]),\n 0n,\n ),\n );\n const totals: WalletLifetimeTotalsV1 = {\n schemaVersion: ECONOMY_CONTRACT_VERSION,\n bought: sumField(\"bought\"),\n earned: sumField(\"earned\"),\n allocated: sumField(\"allocated\"),\n reclaimed: sumField(\"reclaimed\"),\n spent: sumField(\"spent\"),\n reversed: sumField(\"reversed\"),\n };\n assertWalletLifetimeTotals(totals);\n return {\n schemaVersion: ECONOMY_CONTRACT_VERSION,\n portfolioId: scope.portfolioId,\n subjectAccountId: scope.subjectAccountId,\n components: ordered,\n totals,\n asOf,\n };\n}\n\n/** Validates a portfolio lifetime read independently of its producing adapter. */\nexport function assertWalletPortfolioLifetime(\n lifetime: WalletPortfolioLifetimeV1,\n): void {\n const scope: WalletPortfolioReadScopeV1 = {\n schemaVersion: lifetime.schemaVersion,\n portfolioId: lifetime.portfolioId,\n subjectAccountId: lifetime.subjectAccountId,\n components: lifetime.components.map(\n ({ walletId, role, beneficiaryAccountId }) => ({\n walletId,\n role,\n ...(beneficiaryAccountId === undefined\n ? {}\n : { beneficiaryAccountId }),\n }),\n ),\n };\n const rebuilt = createWalletPortfolioLifetime(\n scope,\n lifetime.components,\n lifetime.asOf,\n );\n for (const field of [\n \"bought\",\n \"earned\",\n \"allocated\",\n \"reclaimed\",\n \"spent\",\n \"reversed\",\n ] as const) {\n economyAssert(\n lifetime.totals[field] === rebuilt.totals[field],\n \"INVALID_CONTRACT\",\n \"Portfolio lifetime totals must equal their component column sums\",\n );\n }\n}\n\n/** Validates the economic/workflow activity discriminant and safe display data. */\nexport function assertWalletActivityEntry(\n entry: WalletActivityEntryV1,\n): void {\n economyAssert(\n entry.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported wallet-activity contract version\",\n );\n assertEconomyIdentifier(entry.activityId, \"activityId\");\n assertEconomyIdentifier(entry.walletId, \"walletId\");\n economyAssert(\n ACTIVITY_TYPES.has(entry.activityType) &&\n ACTIVITY_STATUSES.has(entry.status) &&\n ACTIVITY_SOURCES.has(entry.source),\n \"INVALID_CONTRACT\",\n \"Wallet activity type, status, or source is unsupported\",\n );\n parseIsoTimestamp(entry.occurredAt);\n economyAssert(\n parseTokenSubunits(entry.amount) !== 0n,\n \"INVALID_AMOUNT\",\n \"Wallet activity amount cannot be zero\",\n );\n if (entry.beneficiaryAccountId !== undefined) {\n assertEconomyIdentifier(\n entry.beneficiaryAccountId,\n \"beneficiaryAccountId\",\n );\n }\n if (entry.maskedReference !== undefined) {\n assertSafeDisplayString(entry.maskedReference, \"Masked reference\");\n }\n assertSafeDisplayString(entry.sourceLabel, \"Source label\");\n economyAssert(\n entry.entryKind === \"economic\" || entry.entryKind === \"workflow\",\n \"INVALID_CONTRACT\",\n \"Wallet activity has an unsupported entry kind\",\n );\n if (entry.entryKind === \"economic\") {\n assertEconomyIdentifier(entry.transactionId, \"transactionId\");\n economyAssert(\n entry.status === \"held\" ||\n entry.status === \"settled\" ||\n entry.status === \"reversed\",\n \"INVALID_CONTRACT\",\n \"Economic activity cannot use a workflow status\",\n );\n } else {\n assertEconomyIdentifier(entry.commandId, \"commandId\");\n economyAssert(\n entry.status === \"pending\" || entry.status === \"failed\",\n \"INVALID_CONTRACT\",\n \"Workflow activity cannot use an economic status\",\n );\n }\n}\n\n/** Validates bounded filters and opaque cursor input. */\nexport function assertWalletActivityPageRequest(\n request: WalletActivityPageRequestV1,\n): void {\n economyAssert(\n Number.isSafeInteger(request.limit) &&\n request.limit >= 1 &&\n request.limit <= 100,\n \"INVALID_CONTRACT\",\n \"Activity page limit must be between one and 100\",\n );\n if (request.cursor !== undefined) {\n assertOpaqueCursor(request.cursor);\n }\n const filter = request.filter;\n if (filter === undefined) {\n return;\n }\n if (filter.activityTypes !== undefined) {\n assertUniqueValues(filter.activityTypes, ACTIVITY_TYPES, \"Activity types\");\n }\n if (filter.statuses !== undefined) {\n assertUniqueValues(filter.statuses, ACTIVITY_STATUSES, \"Activity statuses\");\n }\n if (filter.sources !== undefined) {\n assertUniqueValues(filter.sources, ACTIVITY_SOURCES, \"Activity sources\");\n }\n if (filter.beneficiaryAccountId !== undefined) {\n assertEconomyIdentifier(\n filter.beneficiaryAccountId,\n \"beneficiaryAccountId\",\n );\n }\n const from =\n filter.fromInclusive === undefined\n ? undefined\n : parseIsoTimestamp(filter.fromInclusive);\n const to =\n filter.toExclusive === undefined\n ? undefined\n : parseIsoTimestamp(filter.toExclusive);\n economyAssert(\n from === undefined || to === undefined || from < to,\n \"INVALID_TIME_WINDOW\",\n \"Activity filter start must precede its exclusive end\",\n );\n}\n\n/**\n * Validates stable descending `(occurredAt, activityId)` page order and cursor\n * presence. Cursors remain opaque to this provider-neutral package.\n */\nexport function assertWalletActivityPage(page: WalletActivityPageV1): void {\n economyAssert(\n page.schemaVersion === ECONOMY_CONTRACT_VERSION &&\n typeof page.hasMore === \"boolean\",\n \"INVALID_CONTRACT\",\n \"Unsupported wallet-activity-page contract\",\n );\n economyAssert(\n page.hasMore === (page.nextCursor !== undefined),\n \"INVALID_CONTRACT\",\n \"Activity page cursor must be present exactly when more rows exist\",\n );\n economyAssert(\n page.entries.length <= 100 && (!page.hasMore || page.entries.length > 0),\n \"INVALID_CONTRACT\",\n \"Activity pages are bounded and cannot advertise more rows from an empty page\",\n );\n if (page.nextCursor !== undefined) {\n assertOpaqueCursor(page.nextCursor);\n }\n const activityIds = new Set<string>();\n let previous: WalletActivityEntryV1 | undefined;\n for (const entry of page.entries) {\n assertWalletActivityEntry(entry);\n economyAssert(\n !activityIds.has(entry.activityId),\n \"DUPLICATE_IDENTIFIER\",\n \"Activity page cannot repeat an activity ID\",\n );\n activityIds.add(entry.activityId);\n if (previous !== undefined) {\n const previousTime = parseIsoTimestamp(previous.occurredAt);\n const currentTime = parseIsoTimestamp(entry.occurredAt);\n economyAssert(\n previousTime > currentTime ||\n (previousTime === currentTime &&\n previous.activityId.localeCompare(entry.activityId) > 0),\n \"INVALID_CONTRACT\",\n \"Activity page must use stable descending time and ID order\",\n );\n }\n previous = entry;\n }\n}\n\n/** Prevents an activity cursor/result from expanding an authorized portfolio. */\nexport function assertWalletActivityPageForPortfolio(\n page: WalletActivityPageV1,\n scope: WalletPortfolioReadScopeV1,\n): void {\n assertWalletActivityPage(page);\n assertWalletPortfolioReadScope(scope);\n const walletIds = new Set(scope.components.map((item) => item.walletId));\n economyAssert(\n page.entries.every((entry) => walletIds.has(entry.walletId)),\n \"INVALID_CONTRACT\",\n \"Portfolio activity contains a wallet outside its authorized read scope\",\n );\n}\n\n/** Read-only adapter boundary; authorization must precede scope construction. */\nexport interface EconomyQueryPortV1 {\n getWalletSummary(walletId: WalletId): Promise<WalletBalanceSummaryV1 | null>;\n getWalletLifetime(\n walletId: WalletId,\n ): Promise<WalletLifetimeSnapshotV1 | null>;\n listWalletActivity(\n walletId: WalletId,\n request: WalletActivityPageRequestV1,\n ): Promise<WalletActivityPageV1>;\n getPortfolioSummary(\n scope: WalletPortfolioReadScopeV1,\n ): Promise<WalletPortfolioSummaryV1>;\n getPortfolioLifetime(\n scope: WalletPortfolioReadScopeV1,\n ): Promise<WalletPortfolioLifetimeV1>;\n listPortfolioActivity(\n scope: WalletPortfolioReadScopeV1,\n request: WalletActivityPageRequestV1,\n ): Promise<WalletActivityPageV1>;\n}\n","import {\n ECONOMY_CONTRACT_VERSION,\n assertEconomyIdentifier,\n parseIsoTimestamp,\n type EconomyContractVersion,\n type IsoTimestamp,\n} from \"./contracts.js\";\nimport {\n isWholeTokenAmount,\n parseTokenSubunits,\n serializeTokenSubunits,\n type TokenSubunitString,\n} from \"./amount.js\";\nimport { economyAssert } from \"./errors.js\";\n\nexport type RecurrenceInterval = \"daily\" | \"weekly\" | \"monthly\";\n\n/** Provider-neutral subscription contract. Site policy controls enablement. */\nexport interface TokenSubscriptionPlanV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly planId: string;\n readonly catalogVersion: string;\n readonly interval: RecurrenceInterval;\n readonly priceMinorUnits: string;\n readonly currency: \"GBP\";\n readonly grantAmount: TokenSubunitString;\n readonly enabled: boolean;\n readonly effectiveFrom: IsoTimestamp;\n}\n\n/** Future convenience plan contract; disabled until public spend is live. */\nexport const BASELINE_MONTHLY_SUBSCRIPTION_PLAN: TokenSubscriptionPlanV1 =\n Object.freeze({\n schemaVersion: ECONOMY_CONTRACT_VERSION,\n planId: \"monthly-10-100-v1\",\n catalogVersion: \"gbp-subscriptions-v1\",\n interval: \"monthly\",\n priceMinorUnits: \"1000\",\n currency: \"GBP\",\n grantAmount: serializeTokenSubunits(100_000n),\n enabled: false,\n effectiveFrom: \"2026-07-15T00:00:00.000Z\",\n });\n\n/** Validates future provider-neutral recurrence without enabling it. */\nexport function assertTokenSubscriptionPlan(\n plan: TokenSubscriptionPlanV1,\n): void {\n economyAssert(\n plan.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported subscription-plan contract version\",\n );\n assertEconomyIdentifier(plan.planId, \"planId\");\n assertEconomyIdentifier(plan.catalogVersion, \"catalogVersion\");\n economyAssert(\n [\"daily\", \"weekly\", \"monthly\"].includes(plan.interval) &&\n plan.currency === \"GBP\" &&\n typeof plan.enabled === \"boolean\",\n \"INVALID_CONTRACT\",\n \"Subscription recurrence, currency, or enabled state is invalid\",\n );\n economyAssert(\n /^(?:0|[1-9][0-9]*)$/u.test(plan.priceMinorUnits) &&\n BigInt(plan.priceMinorUnits) > 0n,\n \"INVALID_AMOUNT\",\n \"Subscription price must be a positive integer minor-unit string\",\n );\n const grantAmount = parseTokenSubunits(plan.grantAmount);\n economyAssert(\n grantAmount > 0n && isWholeTokenAmount(grantAmount),\n \"AMOUNT_NOT_WHOLE_TOKEN\",\n \"Subscription grants must contain whole Tokens\",\n );\n parseIsoTimestamp(plan.effectiveFrom);\n}\n","import { parseTokenSubunits, type TokenSubunitString } from \"./amount.js\";\nimport {\n ECONOMY_CONTRACT_VERSION,\n assertEconomyIdentifier,\n parseIsoTimestamp,\n type AccountId,\n type AllocationId,\n type EconomyContractVersion,\n type IsoTimestamp,\n type TransactionId,\n} from \"./contracts.js\";\nimport { economyAssert } from \"./errors.js\";\n\nexport type SpendRequestPurpose = \"gameplay-conversion\" | \"non-gameplay\";\nexport type SpendRequestStatus =\n | \"requested\"\n | \"approved\"\n | \"rejected\"\n | \"expired\"\n | \"executed\"\n | \"cancelled\";\n\n/** Future child request; baseline adapters must reject creation while disabled. */\nexport interface SpendRequestV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly requestId: string;\n readonly childAccountId: AccountId;\n readonly allocationId: AllocationId;\n readonly purpose: SpendRequestPurpose;\n readonly amount: TokenSubunitString;\n readonly status: SpendRequestStatus;\n readonly requestedAt: IsoTimestamp;\n readonly expiresAt: IsoTimestamp;\n readonly decidedByAccountId?: AccountId;\n readonly decidedAt?: IsoTimestamp;\n readonly approvalNonceHash?: string;\n readonly resultingTransactionId?: TransactionId;\n}\n\n/** Validates future child requests while creation remains policy-disabled. */\nexport function assertSpendRequest(request: SpendRequestV1): void {\n economyAssert(\n request.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported spend-request contract version\",\n );\n assertEconomyIdentifier(request.requestId, \"requestId\");\n assertEconomyIdentifier(request.childAccountId, \"childAccountId\");\n assertEconomyIdentifier(request.allocationId, \"allocationId\");\n economyAssert(\n request.purpose === \"gameplay-conversion\" ||\n request.purpose === \"non-gameplay\",\n \"INVALID_CONTRACT\",\n \"Spend request has an unsupported purpose\",\n );\n economyAssert(\n [\n \"requested\",\n \"approved\",\n \"rejected\",\n \"expired\",\n \"executed\",\n \"cancelled\",\n ].includes(request.status),\n \"INVALID_CONTRACT\",\n \"Spend request has an unsupported status\",\n );\n economyAssert(\n parseTokenSubunits(request.amount) > 0n,\n \"INVALID_AMOUNT\",\n \"Spend-request amount must be positive\",\n );\n const requestedAt = parseIsoTimestamp(request.requestedAt);\n const expiresAt = parseIsoTimestamp(request.expiresAt);\n economyAssert(\n expiresAt > requestedAt,\n \"INVALID_TIME_WINDOW\",\n \"Spend-request expiry must follow creation\",\n );\n\n const decisionRequired = [\"approved\", \"rejected\", \"executed\"].includes(\n request.status,\n );\n economyAssert(\n !decisionRequired ||\n (request.decidedByAccountId !== undefined &&\n request.decidedAt !== undefined),\n \"INVALID_CONTRACT\",\n \"Decided spend requests require a guardian actor and timestamp\",\n );\n if (request.decidedByAccountId !== undefined) {\n assertEconomyIdentifier(request.decidedByAccountId, \"decidedByAccountId\");\n }\n if (request.decidedAt !== undefined) {\n const decidedAt = parseIsoTimestamp(request.decidedAt);\n economyAssert(\n decidedAt >= requestedAt && decidedAt <= expiresAt,\n \"INVALID_TIME_WINDOW\",\n \"Spend-request decision must occur before expiry\",\n );\n }\n if (request.approvalNonceHash !== undefined) {\n economyAssert(\n /^sha256:[a-f0-9]{64}$/u.test(request.approvalNonceHash),\n \"INVALID_CONTRACT\",\n \"Approval nonces must be stored as SHA-256 hashes\",\n );\n }\n if (request.status === \"approved\" || request.status === \"executed\") {\n economyAssert(\n request.approvalNonceHash !== undefined,\n \"INVALID_CONTRACT\",\n \"Approved spend requests require a one-time approval nonce hash\",\n );\n }\n if (request.resultingTransactionId !== undefined) {\n assertEconomyIdentifier(\n request.resultingTransactionId,\n \"resultingTransactionId\",\n );\n economyAssert(\n request.status === \"executed\",\n \"INVALID_CONTRACT\",\n \"Only executed spend requests may reference a ledger transaction\",\n );\n }\n}\n"],"mappings":"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","names":["assertCanonicalHash","ACTIVITY_TYPES","ACTIVITY_STATUSES","ACTIVITY_SOURCES","hasControlCharacters"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/amount.ts","../src/canonical-order.ts","../src/contracts.ts","../src/acquisition.ts","../src/allocations.ts","../src/early-backers.ts","../src/ledger.ts","../src/integrity.ts","../src/lots.ts","../src/module-allowances.ts","../src/operations.ts","../src/paid-lots.ts","../src/ports/persistence.ts","../src/wallets.ts","../src/projection.ts","../src/ports/query.ts","../src/purchase-caps.ts","../src/purchase-intents.ts","../src/recurrence.ts","../src/spend-requests.ts"],"sourcesContent":["export * from \"./acquisition.js\";\nexport * from \"./allocations.js\";\nexport * from \"./amount.js\";\nexport * from \"./contracts.js\";\nexport * from \"./early-backers.js\";\nexport * from \"./errors.js\";\nexport * from \"./integrity.js\";\nexport * from \"./ledger.js\";\nexport * from \"./lots.js\";\nexport * from \"./module-allowances.js\";\nexport * from \"./operations.js\";\nexport * from \"./paid-lots.js\";\nexport * from \"./ports/persistence.js\";\nexport * from \"./ports/query.js\";\nexport * from \"./projection.js\";\nexport * from \"./purchase-caps.js\";\nexport * from \"./purchase-intents.js\";\nexport * from \"./recurrence.js\";\nexport * from \"./spend-requests.js\";\nexport * from \"./wallets.js\";\n","/** Stable machine-readable failures exposed by the economy domain. */\nexport type EconomyErrorCode =\n | \"INVALID_AMOUNT\"\n | \"AMOUNT_OUT_OF_RANGE\"\n | \"AMOUNT_NOT_WHOLE_TOKEN\"\n | \"INVALID_CONTRACT\"\n | \"UNBALANCED_TRANSACTION\"\n | \"DUPLICATE_IDENTIFIER\"\n | \"DUPLICATE_TRANSACTION\"\n | \"INSUFFICIENT_BALANCE\"\n | \"INSUFFICIENT_ELIGIBLE_LOTS\"\n | \"SOURCE_LOT_RESTRICTED\"\n | \"REVERSAL_ALREADY_EXISTS\"\n | \"NEGATIVE_PROJECTION\"\n | \"INVALID_TIME_WINDOW\";\n\nexport interface EconomyErrorEnvelopeV1 {\n readonly schemaVersion: \"1\";\n readonly error: {\n readonly code: EconomyErrorCode;\n readonly message: string;\n readonly requestId?: string;\n };\n}\n\n/**\n * Domain error with a stable code and deliberately non-sensitive message.\n * Provider evidence, identities, and payment details must not be included.\n */\nexport class EconomyError extends Error {\n readonly code: EconomyErrorCode;\n\n constructor(code: EconomyErrorCode, message: string) {\n super(message);\n this.name = \"EconomyError\";\n this.code = code;\n }\n}\n\n/** Throws a stable economy error when a domain assertion fails. */\nexport function economyAssert(\n condition: unknown,\n code: EconomyErrorCode,\n message: string,\n): asserts condition {\n if (!condition) {\n throw new EconomyError(code, message);\n }\n}\n\n/** Creates a bounded, non-sensitive error contract for an HTTP adapter. */\nexport function toEconomyErrorEnvelope(\n error: EconomyError,\n requestId?: string,\n): EconomyErrorEnvelopeV1 {\n return {\n schemaVersion: \"1\",\n error: {\n code: error.code,\n message: error.message.slice(0, 256),\n ...(requestId === undefined ? {} : { requestId }),\n },\n };\n}\n","import { EconomyError, economyAssert } from \"./errors.js\";\n\n/** Number of indivisible subunits in one public Token. */\nexport const TOKEN_SUBUNITS_PER_TOKEN = 1_000n;\n\n/** PostgreSQL-compatible signed bigint bounds. */\nexport const TOKEN_SUBUNITS_MIN = -(2n ** 63n);\nexport const TOKEN_SUBUNITS_MAX = 2n ** 63n - 1n;\n\ndeclare const tokenSubunitStringBrand: unique symbol;\n\n/** Canonical base-10 representation used at JSON and persistence boundaries. */\nexport type TokenSubunitString = string & {\n readonly [tokenSubunitStringBrand]: \"TokenSubunitString\";\n};\n\nconst CANONICAL_INTEGER = /^(?:0|-?[1-9][0-9]*)$/u;\n\nfunction assertInRange(amount: bigint): void {\n economyAssert(\n amount >= TOKEN_SUBUNITS_MIN && amount <= TOKEN_SUBUNITS_MAX,\n \"AMOUNT_OUT_OF_RANGE\",\n \"TokenSubunit amount is outside the signed 64-bit range\",\n );\n}\n\n/** Parses a canonical base-10 TokenSubunit string without floating point. */\nexport function parseTokenSubunits(value: string): bigint {\n economyAssert(\n typeof value === \"string\" && CANONICAL_INTEGER.test(value),\n \"INVALID_AMOUNT\",\n \"TokenSubunit amount must be a canonical base-10 integer string\",\n );\n\n try {\n const amount = BigInt(value);\n assertInRange(amount);\n return amount;\n } catch (error) {\n if (error instanceof EconomyError) {\n throw error;\n }\n throw new EconomyError(\"INVALID_AMOUNT\", \"TokenSubunit amount is invalid\");\n }\n}\n\n/** Serializes a signed 64-bit TokenSubunit amount to canonical base-10. */\nexport function serializeTokenSubunits(amount: bigint): TokenSubunitString {\n assertInRange(amount);\n return amount.toString(10) as TokenSubunitString;\n}\n\n/** Converts an exact whole-Token integer into TokenSubunits. */\nexport function wholeTokensToSubunits(tokens: bigint): bigint {\n const amount = tokens * TOKEN_SUBUNITS_PER_TOKEN;\n assertInRange(amount);\n return amount;\n}\n\n/** Returns true when a subunit amount represents an exact whole Token. */\nexport function isWholeTokenAmount(amount: bigint): boolean {\n return amount % TOKEN_SUBUNITS_PER_TOKEN === 0n;\n}\n\n/** Converts TokenSubunits to whole Tokens, rejecting fractional progress. */\nexport function subunitsToWholeTokens(amount: bigint): bigint {\n economyAssert(\n isWholeTokenAmount(amount),\n \"AMOUNT_NOT_WHOLE_TOKEN\",\n \"Amount must contain whole Tokens\",\n );\n return amount / TOKEN_SUBUNITS_PER_TOKEN;\n}\n\n/** Sums amount strings with signed 64-bit overflow protection. */\nexport function sumTokenSubunits(values: readonly string[]): bigint {\n let total = 0n;\n for (const value of values) {\n total += parseTokenSubunits(value);\n assertInRange(total);\n }\n return total;\n}\n","/**\n * Compares strings using locale-independent ECMAScript UTF-16 code-unit order.\n *\n * Canonical transaction identifiers and metadata keys use a validated ASCII\n * alphabet, so this ordering is byte-for-byte equivalent to PostgreSQL\n * `COLLATE \"C\"` for those fields.\n */\nexport function compareUnicodeCodeUnits(left: string, right: string): number {\n if (left === right) {\n return 0;\n }\n return left < right ? -1 : 1;\n}\n","import { compareUnicodeCodeUnits } from \"./canonical-order.js\";\nimport { economyAssert } from \"./errors.js\";\n\nexport const ECONOMY_CONTRACT_VERSION = \"1\" as const;\nexport type EconomyContractVersion = typeof ECONOMY_CONTRACT_VERSION;\n\nexport type AccountId = string;\nexport type AllocationId = string;\nexport type HouseholdId = string;\nexport type LearningEntitlementId = string;\nexport type LearningModuleVersionId = string;\nexport type LotId = string;\nexport type ModuleAllowanceId = string;\nexport type ModuleSpendHoldId = string;\nexport type ModuleSpendQuoteId = string;\nexport type PostingId = string;\nexport type ProviderEventId = string;\nexport type TransactionId = string;\nexport type WalletId = string;\nexport type IsoTimestamp = string;\n\nconst IDENTIFIER = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/u;\n\n/** Validates opaque pseudonymous domain identifiers. */\nexport function assertEconomyIdentifier(\n value: string,\n label = \"identifier\",\n): void {\n economyAssert(\n typeof value === \"string\" && IDENTIFIER.test(value),\n \"INVALID_CONTRACT\",\n `${label} must be a non-empty opaque identifier`,\n );\n}\n\n/** Parses a bounded ISO timestamp and returns milliseconds since epoch. */\nexport function parseIsoTimestamp(value: IsoTimestamp): number {\n economyAssert(\n typeof value === \"string\",\n \"INVALID_CONTRACT\",\n \"Timestamp must be an ISO-8601 UTC value\",\n );\n const match = /^(\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2})(?:\\.(\\d{3}))?Z$/u.exec(\n value,\n );\n economyAssert(\n match !== null,\n \"INVALID_CONTRACT\",\n \"Timestamp must be an ISO-8601 UTC value\",\n );\n const milliseconds = Date.parse(value);\n const base = match[1];\n const fraction = match[2] ?? \"000\";\n economyAssert(\n Number.isFinite(milliseconds) &&\n base !== undefined &&\n new Date(milliseconds).toISOString() === `${base}.${fraction}Z`,\n \"INVALID_CONTRACT\",\n \"Timestamp must be valid\",\n );\n return milliseconds;\n}\n\n/** Returns a new record with keys sorted by locale-independent code units. */\nexport function sortStringRecord(\n value: Readonly<Record<string, string>>,\n): Readonly<Record<string, string>> {\n return Object.fromEntries(\n Object.entries(value).sort(([left], [right]) =>\n compareUnicodeCodeUnits(left, right),\n ),\n );\n}\n","import {\n TOKEN_SUBUNITS_PER_TOKEN,\n isWholeTokenAmount,\n parseTokenSubunits,\n serializeTokenSubunits,\n type TokenSubunitString,\n} from \"./amount.js\";\nimport {\n ECONOMY_CONTRACT_VERSION,\n assertEconomyIdentifier,\n parseIsoTimestamp,\n type AccountId,\n type EconomyContractVersion,\n type HouseholdId,\n type IsoTimestamp,\n type ProviderEventId,\n type WalletId,\n} from \"./contracts.js\";\nimport { economyAssert } from \"./errors.js\";\nimport type { ActivityStatus, ActivityType } from \"./ledger.js\";\n\nexport interface TokenPackV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly packId: string;\n readonly catalogVersion: string;\n readonly currency: \"GBP\";\n readonly priceMinorUnits: string;\n readonly grantAmount: TokenSubunitString;\n readonly active: boolean;\n}\n\n/** Product-copy reference only; it is not a redemption or exchange promise. */\nexport interface TokenReferenceRateV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly rateVersion: string;\n readonly currency: \"GBP\";\n readonly referenceMinorUnitsPerToken: string;\n readonly tokenSubunitsPerToken: string;\n readonly cashRedemptionAllowed: false;\n}\n\nexport const BASELINE_GBP_REFERENCE_RATE: TokenReferenceRateV1 = Object.freeze({\n schemaVersion: ECONOMY_CONTRACT_VERSION,\n rateVersion: \"gbp-reference-v1\",\n currency: \"GBP\",\n referenceMinorUnitsPerToken: \"10\",\n tokenSubunitsPerToken: TOKEN_SUBUNITS_PER_TOKEN.toString(10),\n cashRedemptionAllowed: false,\n});\n\nexport const BASELINE_GBP_CATALOG_VERSION = \"gbp-v1\" as const;\n\n/** Initial flat-price public catalog. Changes require a new catalog version. */\nexport const BASELINE_GBP_TOKEN_PACKS: readonly TokenPackV1[] = Object.freeze([\n Object.freeze({\n schemaVersion: ECONOMY_CONTRACT_VERSION,\n packId: \"gbp_5_50_v1\",\n catalogVersion: BASELINE_GBP_CATALOG_VERSION,\n currency: \"GBP\",\n priceMinorUnits: \"500\",\n grantAmount: serializeTokenSubunits(50_000n),\n active: true,\n }),\n Object.freeze({\n schemaVersion: ECONOMY_CONTRACT_VERSION,\n packId: \"gbp_10_100_v1\",\n catalogVersion: BASELINE_GBP_CATALOG_VERSION,\n currency: \"GBP\",\n priceMinorUnits: \"1000\",\n grantAmount: serializeTokenSubunits(100_000n),\n active: true,\n }),\n Object.freeze({\n schemaVersion: ECONOMY_CONTRACT_VERSION,\n packId: \"gbp_25_250_v1\",\n catalogVersion: BASELINE_GBP_CATALOG_VERSION,\n currency: \"GBP\",\n priceMinorUnits: \"2500\",\n grantAmount: serializeTokenSubunits(250_000n),\n active: true,\n }),\n Object.freeze({\n schemaVersion: ECONOMY_CONTRACT_VERSION,\n packId: \"gbp_50_500_v1\",\n catalogVersion: BASELINE_GBP_CATALOG_VERSION,\n currency: \"GBP\",\n priceMinorUnits: \"5000\",\n grantAmount: serializeTokenSubunits(500_000n),\n active: true,\n }),\n]);\n\nexport interface PurchaseLimitPolicyV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly maxOrderPriceMinorUnits: string;\n readonly rollingPayerPriceMinorUnits: string;\n readonly rollingHouseholdPriceMinorUnits: string;\n readonly rollingDays: number;\n}\n\n/** Default server limits; household controls may only lower these values. */\nexport const BASELINE_PURCHASE_LIMIT_POLICY: PurchaseLimitPolicyV1 =\n Object.freeze({\n schemaVersion: ECONOMY_CONTRACT_VERSION,\n maxOrderPriceMinorUnits: \"5000\",\n rollingPayerPriceMinorUnits: \"10000\",\n rollingHouseholdPriceMinorUnits: \"10000\",\n rollingDays: 30,\n });\n\nexport type PurchaseIntentStatus =\n | \"created\"\n | \"checkout-created\"\n | \"paid-unreconciled\"\n | \"credited\"\n | \"expired\"\n | \"cancelled\"\n | \"disputed\";\n\n/** Short-lived server authority binding checkout facts to a payer/household. */\nexport interface PurchaseIntentV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly intentId: string;\n readonly payerAccountId: AccountId;\n readonly receivingHouseholdId: HouseholdId;\n readonly receivingWalletId: WalletId;\n readonly packId: string;\n readonly catalogVersion: string;\n readonly expectedCurrency: \"GBP\";\n readonly expectedPriceMinorUnits: string;\n readonly grantAmount: TokenSubunitString;\n readonly status: PurchaseIntentStatus;\n readonly createdAt: IsoTimestamp;\n readonly expiresAt: IsoTimestamp;\n readonly providerCheckoutReferenceHash?: string;\n}\n\nexport interface RewardRateV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly rateVersion: string;\n readonly provider: \"ayet\" | \"bitlabs\";\n /** TokenSubunits granted per denominator of authoritative GBP minor units. */\n readonly tokenSubunitsNumerator: string;\n readonly gbpMinorUnitsDenominator: string;\n readonly effectiveFrom: IsoTimestamp;\n readonly effectiveUntil?: IsoTimestamp;\n}\n\nexport interface FxSnapshotV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly snapshotId: string;\n readonly sourceCurrency: string;\n readonly quoteCurrency: \"GBP\";\n /** Exact rational conversion to GBP minor units. */\n readonly gbpMinorUnitsNumerator: string;\n readonly sourceMinorUnitsDenominator: string;\n readonly capturedAt: IsoTimestamp;\n}\n\nexport type RewardConversionStatus =\n | \"pending\"\n | \"completed\"\n | \"reconciled\";\n\nexport type BitLabsConversionState =\n | \"PENDING\"\n | \"COMPLETED\"\n | \"RECONCILED\";\n\nexport interface RewardActivityTransitionV1 {\n readonly conversionStatus: RewardConversionStatus;\n readonly activityType: ActivityType;\n readonly activityStatus: ActivityStatus;\n}\n\nexport interface RewardConversionV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly provider: \"ayet\" | \"bitlabs\";\n readonly providerEventId: ProviderEventId;\n readonly beneficiaryAccountId: AccountId;\n readonly walletId: WalletId;\n readonly status: RewardConversionStatus;\n readonly providerPayoutMinorUnits: string;\n readonly providerCurrency: string;\n readonly gbpMinorUnits: string;\n readonly tokenSubunits: TokenSubunitString;\n readonly rateVersion: string;\n readonly fxSnapshotId: string;\n readonly occurredAt: IsoTimestamp;\n}\n\n/** Validates a minimized, signed-provider conversion record before journaling. */\nexport function assertRewardConversion(\n conversion: RewardConversionV1,\n): void {\n economyAssert(\n conversion.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported reward-conversion contract version\",\n );\n economyAssert(\n conversion.provider === \"ayet\" || conversion.provider === \"bitlabs\",\n \"INVALID_CONTRACT\",\n \"Unsupported reward-conversion provider\",\n );\n assertEconomyIdentifier(conversion.providerEventId, \"providerEventId\");\n assertEconomyIdentifier(\n conversion.beneficiaryAccountId,\n \"beneficiaryAccountId\",\n );\n assertEconomyIdentifier(conversion.walletId, \"walletId\");\n economyAssert(\n [\"pending\", \"completed\", \"reconciled\"].includes(conversion.status),\n \"INVALID_CONTRACT\",\n \"Unsupported reward-conversion status\",\n );\n economyAssert(\n /^[A-Z]{3}$/u.test(conversion.providerCurrency),\n \"INVALID_CONTRACT\",\n \"Reward payout currency must use an uppercase ISO code\",\n );\n economyAssert(\n parseNonNegativeInteger(\n conversion.providerPayoutMinorUnits,\n \"Provider payout\",\n ) > 0n &&\n parseNonNegativeInteger(conversion.gbpMinorUnits, \"GBP payout\") >= 0n &&\n parseTokenSubunits(conversion.tokenSubunits) > 0n,\n \"INVALID_AMOUNT\",\n \"Reward conversion must carry positive payout and Token values\",\n );\n assertEconomyIdentifier(conversion.rateVersion, \"rateVersion\");\n assertEconomyIdentifier(conversion.fxSnapshotId, \"fxSnapshotId\");\n parseIsoTimestamp(conversion.occurredAt);\n}\n\nfunction parseNonNegativeInteger(value: string, label: string): bigint {\n economyAssert(\n /^(?:0|[1-9][0-9]*)$/u.test(value),\n \"INVALID_AMOUNT\",\n `${label} must be a non-negative integer string`,\n );\n return BigInt(value);\n}\n\n/** Validates a paid pack; pack grants are whole Tokens in the baseline. */\nexport function assertTokenPack(pack: TokenPackV1): void {\n economyAssert(\n pack.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported Token pack contract version\",\n );\n assertEconomyIdentifier(pack.packId, \"packId\");\n assertEconomyIdentifier(pack.catalogVersion, \"catalogVersion\");\n economyAssert(\n pack.currency === \"GBP\" && typeof pack.active === \"boolean\",\n \"INVALID_CONTRACT\",\n \"Token packs must use GBP and declare whether they are active\",\n );\n economyAssert(\n parseNonNegativeInteger(pack.priceMinorUnits, \"Pack price\") > 0n,\n \"INVALID_AMOUNT\",\n \"Pack price must be positive\",\n );\n const grant = parseTokenSubunits(pack.grantAmount);\n economyAssert(\n grant > 0n && isWholeTokenAmount(grant),\n \"AMOUNT_NOT_WHOLE_TOKEN\",\n \"Paid pack grants must contain whole Tokens\",\n );\n}\n\n/** Validates nominal reference metadata without creating redemption rights. */\nexport function assertTokenReferenceRate(\n rate: TokenReferenceRateV1,\n): void {\n economyAssert(\n rate.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported Token reference-rate contract version\",\n );\n assertEconomyIdentifier(rate.rateVersion, \"rateVersion\");\n const referenceMinorUnits = parseNonNegativeInteger(\n rate.referenceMinorUnitsPerToken,\n \"Reference minor units per Token\",\n );\n const subunitsPerToken = parseNonNegativeInteger(\n rate.tokenSubunitsPerToken,\n \"TokenSubunits per Token\",\n );\n economyAssert(\n rate.currency === \"GBP\" &&\n referenceMinorUnits > 0n &&\n subunitsPerToken === TOKEN_SUBUNITS_PER_TOKEN &&\n rate.cashRedemptionAllowed === false,\n \"INVALID_CONTRACT\",\n \"Token reference rate must preserve the GBP nominal, subunit, and no-redemption boundary\",\n );\n}\n\n/** Proves that every pack in one catalog uses the same flat nominal ratio. */\nexport function assertFlatTokenCatalog(\n packs: readonly TokenPackV1[],\n referenceRate: TokenReferenceRateV1,\n): void {\n assertTokenReferenceRate(referenceRate);\n economyAssert(\n packs.length > 0,\n \"INVALID_CONTRACT\",\n \"Token catalog must contain at least one pack\",\n );\n const packIds = new Set<string>();\n const catalogVersion = packs[0]?.catalogVersion;\n const referenceMinorUnits = BigInt(\n referenceRate.referenceMinorUnitsPerToken,\n );\n const subunitsPerToken = BigInt(referenceRate.tokenSubunitsPerToken);\n for (const pack of packs) {\n assertTokenPack(pack);\n economyAssert(\n !packIds.has(pack.packId),\n \"DUPLICATE_IDENTIFIER\",\n \"Token catalog pack IDs must be unique\",\n );\n economyAssert(\n pack.catalogVersion === catalogVersion,\n \"INVALID_CONTRACT\",\n \"Token catalog packs must share one catalog version\",\n );\n packIds.add(pack.packId);\n const scaledReference =\n parseTokenSubunits(pack.grantAmount) * referenceMinorUnits;\n economyAssert(\n scaledReference % subunitsPerToken === 0n &&\n scaledReference / subunitsPerToken === BigInt(pack.priceMinorUnits),\n \"INVALID_CONTRACT\",\n \"Token catalog must use the declared flat nominal reference ratio\",\n );\n }\n}\n\n/** Validates server-side order and rolling acquisition ceilings. */\nexport function assertPurchaseLimitPolicy(\n policy: PurchaseLimitPolicyV1,\n): void {\n economyAssert(\n policy.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported purchase-limit contract version\",\n );\n const maxOrder = parseNonNegativeInteger(\n policy.maxOrderPriceMinorUnits,\n \"Maximum order\",\n );\n const payer = parseNonNegativeInteger(\n policy.rollingPayerPriceMinorUnits,\n \"Rolling payer limit\",\n );\n const household = parseNonNegativeInteger(\n policy.rollingHouseholdPriceMinorUnits,\n \"Rolling household limit\",\n );\n economyAssert(\n maxOrder > 0n && payer >= maxOrder && household >= maxOrder,\n \"INVALID_AMOUNT\",\n \"Rolling purchase limits must cover at least one maximum order\",\n );\n economyAssert(\n Number.isSafeInteger(policy.rollingDays) &&\n policy.rollingDays >= 1 &&\n policy.rollingDays <= 365,\n \"INVALID_CONTRACT\",\n \"Purchase-limit rolling window must be a bounded whole-day count\",\n );\n}\n\n/** Validates the immutable server-side facts bound into a purchase intent. */\nexport function assertPurchaseIntentBinding(\n intent: PurchaseIntentV1,\n pack: TokenPackV1,\n): void {\n assertTokenPack(pack);\n economyAssert(\n intent.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported purchase-intent contract version\",\n );\n assertEconomyIdentifier(intent.intentId, \"intentId\");\n assertEconomyIdentifier(intent.payerAccountId, \"payerAccountId\");\n assertEconomyIdentifier(intent.receivingHouseholdId, \"receivingHouseholdId\");\n assertEconomyIdentifier(intent.receivingWalletId, \"receivingWalletId\");\n assertEconomyIdentifier(intent.packId, \"packId\");\n assertEconomyIdentifier(intent.catalogVersion, \"catalogVersion\");\n\n const createdAt = parseIsoTimestamp(intent.createdAt);\n const expiresAt = parseIsoTimestamp(intent.expiresAt);\n economyAssert(\n expiresAt > createdAt,\n \"INVALID_TIME_WINDOW\",\n \"Purchase intent expiry must follow its creation time\",\n );\n economyAssert(\n intent.expectedCurrency === \"GBP\" &&\n intent.packId === pack.packId &&\n intent.catalogVersion === pack.catalogVersion &&\n intent.expectedCurrency === pack.currency &&\n intent.expectedPriceMinorUnits === pack.priceMinorUnits &&\n intent.grantAmount === pack.grantAmount,\n \"INVALID_CONTRACT\",\n \"Purchase intent does not match its authoritative catalog pack\",\n );\n parseNonNegativeInteger(intent.expectedPriceMinorUnits, \"Expected price\");\n parseTokenSubunits(intent.grantAmount);\n economyAssert(\n [\n \"created\",\n \"checkout-created\",\n \"paid-unreconciled\",\n \"credited\",\n \"expired\",\n \"cancelled\",\n \"disputed\",\n ].includes(intent.status),\n \"INVALID_CONTRACT\",\n \"Purchase intent has an unsupported status\",\n );\n if (intent.providerCheckoutReferenceHash !== undefined) {\n economyAssert(\n /^sha256:[a-f0-9]{64}$/u.test(intent.providerCheckoutReferenceHash),\n \"INVALID_CONTRACT\",\n \"Checkout references must be stored as sanitized SHA-256 hashes\",\n );\n }\n}\n\n/** Rejects stale, inactive, or already-consumed intents before checkout creation. */\nexport function assertOpenPurchaseIntent(\n intent: PurchaseIntentV1,\n pack: TokenPackV1,\n checkedAt: IsoTimestamp,\n): void {\n assertPurchaseIntentBinding(intent, pack);\n const checkedAtValue = parseIsoTimestamp(checkedAt);\n economyAssert(\n pack.active &&\n (intent.status === \"created\" || intent.status === \"checkout-created\") &&\n checkedAtValue >= parseIsoTimestamp(intent.createdAt) &&\n checkedAtValue < parseIsoTimestamp(intent.expiresAt),\n \"INVALID_TIME_WINDOW\",\n \"Purchase intent is inactive, expired, or not open for checkout\",\n );\n}\n\nexport function assertRewardRate(rate: RewardRateV1): void {\n economyAssert(\n rate.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported reward-rate contract version\",\n );\n assertEconomyIdentifier(rate.rateVersion, \"rateVersion\");\n economyAssert(\n rate.provider === \"ayet\" || rate.provider === \"bitlabs\",\n \"INVALID_CONTRACT\",\n \"Unsupported reward provider\",\n );\n const effectiveFrom = parseIsoTimestamp(rate.effectiveFrom);\n if (rate.effectiveUntil !== undefined) {\n economyAssert(\n parseIsoTimestamp(rate.effectiveUntil) > effectiveFrom,\n \"INVALID_TIME_WINDOW\",\n \"Reward-rate expiry must follow its effective time\",\n );\n }\n}\n\nexport function assertFxSnapshot(fx: FxSnapshotV1): void {\n economyAssert(\n fx.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported FX snapshot contract version\",\n );\n assertEconomyIdentifier(fx.snapshotId, \"snapshotId\");\n economyAssert(\n /^[A-Z]{3}$/u.test(fx.sourceCurrency) && fx.quoteCurrency === \"GBP\",\n \"INVALID_CONTRACT\",\n \"FX snapshots must convert an ISO currency into GBP\",\n );\n parseIsoTimestamp(fx.capturedAt);\n}\n\n/** Converts provider payout using exact rational FX and rate snapshots. */\nexport function convertRewardPayout(\n providerPayoutMinorUnits: string,\n rate: RewardRateV1,\n fx: FxSnapshotV1,\n): { readonly gbpMinorUnits: string; readonly tokenSubunits: TokenSubunitString } {\n assertRewardRate(rate);\n assertFxSnapshot(fx);\n const payout = parseNonNegativeInteger(\n providerPayoutMinorUnits,\n \"Provider payout\",\n );\n const fxNumerator = parseNonNegativeInteger(\n fx.gbpMinorUnitsNumerator,\n \"FX numerator\",\n );\n const fxDenominator = parseNonNegativeInteger(\n fx.sourceMinorUnitsDenominator,\n \"FX denominator\",\n );\n const tokenNumerator = parseNonNegativeInteger(\n rate.tokenSubunitsNumerator,\n \"Rate numerator\",\n );\n const tokenDenominator = parseNonNegativeInteger(\n rate.gbpMinorUnitsDenominator,\n \"Rate denominator\",\n );\n economyAssert(\n fxDenominator > 0n && tokenDenominator > 0n,\n \"INVALID_AMOUNT\",\n \"FX and reward-rate denominators must be positive\",\n );\n economyAssert(\n fxNumerator > 0n && tokenNumerator > 0n,\n \"INVALID_AMOUNT\",\n \"FX and reward-rate numerators must be positive\",\n );\n\n const gbpMinorUnits = (payout * fxNumerator) / fxDenominator;\n const tokenSubunits = (gbpMinorUnits * tokenNumerator) / tokenDenominator;\n return {\n gbpMinorUnits: gbpMinorUnits.toString(10),\n tokenSubunits: serializeTokenSubunits(tokenSubunits),\n };\n}\n\n/** Maps BitLabs' signed callback state into an immutable journal transition. */\nexport function mapBitLabsConversionState(\n state: string,\n): RewardActivityTransitionV1 {\n const transitions: Readonly<\n Record<BitLabsConversionState, RewardActivityTransitionV1>\n > = {\n PENDING: {\n conversionStatus: \"pending\",\n activityType: \"hold\",\n activityStatus: \"held\",\n },\n COMPLETED: {\n conversionStatus: \"completed\",\n activityType: \"offerwall\",\n activityStatus: \"settled\",\n },\n RECONCILED: {\n conversionStatus: \"reconciled\",\n activityType: \"reversal\",\n activityStatus: \"reversed\",\n },\n };\n const transition = transitions[state as BitLabsConversionState];\n economyAssert(\n transition !== undefined,\n \"INVALID_CONTRACT\",\n \"Unsupported BitLabs conversion state\",\n );\n return transition;\n}\n","import {\n isWholeTokenAmount,\n parseTokenSubunits,\n serializeTokenSubunits,\n sumTokenSubunits,\n type TokenSubunitString,\n} from \"./amount.js\";\nimport {\n ECONOMY_CONTRACT_VERSION,\n assertEconomyIdentifier,\n parseIsoTimestamp,\n type AccountId,\n type AllocationId,\n type EconomyContractVersion,\n type HouseholdId,\n type IsoTimestamp,\n type WalletId,\n} from \"./contracts.js\";\nimport { economyAssert } from \"./errors.js\";\nimport type { SourceLotSliceV1 } from \"./lots.js\";\n\nexport type AllocationStatus = \"active\" | \"closed\";\nexport type PeriodicLimitWindow = \"daily\" | \"weekly\" | \"monthly\";\n\nexport interface GameplayLimitsV1 {\n readonly perTransaction: TokenSubunitString;\n readonly periodic: TokenSubunitString;\n readonly periodicWindow: PeriodicLimitWindow;\n}\n\n/** Guardian-funded, child-visible reservation. This is not a gameplay ledger. */\nexport interface GameplayAllocationV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly allocationId: AllocationId;\n readonly householdId: HouseholdId;\n readonly hostWalletId: WalletId;\n readonly childWalletId: WalletId;\n readonly childAccountId: AccountId;\n readonly status: AllocationStatus;\n readonly reservedAmount: TokenSubunitString;\n readonly remainingAmount: TokenSubunitString;\n readonly reclaimedAmount: TokenSubunitString;\n readonly fundingSlices: readonly SourceLotSliceV1[];\n readonly reclaimedSlices: readonly SourceLotSliceV1[];\n readonly limits: GameplayLimitsV1;\n readonly version: number;\n readonly createdAt: IsoTimestamp;\n readonly updatedAt: IsoTimestamp;\n}\n\nfunction assertWholePositive(amount: TokenSubunitString, label: string): bigint {\n const parsed = parseTokenSubunits(amount);\n economyAssert(parsed > 0n, \"INVALID_AMOUNT\", `${label} must be positive`);\n economyAssert(\n isWholeTokenAmount(parsed),\n \"AMOUNT_NOT_WHOLE_TOKEN\",\n `${label} must contain whole Tokens`,\n );\n return parsed;\n}\n\nfunction assertSlices(\n slices: readonly SourceLotSliceV1[],\n expectedAmount: bigint,\n label: string,\n): void {\n economyAssert(slices.length > 0, \"INVALID_CONTRACT\", `${label} are required`);\n const lotIds = new Set<string>();\n for (const slice of slices) {\n assertEconomyIdentifier(slice.lotId, \"lotId\");\n economyAssert(\n !lotIds.has(slice.lotId),\n \"DUPLICATE_IDENTIFIER\",\n `${label} must not repeat a lot`,\n );\n lotIds.add(slice.lotId);\n economyAssert(\n parseTokenSubunits(slice.amount) > 0n,\n \"INVALID_AMOUNT\",\n `${label} amounts must be positive`,\n );\n }\n economyAssert(\n sumTokenSubunits(slices.map((slice) => slice.amount)) === expectedAmount,\n \"INVALID_CONTRACT\",\n `${label} must sum to the command amount`,\n );\n}\n\n/** Validates allocation arithmetic and whole-Token reservation policy. */\nexport function assertGameplayAllocation(\n allocation: GameplayAllocationV1,\n): void {\n economyAssert(\n allocation.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported allocation contract version\",\n );\n assertEconomyIdentifier(allocation.allocationId, \"allocationId\");\n assertEconomyIdentifier(allocation.householdId, \"householdId\");\n assertEconomyIdentifier(allocation.hostWalletId, \"hostWalletId\");\n assertEconomyIdentifier(allocation.childWalletId, \"childWalletId\");\n assertEconomyIdentifier(allocation.childAccountId, \"childAccountId\");\n const createdAt = parseIsoTimestamp(allocation.createdAt);\n const updatedAt = parseIsoTimestamp(allocation.updatedAt);\n economyAssert(\n updatedAt >= createdAt,\n \"INVALID_TIME_WINDOW\",\n \"Allocation update time cannot precede its creation time\",\n );\n economyAssert(\n allocation.status === \"active\" || allocation.status === \"closed\",\n \"INVALID_CONTRACT\",\n \"Allocation has an unsupported status\",\n );\n\n const reserved = parseTokenSubunits(allocation.reservedAmount);\n const remaining = parseTokenSubunits(allocation.remainingAmount);\n const reclaimed = parseTokenSubunits(allocation.reclaimedAmount);\n economyAssert(\n reserved > 0n &&\n remaining >= 0n &&\n reclaimed >= 0n &&\n isWholeTokenAmount(reserved) &&\n isWholeTokenAmount(remaining) &&\n isWholeTokenAmount(reclaimed),\n \"AMOUNT_NOT_WHOLE_TOKEN\",\n \"Allocation reservations and reclaims must contain whole Tokens\",\n );\n economyAssert(\n remaining + reclaimed <= reserved,\n \"INVALID_CONTRACT\",\n \"Allocation remaining and reclaimed amounts exceed its reservation\",\n );\n\n const fundingByLot = new Map<string, bigint>();\n let funded = 0n;\n for (const slice of allocation.fundingSlices) {\n assertEconomyIdentifier(slice.lotId, \"lotId\");\n const amount = parseTokenSubunits(slice.amount);\n economyAssert(\n amount > 0n,\n \"INVALID_AMOUNT\",\n \"Allocation funding slices must be positive\",\n );\n funded += amount;\n fundingByLot.set(\n slice.lotId,\n (fundingByLot.get(slice.lotId) ?? 0n) + amount,\n );\n }\n economyAssert(\n funded === reserved,\n \"INVALID_CONTRACT\",\n \"Allocation funding provenance must equal its total reservation\",\n );\n\n const reclaimedByLot = new Map<string, bigint>();\n let reclaimedFromSlices = 0n;\n for (const slice of allocation.reclaimedSlices) {\n assertEconomyIdentifier(slice.lotId, \"lotId\");\n const amount = parseTokenSubunits(slice.amount);\n economyAssert(\n amount > 0n,\n \"INVALID_AMOUNT\",\n \"Allocation reclaim slices must be positive\",\n );\n reclaimedFromSlices += amount;\n reclaimedByLot.set(\n slice.lotId,\n (reclaimedByLot.get(slice.lotId) ?? 0n) + amount,\n );\n }\n economyAssert(\n reclaimedFromSlices === reclaimed,\n \"INVALID_CONTRACT\",\n \"Allocation reclaim provenance must equal its reclaimed amount\",\n );\n for (const [lotId, amount] of reclaimedByLot) {\n economyAssert(\n amount <= (fundingByLot.get(lotId) ?? 0n),\n \"SOURCE_LOT_RESTRICTED\",\n \"Reclaimed provenance cannot exceed allocation funding\",\n );\n }\n economyAssert(\n allocation.version >= 1 && Number.isSafeInteger(allocation.version),\n \"INVALID_CONTRACT\",\n \"Allocation version must be a positive safe integer\",\n );\n\n const perTransaction = parseTokenSubunits(allocation.limits.perTransaction);\n const periodic = parseTokenSubunits(allocation.limits.periodic);\n economyAssert(\n [\"daily\", \"weekly\", \"monthly\"].includes(allocation.limits.periodicWindow),\n \"INVALID_CONTRACT\",\n \"Gameplay limit has an unsupported period\",\n );\n economyAssert(\n perTransaction >= 0n &&\n periodic >= 0n &&\n isWholeTokenAmount(perTransaction) &&\n isWholeTokenAmount(periodic),\n \"AMOUNT_NOT_WHOLE_TOKEN\",\n \"Gameplay limits must contain whole Tokens\",\n );\n economyAssert(\n perTransaction <= periodic || periodic === 0n,\n \"INVALID_CONTRACT\",\n \"Per-transaction limit cannot exceed an enabled periodic limit\",\n );\n}\n\nexport interface CreateGameplayAllocationInputV1 {\n readonly allocationId: AllocationId;\n readonly householdId: HouseholdId;\n readonly hostWalletId: WalletId;\n readonly childWalletId: WalletId;\n readonly childAccountId: AccountId;\n readonly amount: TokenSubunitString;\n readonly fundingSlices: readonly SourceLotSliceV1[];\n readonly limits: GameplayLimitsV1;\n readonly occurredAt: IsoTimestamp;\n}\n\n/** Creates a new whole-Token reservation from already-selected source lots. */\nexport function createGameplayAllocation(\n input: CreateGameplayAllocationInputV1,\n): GameplayAllocationV1 {\n const amount = assertWholePositive(input.amount, \"Allocation amount\");\n assertSlices(input.fundingSlices, amount, \"Allocation funding slices\");\n const allocation: GameplayAllocationV1 = {\n schemaVersion: ECONOMY_CONTRACT_VERSION,\n allocationId: input.allocationId,\n householdId: input.householdId,\n hostWalletId: input.hostWalletId,\n childWalletId: input.childWalletId,\n childAccountId: input.childAccountId,\n status: \"active\",\n reservedAmount: input.amount,\n remainingAmount: input.amount,\n reclaimedAmount: serializeTokenSubunits(0n),\n fundingSlices: input.fundingSlices,\n reclaimedSlices: [],\n limits: input.limits,\n version: 1,\n createdAt: input.occurredAt,\n updatedAt: input.occurredAt,\n };\n assertGameplayAllocation(allocation);\n return allocation;\n}\n\nexport interface BoostGameplayAllocationInputV1 {\n readonly amount: TokenSubunitString;\n readonly fundingSlices: readonly SourceLotSliceV1[];\n readonly expectedVersion: number;\n readonly occurredAt: IsoTimestamp;\n}\n\n/** Returns the next immutable allocation state after a whole-Token boost. */\nexport function boostGameplayAllocation(\n allocation: GameplayAllocationV1,\n input: BoostGameplayAllocationInputV1,\n): GameplayAllocationV1 {\n assertGameplayAllocation(allocation);\n economyAssert(\n allocation.status === \"active\" && allocation.version === input.expectedVersion,\n \"INVALID_CONTRACT\",\n \"Allocation is closed or its optimistic version is stale\",\n );\n const amount = assertWholePositive(input.amount, \"Boost amount\");\n assertSlices(input.fundingSlices, amount, \"Boost funding slices\");\n\n const next: GameplayAllocationV1 = {\n ...allocation,\n reservedAmount: serializeTokenSubunits(\n parseTokenSubunits(allocation.reservedAmount) + amount,\n ),\n remainingAmount: serializeTokenSubunits(\n parseTokenSubunits(allocation.remainingAmount) + amount,\n ),\n fundingSlices: [...allocation.fundingSlices, ...input.fundingSlices],\n version: allocation.version + 1,\n updatedAt: input.occurredAt,\n };\n assertGameplayAllocation(next);\n return next;\n}\n\nexport interface ReclaimGameplayAllocationInputV1 {\n readonly amount: TokenSubunitString;\n readonly sourceSlices: readonly SourceLotSliceV1[];\n readonly expectedVersion: number;\n readonly occurredAt: IsoTimestamp;\n}\n\n/** Reclaims unused whole Tokens without changing spent history. */\nexport function reclaimGameplayAllocation(\n allocation: GameplayAllocationV1,\n input: ReclaimGameplayAllocationInputV1,\n): GameplayAllocationV1 {\n assertGameplayAllocation(allocation);\n economyAssert(\n allocation.status === \"active\" && allocation.version === input.expectedVersion,\n \"INVALID_CONTRACT\",\n \"Allocation is closed or its optimistic version is stale\",\n );\n const amount = assertWholePositive(input.amount, \"Reclaim amount\");\n economyAssert(\n amount <= parseTokenSubunits(allocation.remainingAmount),\n \"INSUFFICIENT_BALANCE\",\n \"Cannot reclaim more than the unused allocation\",\n );\n assertSlices(input.sourceSlices, amount, \"Reclaim source slices\");\n const fundedLotIds = new Set(\n allocation.fundingSlices.map((slice) => slice.lotId),\n );\n economyAssert(\n input.sourceSlices.every((slice) => fundedLotIds.has(slice.lotId)),\n \"SOURCE_LOT_RESTRICTED\",\n \"Reclaim slices must originate from the allocation\",\n );\n\n const remaining = parseTokenSubunits(allocation.remainingAmount) - amount;\n const next: GameplayAllocationV1 = {\n ...allocation,\n remainingAmount: serializeTokenSubunits(remaining),\n reclaimedAmount: serializeTokenSubunits(\n parseTokenSubunits(allocation.reclaimedAmount) + amount,\n ),\n reclaimedSlices: [...allocation.reclaimedSlices, ...input.sourceSlices],\n status: remaining === 0n ? \"closed\" : allocation.status,\n version: allocation.version + 1,\n updatedAt: input.occurredAt,\n };\n assertGameplayAllocation(next);\n return next;\n}\n","import {\n parseTokenSubunits,\n serializeTokenSubunits,\n type TokenSubunitString,\n} from \"./amount.js\";\nimport {\n ECONOMY_CONTRACT_VERSION,\n assertEconomyIdentifier,\n parseIsoTimestamp,\n type AccountId,\n type EconomyContractVersion,\n type HouseholdId,\n type IsoTimestamp,\n type LotId,\n} from \"./contracts.js\";\nimport { economyAssert } from \"./errors.js\";\n\nexport const PRE_UTILITY_BACKER_COHORT = \"pre_utility_backer_v1\" as const;\n\nexport interface EarlyBackerWindowV1 {\n readonly publicTokensLaunchAt: IsoTimestamp;\n readonly firstPublicSpendLiveAt?: IsoTimestamp;\n}\n\n/** Paid-lot facts required to recalculate retained early-backer basis. */\nexport interface PaidLotRetentionV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly lotId: LotId;\n readonly payerAccountId: AccountId;\n readonly receivingHouseholdId: HouseholdId;\n readonly purchaseId: string;\n readonly catalogVersion: string;\n readonly purchasedAt: IsoTimestamp;\n readonly settledAt: IsoTimestamp;\n readonly creditedAt: IsoTimestamp;\n readonly retainedAmount: TokenSubunitString;\n}\n\nexport interface EarlyBackerEvaluationV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly cohortKey: typeof PRE_UTILITY_BACKER_COHORT;\n readonly status: \"not-qualified\" | \"provisional\";\n readonly payerAccountId: AccountId;\n readonly receivingHouseholdId: HouseholdId;\n readonly netRetainedAmount: TokenSubunitString;\n readonly contributingLotIds: readonly LotId[];\n readonly evaluatedAt: IsoTimestamp;\n}\n\nexport const EARLY_BACKER_SETTLEMENT_POLICY_V2 =\n \"settlement-window-v2\" as const;\n\n/**\n * Additive evaluation result using settlement as the sole qualification event.\n * Purchase and credit times remain provenance/order facts.\n */\nexport interface EarlyBackerEvaluationV2 {\n readonly schemaVersion: EconomyContractVersion;\n readonly policyVersion: typeof EARLY_BACKER_SETTLEMENT_POLICY_V2;\n readonly qualificationEvent: \"settled-at\";\n readonly cohortKey: typeof PRE_UTILITY_BACKER_COHORT;\n readonly status: \"not-qualified\" | \"provisional\";\n readonly payerAccountId: AccountId;\n readonly receivingHouseholdId: HouseholdId;\n readonly netRetainedAmount: TokenSubunitString;\n readonly contributingLotIds: readonly LotId[];\n readonly evaluatedAt: IsoTimestamp;\n}\n\nfunction isWithinWindow(\n timestamp: IsoTimestamp,\n launch: number,\n cutoff: number | undefined,\n): boolean {\n const value = parseIsoTimestamp(timestamp);\n return value >= launch && (cutoff === undefined || value < cutoff);\n}\n\n/**\n * Recalculates provisional cohort basis from retained paid lots. It promises no\n * future reward and deliberately has no permanent entitled state.\n */\nexport function evaluateEarlyBacker(\n payerAccountId: AccountId,\n receivingHouseholdId: HouseholdId,\n paidLots: readonly PaidLotRetentionV1[],\n window: EarlyBackerWindowV1,\n evaluatedAt: IsoTimestamp,\n): EarlyBackerEvaluationV1 {\n assertEconomyIdentifier(payerAccountId, \"payerAccountId\");\n assertEconomyIdentifier(receivingHouseholdId, \"receivingHouseholdId\");\n const launch = parseIsoTimestamp(window.publicTokensLaunchAt);\n const cutoff =\n window.firstPublicSpendLiveAt === undefined\n ? undefined\n : parseIsoTimestamp(window.firstPublicSpendLiveAt);\n economyAssert(\n cutoff === undefined || cutoff > launch,\n \"INVALID_TIME_WINDOW\",\n \"First public spend must occur after public Token launch\",\n );\n parseIsoTimestamp(evaluatedAt);\n\n let retained = 0n;\n const contributingLotIds: LotId[] = [];\n const seenLotIds = new Set<string>();\n for (const lot of paidLots) {\n economyAssert(\n lot.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported paid-lot retention contract version\",\n );\n assertEconomyIdentifier(lot.lotId, \"lotId\");\n economyAssert(\n !seenLotIds.has(lot.lotId),\n \"DUPLICATE_IDENTIFIER\",\n \"Paid-lot retention input must not repeat a source lot\",\n );\n seenLotIds.add(lot.lotId);\n assertEconomyIdentifier(lot.payerAccountId, \"payerAccountId\");\n assertEconomyIdentifier(lot.receivingHouseholdId, \"receivingHouseholdId\");\n assertEconomyIdentifier(lot.purchaseId, \"purchaseId\");\n assertEconomyIdentifier(lot.catalogVersion, \"catalogVersion\");\n const purchasedAt = parseIsoTimestamp(lot.purchasedAt);\n const settledAt = parseIsoTimestamp(lot.settledAt);\n const creditedAt = parseIsoTimestamp(lot.creditedAt);\n economyAssert(\n purchasedAt <= settledAt && settledAt <= creditedAt,\n \"INVALID_TIME_WINDOW\",\n \"Paid-lot timestamps must follow purchase, settlement, then credit order\",\n );\n if (\n lot.payerAccountId !== payerAccountId ||\n lot.receivingHouseholdId !== receivingHouseholdId\n ) {\n continue;\n }\n const inWindow =\n isWithinWindow(lot.purchasedAt, launch, cutoff) &&\n isWithinWindow(lot.settledAt, launch, cutoff) &&\n isWithinWindow(lot.creditedAt, launch, cutoff);\n const amount = parseTokenSubunits(lot.retainedAmount);\n economyAssert(\n amount >= 0n,\n \"INVALID_AMOUNT\",\n \"Retained paid-lot basis cannot be negative\",\n );\n if (inWindow && amount > 0n) {\n retained += amount;\n contributingLotIds.push(lot.lotId);\n }\n }\n\n return {\n schemaVersion: ECONOMY_CONTRACT_VERSION,\n cohortKey: PRE_UTILITY_BACKER_COHORT,\n status: retained > 0n ? \"provisional\" : \"not-qualified\",\n payerAccountId,\n receivingHouseholdId,\n netRetainedAmount: serializeTokenSubunits(retained),\n contributingLotIds: contributingLotIds.sort((left, right) =>\n left.localeCompare(right),\n ),\n evaluatedAt,\n };\n}\n\n/**\n * Evaluates the approved settlement-window policy. The caller owns environment\n * and rollout classification: `publicTokensLaunchAt` and\n * `firstPublicSpendLiveAt` must be derived from the entire public cohort, so\n * staff, test, and closed-beta availability cannot open or close this window.\n * The caller must also exclude non-production/test lots before evaluation.\n */\nexport function evaluateEarlyBackerBySettlementV2(\n payerAccountId: AccountId,\n receivingHouseholdId: HouseholdId,\n paidLots: readonly PaidLotRetentionV1[],\n window: EarlyBackerWindowV1,\n evaluatedAt: IsoTimestamp,\n): EarlyBackerEvaluationV2 {\n assertEconomyIdentifier(payerAccountId, \"payerAccountId\");\n assertEconomyIdentifier(receivingHouseholdId, \"receivingHouseholdId\");\n const launch = parseIsoTimestamp(window.publicTokensLaunchAt);\n const cutoff =\n window.firstPublicSpendLiveAt === undefined\n ? undefined\n : parseIsoTimestamp(window.firstPublicSpendLiveAt);\n economyAssert(\n cutoff === undefined || cutoff > launch,\n \"INVALID_TIME_WINDOW\",\n \"First public spend must occur after public Token launch\",\n );\n const evaluationTime = parseIsoTimestamp(evaluatedAt);\n\n let retained = 0n;\n const contributingLotIds: LotId[] = [];\n const seenLotIds = new Set<string>();\n for (const lot of paidLots) {\n economyAssert(\n lot.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported paid-lot retention contract version\",\n );\n assertEconomyIdentifier(lot.lotId, \"lotId\");\n economyAssert(\n !seenLotIds.has(lot.lotId),\n \"DUPLICATE_IDENTIFIER\",\n \"Paid-lot retention input must not repeat a source lot\",\n );\n seenLotIds.add(lot.lotId);\n assertEconomyIdentifier(lot.payerAccountId, \"payerAccountId\");\n assertEconomyIdentifier(lot.receivingHouseholdId, \"receivingHouseholdId\");\n assertEconomyIdentifier(lot.purchaseId, \"purchaseId\");\n assertEconomyIdentifier(lot.catalogVersion, \"catalogVersion\");\n const purchasedAt = parseIsoTimestamp(lot.purchasedAt);\n const settledAt = parseIsoTimestamp(lot.settledAt);\n const creditedAt = parseIsoTimestamp(lot.creditedAt);\n economyAssert(\n purchasedAt <= settledAt && settledAt <= creditedAt,\n \"INVALID_TIME_WINDOW\",\n \"Paid-lot timestamps must follow purchase, settlement, then credit order\",\n );\n const amount = parseTokenSubunits(lot.retainedAmount);\n economyAssert(\n amount >= 0n,\n \"INVALID_AMOUNT\",\n \"Retained paid-lot basis cannot be negative\",\n );\n if (\n lot.payerAccountId === payerAccountId &&\n lot.receivingHouseholdId === receivingHouseholdId &&\n settledAt >= launch &&\n (cutoff === undefined || settledAt < cutoff) &&\n settledAt <= evaluationTime &&\n amount > 0n\n ) {\n retained += amount;\n contributingLotIds.push(lot.lotId);\n }\n }\n\n return {\n schemaVersion: ECONOMY_CONTRACT_VERSION,\n policyVersion: EARLY_BACKER_SETTLEMENT_POLICY_V2,\n qualificationEvent: \"settled-at\",\n cohortKey: PRE_UTILITY_BACKER_COHORT,\n status: retained > 0n ? \"provisional\" : \"not-qualified\",\n payerAccountId,\n receivingHouseholdId,\n netRetainedAmount: serializeTokenSubunits(retained),\n contributingLotIds: contributingLotIds.sort((left, right) =>\n left.localeCompare(right),\n ),\n evaluatedAt,\n };\n}\n","import {\n parseTokenSubunits,\n serializeTokenSubunits,\n sumTokenSubunits,\n type TokenSubunitString,\n} from \"./amount.js\";\nimport { compareUnicodeCodeUnits } from \"./canonical-order.js\";\nimport {\n ECONOMY_CONTRACT_VERSION,\n assertEconomyIdentifier,\n parseIsoTimestamp,\n sortStringRecord,\n type AccountId,\n type EconomyContractVersion,\n type IsoTimestamp,\n type LotId,\n type PostingId,\n type ProviderEventId,\n type TransactionId,\n type WalletId,\n} from \"./contracts.js\";\nimport { economyAssert } from \"./errors.js\";\nimport type { TokenSource } from \"./lots.js\";\n\nexport type ActivityType =\n | \"purchase\"\n | \"subscription\"\n | \"rewarded-ad\"\n | \"offerwall\"\n | \"allocation\"\n | \"boost\"\n | \"reclaim\"\n | \"spend\"\n | \"hold\"\n | \"refund\"\n | \"chargeback\"\n | \"adjustment\"\n | \"reversal\"\n | \"event\"\n | \"competition\";\n\nexport type ActivityStatus =\n | \"pending\"\n | \"held\"\n | \"settled\"\n | \"reversed\"\n | \"failed\";\n\n/**\n * States permitted on an immutable transaction accepted by the V2\n * persistence boundary. Pending and failed work belongs to the command\n * workflow, while a reversed presentation state is derived from an immutable\n * compensating transaction rather than written back to the original journal\n * row.\n */\nexport type EconomicJournalStatus = \"held\" | \"settled\";\n\n/** A journal transaction that has an immediate economic effect. */\nexport type EconomicJournalTransactionV1 = Omit<\n LedgerTransactionV1,\n \"status\"\n> & {\n readonly status: EconomicJournalStatus;\n};\n\nconst ACTIVITY_TYPES = new Set<ActivityType>([\n \"purchase\",\n \"subscription\",\n \"rewarded-ad\",\n \"offerwall\",\n \"allocation\",\n \"boost\",\n \"reclaim\",\n \"spend\",\n \"hold\",\n \"refund\",\n \"chargeback\",\n \"adjustment\",\n \"reversal\",\n \"event\",\n \"competition\",\n]);\n\nconst ACTIVITY_STATUSES = new Set<ActivityStatus>([\n \"pending\",\n \"held\",\n \"settled\",\n \"reversed\",\n \"failed\",\n]);\n\nconst ACTIVITY_SOURCES = new Set<TokenSource>([\n \"shopify\",\n \"ayet\",\n \"bitlabs\",\n \"subscription\",\n \"event\",\n \"competition\",\n \"adjustment\",\n]);\n\nfunction assertCanonicalHash(value: string, label: string): void {\n economyAssert(\n /^sha256:[a-f0-9]{64}$/u.test(value),\n \"INVALID_CONTRACT\",\n `${label} must be a canonical SHA-256 reference`,\n );\n}\n\nfunction hasControlCharacters(value: string): boolean {\n return [...value].some((character) => {\n const code = character.charCodeAt(0);\n return code <= 31 || code === 127;\n });\n}\n\n/** One signed side of an immutable double-entry transaction. */\nexport interface LedgerPostingV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly postingId: PostingId;\n readonly transactionId: TransactionId;\n readonly accountId: AccountId;\n readonly walletId?: WalletId;\n readonly lotId?: LotId;\n readonly amount: TokenSubunitString;\n}\n\n/** Immutable transaction envelope. Posting amounts must sum to exactly zero. */\nexport interface LedgerTransactionV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly transactionId: TransactionId;\n readonly activityType: ActivityType;\n readonly status: ActivityStatus;\n readonly idempotencyKey: string;\n readonly providerEventId?: ProviderEventId;\n readonly reversesTransactionId?: TransactionId;\n readonly effectiveAt: IsoTimestamp;\n readonly recordedAt: IsoTimestamp;\n readonly previousCanonicalHash?: string;\n readonly canonicalHash?: string;\n readonly metadata: Readonly<Record<string, string>>;\n readonly postings: readonly LedgerPostingV1[];\n}\n\n/** Privacy-safe, display-oriented journal entry returned by an API adapter. */\nexport interface ActivityEntryV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly transactionId: TransactionId;\n readonly activityType: ActivityType;\n readonly status: ActivityStatus;\n readonly occurredAt: IsoTimestamp;\n readonly amount: TokenSubunitString;\n /** Stable source identity used for filtering and provenance presentation. */\n readonly source: TokenSource;\n readonly beneficiaryAccountId?: AccountId;\n readonly maskedReference?: string;\n readonly sourceLabel: string;\n}\n\n/** Validates one privacy-safe activity row returned by an HTTP adapter. */\nexport function assertActivityEntry(entry: ActivityEntryV1): void {\n economyAssert(\n entry.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported activity-entry contract version\",\n );\n assertEconomyIdentifier(entry.transactionId, \"transactionId\");\n economyAssert(\n ACTIVITY_TYPES.has(entry.activityType) &&\n ACTIVITY_STATUSES.has(entry.status) &&\n ACTIVITY_SOURCES.has(entry.source),\n \"INVALID_CONTRACT\",\n \"Activity type, status, or source is unsupported\",\n );\n parseIsoTimestamp(entry.occurredAt);\n economyAssert(\n parseTokenSubunits(entry.amount) !== 0n,\n \"INVALID_AMOUNT\",\n \"Activity entries cannot contain a zero amount\",\n );\n if (entry.beneficiaryAccountId !== undefined) {\n assertEconomyIdentifier(\n entry.beneficiaryAccountId,\n \"beneficiaryAccountId\",\n );\n }\n if (entry.maskedReference !== undefined) {\n economyAssert(\n typeof entry.maskedReference === \"string\" &&\n entry.maskedReference.length > 0 &&\n entry.maskedReference.length <= 128 &&\n !hasControlCharacters(entry.maskedReference),\n \"INVALID_CONTRACT\",\n \"Masked activity references must be bounded and safe for display\",\n );\n }\n economyAssert(\n typeof entry.sourceLabel === \"string\" &&\n entry.sourceLabel.trim().length > 0 &&\n entry.sourceLabel.length <= 128 &&\n !hasControlCharacters(entry.sourceLabel),\n \"INVALID_CONTRACT\",\n \"Activity source labels must be bounded and safe for display\",\n );\n}\n\n/** Proves the structural and arithmetic invariants of one transaction. */\nexport function assertBalancedTransaction(\n transaction: LedgerTransactionV1,\n): void {\n economyAssert(\n transaction.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported ledger contract version\",\n );\n assertEconomyIdentifier(transaction.transactionId, \"transactionId\");\n assertEconomyIdentifier(transaction.idempotencyKey, \"idempotencyKey\");\n economyAssert(\n ACTIVITY_TYPES.has(transaction.activityType) &&\n ACTIVITY_STATUSES.has(transaction.status),\n \"INVALID_CONTRACT\",\n \"Transaction activity type or status is unsupported\",\n );\n if (transaction.providerEventId !== undefined) {\n assertEconomyIdentifier(transaction.providerEventId, \"providerEventId\");\n }\n if (transaction.reversesTransactionId !== undefined) {\n assertEconomyIdentifier(\n transaction.reversesTransactionId,\n \"reversesTransactionId\",\n );\n }\n economyAssert(\n (transaction.activityType === \"reversal\") ===\n (transaction.reversesTransactionId !== undefined),\n \"INVALID_CONTRACT\",\n \"Reversal transactions must identify exactly one original transaction\",\n );\n const effectiveAt = parseIsoTimestamp(transaction.effectiveAt);\n const recordedAt = parseIsoTimestamp(transaction.recordedAt);\n economyAssert(\n recordedAt >= effectiveAt,\n \"INVALID_TIME_WINDOW\",\n \"Transaction recording time cannot precede its effective time\",\n );\n if (transaction.previousCanonicalHash !== undefined) {\n assertCanonicalHash(\n transaction.previousCanonicalHash,\n \"Previous canonical hash\",\n );\n }\n if (transaction.canonicalHash !== undefined) {\n assertCanonicalHash(transaction.canonicalHash, \"Canonical hash\");\n }\n const metadataEntries = Object.entries(transaction.metadata);\n economyAssert(\n metadataEntries.length <= 32 &&\n metadataEntries.every(\n ([key, value]) =>\n /^[A-Za-z][A-Za-z0-9_.-]{0,63}$/u.test(key) &&\n value.length <= 512 &&\n !hasControlCharacters(value),\n ),\n \"INVALID_CONTRACT\",\n \"Transaction metadata must be bounded and free of control characters\",\n );\n economyAssert(\n transaction.postings.length >= 2,\n \"UNBALANCED_TRANSACTION\",\n \"A ledger transaction needs at least two postings\",\n );\n\n const postingIds = new Set<string>();\n for (const posting of transaction.postings) {\n economyAssert(\n posting.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported posting contract version\",\n );\n assertEconomyIdentifier(posting.postingId, \"postingId\");\n assertEconomyIdentifier(posting.accountId, \"accountId\");\n if (posting.walletId !== undefined) {\n assertEconomyIdentifier(posting.walletId, \"walletId\");\n }\n if (posting.lotId !== undefined) {\n assertEconomyIdentifier(posting.lotId, \"lotId\");\n }\n economyAssert(\n posting.transactionId === transaction.transactionId,\n \"INVALID_CONTRACT\",\n \"Posting transactionId must match its transaction\",\n );\n economyAssert(\n !postingIds.has(posting.postingId),\n \"DUPLICATE_IDENTIFIER\",\n \"Posting identifiers must be unique within a transaction\",\n );\n postingIds.add(posting.postingId);\n economyAssert(\n parseTokenSubunits(posting.amount) !== 0n,\n \"INVALID_AMOUNT\",\n \"Zero-value postings are not permitted\",\n );\n }\n\n economyAssert(\n sumTokenSubunits(transaction.postings.map((posting) => posting.amount)) ===\n 0n,\n \"UNBALANCED_TRANSACTION\",\n \"Ledger postings must sum to zero TokenSubunits\",\n );\n}\n\n/**\n * Narrows a balanced V1 transaction to the states accepted by the V2 journal.\n * This is additive: legacy V1 validators retain their existing status union.\n */\nexport function assertEconomicJournalTransaction(\n transaction: LedgerTransactionV1,\n): asserts transaction is EconomicJournalTransactionV1 {\n assertBalancedTransaction(transaction);\n economyAssert(\n transaction.status === \"held\" || transaction.status === \"settled\",\n \"INVALID_CONTRACT\",\n \"Pending, failed, and derived reversed activity cannot be journal transactions\",\n );\n}\n\n/**\n * Produces deterministic UTF-8 JSON for an approved SHA-256/HSM adapter.\n * Hashing itself deliberately remains outside this provider-neutral package.\n */\nexport function canonicalTransactionPayload(\n transaction: LedgerTransactionV1,\n): string {\n assertBalancedTransaction(transaction);\n const postings = [...transaction.postings]\n .sort((left, right) =>\n compareUnicodeCodeUnits(left.postingId, right.postingId),\n )\n .map((posting) => ({\n schemaVersion: posting.schemaVersion,\n postingId: posting.postingId,\n transactionId: posting.transactionId,\n accountId: posting.accountId,\n ...(posting.walletId === undefined ? {} : { walletId: posting.walletId }),\n ...(posting.lotId === undefined ? {} : { lotId: posting.lotId }),\n amount: posting.amount,\n }));\n\n return JSON.stringify({\n schemaVersion: transaction.schemaVersion,\n transactionId: transaction.transactionId,\n activityType: transaction.activityType,\n status: transaction.status,\n idempotencyKey: transaction.idempotencyKey,\n ...(transaction.providerEventId === undefined\n ? {}\n : { providerEventId: transaction.providerEventId }),\n ...(transaction.reversesTransactionId === undefined\n ? {}\n : { reversesTransactionId: transaction.reversesTransactionId }),\n effectiveAt: transaction.effectiveAt,\n recordedAt: transaction.recordedAt,\n ...(transaction.previousCanonicalHash === undefined\n ? {}\n : { previousCanonicalHash: transaction.previousCanonicalHash }),\n metadata: sortStringRecord(transaction.metadata),\n postings,\n });\n}\n\nexport interface ReversalInputV1 {\n readonly transactionId: TransactionId;\n readonly postingIds: readonly PostingId[];\n readonly idempotencyKey: string;\n readonly effectiveAt: IsoTimestamp;\n readonly recordedAt: IsoTimestamp;\n readonly metadata?: Readonly<Record<string, string>>;\n readonly previousCanonicalHash?: string;\n}\n\n/** Creates an immutable compensating transaction; it never edits the original. */\nexport function createReversalTransaction(\n original: LedgerTransactionV1,\n input: ReversalInputV1,\n): LedgerTransactionV1 {\n assertBalancedTransaction(original);\n economyAssert(\n original.reversesTransactionId === undefined,\n \"INVALID_CONTRACT\",\n \"A reversal cannot itself be reversed by this helper\",\n );\n economyAssert(\n input.postingIds.length === original.postings.length,\n \"INVALID_CONTRACT\",\n \"A reversal needs one new posting identifier per original posting\",\n );\n\n const postings = original.postings.map((posting, index) => {\n const postingId = input.postingIds[index];\n economyAssert(\n postingId !== undefined,\n \"INVALID_CONTRACT\",\n \"Missing reversal posting identifier\",\n );\n return {\n ...posting,\n postingId,\n transactionId: input.transactionId,\n amount: serializeTokenSubunits(-parseTokenSubunits(posting.amount)),\n } satisfies LedgerPostingV1;\n });\n\n const transaction: LedgerTransactionV1 = {\n schemaVersion: ECONOMY_CONTRACT_VERSION,\n transactionId: input.transactionId,\n activityType: \"reversal\",\n status: \"settled\",\n idempotencyKey: input.idempotencyKey,\n reversesTransactionId: original.transactionId,\n effectiveAt: input.effectiveAt,\n recordedAt: input.recordedAt,\n ...(input.previousCanonicalHash === undefined\n ? {}\n : { previousCanonicalHash: input.previousCanonicalHash }),\n metadata: input.metadata ?? {},\n postings,\n };\n assertBalancedTransaction(transaction);\n return transaction;\n}\n\n/** Rejects a second effective reversal for the same original transaction. */\nexport function assertReversalAvailable(\n originalTransactionId: TransactionId,\n existingTransactions: readonly LedgerTransactionV1[],\n): void {\n assertEconomyIdentifier(originalTransactionId, \"originalTransactionId\");\n economyAssert(\n !existingTransactions.some(\n (transaction) =>\n transaction.reversesTransactionId === originalTransactionId &&\n transaction.status !== \"failed\",\n ),\n \"REVERSAL_ALREADY_EXISTS\",\n \"The transaction already has an effective reversal\",\n );\n}\n","import {\n ECONOMY_CONTRACT_VERSION,\n assertEconomyIdentifier,\n parseIsoTimestamp,\n type EconomyContractVersion,\n type IsoTimestamp,\n type TransactionId,\n} from \"./contracts.js\";\nimport { economyAssert } from \"./errors.js\";\nimport {\n assertEconomicJournalTransaction,\n type EconomicJournalTransactionV1,\n} from \"./ledger.js\";\n\nexport type JournalChainId = string;\n\n/** Locked head of one canonical transaction hash chain. */\nexport interface JournalChainHeadV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly chainId: JournalChainId;\n readonly version: number;\n readonly lastTransactionId?: TransactionId;\n readonly canonicalHash?: string;\n readonly updatedAt: IsoTimestamp;\n}\n\n/** An effective economic transaction carrying its approved canonical hash. */\nexport type ChainedEconomicJournalTransactionV1 =\n EconomicJournalTransactionV1 & {\n readonly canonicalHash: string;\n };\n\nfunction assertCanonicalHash(value: string, label: string): void {\n economyAssert(\n typeof value === \"string\" && /^sha256:[a-f0-9]{64}$/u.test(value),\n \"INVALID_CONTRACT\",\n `${label} must be a canonical SHA-256 reference`,\n );\n}\n\n/** Validates an empty or populated journal-chain head. */\nexport function assertJournalChainHead(head: JournalChainHeadV1): void {\n economyAssert(\n head.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported journal-chain-head contract version\",\n );\n assertEconomyIdentifier(head.chainId, \"chainId\");\n economyAssert(\n Number.isSafeInteger(head.version) && head.version >= 0,\n \"INVALID_CONTRACT\",\n \"Journal-chain-head version must be a non-negative safe integer\",\n );\n parseIsoTimestamp(head.updatedAt);\n const hasTransaction = head.lastTransactionId !== undefined;\n const hasHash = head.canonicalHash !== undefined;\n economyAssert(\n hasTransaction === hasHash && (head.version > 0) === hasTransaction,\n \"INVALID_CONTRACT\",\n \"Journal-chain head identity, hash, and version must describe the same state\",\n );\n if (head.lastTransactionId !== undefined) {\n assertEconomyIdentifier(head.lastTransactionId, \"lastTransactionId\");\n }\n if (head.canonicalHash !== undefined) {\n assertCanonicalHash(head.canonicalHash, \"Journal-chain-head hash\");\n }\n}\n\n/**\n * Proves that a hashed transaction extends the locked head and returns the\n * exact next head. The persistence adapter must compare-and-swap the old\n * version inside the same serializable transaction that appends the journal.\n */\nexport function advanceJournalChainHead(\n head: JournalChainHeadV1,\n transaction: ChainedEconomicJournalTransactionV1,\n): JournalChainHeadV1 {\n assertJournalChainHead(head);\n assertEconomicJournalTransaction(transaction);\n assertCanonicalHash(transaction.canonicalHash, \"Transaction hash\");\n economyAssert(\n transaction.previousCanonicalHash === head.canonicalHash,\n \"INVALID_CONTRACT\",\n \"Transaction previous hash must match the locked journal-chain head\",\n );\n economyAssert(\n transaction.canonicalHash !== head.canonicalHash,\n \"DUPLICATE_TRANSACTION\",\n \"Transaction hash must advance the journal chain\",\n );\n const recordedAt = parseIsoTimestamp(transaction.recordedAt);\n economyAssert(\n recordedAt >= parseIsoTimestamp(head.updatedAt),\n \"INVALID_TIME_WINDOW\",\n \"Journal-chain update cannot precede its locked head\",\n );\n\n return {\n schemaVersion: ECONOMY_CONTRACT_VERSION,\n chainId: head.chainId,\n version: head.version + 1,\n lastTransactionId: transaction.transactionId,\n canonicalHash: transaction.canonicalHash,\n updatedAt: transaction.recordedAt,\n };\n}\n","import {\n parseTokenSubunits,\n serializeTokenSubunits,\n type TokenSubunitString,\n} from \"./amount.js\";\nimport {\n ECONOMY_CONTRACT_VERSION,\n assertEconomyIdentifier,\n parseIsoTimestamp,\n type AccountId,\n type EconomyContractVersion,\n type HouseholdId,\n type IsoTimestamp,\n type LotId,\n type ProviderEventId,\n type TransactionId,\n type WalletId,\n} from \"./contracts.js\";\nimport { EconomyError, economyAssert } from \"./errors.js\";\n\nexport type TokenSource =\n | \"shopify\"\n | \"ayet\"\n | \"bitlabs\"\n | \"subscription\"\n | \"event\"\n | \"competition\"\n | \"adjustment\";\n\nexport type LotTransferPolicy =\n | \"household-allocatable\"\n | \"same-user-only\"\n | \"non-transferable\";\n\nexport type LotRefundState =\n | \"none\"\n | \"partial\"\n | \"refunded\"\n | \"disputed\"\n | \"chargeback-lost\";\n\nexport interface SourceLotV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly lotId: LotId;\n readonly walletId: WalletId;\n readonly beneficiaryAccountId: AccountId;\n readonly householdId?: HouseholdId;\n readonly payerAccountId?: AccountId;\n readonly source: TokenSource;\n readonly providerEventId?: ProviderEventId;\n readonly rateVersion: string;\n readonly settlementEvidenceHash: string;\n readonly transferPolicy: LotTransferPolicy;\n readonly refundState: LotRefundState;\n readonly originalAmount: TokenSubunitString;\n readonly remainingAmount: TokenSubunitString;\n readonly heldAmount: TokenSubunitString;\n readonly reversedAmount: TokenSubunitString;\n readonly settledAt: IsoTimestamp;\n readonly creditedAt: IsoTimestamp;\n readonly cohortKey?: string;\n}\n\nexport type LotUseOperation = \"allocate\" | \"spend\" | \"reclaim\" | \"refund\";\n\nexport interface LotUseContextV1 {\n readonly operation: LotUseOperation;\n readonly beneficiaryAccountId: AccountId;\n readonly householdId?: HouseholdId;\n}\n\nexport interface SourceLotSliceV1 {\n readonly lotId: LotId;\n readonly amount: TokenSubunitString;\n}\n\n/** Versioned mutable projection around immutable V1 source-lot provenance. */\nexport interface VersionedSourceLotV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly lot: SourceLotV1;\n readonly version: number;\n readonly updatedAt: IsoTimestamp;\n}\n\nexport type SourceLotMovementType =\n | \"allocate\"\n | \"boost\"\n | \"reclaim\"\n | \"spend\"\n | \"hold\"\n | \"release-hold\"\n | \"refund\"\n | \"chargeback\"\n | \"reversal\";\n\n/**\n * Immutable movement applied to one source-lot projection by compare-and-swap.\n * Signed deltas are authoritative; `resultingRefundState` is part of the same\n * atomic version transition.\n */\nexport interface SourceLotMovementV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly movementId: string;\n readonly transactionId: TransactionId;\n readonly lotId: LotId;\n readonly movementType: SourceLotMovementType;\n readonly remainingDelta: TokenSubunitString;\n readonly heldDelta: TokenSubunitString;\n readonly reversedDelta: TokenSubunitString;\n readonly expectedVersion: number;\n readonly resultingVersion: number;\n readonly expectedRefundState: LotRefundState;\n readonly resultingRefundState: LotRefundState;\n readonly occurredAt: IsoTimestamp;\n}\n\n/** Validates source-lot arithmetic, evidence, and immutable provenance fields. */\nexport function assertSourceLot(lot: SourceLotV1): void {\n economyAssert(\n lot.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported source-lot contract version\",\n );\n assertEconomyIdentifier(lot.lotId, \"lotId\");\n assertEconomyIdentifier(lot.walletId, \"walletId\");\n assertEconomyIdentifier(lot.beneficiaryAccountId, \"beneficiaryAccountId\");\n if (lot.householdId !== undefined) {\n assertEconomyIdentifier(lot.householdId, \"householdId\");\n }\n if (lot.payerAccountId !== undefined) {\n assertEconomyIdentifier(lot.payerAccountId, \"payerAccountId\");\n }\n if (lot.providerEventId !== undefined) {\n assertEconomyIdentifier(lot.providerEventId, \"providerEventId\");\n }\n assertEconomyIdentifier(lot.rateVersion, \"rateVersion\");\n economyAssert(\n [\n \"shopify\",\n \"ayet\",\n \"bitlabs\",\n \"subscription\",\n \"event\",\n \"competition\",\n \"adjustment\",\n ].includes(lot.source),\n \"INVALID_CONTRACT\",\n \"Source lot has an unsupported source\",\n );\n economyAssert(\n [\"household-allocatable\", \"same-user-only\", \"non-transferable\"].includes(\n lot.transferPolicy,\n ),\n \"INVALID_CONTRACT\",\n \"Source lot has an unsupported transfer policy\",\n );\n economyAssert(\n [\"none\", \"partial\", \"refunded\", \"disputed\", \"chargeback-lost\"].includes(\n lot.refundState,\n ),\n \"INVALID_CONTRACT\",\n \"Source lot has an unsupported refund state\",\n );\n if (lot.source === \"ayet\" || lot.source === \"bitlabs\") {\n economyAssert(\n lot.transferPolicy === \"same-user-only\" &&\n lot.providerEventId !== undefined,\n \"SOURCE_LOT_RESTRICTED\",\n \"Reward-provider lots must remain with the earning account\",\n );\n }\n if (lot.source === \"shopify\") {\n economyAssert(\n lot.transferPolicy === \"household-allocatable\" &&\n lot.householdId !== undefined &&\n lot.payerAccountId !== undefined,\n \"INVALID_CONTRACT\",\n \"Shopify lots must retain payer and receiving-household provenance\",\n );\n }\n economyAssert(\n /^sha256:[a-f0-9]{64}$/u.test(lot.settlementEvidenceHash),\n \"INVALID_CONTRACT\",\n \"Settlement evidence must be a sanitized SHA-256 reference\",\n );\n const settledAt = parseIsoTimestamp(lot.settledAt);\n const creditedAt = parseIsoTimestamp(lot.creditedAt);\n economyAssert(\n creditedAt >= settledAt,\n \"INVALID_TIME_WINDOW\",\n \"Source-lot credit time cannot precede settlement\",\n );\n if (lot.cohortKey !== undefined) {\n assertEconomyIdentifier(lot.cohortKey, \"cohortKey\");\n }\n\n const original = parseTokenSubunits(lot.originalAmount);\n const remaining = parseTokenSubunits(lot.remainingAmount);\n const held = parseTokenSubunits(lot.heldAmount);\n const reversed = parseTokenSubunits(lot.reversedAmount);\n economyAssert(\n original > 0n && remaining >= 0n && held >= 0n && reversed >= 0n,\n \"INVALID_AMOUNT\",\n \"Source-lot amounts must be non-negative and original must be positive\",\n );\n economyAssert(\n remaining <= original && held <= remaining && reversed <= original,\n \"INVALID_CONTRACT\",\n \"Source-lot amount components exceed the original or remaining amount\",\n );\n economyAssert(\n remaining + reversed <= original,\n \"INVALID_CONTRACT\",\n \"Remaining and reversed source-lot amounts exceed the original\",\n );\n}\n\n/** Validates the optimistic projection wrapper used by V2 persistence. */\nexport function assertVersionedSourceLot(\n snapshot: VersionedSourceLotV1,\n): void {\n economyAssert(\n snapshot.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported versioned source-lot contract version\",\n );\n assertSourceLot(snapshot.lot);\n economyAssert(\n Number.isSafeInteger(snapshot.version) && snapshot.version >= 1,\n \"INVALID_CONTRACT\",\n \"Source-lot version must be a positive safe integer\",\n );\n economyAssert(\n parseIsoTimestamp(snapshot.updatedAt) >=\n parseIsoTimestamp(snapshot.lot.creditedAt),\n \"INVALID_TIME_WINDOW\",\n \"Source-lot update time cannot precede its credit\",\n );\n}\n\n/** Creates the only state accepted by the V2 append-source-lot operation. */\nexport function createInitialSourceLotSnapshot(\n lot: SourceLotV1,\n): VersionedSourceLotV1 {\n assertSourceLot(lot);\n economyAssert(\n lot.refundState === \"none\" &&\n lot.originalAmount === lot.remainingAmount &&\n parseTokenSubunits(lot.heldAmount) === 0n &&\n parseTokenSubunits(lot.reversedAmount) === 0n,\n \"INVALID_CONTRACT\",\n \"A new source lot must start fully remaining, clear, and unreversed\",\n );\n return {\n schemaVersion: ECONOMY_CONTRACT_VERSION,\n lot,\n version: 1,\n updatedAt: lot.creditedAt,\n };\n}\n\nfunction assertRefundState(value: LotRefundState): void {\n economyAssert(\n [\n \"none\",\n \"partial\",\n \"refunded\",\n \"disputed\",\n \"chargeback-lost\",\n ].includes(value),\n \"INVALID_CONTRACT\",\n \"Source-lot movement has an unsupported refund state\",\n );\n}\n\n/** Validates movement shape and operation-specific delta direction. */\nexport function assertSourceLotMovement(\n movement: SourceLotMovementV1,\n): void {\n economyAssert(\n movement.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported source-lot-movement contract version\",\n );\n assertEconomyIdentifier(movement.movementId, \"movementId\");\n assertEconomyIdentifier(movement.transactionId, \"transactionId\");\n assertEconomyIdentifier(movement.lotId, \"lotId\");\n economyAssert(\n [\n \"allocate\",\n \"boost\",\n \"reclaim\",\n \"spend\",\n \"hold\",\n \"release-hold\",\n \"refund\",\n \"chargeback\",\n \"reversal\",\n ].includes(movement.movementType),\n \"INVALID_CONTRACT\",\n \"Source-lot movement has an unsupported type\",\n );\n const remaining = parseTokenSubunits(movement.remainingDelta);\n const held = parseTokenSubunits(movement.heldDelta);\n const reversed = parseTokenSubunits(movement.reversedDelta);\n economyAssert(\n remaining !== 0n || held !== 0n || reversed !== 0n,\n \"INVALID_AMOUNT\",\n \"Source-lot movement must change at least one amount\",\n );\n economyAssert(\n Number.isSafeInteger(movement.expectedVersion) &&\n movement.expectedVersion >= 1 &&\n movement.resultingVersion === movement.expectedVersion + 1,\n \"INVALID_CONTRACT\",\n \"Source-lot movement must advance its optimistic version exactly once\",\n );\n assertRefundState(movement.expectedRefundState);\n assertRefundState(movement.resultingRefundState);\n parseIsoTimestamp(movement.occurredAt);\n\n if (\n movement.movementType === \"allocate\" ||\n movement.movementType === \"boost\" ||\n movement.movementType === \"spend\"\n ) {\n economyAssert(\n remaining < 0n &&\n held === 0n &&\n reversed === 0n &&\n movement.resultingRefundState === movement.expectedRefundState,\n \"INVALID_CONTRACT\",\n \"Allocation, boost, and spend movements only consume remaining lot value\",\n );\n } else if (movement.movementType === \"reclaim\") {\n economyAssert(\n remaining > 0n &&\n held === 0n &&\n reversed === 0n &&\n movement.resultingRefundState === movement.expectedRefundState,\n \"INVALID_CONTRACT\",\n \"Reclaim movements only restore remaining lot value\",\n );\n } else if (movement.movementType === \"hold\") {\n economyAssert(\n remaining === 0n &&\n held > 0n &&\n reversed === 0n &&\n movement.resultingRefundState === \"disputed\",\n \"INVALID_CONTRACT\",\n \"Hold movements must enter disputed state and increase held value\",\n );\n } else if (movement.movementType === \"release-hold\") {\n economyAssert(\n remaining === 0n &&\n held < 0n &&\n reversed === 0n &&\n movement.expectedRefundState === \"disputed\" &&\n movement.resultingRefundState !== \"disputed\" &&\n movement.resultingRefundState !== \"refunded\" &&\n movement.resultingRefundState !== \"chargeback-lost\",\n \"INVALID_CONTRACT\",\n \"Released holds must leave disputed state without reversing value\",\n );\n } else {\n economyAssert(\n remaining < 0n &&\n reversed === -remaining &&\n held <= 0n &&\n (movement.resultingRefundState === \"partial\" ||\n movement.resultingRefundState === \"refunded\" ||\n movement.resultingRefundState === \"chargeback-lost\"),\n \"INVALID_CONTRACT\",\n \"Refund, chargeback, and reversal movements must compensate remaining value exactly\",\n );\n if (movement.movementType === \"chargeback\") {\n economyAssert(\n movement.resultingRefundState === \"chargeback-lost\",\n \"INVALID_CONTRACT\",\n \"Chargeback movements must enter chargeback-lost state\",\n );\n } else {\n economyAssert(\n movement.resultingRefundState !== \"chargeback-lost\",\n \"INVALID_CONTRACT\",\n \"Only a chargeback movement may enter chargeback-lost state\",\n );\n }\n }\n}\n\n/**\n * Applies one immutable movement to a locked source-lot snapshot. Persistence\n * must append the movement and compare-and-swap this result atomically.\n */\nexport function applySourceLotMovement(\n snapshot: VersionedSourceLotV1,\n movement: SourceLotMovementV1,\n): VersionedSourceLotV1 {\n assertVersionedSourceLot(snapshot);\n assertSourceLotMovement(movement);\n economyAssert(\n movement.lotId === snapshot.lot.lotId &&\n movement.expectedVersion === snapshot.version &&\n movement.expectedRefundState === snapshot.lot.refundState,\n \"INVALID_CONTRACT\",\n \"Source-lot movement does not match the locked lot version and refund state\",\n );\n economyAssert(\n parseIsoTimestamp(movement.occurredAt) >=\n parseIsoTimestamp(snapshot.updatedAt),\n \"INVALID_TIME_WINDOW\",\n \"Source-lot movement cannot precede its current projection\",\n );\n\n const lot: SourceLotV1 = {\n ...snapshot.lot,\n remainingAmount: serializeTokenSubunits(\n parseTokenSubunits(snapshot.lot.remainingAmount) +\n parseTokenSubunits(movement.remainingDelta),\n ),\n heldAmount: serializeTokenSubunits(\n parseTokenSubunits(snapshot.lot.heldAmount) +\n parseTokenSubunits(movement.heldDelta),\n ),\n reversedAmount: serializeTokenSubunits(\n parseTokenSubunits(snapshot.lot.reversedAmount) +\n parseTokenSubunits(movement.reversedDelta),\n ),\n refundState: movement.resultingRefundState,\n };\n assertSourceLot(lot);\n\n const remaining = parseTokenSubunits(lot.remainingAmount);\n const held = parseTokenSubunits(lot.heldAmount);\n const reversed = parseTokenSubunits(lot.reversedAmount);\n const original = parseTokenSubunits(lot.originalAmount);\n if (lot.refundState === \"none\") {\n economyAssert(\n reversed === 0n && held === 0n,\n \"INVALID_CONTRACT\",\n \"A clear lot cannot retain held or reversed value\",\n );\n } else if (lot.refundState === \"partial\") {\n economyAssert(\n reversed > 0n && remaining > 0n && held === 0n,\n \"INVALID_CONTRACT\",\n \"A partial refund requires retained/reversed value and no active hold\",\n );\n } else if (lot.refundState === \"disputed\") {\n economyAssert(\n held > 0n,\n \"INVALID_CONTRACT\",\n \"A disputed lot must hold affected value\",\n );\n } else {\n economyAssert(\n remaining === 0n && held === 0n && reversed === original,\n \"INVALID_CONTRACT\",\n \"Final refund and lost-chargeback states must reverse the full lot\",\n );\n }\n\n return {\n schemaVersion: ECONOMY_CONTRACT_VERSION,\n lot,\n version: movement.resultingVersion,\n updatedAt: movement.occurredAt,\n };\n}\n\n/** Returns unheld, unconsumed TokenSubunits in a source lot. */\nexport function availableSourceLotAmount(lot: SourceLotV1): bigint {\n assertSourceLot(lot);\n return (\n parseTokenSubunits(lot.remainingAmount) - parseTokenSubunits(lot.heldAmount)\n );\n}\n\n/** Evaluates provider/source restrictions without trusting a browser claim. */\nexport function canUseSourceLot(\n lot: SourceLotV1,\n context: LotUseContextV1,\n): boolean {\n if (context.operation === \"refund\") {\n return true;\n }\n\n if (context.operation === \"allocate\" || context.operation === \"reclaim\") {\n return (\n lot.transferPolicy === \"household-allocatable\" &&\n lot.householdId !== undefined &&\n lot.householdId === context.householdId\n );\n }\n\n if (lot.transferPolicy === \"household-allocatable\") {\n return (\n lot.householdId !== undefined && lot.householdId === context.householdId\n );\n }\n\n return lot.beneficiaryAccountId === context.beneficiaryAccountId;\n}\n\n/**\n * Selects eligible lots deterministically in credited-time/lot-id order.\n * The returned slices are a proposal; persistence must consume them atomically.\n */\nexport function selectSourceLots(\n lots: readonly SourceLotV1[],\n requestedAmount: TokenSubunitString,\n context: LotUseContextV1,\n): readonly SourceLotSliceV1[] {\n const requested = parseTokenSubunits(requestedAmount);\n economyAssert(\n requested > 0n,\n \"INVALID_AMOUNT\",\n \"Requested source-lot amount must be positive\",\n );\n assertEconomyIdentifier(context.beneficiaryAccountId, \"beneficiaryAccountId\");\n\n const ordered = [...lots].sort((left, right) => {\n const timeDifference =\n parseIsoTimestamp(left.creditedAt) - parseIsoTimestamp(right.creditedAt);\n return timeDifference === 0\n ? left.lotId.localeCompare(right.lotId)\n : timeDifference;\n });\n\n let allAvailable = 0n;\n let remaining = requested;\n const slices: SourceLotSliceV1[] = [];\n\n for (const lot of ordered) {\n const available = availableSourceLotAmount(lot);\n allAvailable += available;\n if (available === 0n || !canUseSourceLot(lot, context)) {\n continue;\n }\n const selected = available < remaining ? available : remaining;\n slices.push({ lotId: lot.lotId, amount: serializeTokenSubunits(selected) });\n remaining -= selected;\n if (remaining === 0n) {\n return slices;\n }\n }\n\n if (allAvailable >= requested) {\n throw new EconomyError(\n \"SOURCE_LOT_RESTRICTED\",\n \"Available source lots do not permit this operation\",\n );\n }\n throw new EconomyError(\n \"INSUFFICIENT_ELIGIBLE_LOTS\",\n \"Insufficient eligible source-lot balance\",\n );\n}\n","import {\n isWholeTokenAmount,\n parseTokenSubunits,\n serializeTokenSubunits,\n sumTokenSubunits,\n type TokenSubunitString,\n} from \"./amount.js\";\nimport {\n ECONOMY_CONTRACT_VERSION,\n assertEconomyIdentifier,\n parseIsoTimestamp,\n type AccountId,\n type EconomyContractVersion,\n type HouseholdId,\n type IsoTimestamp,\n type LearningEntitlementId,\n type LearningModuleVersionId,\n type ModuleAllowanceId,\n type ModuleSpendHoldId,\n type ModuleSpendQuoteId,\n type TransactionId,\n type WalletId,\n} from \"./contracts.js\";\nimport { economyAssert } from \"./errors.js\";\nimport type { SourceLotSliceV1 } from \"./lots.js\";\n\nexport const MODULE_ALLOWANCE_PURPOSE =\n \"junior-coder-module-entitlement\" as const;\n\nexport type ModuleAllowanceStatusV1 = \"active\" | \"closed\";\n\n/** Guardian-funded value that can only purchase modules for one child. */\nexport interface ModuleAllowanceV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly purpose: typeof MODULE_ALLOWANCE_PURPOSE;\n readonly allowanceId: ModuleAllowanceId;\n readonly householdId: HouseholdId;\n readonly hostWalletId: WalletId;\n readonly allowanceWalletId: WalletId;\n readonly childAccountId: AccountId;\n readonly status: ModuleAllowanceStatusV1;\n readonly allocatedAmount: TokenSubunitString;\n readonly availableAmount: TokenSubunitString;\n readonly heldAmount: TokenSubunitString;\n readonly spentAmount: TokenSubunitString;\n readonly reclaimedAmount: TokenSubunitString;\n readonly fundingSlices: readonly SourceLotSliceV1[];\n readonly reclaimedSlices: readonly SourceLotSliceV1[];\n readonly version: number;\n readonly createdAt: IsoTimestamp;\n readonly updatedAt: IsoTimestamp;\n}\n\nexport interface CreateModuleAllowanceInputV1 {\n readonly allowanceId: ModuleAllowanceId;\n readonly householdId: HouseholdId;\n readonly hostWalletId: WalletId;\n readonly allowanceWalletId: WalletId;\n readonly childAccountId: AccountId;\n readonly amount: TokenSubunitString;\n readonly fundingSlices: readonly SourceLotSliceV1[];\n readonly occurredAt: IsoTimestamp;\n}\n\nexport interface FundModuleAllowanceInputV1 {\n readonly amount: TokenSubunitString;\n readonly fundingSlices: readonly SourceLotSliceV1[];\n readonly expectedVersion: number;\n readonly occurredAt: IsoTimestamp;\n}\n\nexport interface ReclaimModuleAllowanceInputV1 {\n readonly amount: TokenSubunitString;\n readonly sourceSlices: readonly SourceLotSliceV1[];\n readonly expectedVersion: number;\n readonly occurredAt: IsoTimestamp;\n}\n\nexport interface CloseModuleAllowanceInputV1 {\n readonly expectedVersion: number;\n readonly occurredAt: IsoTimestamp;\n}\n\n/** Immutable Guardian-approved module price and requirements evidence. */\nexport interface ModuleSpendQuoteV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly quoteId: ModuleSpendQuoteId;\n readonly allowanceId: ModuleAllowanceId;\n readonly householdId: HouseholdId;\n readonly guardianAccountId: AccountId;\n readonly childAccountId: AccountId;\n readonly moduleVersionId: LearningModuleVersionId;\n readonly catalogVersion: string;\n readonly amount: TokenSubunitString;\n readonly requirementsManifestVersion: string;\n readonly requirementsManifestHash: string;\n readonly requirementsAcknowledgedAt: IsoTimestamp;\n readonly issuedAt: IsoTimestamp;\n readonly expiresAt: IsoTimestamp;\n}\n\nexport type CreateModuleSpendQuoteInputV1 = Omit<\n ModuleSpendQuoteV1,\n \"schemaVersion\"\n>;\n\nexport type ModuleSpendHoldStatusV1 = \"held\" | \"settled\" | \"released\";\n\n/** Versioned projection for one quote-bound allowance hold. */\nexport interface ModuleSpendHoldV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly holdId: ModuleSpendHoldId;\n readonly quoteId: ModuleSpendQuoteId;\n readonly allowanceId: ModuleAllowanceId;\n readonly householdId: HouseholdId;\n readonly guardianAccountId: AccountId;\n readonly childAccountId: AccountId;\n readonly moduleVersionId: LearningModuleVersionId;\n readonly amount: TokenSubunitString;\n readonly requirementsManifestVersion: string;\n readonly requirementsManifestHash: string;\n readonly sourceSlices: readonly SourceLotSliceV1[];\n readonly status: ModuleSpendHoldStatusV1;\n readonly holdIdempotencyKey: string;\n readonly settlementIdempotencyKey?: string;\n readonly releaseIdempotencyKey?: string;\n readonly entitlementId?: LearningEntitlementId;\n readonly settlementTransactionId?: TransactionId;\n readonly releaseTransactionId?: TransactionId;\n readonly version: number;\n readonly createdAt: IsoTimestamp;\n readonly expiresAt: IsoTimestamp;\n readonly updatedAt: IsoTimestamp;\n}\n\nexport interface CreateModuleSpendHoldInputV1 {\n readonly holdId: ModuleSpendHoldId;\n readonly idempotencyKey: string;\n readonly sourceSlices: readonly SourceLotSliceV1[];\n readonly expectedAllowanceVersion: number;\n readonly occurredAt: IsoTimestamp;\n}\n\nexport interface SettleModuleSpendHoldInputV1 {\n readonly entitlementId: LearningEntitlementId;\n readonly settlementTransactionId: TransactionId;\n readonly idempotencyKey: string;\n readonly expectedAllowanceVersion: number;\n readonly expectedHoldVersion: number;\n readonly occurredAt: IsoTimestamp;\n}\n\nexport interface ReleaseModuleSpendHoldInputV1 {\n readonly releaseTransactionId: TransactionId;\n readonly idempotencyKey: string;\n readonly expectedAllowanceVersion: number;\n readonly expectedHoldVersion: number;\n readonly occurredAt: IsoTimestamp;\n}\n\nexport interface ModuleSpendTransitionResultV1 {\n readonly allowance: ModuleAllowanceV1;\n readonly hold: ModuleSpendHoldV1;\n}\n\n/** Durable economic receipt for an activated learning entitlement. */\nexport interface ModulePurchaseReceiptV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly receiptId: string;\n readonly quoteId: ModuleSpendQuoteId;\n readonly holdId: ModuleSpendHoldId;\n readonly allowanceId: ModuleAllowanceId;\n readonly householdId: HouseholdId;\n readonly guardianAccountId: AccountId;\n readonly childAccountId: AccountId;\n readonly moduleVersionId: LearningModuleVersionId;\n readonly entitlementId: LearningEntitlementId;\n readonly amount: TokenSubunitString;\n readonly requirementsManifestVersion: string;\n readonly requirementsManifestHash: string;\n readonly settlementTransactionId: TransactionId;\n readonly issuedAt: IsoTimestamp;\n}\n\nexport interface CreateModulePurchaseReceiptInputV1 {\n readonly receiptId: string;\n readonly issuedAt: IsoTimestamp;\n}\n\nexport type ModulePurchaseFinancialStateV1 =\n | \"missing\"\n | \"held\"\n | \"settled\"\n | \"released\";\nexport type ModulePurchaseEntitlementStateV1 =\n | \"missing\"\n | \"pending\"\n | \"active\"\n | \"cancelled\";\n\n/** Privacy-minimized observation used by an authoritative reconciler. */\nexport interface ModulePurchaseReconciliationObservationV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly quoteId: ModuleSpendQuoteId;\n readonly holdId: ModuleSpendHoldId;\n readonly childAccountId: AccountId;\n readonly moduleVersionId: LearningModuleVersionId;\n readonly financialState: ModulePurchaseFinancialStateV1;\n readonly entitlementState: ModulePurchaseEntitlementStateV1;\n readonly receiptPresent: boolean;\n readonly observedAt: IsoTimestamp;\n}\n\nexport type ModulePurchaseReconciliationActionV1 =\n | \"none\"\n | \"resume-settlement\"\n | \"release-hold\"\n | \"activate-entitlement\"\n | \"issue-receipt\"\n | \"cancel-pending-entitlement\"\n | \"manual-review\";\n\nexport interface ModulePurchaseReconciliationResultV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly action: ModulePurchaseReconciliationActionV1;\n readonly blocking: boolean;\n readonly consistent: boolean;\n readonly reasonCode: string;\n}\n\nfunction assertWholePositive(amount: TokenSubunitString, label: string): bigint {\n const parsed = parseTokenSubunits(amount);\n economyAssert(parsed > 0n, \"INVALID_AMOUNT\", `${label} must be positive`);\n economyAssert(\n isWholeTokenAmount(parsed),\n \"AMOUNT_NOT_WHOLE_TOKEN\",\n `${label} must contain whole Tokens`,\n );\n return parsed;\n}\n\nfunction assertPositiveSlices(\n slices: readonly SourceLotSliceV1[],\n expectedAmount: bigint,\n label: string,\n): void {\n economyAssert(slices.length > 0, \"INVALID_CONTRACT\", `${label} are required`);\n const lotIds = new Set<string>();\n for (const slice of slices) {\n assertEconomyIdentifier(slice.lotId, \"lotId\");\n economyAssert(\n !lotIds.has(slice.lotId),\n \"DUPLICATE_IDENTIFIER\",\n `${label} must not repeat a lot`,\n );\n lotIds.add(slice.lotId);\n economyAssert(\n parseTokenSubunits(slice.amount) > 0n,\n \"INVALID_AMOUNT\",\n `${label} amounts must be positive`,\n );\n }\n economyAssert(\n sumTokenSubunits(slices.map((slice) => slice.amount)) === expectedAmount,\n \"INVALID_CONTRACT\",\n `${label} must sum to the operation amount`,\n );\n}\n\nfunction sumSlicesByLot(\n slices: readonly SourceLotSliceV1[],\n): ReadonlyMap<string, bigint> {\n const totals = new Map<string, bigint>();\n for (const slice of slices) {\n assertEconomyIdentifier(slice.lotId, \"lotId\");\n const amount = parseTokenSubunits(slice.amount);\n economyAssert(amount > 0n, \"INVALID_AMOUNT\", \"Lot slices must be positive\");\n totals.set(slice.lotId, (totals.get(slice.lotId) ?? 0n) + amount);\n }\n return totals;\n}\n\nfunction assertSha256Reference(value: string, label: string): void {\n economyAssert(\n typeof value === \"string\" && /^sha256:[a-f0-9]{64}$/u.test(value),\n \"INVALID_CONTRACT\",\n `${label} must be a canonical SHA-256 reference`,\n );\n}\n\nfunction assertUpdatedAt(\n current: IsoTimestamp,\n occurredAt: IsoTimestamp,\n label: string,\n): void {\n economyAssert(\n parseIsoTimestamp(occurredAt) >= parseIsoTimestamp(current),\n \"INVALID_TIME_WINDOW\",\n `${label} cannot precede the current state`,\n );\n}\n\n/** Validates exact arithmetic and source-lot provenance for an allowance. */\nexport function assertModuleAllowance(allowance: ModuleAllowanceV1): void {\n economyAssert(\n allowance.schemaVersion === ECONOMY_CONTRACT_VERSION &&\n allowance.purpose === MODULE_ALLOWANCE_PURPOSE,\n \"INVALID_CONTRACT\",\n \"Unsupported Module Allowance contract\",\n );\n assertEconomyIdentifier(allowance.allowanceId, \"allowanceId\");\n assertEconomyIdentifier(allowance.householdId, \"householdId\");\n assertEconomyIdentifier(allowance.hostWalletId, \"hostWalletId\");\n assertEconomyIdentifier(allowance.allowanceWalletId, \"allowanceWalletId\");\n assertEconomyIdentifier(allowance.childAccountId, \"childAccountId\");\n economyAssert(\n allowance.hostWalletId !== allowance.allowanceWalletId,\n \"INVALID_CONTRACT\",\n \"Host and Module Allowance wallets must be distinct\",\n );\n economyAssert(\n allowance.status === \"active\" || allowance.status === \"closed\",\n \"INVALID_CONTRACT\",\n \"Module Allowance status is unsupported\",\n );\n const createdAt = parseIsoTimestamp(allowance.createdAt);\n const updatedAt = parseIsoTimestamp(allowance.updatedAt);\n economyAssert(\n updatedAt >= createdAt,\n \"INVALID_TIME_WINDOW\",\n \"Module Allowance update cannot precede creation\",\n );\n economyAssert(\n Number.isSafeInteger(allowance.version) && allowance.version >= 1,\n \"INVALID_CONTRACT\",\n \"Module Allowance version must be a positive safe integer\",\n );\n\n const allocated = parseTokenSubunits(allowance.allocatedAmount);\n const available = parseTokenSubunits(allowance.availableAmount);\n const held = parseTokenSubunits(allowance.heldAmount);\n const spent = parseTokenSubunits(allowance.spentAmount);\n const reclaimed = parseTokenSubunits(allowance.reclaimedAmount);\n economyAssert(\n allocated > 0n &&\n [allocated, available, held, spent, reclaimed].every(\n (amount) => amount >= 0n && isWholeTokenAmount(amount),\n ),\n \"AMOUNT_NOT_WHOLE_TOKEN\",\n \"Module Allowance amounts must be non-negative whole Tokens\",\n );\n economyAssert(\n allocated === available + held + spent + reclaimed,\n \"INVALID_CONTRACT\",\n \"Module Allowance buckets must equal its lifetime allocation\",\n );\n economyAssert(\n allowance.status !== \"closed\" || (available === 0n && held === 0n),\n \"INVALID_CONTRACT\",\n \"A closed Module Allowance cannot retain available or held value\",\n );\n\n const fundedByLot = sumSlicesByLot(allowance.fundingSlices);\n const reclaimedByLot = sumSlicesByLot(allowance.reclaimedSlices);\n economyAssert(\n sumTokenSubunits(allowance.fundingSlices.map((slice) => slice.amount)) ===\n allocated,\n \"INVALID_CONTRACT\",\n \"Module Allowance funding provenance must equal allocated value\",\n );\n economyAssert(\n sumTokenSubunits(allowance.reclaimedSlices.map((slice) => slice.amount)) ===\n reclaimed,\n \"INVALID_CONTRACT\",\n \"Module Allowance reclaim provenance must equal reclaimed value\",\n );\n for (const [lotId, amount] of reclaimedByLot) {\n economyAssert(\n amount <= (fundedByLot.get(lotId) ?? 0n),\n \"SOURCE_LOT_RESTRICTED\",\n \"Reclaimed provenance cannot exceed Module Allowance funding\",\n );\n }\n}\n\n/** Creates a child-specific Module Allowance from locked source-lot slices. */\nexport function createModuleAllowance(\n input: CreateModuleAllowanceInputV1,\n): ModuleAllowanceV1 {\n const amount = assertWholePositive(input.amount, \"Module Allowance amount\");\n assertPositiveSlices(input.fundingSlices, amount, \"Funding slices\");\n const allowance: ModuleAllowanceV1 = {\n schemaVersion: ECONOMY_CONTRACT_VERSION,\n purpose: MODULE_ALLOWANCE_PURPOSE,\n allowanceId: input.allowanceId,\n householdId: input.householdId,\n hostWalletId: input.hostWalletId,\n allowanceWalletId: input.allowanceWalletId,\n childAccountId: input.childAccountId,\n status: \"active\",\n allocatedAmount: input.amount,\n availableAmount: input.amount,\n heldAmount: serializeTokenSubunits(0n),\n spentAmount: serializeTokenSubunits(0n),\n reclaimedAmount: serializeTokenSubunits(0n),\n fundingSlices: input.fundingSlices,\n reclaimedSlices: [],\n version: 1,\n createdAt: input.occurredAt,\n updatedAt: input.occurredAt,\n };\n assertModuleAllowance(allowance);\n return allowance;\n}\n\n/** Adds Guardian-selected source-lot value without replacing prior history. */\nexport function fundModuleAllowance(\n allowance: ModuleAllowanceV1,\n input: FundModuleAllowanceInputV1,\n): ModuleAllowanceV1 {\n assertModuleAllowance(allowance);\n economyAssert(\n allowance.status === \"active\" && allowance.version === input.expectedVersion,\n \"INVALID_CONTRACT\",\n \"Module Allowance is closed or its optimistic version is stale\",\n );\n assertUpdatedAt(allowance.updatedAt, input.occurredAt, \"Funding time\");\n const amount = assertWholePositive(input.amount, \"Module Allowance funding\");\n assertPositiveSlices(input.fundingSlices, amount, \"Funding slices\");\n const next: ModuleAllowanceV1 = {\n ...allowance,\n allocatedAmount: serializeTokenSubunits(\n parseTokenSubunits(allowance.allocatedAmount) + amount,\n ),\n availableAmount: serializeTokenSubunits(\n parseTokenSubunits(allowance.availableAmount) + amount,\n ),\n fundingSlices: [...allowance.fundingSlices, ...input.fundingSlices],\n version: allowance.version + 1,\n updatedAt: input.occurredAt,\n };\n assertModuleAllowance(next);\n return next;\n}\n\n/** Returns unused value to its source lots without changing spent history. */\nexport function reclaimModuleAllowance(\n allowance: ModuleAllowanceV1,\n input: ReclaimModuleAllowanceInputV1,\n): ModuleAllowanceV1 {\n assertModuleAllowance(allowance);\n economyAssert(\n allowance.status === \"active\" && allowance.version === input.expectedVersion,\n \"INVALID_CONTRACT\",\n \"Module Allowance is closed or its optimistic version is stale\",\n );\n assertUpdatedAt(allowance.updatedAt, input.occurredAt, \"Reclaim time\");\n const amount = assertWholePositive(input.amount, \"Module Allowance reclaim\");\n economyAssert(\n amount <= parseTokenSubunits(allowance.availableAmount),\n \"INSUFFICIENT_BALANCE\",\n \"Cannot reclaim held, spent, or unavailable Module Allowance value\",\n );\n assertPositiveSlices(input.sourceSlices, amount, \"Reclaim slices\");\n const fundedLotIds = new Set(\n allowance.fundingSlices.map((slice) => slice.lotId),\n );\n economyAssert(\n input.sourceSlices.every((slice) => fundedLotIds.has(slice.lotId)),\n \"SOURCE_LOT_RESTRICTED\",\n \"Reclaim slices must originate from the Module Allowance\",\n );\n const next: ModuleAllowanceV1 = {\n ...allowance,\n availableAmount: serializeTokenSubunits(\n parseTokenSubunits(allowance.availableAmount) - amount,\n ),\n reclaimedAmount: serializeTokenSubunits(\n parseTokenSubunits(allowance.reclaimedAmount) + amount,\n ),\n reclaimedSlices: [...allowance.reclaimedSlices, ...input.sourceSlices],\n version: allowance.version + 1,\n updatedAt: input.occurredAt,\n };\n assertModuleAllowance(next);\n return next;\n}\n\n/** Closes an empty allowance; funding later requires a new allowance. */\nexport function closeModuleAllowance(\n allowance: ModuleAllowanceV1,\n input: CloseModuleAllowanceInputV1,\n): ModuleAllowanceV1 {\n assertModuleAllowance(allowance);\n economyAssert(\n allowance.status === \"active\" && allowance.version === input.expectedVersion,\n \"INVALID_CONTRACT\",\n \"Module Allowance is closed or its optimistic version is stale\",\n );\n assertUpdatedAt(allowance.updatedAt, input.occurredAt, \"Closure time\");\n economyAssert(\n parseTokenSubunits(allowance.availableAmount) === 0n &&\n parseTokenSubunits(allowance.heldAmount) === 0n,\n \"INVALID_CONTRACT\",\n \"Available value must be reclaimed and holds resolved before closure\",\n );\n const next: ModuleAllowanceV1 = {\n ...allowance,\n status: \"closed\",\n version: allowance.version + 1,\n updatedAt: input.occurredAt,\n };\n assertModuleAllowance(next);\n return next;\n}\n\n/** Validates immutable price, Guardian acknowledgement, and manifest evidence. */\nexport function assertModuleSpendQuote(quote: ModuleSpendQuoteV1): void {\n economyAssert(\n quote.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported module-spend quote contract version\",\n );\n assertEconomyIdentifier(quote.quoteId, \"quoteId\");\n assertEconomyIdentifier(quote.allowanceId, \"allowanceId\");\n assertEconomyIdentifier(quote.householdId, \"householdId\");\n assertEconomyIdentifier(quote.guardianAccountId, \"guardianAccountId\");\n assertEconomyIdentifier(quote.childAccountId, \"childAccountId\");\n assertEconomyIdentifier(quote.moduleVersionId, \"moduleVersionId\");\n assertEconomyIdentifier(quote.catalogVersion, \"catalogVersion\");\n assertEconomyIdentifier(\n quote.requirementsManifestVersion,\n \"requirementsManifestVersion\",\n );\n assertSha256Reference(\n quote.requirementsManifestHash,\n \"Requirements manifest hash\",\n );\n assertWholePositive(quote.amount, \"Module price\");\n const acknowledgedAt = parseIsoTimestamp(quote.requirementsAcknowledgedAt);\n const issuedAt = parseIsoTimestamp(quote.issuedAt);\n const expiresAt = parseIsoTimestamp(quote.expiresAt);\n economyAssert(\n acknowledgedAt <= issuedAt && expiresAt > issuedAt,\n \"INVALID_TIME_WINDOW\",\n \"Requirements must be acknowledged before a bounded quote is issued\",\n );\n}\n\n/** Creates immutable quote evidence from server-derived catalog facts. */\nexport function createModuleSpendQuote(\n input: CreateModuleSpendQuoteInputV1,\n): ModuleSpendQuoteV1 {\n const quote: ModuleSpendQuoteV1 = {\n schemaVersion: ECONOMY_CONTRACT_VERSION,\n ...input,\n };\n assertModuleSpendQuote(quote);\n return quote;\n}\n\n/** Validates one quote-bound hold lifecycle projection. */\nexport function assertModuleSpendHold(hold: ModuleSpendHoldV1): void {\n economyAssert(\n hold.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported module-spend hold contract version\",\n );\n assertEconomyIdentifier(hold.holdId, \"holdId\");\n assertEconomyIdentifier(hold.quoteId, \"quoteId\");\n assertEconomyIdentifier(hold.allowanceId, \"allowanceId\");\n assertEconomyIdentifier(hold.householdId, \"householdId\");\n assertEconomyIdentifier(hold.guardianAccountId, \"guardianAccountId\");\n assertEconomyIdentifier(hold.childAccountId, \"childAccountId\");\n assertEconomyIdentifier(hold.moduleVersionId, \"moduleVersionId\");\n assertEconomyIdentifier(\n hold.requirementsManifestVersion,\n \"requirementsManifestVersion\",\n );\n assertSha256Reference(\n hold.requirementsManifestHash,\n \"Requirements manifest hash\",\n );\n assertEconomyIdentifier(hold.holdIdempotencyKey, \"holdIdempotencyKey\");\n const amount = assertWholePositive(hold.amount, \"Module hold amount\");\n assertPositiveSlices(hold.sourceSlices, amount, \"Hold source slices\");\n economyAssert(\n [\"held\", \"settled\", \"released\"].includes(hold.status),\n \"INVALID_CONTRACT\",\n \"Module hold status is unsupported\",\n );\n economyAssert(\n Number.isSafeInteger(hold.version) && hold.version >= 1,\n \"INVALID_CONTRACT\",\n \"Module hold version must be a positive safe integer\",\n );\n const createdAt = parseIsoTimestamp(hold.createdAt);\n const expiresAt = parseIsoTimestamp(hold.expiresAt);\n const updatedAt = parseIsoTimestamp(hold.updatedAt);\n economyAssert(\n expiresAt > createdAt && updatedAt >= createdAt,\n \"INVALID_TIME_WINDOW\",\n \"Module hold requires a bounded lifetime and ordered updates\",\n );\n\n if (hold.status === \"held\") {\n economyAssert(\n hold.entitlementId === undefined &&\n hold.settlementTransactionId === undefined &&\n hold.releaseTransactionId === undefined &&\n hold.settlementIdempotencyKey === undefined &&\n hold.releaseIdempotencyKey === undefined,\n \"INVALID_CONTRACT\",\n \"An unsettled hold cannot claim an entitlement or final transaction\",\n );\n } else if (hold.status === \"settled\") {\n economyAssert(\n hold.entitlementId !== undefined &&\n hold.settlementTransactionId !== undefined &&\n hold.settlementIdempotencyKey !== undefined &&\n hold.releaseTransactionId === undefined &&\n hold.releaseIdempotencyKey === undefined,\n \"INVALID_CONTRACT\",\n \"A settled hold requires entitlement and transaction evidence\",\n );\n assertEconomyIdentifier(hold.entitlementId, \"entitlementId\");\n assertEconomyIdentifier(\n hold.settlementTransactionId,\n \"settlementTransactionId\",\n );\n assertEconomyIdentifier(\n hold.settlementIdempotencyKey,\n \"settlementIdempotencyKey\",\n );\n } else {\n economyAssert(\n hold.entitlementId === undefined &&\n hold.settlementTransactionId === undefined &&\n hold.settlementIdempotencyKey === undefined &&\n hold.releaseTransactionId !== undefined &&\n hold.releaseIdempotencyKey !== undefined,\n \"INVALID_CONTRACT\",\n \"A released hold requires release evidence only\",\n );\n assertEconomyIdentifier(hold.releaseTransactionId, \"releaseTransactionId\");\n assertEconomyIdentifier(hold.releaseIdempotencyKey, \"releaseIdempotencyKey\");\n }\n}\n\nfunction assertAllowanceMatchesQuote(\n allowance: ModuleAllowanceV1,\n quote: ModuleSpendQuoteV1,\n): void {\n economyAssert(\n allowance.status === \"active\" &&\n allowance.allowanceId === quote.allowanceId &&\n allowance.householdId === quote.householdId &&\n allowance.childAccountId === quote.childAccountId,\n \"INVALID_CONTRACT\",\n \"Module quote does not belong to this active child allowance\",\n );\n}\n\nfunction assertAllowanceMatchesHold(\n allowance: ModuleAllowanceV1,\n hold: ModuleSpendHoldV1,\n): void {\n economyAssert(\n allowance.status === \"active\" &&\n allowance.allowanceId === hold.allowanceId &&\n allowance.householdId === hold.householdId &&\n allowance.childAccountId === hold.childAccountId,\n \"INVALID_CONTRACT\",\n \"Module hold does not belong to this active child allowance\",\n );\n}\n\n/** Moves quoted value from available to held after all bindings are checked. */\nexport function createModuleSpendHold(\n allowance: ModuleAllowanceV1,\n quote: ModuleSpendQuoteV1,\n input: CreateModuleSpendHoldInputV1,\n): ModuleSpendTransitionResultV1 {\n assertModuleAllowance(allowance);\n assertModuleSpendQuote(quote);\n assertAllowanceMatchesQuote(allowance, quote);\n economyAssert(\n allowance.version === input.expectedAllowanceVersion,\n \"INVALID_CONTRACT\",\n \"Module Allowance optimistic version is stale\",\n );\n const occurredAt = parseIsoTimestamp(input.occurredAt);\n economyAssert(\n occurredAt >= parseIsoTimestamp(allowance.updatedAt) &&\n occurredAt >= parseIsoTimestamp(quote.issuedAt) &&\n occurredAt < parseIsoTimestamp(quote.expiresAt),\n \"INVALID_TIME_WINDOW\",\n \"Module quote is not valid at hold time\",\n );\n const amount = parseTokenSubunits(quote.amount);\n economyAssert(\n amount <= parseTokenSubunits(allowance.availableAmount),\n \"INSUFFICIENT_BALANCE\",\n \"Module Allowance has insufficient available value\",\n );\n assertEconomyIdentifier(input.holdId, \"holdId\");\n assertEconomyIdentifier(input.idempotencyKey, \"idempotencyKey\");\n assertPositiveSlices(input.sourceSlices, amount, \"Hold source slices\");\n const fundedLotIds = new Set(\n allowance.fundingSlices.map((slice) => slice.lotId),\n );\n economyAssert(\n input.sourceSlices.every((slice) => fundedLotIds.has(slice.lotId)),\n \"SOURCE_LOT_RESTRICTED\",\n \"Hold slices must originate from the Module Allowance\",\n );\n\n const nextAllowance: ModuleAllowanceV1 = {\n ...allowance,\n availableAmount: serializeTokenSubunits(\n parseTokenSubunits(allowance.availableAmount) - amount,\n ),\n heldAmount: serializeTokenSubunits(\n parseTokenSubunits(allowance.heldAmount) + amount,\n ),\n version: allowance.version + 1,\n updatedAt: input.occurredAt,\n };\n const hold: ModuleSpendHoldV1 = {\n schemaVersion: ECONOMY_CONTRACT_VERSION,\n holdId: input.holdId,\n quoteId: quote.quoteId,\n allowanceId: quote.allowanceId,\n householdId: quote.householdId,\n guardianAccountId: quote.guardianAccountId,\n childAccountId: quote.childAccountId,\n moduleVersionId: quote.moduleVersionId,\n amount: quote.amount,\n requirementsManifestVersion: quote.requirementsManifestVersion,\n requirementsManifestHash: quote.requirementsManifestHash,\n sourceSlices: input.sourceSlices,\n status: \"held\",\n holdIdempotencyKey: input.idempotencyKey,\n version: 1,\n createdAt: input.occurredAt,\n expiresAt: quote.expiresAt,\n updatedAt: input.occurredAt,\n };\n assertModuleAllowance(nextAllowance);\n assertModuleSpendHold(hold);\n return { allowance: nextAllowance, hold };\n}\n\n/** Settles a hold only when the pending learning entitlement is identified. */\nexport function settleModuleSpendHold(\n allowance: ModuleAllowanceV1,\n hold: ModuleSpendHoldV1,\n input: SettleModuleSpendHoldInputV1,\n): ModuleSpendTransitionResultV1 {\n assertModuleAllowance(allowance);\n assertModuleSpendHold(hold);\n assertAllowanceMatchesHold(allowance, hold);\n economyAssert(\n hold.status === \"held\" &&\n allowance.version === input.expectedAllowanceVersion &&\n hold.version === input.expectedHoldVersion,\n \"INVALID_CONTRACT\",\n \"Module hold is final or an optimistic version is stale\",\n );\n assertEconomyIdentifier(input.entitlementId, \"entitlementId\");\n assertEconomyIdentifier(\n input.settlementTransactionId,\n \"settlementTransactionId\",\n );\n assertEconomyIdentifier(input.idempotencyKey, \"idempotencyKey\");\n const occurredAt = parseIsoTimestamp(input.occurredAt);\n economyAssert(\n occurredAt >= parseIsoTimestamp(allowance.updatedAt) &&\n occurredAt >= parseIsoTimestamp(hold.updatedAt) &&\n occurredAt < parseIsoTimestamp(hold.expiresAt),\n \"INVALID_TIME_WINDOW\",\n \"Module hold cannot settle outside its valid lifetime\",\n );\n const amount = parseTokenSubunits(hold.amount);\n economyAssert(\n amount <= parseTokenSubunits(allowance.heldAmount),\n \"INSUFFICIENT_BALANCE\",\n \"Module Allowance does not contain the quoted held value\",\n );\n const nextAllowance: ModuleAllowanceV1 = {\n ...allowance,\n heldAmount: serializeTokenSubunits(\n parseTokenSubunits(allowance.heldAmount) - amount,\n ),\n spentAmount: serializeTokenSubunits(\n parseTokenSubunits(allowance.spentAmount) + amount,\n ),\n version: allowance.version + 1,\n updatedAt: input.occurredAt,\n };\n const nextHold: ModuleSpendHoldV1 = {\n ...hold,\n status: \"settled\",\n settlementIdempotencyKey: input.idempotencyKey,\n entitlementId: input.entitlementId,\n settlementTransactionId: input.settlementTransactionId,\n version: hold.version + 1,\n updatedAt: input.occurredAt,\n };\n assertModuleAllowance(nextAllowance);\n assertModuleSpendHold(nextHold);\n return { allowance: nextAllowance, hold: nextHold };\n}\n\n/** Releases failed or expired held value back to the same allowance. */\nexport function releaseModuleSpendHold(\n allowance: ModuleAllowanceV1,\n hold: ModuleSpendHoldV1,\n input: ReleaseModuleSpendHoldInputV1,\n): ModuleSpendTransitionResultV1 {\n assertModuleAllowance(allowance);\n assertModuleSpendHold(hold);\n assertAllowanceMatchesHold(allowance, hold);\n economyAssert(\n hold.status === \"held\" &&\n allowance.version === input.expectedAllowanceVersion &&\n hold.version === input.expectedHoldVersion,\n \"INVALID_CONTRACT\",\n \"Module hold is final or an optimistic version is stale\",\n );\n assertEconomyIdentifier(input.releaseTransactionId, \"releaseTransactionId\");\n assertEconomyIdentifier(input.idempotencyKey, \"idempotencyKey\");\n const occurredAt = parseIsoTimestamp(input.occurredAt);\n economyAssert(\n occurredAt >= parseIsoTimestamp(allowance.updatedAt) &&\n occurredAt >= parseIsoTimestamp(hold.updatedAt),\n \"INVALID_TIME_WINDOW\",\n \"Module hold release cannot precede its current state\",\n );\n const amount = parseTokenSubunits(hold.amount);\n economyAssert(\n amount <= parseTokenSubunits(allowance.heldAmount),\n \"INSUFFICIENT_BALANCE\",\n \"Module Allowance does not contain the quoted held value\",\n );\n const nextAllowance: ModuleAllowanceV1 = {\n ...allowance,\n availableAmount: serializeTokenSubunits(\n parseTokenSubunits(allowance.availableAmount) + amount,\n ),\n heldAmount: serializeTokenSubunits(\n parseTokenSubunits(allowance.heldAmount) - amount,\n ),\n version: allowance.version + 1,\n updatedAt: input.occurredAt,\n };\n const nextHold: ModuleSpendHoldV1 = {\n ...hold,\n status: \"released\",\n releaseIdempotencyKey: input.idempotencyKey,\n releaseTransactionId: input.releaseTransactionId,\n version: hold.version + 1,\n updatedAt: input.occurredAt,\n };\n assertModuleAllowance(nextAllowance);\n assertModuleSpendHold(nextHold);\n return { allowance: nextAllowance, hold: nextHold };\n}\n\n/** Validates a durable receipt against settled economic evidence. */\nexport function assertModulePurchaseReceipt(\n receipt: ModulePurchaseReceiptV1,\n): void {\n economyAssert(\n receipt.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported module-purchase receipt contract version\",\n );\n assertEconomyIdentifier(receipt.receiptId, \"receiptId\");\n assertEconomyIdentifier(receipt.quoteId, \"quoteId\");\n assertEconomyIdentifier(receipt.holdId, \"holdId\");\n assertEconomyIdentifier(receipt.allowanceId, \"allowanceId\");\n assertEconomyIdentifier(receipt.householdId, \"householdId\");\n assertEconomyIdentifier(receipt.guardianAccountId, \"guardianAccountId\");\n assertEconomyIdentifier(receipt.childAccountId, \"childAccountId\");\n assertEconomyIdentifier(receipt.moduleVersionId, \"moduleVersionId\");\n assertEconomyIdentifier(receipt.entitlementId, \"entitlementId\");\n assertEconomyIdentifier(\n receipt.requirementsManifestVersion,\n \"requirementsManifestVersion\",\n );\n assertSha256Reference(\n receipt.requirementsManifestHash,\n \"Requirements manifest hash\",\n );\n assertEconomyIdentifier(\n receipt.settlementTransactionId,\n \"settlementTransactionId\",\n );\n assertWholePositive(receipt.amount, \"Receipt amount\");\n parseIsoTimestamp(receipt.issuedAt);\n}\n\n/** Creates a receipt only when quote and settled hold evidence match exactly. */\nexport function createModulePurchaseReceipt(\n quote: ModuleSpendQuoteV1,\n hold: ModuleSpendHoldV1,\n input: CreateModulePurchaseReceiptInputV1,\n): ModulePurchaseReceiptV1 {\n assertModuleSpendQuote(quote);\n assertModuleSpendHold(hold);\n economyAssert(\n hold.status === \"settled\" &&\n hold.quoteId === quote.quoteId &&\n hold.allowanceId === quote.allowanceId &&\n hold.householdId === quote.householdId &&\n hold.guardianAccountId === quote.guardianAccountId &&\n hold.childAccountId === quote.childAccountId &&\n hold.moduleVersionId === quote.moduleVersionId &&\n hold.amount === quote.amount &&\n hold.requirementsManifestVersion === quote.requirementsManifestVersion &&\n hold.requirementsManifestHash === quote.requirementsManifestHash,\n \"INVALID_CONTRACT\",\n \"Receipt quote and settled hold evidence do not match\",\n );\n economyAssert(\n parseIsoTimestamp(input.issuedAt) >= parseIsoTimestamp(hold.updatedAt),\n \"INVALID_TIME_WINDOW\",\n \"Receipt cannot precede settlement\",\n );\n const receipt: ModulePurchaseReceiptV1 = {\n schemaVersion: ECONOMY_CONTRACT_VERSION,\n receiptId: input.receiptId,\n quoteId: quote.quoteId,\n holdId: hold.holdId,\n allowanceId: quote.allowanceId,\n householdId: quote.householdId,\n guardianAccountId: quote.guardianAccountId,\n childAccountId: quote.childAccountId,\n moduleVersionId: quote.moduleVersionId,\n entitlementId: hold.entitlementId!,\n amount: quote.amount,\n requirementsManifestVersion: quote.requirementsManifestVersion,\n requirementsManifestHash: quote.requirementsManifestHash,\n settlementTransactionId: hold.settlementTransactionId!,\n issuedAt: input.issuedAt,\n };\n assertModulePurchaseReceipt(receipt);\n return receipt;\n}\n\n/** Validates privacy-minimized cross-service reconciliation evidence. */\nexport function assertModulePurchaseReconciliationObservation(\n observation: ModulePurchaseReconciliationObservationV1,\n): void {\n economyAssert(\n observation.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported module-purchase reconciliation contract version\",\n );\n assertEconomyIdentifier(observation.quoteId, \"quoteId\");\n assertEconomyIdentifier(observation.holdId, \"holdId\");\n assertEconomyIdentifier(observation.childAccountId, \"childAccountId\");\n assertEconomyIdentifier(observation.moduleVersionId, \"moduleVersionId\");\n economyAssert(\n [\"missing\", \"held\", \"settled\", \"released\"].includes(\n observation.financialState,\n ),\n \"INVALID_CONTRACT\",\n \"Reconciliation financial state is unsupported\",\n );\n economyAssert(\n [\"missing\", \"pending\", \"active\", \"cancelled\"].includes(\n observation.entitlementState,\n ),\n \"INVALID_CONTRACT\",\n \"Reconciliation entitlement state is unsupported\",\n );\n economyAssert(\n typeof observation.receiptPresent === \"boolean\",\n \"INVALID_CONTRACT\",\n \"Receipt presence must be Boolean\",\n );\n parseIsoTimestamp(observation.observedAt);\n}\n\nfunction reconciliationResult(\n action: ModulePurchaseReconciliationActionV1,\n reasonCode: string,\n blocking = false,\n consistent = false,\n): ModulePurchaseReconciliationResultV1 {\n return {\n schemaVersion: ECONOMY_CONTRACT_VERSION,\n action,\n blocking,\n consistent,\n reasonCode,\n };\n}\n\n/**\n * Returns one forward-safe action. Callers must reload and lock authoritative\n * state before carrying it out; `manual-review` never authorizes a mutation.\n */\nexport function reconcileModulePurchase(\n observation: ModulePurchaseReconciliationObservationV1,\n): ModulePurchaseReconciliationResultV1 {\n assertModulePurchaseReconciliationObservation(observation);\n const { financialState, entitlementState, receiptPresent } = observation;\n\n if (receiptPresent && !(financialState === \"settled\" && entitlementState === \"active\")) {\n return reconciliationResult(\n \"manual-review\",\n \"receipt-conflicts-with-authoritative-state\",\n true,\n );\n }\n if (financialState === \"settled\" && entitlementState === \"active\") {\n return receiptPresent\n ? reconciliationResult(\"none\", \"purchase-consistent\", false, true)\n : reconciliationResult(\"issue-receipt\", \"settled-active-receipt-missing\");\n }\n if (financialState === \"held\" && entitlementState === \"pending\") {\n return reconciliationResult(\"resume-settlement\", \"held-pending\");\n }\n if (\n financialState === \"held\" &&\n (entitlementState === \"missing\" || entitlementState === \"cancelled\")\n ) {\n return reconciliationResult(\"release-hold\", \"held-without-usable-entitlement\");\n }\n if (financialState === \"settled\" && entitlementState === \"pending\") {\n return reconciliationResult(\"activate-entitlement\", \"settled-pending\");\n }\n if (\n (financialState === \"missing\" || financialState === \"released\") &&\n entitlementState === \"pending\"\n ) {\n return reconciliationResult(\n \"cancel-pending-entitlement\",\n \"pending-without-settlement-path\",\n );\n }\n if (\n (financialState === \"missing\" || financialState === \"released\") &&\n (entitlementState === \"missing\" || entitlementState === \"cancelled\")\n ) {\n return reconciliationResult(\"none\", \"no-active-purchase\", false, true);\n }\n return reconciliationResult(\n \"manual-review\",\n financialState === \"settled\"\n ? \"settled-debit-without-entitlement\"\n : \"active-entitlement-without-settled-debit\",\n true,\n );\n}\n","import { parseTokenSubunits, type TokenSubunitString } from \"./amount.js\";\nimport {\n ECONOMY_CONTRACT_VERSION,\n assertEconomyIdentifier,\n parseIsoTimestamp,\n type AccountId,\n type EconomyContractVersion,\n type IsoTimestamp,\n type TransactionId,\n type WalletId,\n} from \"./contracts.js\";\nimport { economyAssert } from \"./errors.js\";\n\nexport type AdjustmentStatus =\n | \"draft\"\n | \"pending-approval\"\n | \"approved\"\n | \"rejected\"\n | \"executed\"\n | \"expired\";\n\n/** Dual-control request; the resulting change is always a ledger transaction. */\nexport interface AdjustmentRequestV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly adjustmentId: string;\n readonly walletId: WalletId;\n readonly amount: TokenSubunitString;\n readonly reason: string;\n readonly ticketReference: string;\n readonly status: AdjustmentStatus;\n readonly initiatedByAccountId: AccountId;\n readonly initiatedAt: IsoTimestamp;\n readonly approvedByAccountId?: AccountId;\n readonly approvedAt?: IsoTimestamp;\n readonly resultingTransactionId?: TransactionId;\n}\n\n/** Proves that production adjustment approval was performed by another actor. */\nexport function assertDistinctAdjustmentApproval(\n request: AdjustmentRequestV1,\n): void {\n economyAssert(\n request.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported adjustment contract version\",\n );\n assertEconomyIdentifier(request.adjustmentId, \"adjustmentId\");\n assertEconomyIdentifier(request.walletId, \"walletId\");\n assertEconomyIdentifier(request.initiatedByAccountId, \"initiatedByAccountId\");\n economyAssert(\n parseTokenSubunits(request.amount) !== 0n,\n \"INVALID_AMOUNT\",\n \"Adjustment amount cannot be zero\",\n );\n economyAssert(\n request.reason.trim().length > 0 && request.reason.length <= 512,\n \"INVALID_CONTRACT\",\n \"Adjustment reason is required and must be bounded\",\n );\n assertEconomyIdentifier(request.ticketReference, \"ticketReference\");\n const initiatedAt = parseIsoTimestamp(request.initiatedAt);\n economyAssert(\n request.approvedByAccountId !== undefined &&\n request.approvedByAccountId !== request.initiatedByAccountId,\n \"INVALID_CONTRACT\",\n \"Adjustment approval requires a distinct authorized operator\",\n );\n assertEconomyIdentifier(request.approvedByAccountId, \"approvedByAccountId\");\n economyAssert(\n request.approvedAt !== undefined &&\n parseIsoTimestamp(request.approvedAt) >= initiatedAt,\n \"INVALID_TIME_WINDOW\",\n \"Adjustment approval time must follow initiation\",\n );\n economyAssert(\n request.status === \"approved\" || request.status === \"executed\",\n \"INVALID_CONTRACT\",\n \"Only approved adjustments satisfy dual-control approval\",\n );\n if (request.resultingTransactionId !== undefined) {\n assertEconomyIdentifier(\n request.resultingTransactionId,\n \"resultingTransactionId\",\n );\n }\n}\n","import {\n parseTokenSubunits,\n serializeTokenSubunits,\n type TokenSubunitString,\n} from \"./amount.js\";\nimport { compareUnicodeCodeUnits } from \"./canonical-order.js\";\nimport {\n ECONOMY_CONTRACT_VERSION,\n assertEconomyIdentifier,\n parseIsoTimestamp,\n type AccountId,\n type EconomyContractVersion,\n type HouseholdId,\n type IsoTimestamp,\n type LotId,\n} from \"./contracts.js\";\nimport type { PaidLotRetentionV1 } from \"./early-backers.js\";\nimport { economyAssert } from \"./errors.js\";\nimport { assertSourceLot, type SourceLotV1 } from \"./lots.js\";\n\nexport type PaidLotLifecycleStatusV1 =\n | \"clear\"\n | \"partially-reversed\"\n | \"disputed\"\n | \"fully-reversed\"\n | \"chargeback-lost\";\n\nexport type PaidLotLifecycleEventTypeV1 =\n | \"refund\"\n | \"dispute-hold\"\n | \"dispute-won\"\n | \"dispute-lost\"\n | \"chargeback\"\n | \"reversal\";\n\n/** Paid-purchase facts not already carried by the source lot. */\nexport interface PaidLotPurchaseProvenanceV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly purchaseId: string;\n readonly catalogVersion: string;\n readonly purchasedAt: IsoTimestamp;\n}\n\n/** Provider-neutral refund/dispute evidence for a paid source lot. */\nexport interface PaidLotLifecycleEventV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly eventId: string;\n readonly lotId: LotId;\n readonly eventType: PaidLotLifecycleEventTypeV1;\n readonly amount: TokenSubunitString;\n readonly occurredAt: IsoTimestamp;\n}\n\nexport interface PaidLotLifecycleReceiptV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly event: PaidLotLifecycleEventV1;\n}\n\n/**\n * Retained paid-lot projection. Immutable purchase/original facts plus every\n * receipt are sufficient to rebuild all derived amounts in occurrence order.\n */\nexport interface PaidLotLifecycleV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly lotId: LotId;\n readonly payerAccountId: AccountId;\n readonly receivingHouseholdId: HouseholdId;\n readonly purchaseId: string;\n readonly catalogVersion: string;\n readonly purchasedAt: IsoTimestamp;\n readonly settledAt: IsoTimestamp;\n readonly creditedAt: IsoTimestamp;\n readonly originalAmount: TokenSubunitString;\n readonly retainedAmount: TokenSubunitString;\n readonly heldAmount: TokenSubunitString;\n readonly reversedAmount: TokenSubunitString;\n readonly refundedAmount: TokenSubunitString;\n readonly chargebackAmount: TokenSubunitString;\n readonly oneTimeReversalAmount: TokenSubunitString;\n readonly status: PaidLotLifecycleStatusV1;\n readonly version: number;\n readonly receipts: readonly PaidLotLifecycleReceiptV1[];\n readonly effectiveEventIds: readonly string[];\n}\n\n/** Exact signed projection deltas produced when one receipt is appended. */\nexport interface PaidLotLifecycleArithmeticV1 {\n readonly retainedDelta: TokenSubunitString;\n readonly heldDelta: TokenSubunitString;\n readonly reversedDelta: TokenSubunitString;\n readonly refundedDelta: TokenSubunitString;\n readonly chargebackDelta: TokenSubunitString;\n readonly oneTimeReversalDelta: TokenSubunitString;\n}\n\nexport interface PaidLotLifecycleMutationResultV1 {\n readonly lifecycle: PaidLotLifecycleV1;\n /** False only for an exact event-ID replay already recorded. */\n readonly applied: boolean;\n readonly stateChanged: boolean;\n readonly arithmetic: PaidLotLifecycleArithmeticV1;\n}\n\ninterface PaidLotImmutableFacts {\n readonly schemaVersion: EconomyContractVersion;\n readonly lotId: LotId;\n readonly payerAccountId: AccountId;\n readonly receivingHouseholdId: HouseholdId;\n readonly purchaseId: string;\n readonly catalogVersion: string;\n readonly purchasedAt: IsoTimestamp;\n readonly settledAt: IsoTimestamp;\n readonly creditedAt: IsoTimestamp;\n readonly originalAmount: TokenSubunitString;\n}\n\ninterface PaidLotProjection {\n readonly retained: bigint;\n readonly held: bigint;\n readonly reversed: bigint;\n readonly refunded: bigint;\n readonly chargeback: bigint;\n readonly oneTimeReversal: bigint;\n readonly status: PaidLotLifecycleStatusV1;\n readonly effectiveEventIds: readonly string[];\n}\n\nconst ZERO_ARITHMETIC: PaidLotLifecycleArithmeticV1 = Object.freeze({\n retainedDelta: serializeTokenSubunits(0n),\n heldDelta: serializeTokenSubunits(0n),\n reversedDelta: serializeTokenSubunits(0n),\n refundedDelta: serializeTokenSubunits(0n),\n chargebackDelta: serializeTokenSubunits(0n),\n oneTimeReversalDelta: serializeTokenSubunits(0n),\n});\n\nconst EVENT_TYPES: readonly PaidLotLifecycleEventTypeV1[] = [\n \"refund\",\n \"dispute-hold\",\n \"dispute-won\",\n \"dispute-lost\",\n \"chargeback\",\n \"reversal\",\n];\n\nconst EVENT_PRECEDENCE: Readonly<Record<PaidLotLifecycleEventTypeV1, number>> = {\n \"dispute-hold\": 0,\n \"dispute-won\": 1,\n \"dispute-lost\": 1,\n refund: 2,\n chargeback: 3,\n reversal: 4,\n};\n\n/** Validates the paid purchase facts paired with a source lot. */\nexport function assertPaidLotPurchaseProvenance(\n provenance: PaidLotPurchaseProvenanceV1,\n): void {\n economyAssert(\n provenance.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported paid-lot provenance contract version\",\n );\n assertEconomyIdentifier(provenance.purchaseId, \"purchaseId\");\n assertEconomyIdentifier(provenance.catalogVersion, \"catalogVersion\");\n parseIsoTimestamp(provenance.purchasedAt);\n}\n\n/** Validates one provider-neutral paid-lot lifecycle event. */\nexport function assertPaidLotLifecycleEvent(\n event: PaidLotLifecycleEventV1,\n): void {\n economyAssert(\n event.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported paid-lot lifecycle event contract version\",\n );\n assertEconomyIdentifier(event.eventId, \"eventId\");\n assertEconomyIdentifier(event.lotId, \"lotId\");\n economyAssert(\n EVENT_TYPES.includes(event.eventType),\n \"INVALID_CONTRACT\",\n \"Paid-lot lifecycle event type is unsupported\",\n );\n economyAssert(\n parseTokenSubunits(event.amount) > 0n,\n \"INVALID_AMOUNT\",\n \"Paid-lot lifecycle event amount must be positive\",\n );\n parseIsoTimestamp(event.occurredAt);\n}\n\nfunction sameEvent(\n left: PaidLotLifecycleEventV1,\n right: PaidLotLifecycleEventV1,\n): boolean {\n return (\n left.schemaVersion === right.schemaVersion &&\n left.eventId === right.eventId &&\n left.lotId === right.lotId &&\n left.eventType === right.eventType &&\n left.amount === right.amount &&\n left.occurredAt === right.occurredAt\n );\n}\n\nfunction compareEvents(\n left: PaidLotLifecycleEventV1,\n right: PaidLotLifecycleEventV1,\n): number {\n const timeDifference =\n parseIsoTimestamp(left.occurredAt) - parseIsoTimestamp(right.occurredAt);\n if (timeDifference !== 0) {\n return timeDifference;\n }\n const precedenceDifference =\n EVENT_PRECEDENCE[left.eventType] - EVENT_PRECEDENCE[right.eventType];\n return precedenceDifference === 0\n ? compareUnicodeCodeUnits(left.eventId, right.eventId)\n : precedenceDifference;\n}\n\nfunction deriveStatus(\n retained: bigint,\n held: bigint,\n reversed: bigint,\n chargeback: bigint,\n): PaidLotLifecycleStatusV1 {\n if (held > 0n) {\n return \"disputed\";\n }\n if (chargeback > 0n) {\n return \"chargeback-lost\";\n }\n if (retained === 0n) {\n return \"fully-reversed\";\n }\n return reversed > 0n ? \"partially-reversed\" : \"clear\";\n}\n\nfunction immutableFactsFromLifecycle(\n lifecycle: PaidLotLifecycleV1,\n): PaidLotImmutableFacts {\n return {\n schemaVersion: lifecycle.schemaVersion,\n lotId: lifecycle.lotId,\n payerAccountId: lifecycle.payerAccountId,\n receivingHouseholdId: lifecycle.receivingHouseholdId,\n purchaseId: lifecycle.purchaseId,\n catalogVersion: lifecycle.catalogVersion,\n purchasedAt: lifecycle.purchasedAt,\n settledAt: lifecycle.settledAt,\n creditedAt: lifecycle.creditedAt,\n originalAmount: lifecycle.originalAmount,\n };\n}\n\nfunction assertImmutableFacts(facts: PaidLotImmutableFacts): void {\n economyAssert(\n facts.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported paid-lot lifecycle contract version\",\n );\n assertEconomyIdentifier(facts.lotId, \"lotId\");\n assertEconomyIdentifier(facts.payerAccountId, \"payerAccountId\");\n assertEconomyIdentifier(\n facts.receivingHouseholdId,\n \"receivingHouseholdId\",\n );\n assertEconomyIdentifier(facts.purchaseId, \"purchaseId\");\n assertEconomyIdentifier(facts.catalogVersion, \"catalogVersion\");\n const purchasedAt = parseIsoTimestamp(facts.purchasedAt);\n const settledAt = parseIsoTimestamp(facts.settledAt);\n const creditedAt = parseIsoTimestamp(facts.creditedAt);\n economyAssert(\n purchasedAt <= settledAt && settledAt <= creditedAt,\n \"INVALID_TIME_WINDOW\",\n \"Paid-lot timestamps must follow purchase, settlement, then credit order\",\n );\n economyAssert(\n parseTokenSubunits(facts.originalAmount) > 0n,\n \"INVALID_AMOUNT\",\n \"Paid-lot original amount must be positive\",\n );\n}\n\nfunction projectPaidLot(\n facts: PaidLotImmutableFacts,\n receipts: readonly PaidLotLifecycleReceiptV1[],\n): PaidLotProjection {\n assertImmutableFacts(facts);\n const eventIds = new Set<string>();\n let reversalReceipts = 0;\n for (const receipt of receipts) {\n economyAssert(\n receipt.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported paid-lot receipt contract version\",\n );\n assertPaidLotLifecycleEvent(receipt.event);\n economyAssert(\n receipt.event.lotId === facts.lotId &&\n !eventIds.has(receipt.event.eventId),\n \"DUPLICATE_IDENTIFIER\",\n \"Paid-lot receipts must be unique and belong to the lifecycle lot\",\n );\n eventIds.add(receipt.event.eventId);\n if (receipt.event.eventType === \"reversal\") {\n reversalReceipts += 1;\n }\n }\n economyAssert(\n reversalReceipts <= 1,\n \"REVERSAL_ALREADY_EXISTS\",\n \"Paid-lot lifecycle permits only one distinct reversal event\",\n );\n\n let retained = parseTokenSubunits(facts.originalAmount);\n let held = 0n;\n let reversed = 0n;\n let refunded = 0n;\n let chargeback = 0n;\n let oneTimeReversal = 0n;\n const effectiveEventIds: string[] = [];\n for (const receipt of [...receipts].sort((left, right) =>\n compareEvents(left.event, right.event),\n )) {\n const event = receipt.event;\n economyAssert(\n parseIsoTimestamp(event.occurredAt) >=\n parseIsoTimestamp(facts.creditedAt),\n \"INVALID_TIME_WINDOW\",\n \"Paid-lot lifecycle event cannot precede credit\",\n );\n const amount = parseTokenSubunits(event.amount);\n if (event.eventType === \"dispute-hold\") {\n economyAssert(\n amount <= retained - held,\n \"INSUFFICIENT_ELIGIBLE_LOTS\",\n \"Dispute hold exceeds unheld retained paid-lot basis\",\n );\n held += amount;\n } else if (event.eventType === \"dispute-won\") {\n economyAssert(\n amount <= held,\n \"INVALID_AMOUNT\",\n \"Dispute-win release exceeds held paid-lot basis\",\n );\n held -= amount;\n } else if (event.eventType === \"dispute-lost\") {\n economyAssert(\n amount <= held,\n \"INVALID_AMOUNT\",\n \"Dispute-loss amount exceeds held paid-lot basis\",\n );\n held -= amount;\n retained -= amount;\n reversed += amount;\n chargeback += amount;\n } else {\n economyAssert(\n amount <= retained - held,\n \"INSUFFICIENT_ELIGIBLE_LOTS\",\n \"Paid-lot reversal exceeds unheld retained basis\",\n );\n if (event.eventType === \"reversal\") {\n oneTimeReversal += amount;\n } else if (event.eventType === \"refund\") {\n refunded += amount;\n } else {\n chargeback += amount;\n }\n retained -= amount;\n reversed += amount;\n }\n effectiveEventIds.push(event.eventId);\n }\n\n return {\n retained,\n held,\n reversed,\n refunded,\n chargeback,\n oneTimeReversal,\n status: deriveStatus(retained, held, reversed, chargeback),\n effectiveEventIds,\n };\n}\n\nfunction projectionMatchesLifecycle(\n projection: PaidLotProjection,\n lifecycle: PaidLotLifecycleV1,\n): boolean {\n return (\n serializeTokenSubunits(projection.retained) === lifecycle.retainedAmount &&\n serializeTokenSubunits(projection.held) === lifecycle.heldAmount &&\n serializeTokenSubunits(projection.reversed) === lifecycle.reversedAmount &&\n serializeTokenSubunits(projection.refunded) === lifecycle.refundedAmount &&\n serializeTokenSubunits(projection.chargeback) ===\n lifecycle.chargebackAmount &&\n serializeTokenSubunits(projection.oneTimeReversal) ===\n lifecycle.oneTimeReversalAmount &&\n projection.status === lifecycle.status &&\n projection.effectiveEventIds.length ===\n lifecycle.effectiveEventIds.length &&\n projection.effectiveEventIds.every(\n (eventId, index) => eventId === lifecycle.effectiveEventIds[index],\n )\n );\n}\n\n/** Validates and deterministically rebuilds retained paid-lot arithmetic. */\nexport function assertPaidLotLifecycle(\n lifecycle: PaidLotLifecycleV1,\n): void {\n economyAssert(\n Number.isSafeInteger(lifecycle.version) &&\n lifecycle.version === lifecycle.receipts.length + 1,\n \"INVALID_CONTRACT\",\n \"Paid-lot lifecycle version must match its receipt count\",\n );\n const projection = projectPaidLot(\n immutableFactsFromLifecycle(lifecycle),\n lifecycle.receipts,\n );\n economyAssert(\n projectionMatchesLifecycle(projection, lifecycle),\n \"INVALID_CONTRACT\",\n \"Paid-lot lifecycle does not match its immutable event rebuild\",\n );\n}\n\n/** Creates the retained projection for one newly credited paid source lot. */\nexport function createPaidLotLifecycle(\n lot: SourceLotV1,\n provenance: PaidLotPurchaseProvenanceV1,\n): PaidLotLifecycleV1 {\n assertSourceLot(lot);\n assertPaidLotPurchaseProvenance(provenance);\n economyAssert(\n lot.payerAccountId !== undefined && lot.householdId !== undefined,\n \"INVALID_CONTRACT\",\n \"Paid-lot lifecycle requires payer and receiving-household provenance\",\n );\n economyAssert(\n lot.refundState === \"none\" &&\n parseTokenSubunits(lot.heldAmount) === 0n &&\n parseTokenSubunits(lot.reversedAmount) === 0n,\n \"INVALID_CONTRACT\",\n \"Paid-lot lifecycle must be created before any refund or dispute movement\",\n );\n economyAssert(\n parseIsoTimestamp(provenance.purchasedAt) <=\n parseIsoTimestamp(lot.settledAt),\n \"INVALID_TIME_WINDOW\",\n \"Paid purchase time cannot follow settlement\",\n );\n const facts: PaidLotImmutableFacts = {\n schemaVersion: ECONOMY_CONTRACT_VERSION,\n lotId: lot.lotId,\n payerAccountId: lot.payerAccountId,\n receivingHouseholdId: lot.householdId,\n purchaseId: provenance.purchaseId,\n catalogVersion: provenance.catalogVersion,\n purchasedAt: provenance.purchasedAt,\n settledAt: lot.settledAt,\n creditedAt: lot.creditedAt,\n originalAmount: lot.originalAmount,\n };\n const projection = projectPaidLot(facts, []);\n const lifecycle: PaidLotLifecycleV1 = {\n ...facts,\n retainedAmount: serializeTokenSubunits(projection.retained),\n heldAmount: serializeTokenSubunits(projection.held),\n reversedAmount: serializeTokenSubunits(projection.reversed),\n refundedAmount: serializeTokenSubunits(projection.refunded),\n chargebackAmount: serializeTokenSubunits(projection.chargeback),\n oneTimeReversalAmount: serializeTokenSubunits(\n projection.oneTimeReversal,\n ),\n status: projection.status,\n version: 1,\n receipts: [],\n effectiveEventIds: [],\n };\n assertPaidLotLifecycle(lifecycle);\n return lifecycle;\n}\n\n/**\n * Appends one event then rebuilds every receipt in authoritative occurrence\n * order. Exact retries succeed before stale-version validation.\n */\nexport function applyPaidLotLifecycleEvent(\n lifecycle: PaidLotLifecycleV1,\n event: PaidLotLifecycleEventV1,\n expectedVersion: number,\n): PaidLotLifecycleMutationResultV1 {\n assertPaidLotLifecycle(lifecycle);\n assertPaidLotLifecycleEvent(event);\n economyAssert(\n event.lotId === lifecycle.lotId,\n \"INVALID_CONTRACT\",\n \"Paid-lot event belongs to another source lot\",\n );\n const replay = lifecycle.receipts.find(\n (receipt) => receipt.event.eventId === event.eventId,\n );\n if (replay !== undefined) {\n economyAssert(\n sameEvent(replay.event, event),\n \"DUPLICATE_IDENTIFIER\",\n \"Paid-lot event ID was reused with different facts\",\n );\n return {\n lifecycle,\n applied: false,\n stateChanged: false,\n arithmetic: ZERO_ARITHMETIC,\n };\n }\n economyAssert(\n expectedVersion === lifecycle.version,\n \"INVALID_CONTRACT\",\n \"Paid-lot lifecycle event has a stale expected version\",\n );\n\n const receipts: readonly PaidLotLifecycleReceiptV1[] = [\n ...lifecycle.receipts,\n { schemaVersion: ECONOMY_CONTRACT_VERSION, event },\n ];\n const projection = projectPaidLot(\n immutableFactsFromLifecycle(lifecycle),\n receipts,\n );\n const before = {\n retained: parseTokenSubunits(lifecycle.retainedAmount),\n held: parseTokenSubunits(lifecycle.heldAmount),\n reversed: parseTokenSubunits(lifecycle.reversedAmount),\n refunded: parseTokenSubunits(lifecycle.refundedAmount),\n chargeback: parseTokenSubunits(lifecycle.chargebackAmount),\n oneTimeReversal: parseTokenSubunits(lifecycle.oneTimeReversalAmount),\n };\n const next: PaidLotLifecycleV1 = {\n ...lifecycle,\n retainedAmount: serializeTokenSubunits(projection.retained),\n heldAmount: serializeTokenSubunits(projection.held),\n reversedAmount: serializeTokenSubunits(projection.reversed),\n refundedAmount: serializeTokenSubunits(projection.refunded),\n chargebackAmount: serializeTokenSubunits(projection.chargeback),\n oneTimeReversalAmount: serializeTokenSubunits(\n projection.oneTimeReversal,\n ),\n status: projection.status,\n version: lifecycle.version + 1,\n receipts,\n effectiveEventIds: projection.effectiveEventIds,\n };\n assertPaidLotLifecycle(next);\n const arithmetic: PaidLotLifecycleArithmeticV1 = {\n retainedDelta: serializeTokenSubunits(\n projection.retained - before.retained,\n ),\n heldDelta: serializeTokenSubunits(projection.held - before.held),\n reversedDelta: serializeTokenSubunits(\n projection.reversed - before.reversed,\n ),\n refundedDelta: serializeTokenSubunits(\n projection.refunded - before.refunded,\n ),\n chargebackDelta: serializeTokenSubunits(\n projection.chargeback - before.chargeback,\n ),\n oneTimeReversalDelta: serializeTokenSubunits(\n projection.oneTimeReversal - before.oneTimeReversal,\n ),\n };\n return {\n lifecycle: next,\n applied: true,\n stateChanged: Object.values(arithmetic).some((delta) => delta !== \"0\"),\n arithmetic,\n };\n}\n\n/** Reduces unordered/retried lifecycle evidence in canonical event order. */\nexport function reducePaidLotLifecycleEvents(\n initial: PaidLotLifecycleV1,\n events: readonly PaidLotLifecycleEventV1[],\n): PaidLotLifecycleV1 {\n assertPaidLotLifecycle(initial);\n const unique = new Map<string, PaidLotLifecycleEventV1>();\n for (const event of events) {\n assertPaidLotLifecycleEvent(event);\n const existing = unique.get(event.eventId);\n if (existing !== undefined) {\n economyAssert(\n sameEvent(existing, event),\n \"DUPLICATE_IDENTIFIER\",\n \"Paid-lot event ID was reused with different facts\",\n );\n } else {\n unique.set(event.eventId, event);\n }\n }\n let lifecycle = initial;\n for (const event of [...unique.values()].sort(compareEvents)) {\n lifecycle = applyPaidLotLifecycleEvent(\n lifecycle,\n event,\n lifecycle.version,\n ).lifecycle;\n }\n return lifecycle;\n}\n\n/** Creates the exact retained-basis input used by early-backer evaluators. */\nexport function createEarlyBackerRetentionFromPaidLot(\n lifecycle: PaidLotLifecycleV1,\n): PaidLotRetentionV1 {\n assertPaidLotLifecycle(lifecycle);\n return {\n schemaVersion: ECONOMY_CONTRACT_VERSION,\n lotId: lifecycle.lotId,\n payerAccountId: lifecycle.payerAccountId,\n receivingHouseholdId: lifecycle.receivingHouseholdId,\n purchaseId: lifecycle.purchaseId,\n catalogVersion: lifecycle.catalogVersion,\n purchasedAt: lifecycle.purchasedAt,\n settledAt: lifecycle.settledAt,\n creditedAt: lifecycle.creditedAt,\n retainedAmount: lifecycle.retainedAmount,\n };\n}\n","import type { TokenSubunitString } from \"../amount.js\";\nimport type { GameplayAllocationV1 } from \"../allocations.js\";\nimport {\n ECONOMY_CONTRACT_VERSION,\n assertEconomyIdentifier,\n parseIsoTimestamp,\n type AccountId,\n type AllocationId,\n type EconomyContractVersion,\n type HouseholdId,\n type IsoTimestamp,\n type LotId,\n type TransactionId,\n type WalletId,\n} from \"../contracts.js\";\nimport { economyAssert } from \"../errors.js\";\nimport type {\n ChainedEconomicJournalTransactionV1,\n JournalChainHeadV1,\n} from \"../integrity.js\";\nimport type { LedgerTransactionV1 } from \"../ledger.js\";\nimport type {\n SourceLotMovementV1,\n SourceLotV1,\n VersionedSourceLotV1,\n} from \"../lots.js\";\nimport type {\n BalanceProjection,\n BalanceProjectionSnapshotV1,\n WalletBalanceDeltaV1,\n WalletBalanceProjectionV1,\n WalletLifetimeDeltaV1,\n} from \"../projection.js\";\nimport type {\n WalletOwnerReferenceV1,\n WalletV1,\n} from \"../wallets.js\";\n\nexport type EconomyCommandType =\n | \"credit-purchase\"\n | \"credit-subscription\"\n | \"credit-reward\"\n | \"credit-event\"\n | \"credit-competition\"\n | \"allocate\"\n | \"boost\"\n | \"reclaim\"\n | \"spend\"\n | \"hold\"\n | \"release-hold\"\n | \"refund\"\n | \"chargeback\"\n | \"reverse\"\n | \"adjust\";\n\nexport interface EconomyCommandEnvelopeV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly commandId: string;\n readonly commandType: EconomyCommandType;\n readonly idempotencyKey: string;\n readonly actorAccountId: AccountId;\n readonly subjectAccountId: AccountId;\n readonly relationshipId?: string;\n readonly authorizationVersion?: number;\n readonly payloadHash: string;\n readonly acceptedAt: IsoTimestamp;\n readonly acceptedRegion: string;\n readonly writerFencingToken: string;\n}\n\nexport type EconomyCommandWorkflowStateV1 =\n | \"accepted\"\n | \"processing\"\n | \"failed\"\n | \"completed\";\n\n/** Immutable workflow evidence; it is never an economic journal transaction. */\nexport interface EconomyCommandWorkflowEventV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly workflowEventId: string;\n readonly commandId: string;\n readonly state: EconomyCommandWorkflowStateV1;\n /** Stable non-sensitive classifier; detailed failure data stays operational. */\n readonly failureCode?: string;\n readonly occurredAt: IsoTimestamp;\n}\n\nexport interface EconomyOutboxEventV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly eventId: string;\n readonly transactionId: TransactionId;\n readonly eventType: string;\n readonly payloadHash: string;\n readonly occurredAt: IsoTimestamp;\n}\n\nexport interface PersistedIdempotencyResultV1 {\n readonly transactionId: TransactionId;\n readonly responseHash: string;\n readonly recordedAt: IsoTimestamp;\n}\n\n/** Exact actor/subject/operation namespace for a caller-owned idempotency key. */\nexport interface EconomyIdempotencyScopeV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly idempotencyKey: string;\n readonly commandType: EconomyCommandType;\n readonly actorAccountId: AccountId;\n readonly subjectAccountId: AccountId;\n}\n\n/** V2 replay evidence bound to one accepted command and exact scope. */\nexport interface ScopedPersistedIdempotencyResultV1\n extends PersistedIdempotencyResultV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly commandId: string;\n}\n\n/** Validates replay evidence before it is returned across a command boundary. */\nexport function assertScopedPersistedIdempotencyResult(\n result: ScopedPersistedIdempotencyResultV1,\n): void {\n economyAssert(\n result.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported scoped idempotency-result contract version\",\n );\n assertEconomyIdentifier(result.commandId, \"commandId\");\n assertEconomyIdentifier(result.transactionId, \"transactionId\");\n economyAssert(\n /^sha256:[a-f0-9]{64}$/u.test(result.responseHash),\n \"INVALID_CONTRACT\",\n \"Idempotency response hash must be a canonical SHA-256 reference\",\n );\n parseIsoTimestamp(result.recordedAt);\n}\n\nconst ECONOMY_COMMAND_TYPES = new Set<EconomyCommandType>([\n \"credit-purchase\",\n \"credit-subscription\",\n \"credit-reward\",\n \"credit-event\",\n \"credit-competition\",\n \"allocate\",\n \"boost\",\n \"reclaim\",\n \"spend\",\n \"hold\",\n \"release-hold\",\n \"refund\",\n \"chargeback\",\n \"reverse\",\n \"adjust\",\n]);\n\n/** Validates the namespace that prevents cross-principal replay collisions. */\nexport function assertEconomyIdempotencyScope(\n scope: EconomyIdempotencyScopeV1,\n): void {\n economyAssert(\n scope.schemaVersion === ECONOMY_CONTRACT_VERSION &&\n ECONOMY_COMMAND_TYPES.has(scope.commandType),\n \"INVALID_CONTRACT\",\n \"Unsupported economy idempotency scope\",\n );\n assertEconomyIdentifier(scope.idempotencyKey, \"idempotencyKey\");\n assertEconomyIdentifier(scope.actorAccountId, \"actorAccountId\");\n assertEconomyIdentifier(scope.subjectAccountId, \"subjectAccountId\");\n}\n\n/** Validates minimized accepted-command evidence before durable append. */\nexport function assertEconomyCommandEnvelope(\n envelope: EconomyCommandEnvelopeV1,\n): void {\n economyAssert(\n envelope.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported economy-command-envelope contract version\",\n );\n assertEconomyIdentifier(envelope.commandId, \"commandId\");\n economyAssert(\n ECONOMY_COMMAND_TYPES.has(envelope.commandType),\n \"INVALID_CONTRACT\",\n \"Economy command has an unsupported type\",\n );\n assertEconomyIdentifier(envelope.idempotencyKey, \"idempotencyKey\");\n assertEconomyIdentifier(envelope.actorAccountId, \"actorAccountId\");\n assertEconomyIdentifier(envelope.subjectAccountId, \"subjectAccountId\");\n if (envelope.relationshipId !== undefined) {\n assertEconomyIdentifier(envelope.relationshipId, \"relationshipId\");\n }\n if (envelope.authorizationVersion !== undefined) {\n economyAssert(\n Number.isSafeInteger(envelope.authorizationVersion) &&\n envelope.authorizationVersion >= 1,\n \"INVALID_CONTRACT\",\n \"Command authorization version must be a positive safe integer\",\n );\n }\n economyAssert(\n (envelope.relationshipId === undefined) ===\n (envelope.authorizationVersion === undefined),\n \"INVALID_CONTRACT\",\n \"Relationship identity and authorization version must be supplied together\",\n );\n economyAssert(\n /^sha256:[a-f0-9]{64}$/u.test(envelope.payloadHash),\n \"INVALID_CONTRACT\",\n \"Command payload hash must be a canonical SHA-256 reference\",\n );\n parseIsoTimestamp(envelope.acceptedAt);\n assertEconomyIdentifier(envelope.acceptedRegion, \"acceptedRegion\");\n assertEconomyIdentifier(\n envelope.writerFencingToken,\n \"writerFencingToken\",\n );\n}\n\n/** Validates one immutable command-workflow state event. */\nexport function assertEconomyCommandWorkflowEvent(\n event: EconomyCommandWorkflowEventV1,\n): void {\n economyAssert(\n event.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported command-workflow-event contract version\",\n );\n assertEconomyIdentifier(event.workflowEventId, \"workflowEventId\");\n assertEconomyIdentifier(event.commandId, \"commandId\");\n economyAssert(\n [\"accepted\", \"processing\", \"failed\", \"completed\"].includes(event.state),\n \"INVALID_CONTRACT\",\n \"Command workflow has an unsupported state\",\n );\n economyAssert(\n (event.state === \"failed\") === (event.failureCode !== undefined),\n \"INVALID_CONTRACT\",\n \"Only failed command workflows require a failure code\",\n );\n if (event.failureCode !== undefined) {\n assertEconomyIdentifier(event.failureCode, \"failureCode\");\n }\n parseIsoTimestamp(event.occurredAt);\n}\n\n/** Operations available only inside one serializable database transaction. */\nexport interface EconomyUnitOfWork {\n getWalletForUpdate(walletId: WalletId): Promise<WalletV1 | null>;\n listSpendableLotsForUpdate(walletId: WalletId): Promise<readonly SourceLotV1[]>;\n findLotForUpdate(lotId: LotId): Promise<SourceLotV1 | null>;\n findIdempotencyResult(\n idempotencyKey: string,\n ): Promise<PersistedIdempotencyResultV1 | null>;\n appendTransaction(transaction: LedgerTransactionV1): Promise<void>;\n appendSourceLot(lot: SourceLotV1): Promise<void>;\n updateSourceLotProjection(\n lotId: LotId,\n remainingAmount: TokenSubunitString,\n heldAmount: TokenSubunitString,\n reversedAmount: TokenSubunitString,\n ): Promise<void>;\n saveBalanceProjection(\n projection: BalanceProjection,\n transactionId: TransactionId,\n ): Promise<void>;\n saveIdempotencyResult(\n idempotencyKey: string,\n result: PersistedIdempotencyResultV1,\n ): Promise<void>;\n appendOutboxEvent(event: EconomyOutboxEventV1): Promise<void>;\n}\n\n/** Adapter boundary for serializable, ACID economy mutations. */\nexport interface EconomyPersistencePort {\n runSerializable<T>(\n operation: (unitOfWork: EconomyUnitOfWork) => Promise<T>,\n ): Promise<T>;\n getWallet(walletId: WalletId): Promise<WalletV1 | null>;\n getBalanceProjection(walletId: WalletId): Promise<BalanceProjectionSnapshotV1 | null>;\n getTransaction(transactionId: TransactionId): Promise<LedgerTransactionV1 | null>;\n rebuildProjection(): Promise<BalanceProjection>;\n}\n\n/**\n * V2 mutation surface. Unlike `EconomyUnitOfWork`, it has no absolute balance\n * overwrite: journal, source-lot movement, allocation state, balance/lifetime\n * deltas, idempotency, chain head, and outbox are committed atomically.\n */\nexport interface EconomyUnitOfWorkV2 {\n getWalletForOwnerForUpdate(\n walletId: WalletId,\n owner: WalletOwnerReferenceV1,\n ): Promise<WalletV1 | null>;\n listSpendableLotsForUpdate(\n walletId: WalletId,\n ): Promise<readonly VersionedSourceLotV1[]>;\n findLotForUpdate(lotId: LotId): Promise<VersionedSourceLotV1 | null>;\n getGameplayAllocationForUpdate(\n allocationId: AllocationId,\n householdId: HouseholdId,\n childAccountId: AccountId,\n ): Promise<GameplayAllocationV1 | null>;\n findIdempotencyResult(\n scope: EconomyIdempotencyScopeV1,\n ): Promise<ScopedPersistedIdempotencyResultV1 | null>;\n /** Locks and rejects any stale/non-active regional writer lease. */\n lockActiveWriterFence(\n acceptedRegion: string,\n writerFencingToken: string,\n ): Promise<void>;\n lockJournalChainHead(chainId: string): Promise<JournalChainHeadV1>;\n\n appendCommandEnvelope(envelope: EconomyCommandEnvelopeV1): Promise<void>;\n appendCommandWorkflowEvent(\n event: EconomyCommandWorkflowEventV1,\n ): Promise<void>;\n appendTransaction(\n transaction: ChainedEconomicJournalTransactionV1,\n ): Promise<void>;\n /** Appends `createInitialSourceLotSnapshot()` output; later changes are movements. */\n appendSourceLot(snapshot: VersionedSourceLotV1): Promise<void>;\n /** Appends movement evidence and applies its lot CAS as one operation. */\n applySourceLotMovement(movement: SourceLotMovementV1): Promise<void>;\n appendGameplayAllocation(allocation: GameplayAllocationV1): Promise<void>;\n /**\n * Compares `expectedVersion`, requires `allocation.version` to be exactly the\n * next value, and never overwrites a stale row.\n */\n saveGameplayAllocation(\n allocation: GameplayAllocationV1,\n expectedVersion: number,\n ): Promise<void>;\n /**\n * Atomically adds deltas, verifies them against the appended postings and\n * account bindings, and records transaction-scoped application keys.\n */\n applyWalletBalanceDeltas(\n transactionId: TransactionId,\n deltas: readonly WalletBalanceDeltaV1[],\n ): Promise<void>;\n /**\n * Atomically increments monotonic lifetime counters after verifying the\n * deltas against the appended transaction's deterministic classification.\n */\n applyWalletLifetimeDeltas(\n transactionId: TransactionId,\n deltas: readonly WalletLifetimeDeltaV1[],\n ): Promise<void>;\n saveIdempotencyResult(\n scope: EconomyIdempotencyScopeV1,\n result: ScopedPersistedIdempotencyResultV1,\n ): Promise<void>;\n appendOutboxEvent(event: EconomyOutboxEventV1): Promise<void>;\n /** Compare-and-swaps the full locked head, including its canonical hash. */\n advanceJournalChainHead(\n expected: JournalChainHeadV1,\n next: JournalChainHeadV1,\n ): Promise<void>;\n}\n\n/**\n * Additive authoritative persistence boundary for new consumers. V1 remains\n * exported for compatibility but must not be adapted by delegating its\n * absolute `saveBalanceProjection` operation to this interface.\n */\nexport interface EconomyPersistencePortV2 {\n runSerializable<T>(\n operation: (unitOfWork: EconomyUnitOfWorkV2) => Promise<T>,\n ): Promise<T>;\n getWallet(walletId: WalletId): Promise<WalletV1 | null>;\n listWalletsByOwner(\n owner: WalletOwnerReferenceV1,\n ): Promise<readonly WalletV1[]>;\n getGameplayAllocation(\n allocationId: AllocationId,\n householdId: HouseholdId,\n childAccountId: AccountId,\n ): Promise<GameplayAllocationV1 | null>;\n getCommandEnvelope(\n commandId: string,\n ): Promise<EconomyCommandEnvelopeV1 | null>;\n getTransaction(\n transactionId: TransactionId,\n ): Promise<ChainedEconomicJournalTransactionV1 | null>;\n rebuildWalletBalanceProjections(): Promise<\n readonly WalletBalanceProjectionV1[]\n >;\n}\n\nexport interface EconomyClockPort {\n now(): IsoTimestamp;\n}\n\nexport interface EconomyIdPort {\n nextId(namespace: string): string;\n}\n","import {\n ECONOMY_CONTRACT_VERSION,\n assertEconomyIdentifier,\n parseIsoTimestamp,\n type AccountId,\n type EconomyContractVersion,\n type HouseholdId,\n type IsoTimestamp,\n type WalletId,\n} from \"./contracts.js\";\nimport {\n parseTokenSubunits,\n type TokenSubunitString,\n} from \"./amount.js\";\nimport { economyAssert } from \"./errors.js\";\n\nexport type WalletKind =\n | \"household-treasury\"\n | \"personal\"\n | \"gameplay-allocation\"\n | \"hold\"\n | \"purchase-clearing\"\n | \"provider-clearing\"\n | \"system\";\n\nexport type WalletStatus = \"active\" | \"restricted\" | \"closed\";\nexport type WalletOwnerType = \"account\" | \"household\" | \"system\";\n\n/** Exact owner identity used by persistence lookups and IDOR-safe locking. */\nexport interface WalletOwnerReferenceV1 {\n readonly ownerType: WalletOwnerType;\n readonly ownerId: AccountId | HouseholdId | \"system\";\n}\n\n/** Versioned authoritative wallet descriptor. */\nexport interface WalletV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly walletId: WalletId;\n readonly accountId: AccountId;\n readonly kind: WalletKind;\n readonly ownerType: WalletOwnerType;\n readonly ownerId: AccountId | HouseholdId | \"system\";\n readonly householdId?: HouseholdId;\n readonly status: WalletStatus;\n readonly version: number;\n readonly createdAt: IsoTimestamp;\n readonly closedAt?: IsoTimestamp;\n}\n\n/** Server-computed wallet totals. Clients must never derive authority from it. */\nexport interface WalletBalanceSummaryV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly walletId: WalletId;\n readonly available: TokenSubunitString;\n readonly reserved: TokenSubunitString;\n readonly held: TokenSubunitString;\n readonly rewardProgress: TokenSubunitString;\n readonly version: number;\n readonly asOf: IsoTimestamp;\n}\n\n/** Lifetime aggregates used by the Token profile. */\nexport interface WalletLifetimeTotalsV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly bought: TokenSubunitString;\n readonly earned: TokenSubunitString;\n readonly allocated: TokenSubunitString;\n readonly reclaimed: TokenSubunitString;\n readonly spent: TokenSubunitString;\n readonly reversed: TokenSubunitString;\n}\n\n/** Validates an exact wallet owner without accepting a browser-derived role. */\nexport function assertWalletOwnerReference(\n owner: WalletOwnerReferenceV1,\n): void {\n economyAssert(\n [\"account\", \"household\", \"system\"].includes(owner.ownerType),\n \"INVALID_CONTRACT\",\n \"Wallet owner reference has an unsupported type\",\n );\n if (owner.ownerType === \"system\") {\n economyAssert(\n owner.ownerId === \"system\",\n \"INVALID_CONTRACT\",\n \"System wallet lookups must use the system owner\",\n );\n } else {\n assertEconomyIdentifier(owner.ownerId, \"ownerId\");\n economyAssert(\n owner.ownerId !== \"system\",\n \"INVALID_CONTRACT\",\n \"Account and household wallets cannot use the system owner\",\n );\n }\n}\n\n/** Validates wallet ownership, lifecycle, and optimistic-version facts. */\nexport function assertWallet(wallet: WalletV1): void {\n economyAssert(\n wallet.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported wallet contract version\",\n );\n assertEconomyIdentifier(wallet.walletId, \"walletId\");\n assertEconomyIdentifier(wallet.accountId, \"accountId\");\n economyAssert(\n [\n \"household-treasury\",\n \"personal\",\n \"gameplay-allocation\",\n \"hold\",\n \"purchase-clearing\",\n \"provider-clearing\",\n \"system\",\n ].includes(wallet.kind),\n \"INVALID_CONTRACT\",\n \"Wallet has an unsupported kind\",\n );\n economyAssert(\n [\"account\", \"household\", \"system\"].includes(wallet.ownerType),\n \"INVALID_CONTRACT\",\n \"Wallet has an unsupported owner type\",\n );\n economyAssert(\n [\"active\", \"restricted\", \"closed\"].includes(wallet.status),\n \"INVALID_CONTRACT\",\n \"Wallet has an unsupported status\",\n );\n if (wallet.ownerType === \"system\") {\n economyAssert(\n wallet.ownerId === \"system\",\n \"INVALID_CONTRACT\",\n \"System wallets must be owned by the system\",\n );\n } else {\n assertEconomyIdentifier(wallet.ownerId, \"ownerId\");\n }\n if (wallet.householdId !== undefined) {\n assertEconomyIdentifier(wallet.householdId, \"householdId\");\n }\n if (wallet.ownerType === \"household\") {\n economyAssert(\n wallet.householdId === wallet.ownerId,\n \"INVALID_CONTRACT\",\n \"Household wallets must identify the same household owner\",\n );\n }\n if (wallet.kind === \"household-treasury\") {\n economyAssert(\n wallet.ownerType === \"household\" && wallet.householdId !== undefined,\n \"INVALID_CONTRACT\",\n \"Household treasuries must be owned by their household\",\n );\n }\n if (wallet.kind === \"personal\" || wallet.kind === \"gameplay-allocation\") {\n economyAssert(\n wallet.ownerType === \"account\",\n \"INVALID_CONTRACT\",\n \"Personal and gameplay-allocation wallets must be account-owned\",\n );\n }\n if (wallet.kind === \"gameplay-allocation\") {\n economyAssert(\n wallet.householdId !== undefined,\n \"INVALID_CONTRACT\",\n \"Gameplay-allocation wallets must retain household provenance\",\n );\n }\n if (\n wallet.kind === \"purchase-clearing\" ||\n wallet.kind === \"provider-clearing\" ||\n wallet.kind === \"system\"\n ) {\n economyAssert(\n wallet.ownerType === \"system\" && wallet.householdId === undefined,\n \"INVALID_CONTRACT\",\n \"Clearing and system wallets must be system-owned\",\n );\n }\n economyAssert(\n Number.isSafeInteger(wallet.version) && wallet.version >= 1,\n \"INVALID_CONTRACT\",\n \"Wallet version must be a positive safe integer\",\n );\n const createdAt = parseIsoTimestamp(wallet.createdAt);\n if (wallet.closedAt !== undefined) {\n economyAssert(\n parseIsoTimestamp(wallet.closedAt) >= createdAt &&\n wallet.status === \"closed\",\n \"INVALID_TIME_WINDOW\",\n \"Only closed wallets may have a valid closure time\",\n );\n } else {\n economyAssert(\n wallet.status !== \"closed\",\n \"INVALID_CONTRACT\",\n \"Closed wallets require a closure time\",\n );\n }\n}\n\n/** Validates non-negative server-computed wallet balance categories. */\nexport function assertWalletBalanceSummary(\n summary: WalletBalanceSummaryV1,\n): void {\n economyAssert(\n summary.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported wallet summary contract version\",\n );\n assertEconomyIdentifier(summary.walletId, \"walletId\");\n for (const amount of [\n summary.available,\n summary.reserved,\n summary.held,\n summary.rewardProgress,\n ]) {\n economyAssert(\n parseTokenSubunits(amount) >= 0n,\n \"INVALID_AMOUNT\",\n \"Wallet summary categories cannot be negative\",\n );\n }\n economyAssert(\n Number.isSafeInteger(summary.version) && summary.version >= 1,\n \"INVALID_CONTRACT\",\n \"Wallet summary version must be a positive safe integer\",\n );\n parseIsoTimestamp(summary.asOf);\n}\n\n/** Validates non-negative lifetime aggregates exposed by the profile API. */\nexport function assertWalletLifetimeTotals(\n totals: WalletLifetimeTotalsV1,\n): void {\n economyAssert(\n totals.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported wallet lifetime-total contract version\",\n );\n for (const amount of [\n totals.bought,\n totals.earned,\n totals.allocated,\n totals.reclaimed,\n totals.spent,\n totals.reversed,\n ]) {\n economyAssert(\n parseTokenSubunits(amount) >= 0n,\n \"INVALID_AMOUNT\",\n \"Wallet lifetime totals cannot be negative\",\n );\n }\n}\n","import {\n parseTokenSubunits,\n serializeTokenSubunits,\n type TokenSubunitString,\n} from \"./amount.js\";\nimport {\n ECONOMY_CONTRACT_VERSION,\n assertEconomyIdentifier,\n parseIsoTimestamp,\n type AccountId,\n type EconomyContractVersion,\n type IsoTimestamp,\n type TransactionId,\n type WalletId,\n} from \"./contracts.js\";\nimport { economyAssert } from \"./errors.js\";\nimport {\n assertBalancedTransaction,\n assertEconomicJournalTransaction,\n type ActivityType,\n type EconomicJournalTransactionV1,\n type LedgerTransactionV1,\n} from \"./ledger.js\";\nimport {\n assertWalletBalanceSummary,\n assertWalletLifetimeTotals,\n type WalletBalanceSummaryV1,\n type WalletLifetimeTotalsV1,\n} from \"./wallets.js\";\n\nexport type BalanceProjection = Readonly<Record<AccountId, TokenSubunitString>>;\n\nexport interface BalanceProjectionSnapshotV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly balances: BalanceProjection;\n readonly lastTransactionId?: TransactionId;\n readonly rebuiltAt: IsoTimestamp;\n}\n\nexport type WalletProjectionBucket = \"spendable\" | \"reserved\" | \"held\";\n\n/** Exclusive stored buckets for one wallet; reward progress is derived. */\nexport interface WalletBalanceProjectionV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly walletId: WalletId;\n readonly spendable: TokenSubunitString;\n readonly reserved: TokenSubunitString;\n readonly held: TokenSubunitString;\n readonly version: number;\n readonly lastTransactionId?: TransactionId;\n readonly asOf: IsoTimestamp;\n}\n\n/** One atomic add operation against all exclusive buckets of a wallet. */\nexport interface WalletBalanceDeltaV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly walletId: WalletId;\n readonly spendableDelta: TokenSubunitString;\n readonly reservedDelta: TokenSubunitString;\n readonly heldDelta: TokenSubunitString;\n}\n\n/** Authoritative mapping from a ledger account to one wallet bucket. */\nexport interface WalletPostingAccountBindingV1 {\n readonly accountId: AccountId;\n readonly walletId: WalletId;\n readonly bucket: WalletProjectionBucket;\n}\n\nexport type WalletLifetimeBucket =\n | \"bought\"\n | \"earned\"\n | \"allocated\"\n | \"reclaimed\"\n | \"spent\"\n | \"reversed\";\n\n/** Positive monotonic contribution to one wallet lifetime counter. */\nexport interface WalletLifetimeDeltaV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly walletId: WalletId;\n readonly bucket: WalletLifetimeBucket;\n readonly amount: TokenSubunitString;\n}\n\n/** Validates one exclusive-bucket projection. */\nexport function assertWalletBalanceProjection(\n projection: WalletBalanceProjectionV1,\n): void {\n economyAssert(\n projection.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported wallet-balance-projection contract version\",\n );\n assertEconomyIdentifier(projection.walletId, \"walletId\");\n for (const amount of [\n projection.spendable,\n projection.reserved,\n projection.held,\n ]) {\n economyAssert(\n parseTokenSubunits(amount) >= 0n,\n \"NEGATIVE_PROJECTION\",\n \"Wallet projection buckets cannot be negative\",\n );\n }\n economyAssert(\n Number.isSafeInteger(projection.version) && projection.version >= 1,\n \"INVALID_CONTRACT\",\n \"Wallet projection version must be a positive safe integer\",\n );\n if (projection.lastTransactionId !== undefined) {\n assertEconomyIdentifier(\n projection.lastTransactionId,\n \"lastTransactionId\",\n );\n }\n parseIsoTimestamp(projection.asOf);\n}\n\n/** Validates one non-zero atomic wallet delta. */\nexport function assertWalletBalanceDelta(delta: WalletBalanceDeltaV1): void {\n economyAssert(\n delta.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported wallet-balance-delta contract version\",\n );\n assertEconomyIdentifier(delta.walletId, \"walletId\");\n const values = [\n parseTokenSubunits(delta.spendableDelta),\n parseTokenSubunits(delta.reservedDelta),\n parseTokenSubunits(delta.heldDelta),\n ];\n economyAssert(\n values.some((value) => value !== 0n),\n \"INVALID_AMOUNT\",\n \"Wallet balance delta must change at least one bucket\",\n );\n}\n\n/** Rejects duplicate wallet updates before one atomic persistence call. */\nexport function assertWalletBalanceDeltaBatch(\n transactionId: TransactionId,\n deltas: readonly WalletBalanceDeltaV1[],\n): void {\n assertEconomyIdentifier(transactionId, \"transactionId\");\n economyAssert(\n deltas.length > 0,\n \"INVALID_CONTRACT\",\n \"An economic transaction must update at least one wallet projection\",\n );\n const walletIds = new Set<string>();\n for (const delta of deltas) {\n assertWalletBalanceDelta(delta);\n economyAssert(\n !walletIds.has(delta.walletId),\n \"DUPLICATE_IDENTIFIER\",\n \"A balance-delta batch must update each wallet once\",\n );\n walletIds.add(delta.walletId);\n }\n}\n\n/** Applies an atomic add locally for deterministic tests and rebuilds. */\nexport function applyWalletBalanceDelta(\n projection: WalletBalanceProjectionV1,\n delta: WalletBalanceDeltaV1,\n transactionId: TransactionId,\n asOf: IsoTimestamp,\n): WalletBalanceProjectionV1 {\n assertWalletBalanceProjection(projection);\n assertWalletBalanceDelta(delta);\n assertEconomyIdentifier(transactionId, \"transactionId\");\n economyAssert(\n projection.walletId === delta.walletId,\n \"INVALID_CONTRACT\",\n \"Wallet balance delta must target its projection wallet\",\n );\n economyAssert(\n parseIsoTimestamp(asOf) >= parseIsoTimestamp(projection.asOf),\n \"INVALID_TIME_WINDOW\",\n \"Wallet balance update cannot precede its projection\",\n );\n const next: WalletBalanceProjectionV1 = {\n ...projection,\n spendable: serializeTokenSubunits(\n parseTokenSubunits(projection.spendable) +\n parseTokenSubunits(delta.spendableDelta),\n ),\n reserved: serializeTokenSubunits(\n parseTokenSubunits(projection.reserved) +\n parseTokenSubunits(delta.reservedDelta),\n ),\n held: serializeTokenSubunits(\n parseTokenSubunits(projection.held) +\n parseTokenSubunits(delta.heldDelta),\n ),\n version: projection.version + 1,\n lastTransactionId: transactionId,\n asOf,\n };\n assertWalletBalanceProjection(next);\n return next;\n}\n\n/**\n * Converts exclusive storage buckets to the legacy display DTO. Available is\n * independently usable whole Tokens in this wallet; rewardProgress is this\n * wallet's sub-Token remainder and is never netted with another wallet.\n */\nexport function createWalletBalanceSummary(\n projection: WalletBalanceProjectionV1,\n): WalletBalanceSummaryV1 {\n assertWalletBalanceProjection(projection);\n const spendable = parseTokenSubunits(projection.spendable);\n const rewardProgress = spendable % 1_000n;\n const summary: WalletBalanceSummaryV1 = {\n schemaVersion: ECONOMY_CONTRACT_VERSION,\n walletId: projection.walletId,\n available: serializeTokenSubunits(spendable - rewardProgress),\n reserved: projection.reserved,\n held: projection.held,\n rewardProgress: serializeTokenSubunits(rewardProgress),\n version: projection.version,\n asOf: projection.asOf,\n };\n assertDeterministicWalletBalanceSummary(summary);\n return summary;\n}\n\n/** Enforces the stronger per-wallet semantics required by V1 query adapters. */\nexport function assertDeterministicWalletBalanceSummary(\n summary: WalletBalanceSummaryV1,\n): void {\n assertWalletBalanceSummary(summary);\n economyAssert(\n parseTokenSubunits(summary.available) % 1_000n === 0n &&\n parseTokenSubunits(summary.rewardProgress) < 1_000n,\n \"INVALID_CONTRACT\",\n \"Per-wallet availability must be whole Tokens with sub-Token progress below one Token\",\n );\n}\n\n/**\n * Derives a single delta per wallet from wallet-linked postings and an\n * authoritative account-to-bucket mapping. Unlinked system postings are not\n * wallet projections.\n */\nexport function deriveWalletBalanceDeltas(\n transaction: EconomicJournalTransactionV1,\n bindings: readonly WalletPostingAccountBindingV1[],\n): readonly WalletBalanceDeltaV1[] {\n assertEconomicJournalTransaction(transaction);\n const byAccount = new Map<AccountId, WalletPostingAccountBindingV1>();\n for (const binding of bindings) {\n assertEconomyIdentifier(binding.accountId, \"accountId\");\n assertEconomyIdentifier(binding.walletId, \"walletId\");\n economyAssert(\n [\"spendable\", \"reserved\", \"held\"].includes(binding.bucket),\n \"INVALID_CONTRACT\",\n \"Wallet account binding has an unsupported bucket\",\n );\n economyAssert(\n !byAccount.has(binding.accountId),\n \"DUPLICATE_IDENTIFIER\",\n \"A ledger account may bind to only one wallet bucket\",\n );\n byAccount.set(binding.accountId, binding);\n }\n\n const byWallet = new Map<WalletId, [bigint, bigint, bigint]>();\n for (const posting of transaction.postings) {\n if (posting.walletId === undefined) {\n continue;\n }\n const binding = byAccount.get(posting.accountId);\n economyAssert(\n binding !== undefined && binding.walletId === posting.walletId,\n \"INVALID_CONTRACT\",\n \"Every wallet-linked posting must match an authoritative account binding\",\n );\n const values = byWallet.get(binding.walletId) ?? [0n, 0n, 0n];\n const amount = parseTokenSubunits(posting.amount);\n if (binding.bucket === \"spendable\") {\n values[0] += amount;\n } else if (binding.bucket === \"reserved\") {\n values[1] += amount;\n } else {\n values[2] += amount;\n }\n byWallet.set(binding.walletId, values);\n }\n\n const deltas = [...byWallet.entries()]\n .map(([walletId, values]) => ({\n schemaVersion: ECONOMY_CONTRACT_VERSION,\n walletId,\n spendableDelta: serializeTokenSubunits(values[0]),\n reservedDelta: serializeTokenSubunits(values[1]),\n heldDelta: serializeTokenSubunits(values[2]),\n }))\n .filter(\n (delta) =>\n delta.spendableDelta !== \"0\" ||\n delta.reservedDelta !== \"0\" ||\n delta.heldDelta !== \"0\",\n )\n .sort((left, right) => left.walletId.localeCompare(right.walletId));\n assertWalletBalanceDeltaBatch(transaction.transactionId, deltas);\n return deltas;\n}\n\nconst EARNED_ACTIVITY_TYPES = new Set<ActivityType>([\n \"rewarded-ad\",\n \"offerwall\",\n \"event\",\n \"competition\",\n]);\n\n/**\n * Rebuilds monotonic gross lifetime contributions from a settled transaction.\n * Earlier bought/earned counters are never reduced by a later compensating\n * transaction; removals accrue separately in `reversed`.\n */\nexport function deriveWalletLifetimeDeltas(\n transaction: EconomicJournalTransactionV1,\n): readonly WalletLifetimeDeltaV1[] {\n assertEconomicJournalTransaction(transaction);\n if (transaction.status !== \"settled\") {\n return [];\n }\n const netByWallet = new Map<WalletId, bigint>();\n for (const posting of transaction.postings) {\n if (posting.walletId !== undefined) {\n netByWallet.set(\n posting.walletId,\n (netByWallet.get(posting.walletId) ?? 0n) +\n parseTokenSubunits(posting.amount),\n );\n }\n }\n\n const deltas: WalletLifetimeDeltaV1[] = [];\n for (const [walletId, net] of [...netByWallet.entries()].sort(([left], [right]) =>\n left.localeCompare(right),\n )) {\n let bucket: WalletLifetimeBucket | undefined;\n let amount = 0n;\n if (\n net > 0n &&\n (transaction.activityType === \"purchase\" ||\n transaction.activityType === \"subscription\")\n ) {\n bucket = \"bought\";\n amount = net;\n } else if (net > 0n && EARNED_ACTIVITY_TYPES.has(transaction.activityType)) {\n bucket = \"earned\";\n amount = net;\n } else if (\n net < 0n &&\n (transaction.activityType === \"allocation\" ||\n transaction.activityType === \"boost\")\n ) {\n bucket = \"allocated\";\n amount = -net;\n } else if (net > 0n && transaction.activityType === \"reclaim\") {\n bucket = \"reclaimed\";\n amount = net;\n } else if (net < 0n && transaction.activityType === \"spend\") {\n bucket = \"spent\";\n amount = -net;\n } else if (\n net < 0n &&\n (transaction.activityType === \"refund\" ||\n transaction.activityType === \"chargeback\" ||\n transaction.activityType === \"reversal\")\n ) {\n bucket = \"reversed\";\n amount = -net;\n }\n if (bucket !== undefined) {\n deltas.push({\n schemaVersion: ECONOMY_CONTRACT_VERSION,\n walletId,\n bucket,\n amount: serializeTokenSubunits(amount),\n });\n }\n }\n return deltas;\n}\n\n/** Applies positive lifetime deltas for one wallet without rewriting history. */\nexport function applyWalletLifetimeDeltas(\n current: WalletLifetimeTotalsV1,\n walletId: WalletId,\n deltas: readonly WalletLifetimeDeltaV1[],\n): WalletLifetimeTotalsV1 {\n assertWalletLifetimeTotals(current);\n assertEconomyIdentifier(walletId, \"walletId\");\n const next: Record<WalletLifetimeBucket, bigint> = {\n bought: parseTokenSubunits(current.bought),\n earned: parseTokenSubunits(current.earned),\n allocated: parseTokenSubunits(current.allocated),\n reclaimed: parseTokenSubunits(current.reclaimed),\n spent: parseTokenSubunits(current.spent),\n reversed: parseTokenSubunits(current.reversed),\n };\n for (const delta of deltas) {\n economyAssert(\n delta.schemaVersion === ECONOMY_CONTRACT_VERSION &&\n delta.walletId === walletId &&\n [\n \"bought\",\n \"earned\",\n \"allocated\",\n \"reclaimed\",\n \"spent\",\n \"reversed\",\n ].includes(delta.bucket),\n \"INVALID_CONTRACT\",\n \"Lifetime delta must target the requested wallet and a known bucket\",\n );\n const amount = parseTokenSubunits(delta.amount);\n economyAssert(\n amount > 0n,\n \"INVALID_AMOUNT\",\n \"Lifetime deltas must be positive\",\n );\n next[delta.bucket] += amount;\n }\n const totals: WalletLifetimeTotalsV1 = {\n schemaVersion: ECONOMY_CONTRACT_VERSION,\n bought: serializeTokenSubunits(next.bought),\n earned: serializeTokenSubunits(next.earned),\n allocated: serializeTokenSubunits(next.allocated),\n reclaimed: serializeTokenSubunits(next.reclaimed),\n spent: serializeTokenSubunits(next.spent),\n reversed: serializeTokenSubunits(next.reversed),\n };\n assertWalletLifetimeTotals(totals);\n return totals;\n}\n\n/** Applies one balanced transaction without mutating the existing projection. */\nexport function applyTransactionToProjection(\n current: BalanceProjection,\n transaction: LedgerTransactionV1,\n): BalanceProjection {\n assertBalancedTransaction(transaction);\n const next: Record<AccountId, TokenSubunitString> = { ...current };\n for (const posting of transaction.postings) {\n const prior = parseTokenSubunits(next[posting.accountId] ?? \"0\");\n next[posting.accountId] = serializeTokenSubunits(\n prior + parseTokenSubunits(posting.amount),\n );\n }\n return next;\n}\n\n/**\n * Rebuilds balances deterministically and rejects duplicate economic envelopes.\n */\nexport function rebuildBalanceProjection(\n transactions: readonly LedgerTransactionV1[],\n): BalanceProjection {\n let projection: BalanceProjection = {};\n const transactionIds = new Set<string>();\n const idempotencyKeys = new Set<string>();\n const providerEvents = new Set<string>();\n\n for (const transaction of transactions) {\n economyAssert(\n !transactionIds.has(transaction.transactionId),\n \"DUPLICATE_TRANSACTION\",\n \"Transaction identifiers must be unique\",\n );\n economyAssert(\n !idempotencyKeys.has(transaction.idempotencyKey),\n \"DUPLICATE_TRANSACTION\",\n \"Idempotency keys must be unique\",\n );\n if (transaction.providerEventId !== undefined) {\n economyAssert(\n !providerEvents.has(transaction.providerEventId),\n \"DUPLICATE_TRANSACTION\",\n \"Provider event identifiers must be unique\",\n );\n providerEvents.add(transaction.providerEventId);\n }\n transactionIds.add(transaction.transactionId);\n idempotencyKeys.add(transaction.idempotencyKey);\n projection = applyTransactionToProjection(projection, transaction);\n }\n\n return projection;\n}\n\n/** Enforces non-negative balances only for spendable/reservable accounts. */\nexport function assertNonNegativeAccounts(\n projection: BalanceProjection,\n protectedAccountIds: readonly AccountId[],\n): void {\n for (const accountId of protectedAccountIds) {\n economyAssert(\n parseTokenSubunits(projection[accountId] ?? \"0\") >= 0n,\n \"NEGATIVE_PROJECTION\",\n \"A protected economy account would become negative\",\n );\n }\n}\n\n/** Creates a versioned snapshot after a deterministic rebuild. */\nexport function createProjectionSnapshot(\n transactions: readonly LedgerTransactionV1[],\n rebuiltAt: IsoTimestamp,\n): BalanceProjectionSnapshotV1 {\n parseIsoTimestamp(rebuiltAt);\n const last = transactions.at(-1);\n return {\n schemaVersion: ECONOMY_CONTRACT_VERSION,\n balances: rebuildBalanceProjection(transactions),\n ...(last === undefined ? {} : { lastTransactionId: last.transactionId }),\n rebuiltAt,\n };\n}\n","import {\n parseTokenSubunits,\n serializeTokenSubunits,\n type TokenSubunitString,\n} from \"../amount.js\";\nimport {\n ECONOMY_CONTRACT_VERSION,\n assertEconomyIdentifier,\n parseIsoTimestamp,\n type AccountId,\n type EconomyContractVersion,\n type IsoTimestamp,\n type TransactionId,\n type WalletId,\n} from \"../contracts.js\";\nimport { economyAssert } from \"../errors.js\";\nimport type { ActivityType } from \"../ledger.js\";\nimport type { TokenSource } from \"../lots.js\";\nimport { assertDeterministicWalletBalanceSummary } from \"../projection.js\";\nimport {\n assertWalletLifetimeTotals,\n type WalletBalanceSummaryV1,\n type WalletLifetimeTotalsV1,\n} from \"../wallets.js\";\n\nexport type WalletPortfolioComponentRole =\n | \"household-treasury\"\n | \"personal\"\n | \"gameplay-allocation\"\n | \"hold\";\n\n/** One server-authorized component of a portfolio read. */\nexport interface WalletPortfolioComponentScopeV1 {\n readonly walletId: WalletId;\n readonly role: WalletPortfolioComponentRole;\n readonly beneficiaryAccountId?: AccountId;\n}\n\n/**\n * Explicit portfolio scope assembled after authorization. It prevents a host's\n * household treasury and same-user-only personal wallet from being silently\n * represented as one wallet.\n */\nexport interface WalletPortfolioReadScopeV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly portfolioId: string;\n readonly subjectAccountId: AccountId;\n readonly components: readonly WalletPortfolioComponentScopeV1[];\n}\n\nexport interface WalletBalanceTotalsV1 {\n readonly available: TokenSubunitString;\n readonly reserved: TokenSubunitString;\n readonly held: TokenSubunitString;\n readonly rewardProgress: TokenSubunitString;\n}\n\nexport interface WalletPortfolioBalanceComponentV1\n extends WalletPortfolioComponentScopeV1 {\n readonly summary: WalletBalanceSummaryV1;\n}\n\nexport interface WalletPortfolioSummaryV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly portfolioId: string;\n readonly subjectAccountId: AccountId;\n readonly components: readonly WalletPortfolioBalanceComponentV1[];\n /**\n * Exact column sums for display only. Progress is intentionally not promoted\n * across wallets because their source/transfer policies may differ.\n */\n readonly totals: WalletBalanceTotalsV1;\n readonly asOf: IsoTimestamp;\n}\n\n/** Self-identifying lifetime read for one wallet. */\nexport interface WalletLifetimeSnapshotV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly walletId: WalletId;\n readonly totals: WalletLifetimeTotalsV1;\n readonly version: number;\n readonly asOf: IsoTimestamp;\n}\n\nexport interface WalletPortfolioLifetimeComponentV1\n extends WalletPortfolioComponentScopeV1 {\n readonly snapshot: WalletLifetimeSnapshotV1;\n}\n\nexport interface WalletPortfolioLifetimeV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly portfolioId: string;\n readonly subjectAccountId: AccountId;\n readonly components: readonly WalletPortfolioLifetimeComponentV1[];\n readonly totals: WalletLifetimeTotalsV1;\n readonly asOf: IsoTimestamp;\n}\n\nexport type EconomicActivityStatusV1 = \"held\" | \"settled\" | \"reversed\";\nexport type WorkflowActivityStatusV1 = \"pending\" | \"failed\";\nexport type WalletActivityStatusV1 =\n | EconomicActivityStatusV1\n | WorkflowActivityStatusV1;\n\ninterface WalletActivityBaseV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly activityId: string;\n /** Component wallet whose signed display amount this row represents. */\n readonly walletId: WalletId;\n readonly activityType: ActivityType;\n readonly occurredAt: IsoTimestamp;\n readonly amount: TokenSubunitString;\n readonly source: TokenSource;\n readonly beneficiaryAccountId?: AccountId;\n readonly maskedReference?: string;\n readonly sourceLabel: string;\n}\n\n/** Economically effective or read-model-derived reversal activity. */\nexport interface EconomicWalletActivityEntryV1 extends WalletActivityBaseV1 {\n readonly entryKind: \"economic\";\n readonly transactionId: TransactionId;\n readonly status: EconomicActivityStatusV1;\n}\n\n/**\n * Non-economic accepted/failed work. Its amount is display context only and is\n * excluded from balances and lifetime aggregates.\n */\nexport interface WorkflowWalletActivityEntryV1 extends WalletActivityBaseV1 {\n readonly entryKind: \"workflow\";\n readonly commandId: string;\n readonly status: WorkflowActivityStatusV1;\n}\n\nexport type WalletActivityEntryV1 =\n | EconomicWalletActivityEntryV1\n | WorkflowWalletActivityEntryV1;\n\nexport interface WalletActivityFilterV1 {\n readonly activityTypes?: readonly ActivityType[];\n readonly statuses?: readonly WalletActivityStatusV1[];\n readonly sources?: readonly TokenSource[];\n readonly beneficiaryAccountId?: AccountId;\n readonly fromInclusive?: IsoTimestamp;\n readonly toExclusive?: IsoTimestamp;\n}\n\nexport interface WalletActivityPageRequestV1 {\n readonly limit: number;\n readonly cursor?: string;\n readonly filter?: WalletActivityFilterV1;\n}\n\nexport interface WalletActivityPageV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly entries: readonly WalletActivityEntryV1[];\n readonly hasMore: boolean;\n readonly nextCursor?: string;\n}\n\nconst ACTIVITY_TYPES = new Set<ActivityType>([\n \"purchase\",\n \"subscription\",\n \"rewarded-ad\",\n \"offerwall\",\n \"allocation\",\n \"boost\",\n \"reclaim\",\n \"spend\",\n \"hold\",\n \"refund\",\n \"chargeback\",\n \"adjustment\",\n \"reversal\",\n \"event\",\n \"competition\",\n]);\nconst ACTIVITY_STATUSES = new Set<WalletActivityStatusV1>([\n \"pending\",\n \"held\",\n \"settled\",\n \"reversed\",\n \"failed\",\n]);\nconst ACTIVITY_SOURCES = new Set<TokenSource>([\n \"shopify\",\n \"ayet\",\n \"bitlabs\",\n \"subscription\",\n \"event\",\n \"competition\",\n \"adjustment\",\n]);\nconst PORTFOLIO_ROLES = new Set<WalletPortfolioComponentRole>([\n \"household-treasury\",\n \"personal\",\n \"gameplay-allocation\",\n \"hold\",\n]);\n\nfunction hasControlCharacters(value: string): boolean {\n return [...value].some((character) => {\n const code = character.charCodeAt(0);\n return code <= 31 || code === 127;\n });\n}\n\nfunction assertSafeDisplayString(value: string, label: string): void {\n economyAssert(\n typeof value === \"string\" &&\n value.trim().length > 0 &&\n value.length <= 128 &&\n !hasControlCharacters(value),\n \"INVALID_CONTRACT\",\n `${label} must be bounded and safe for display`,\n );\n}\n\nfunction assertOpaqueCursor(value: string): void {\n economyAssert(\n typeof value === \"string\" &&\n value.length > 0 &&\n value.length <= 512 &&\n !hasControlCharacters(value),\n \"INVALID_CONTRACT\",\n \"Activity cursor must be a bounded opaque value\",\n );\n}\n\nfunction assertUniqueValues<T extends string>(\n values: readonly T[],\n allowed: ReadonlySet<T>,\n label: string,\n): void {\n const unique = new Set(values);\n economyAssert(\n values.length > 0 &&\n values.length === unique.size &&\n values.every((value) => allowed.has(value)),\n \"INVALID_CONTRACT\",\n `${label} must contain unique supported values`,\n );\n}\n\n/** Validates a server-created, bounded portfolio scope. */\nexport function assertWalletPortfolioReadScope(\n scope: WalletPortfolioReadScopeV1,\n): void {\n economyAssert(\n scope.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported wallet-portfolio scope contract version\",\n );\n assertEconomyIdentifier(scope.portfolioId, \"portfolioId\");\n assertEconomyIdentifier(scope.subjectAccountId, \"subjectAccountId\");\n economyAssert(\n scope.components.length > 0 && scope.components.length <= 100,\n \"INVALID_CONTRACT\",\n \"Wallet portfolio must contain between one and 100 components\",\n );\n const walletIds = new Set<string>();\n for (const component of scope.components) {\n assertEconomyIdentifier(component.walletId, \"walletId\");\n economyAssert(\n PORTFOLIO_ROLES.has(component.role),\n \"INVALID_CONTRACT\",\n \"Wallet portfolio component has an unsupported role\",\n );\n economyAssert(\n !walletIds.has(component.walletId),\n \"DUPLICATE_IDENTIFIER\",\n \"Wallet portfolio cannot repeat a wallet\",\n );\n walletIds.add(component.walletId);\n if (component.beneficiaryAccountId !== undefined) {\n assertEconomyIdentifier(\n component.beneficiaryAccountId,\n \"beneficiaryAccountId\",\n );\n }\n economyAssert(\n component.role !== \"gameplay-allocation\" ||\n component.beneficiaryAccountId !== undefined,\n \"INVALID_CONTRACT\",\n \"Gameplay-allocation portfolio components require a beneficiary\",\n );\n }\n}\n\n/** Validates a self-identifying wallet lifetime read. */\nexport function assertWalletLifetimeSnapshot(\n snapshot: WalletLifetimeSnapshotV1,\n): void {\n economyAssert(\n snapshot.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported wallet-lifetime-snapshot contract version\",\n );\n assertEconomyIdentifier(snapshot.walletId, \"walletId\");\n assertWalletLifetimeTotals(snapshot.totals);\n economyAssert(\n Number.isSafeInteger(snapshot.version) && snapshot.version >= 1,\n \"INVALID_CONTRACT\",\n \"Wallet lifetime version must be a positive safe integer\",\n );\n parseIsoTimestamp(snapshot.asOf);\n}\n\nfunction assertPortfolioComponentMatch(\n expected: WalletPortfolioComponentScopeV1,\n actual: WalletPortfolioComponentScopeV1,\n): void {\n economyAssert(\n expected.walletId === actual.walletId &&\n expected.role === actual.role &&\n expected.beneficiaryAccountId === actual.beneficiaryAccountId,\n \"INVALID_CONTRACT\",\n \"Portfolio result component does not match its authorized read scope\",\n );\n}\n\n/**\n * Constructs a portfolio balance without merging wallet identities or\n * promoting sub-Token progress across policy boundaries.\n */\nexport function createWalletPortfolioSummary(\n scope: WalletPortfolioReadScopeV1,\n components: readonly WalletPortfolioBalanceComponentV1[],\n asOf: IsoTimestamp,\n): WalletPortfolioSummaryV1 {\n assertWalletPortfolioReadScope(scope);\n parseIsoTimestamp(asOf);\n economyAssert(\n components.length === scope.components.length,\n \"INVALID_CONTRACT\",\n \"Portfolio balance must include every authorized component exactly once\",\n );\n const byWallet = new Map(components.map((item) => [item.walletId, item]));\n economyAssert(\n byWallet.size === components.length,\n \"DUPLICATE_IDENTIFIER\",\n \"Portfolio balance cannot repeat a wallet\",\n );\n\n const ordered = scope.components.map((expected) => {\n const actual = byWallet.get(expected.walletId);\n economyAssert(\n actual !== undefined,\n \"INVALID_CONTRACT\",\n \"Portfolio balance is missing an authorized wallet\",\n );\n assertPortfolioComponentMatch(expected, actual);\n assertDeterministicWalletBalanceSummary(actual.summary);\n economyAssert(\n actual.summary.walletId === actual.walletId &&\n actual.summary.asOf === asOf,\n \"INVALID_CONTRACT\",\n \"Portfolio component summary must identify its wallet and shared snapshot time\",\n );\n return actual;\n });\n\n const totals: WalletBalanceTotalsV1 = {\n available: serializeTokenSubunits(\n ordered.reduce(\n (sum, item) => sum + parseTokenSubunits(item.summary.available),\n 0n,\n ),\n ),\n reserved: serializeTokenSubunits(\n ordered.reduce(\n (sum, item) => sum + parseTokenSubunits(item.summary.reserved),\n 0n,\n ),\n ),\n held: serializeTokenSubunits(\n ordered.reduce(\n (sum, item) => sum + parseTokenSubunits(item.summary.held),\n 0n,\n ),\n ),\n rewardProgress: serializeTokenSubunits(\n ordered.reduce(\n (sum, item) => sum + parseTokenSubunits(item.summary.rewardProgress),\n 0n,\n ),\n ),\n };\n return {\n schemaVersion: ECONOMY_CONTRACT_VERSION,\n portfolioId: scope.portfolioId,\n subjectAccountId: scope.subjectAccountId,\n components: ordered,\n totals,\n asOf,\n };\n}\n\n/** Validates a portfolio balance read independently of its producing adapter. */\nexport function assertWalletPortfolioSummary(\n summary: WalletPortfolioSummaryV1,\n): void {\n const scope: WalletPortfolioReadScopeV1 = {\n schemaVersion: summary.schemaVersion,\n portfolioId: summary.portfolioId,\n subjectAccountId: summary.subjectAccountId,\n components: summary.components.map(\n ({ walletId, role, beneficiaryAccountId }) => ({\n walletId,\n role,\n ...(beneficiaryAccountId === undefined\n ? {}\n : { beneficiaryAccountId }),\n }),\n ),\n };\n const rebuilt = createWalletPortfolioSummary(\n scope,\n summary.components,\n summary.asOf,\n );\n for (const field of [\n \"available\",\n \"reserved\",\n \"held\",\n \"rewardProgress\",\n ] as const) {\n economyAssert(\n summary.totals[field] === rebuilt.totals[field],\n \"INVALID_CONTRACT\",\n \"Portfolio balance totals must equal their component column sums\",\n );\n }\n}\n\n/** Builds monotonic lifetime totals while retaining per-wallet components. */\nexport function createWalletPortfolioLifetime(\n scope: WalletPortfolioReadScopeV1,\n components: readonly WalletPortfolioLifetimeComponentV1[],\n asOf: IsoTimestamp,\n): WalletPortfolioLifetimeV1 {\n assertWalletPortfolioReadScope(scope);\n parseIsoTimestamp(asOf);\n economyAssert(\n components.length === scope.components.length,\n \"INVALID_CONTRACT\",\n \"Portfolio lifetime must include every authorized component exactly once\",\n );\n const byWallet = new Map(components.map((item) => [item.walletId, item]));\n economyAssert(\n byWallet.size === components.length,\n \"DUPLICATE_IDENTIFIER\",\n \"Portfolio lifetime cannot repeat a wallet\",\n );\n const ordered = scope.components.map((expected) => {\n const actual = byWallet.get(expected.walletId);\n economyAssert(\n actual !== undefined,\n \"INVALID_CONTRACT\",\n \"Portfolio lifetime is missing an authorized wallet\",\n );\n assertPortfolioComponentMatch(expected, actual);\n assertWalletLifetimeSnapshot(actual.snapshot);\n economyAssert(\n actual.snapshot.walletId === actual.walletId &&\n actual.snapshot.asOf === asOf,\n \"INVALID_CONTRACT\",\n \"Portfolio lifetime component must identify its wallet and shared snapshot time\",\n );\n return actual;\n });\n const sumField = (\n field: Exclude<keyof WalletLifetimeTotalsV1, \"schemaVersion\">,\n ): TokenSubunitString =>\n serializeTokenSubunits(\n ordered.reduce(\n (sum, item) => sum + parseTokenSubunits(item.snapshot.totals[field]),\n 0n,\n ),\n );\n const totals: WalletLifetimeTotalsV1 = {\n schemaVersion: ECONOMY_CONTRACT_VERSION,\n bought: sumField(\"bought\"),\n earned: sumField(\"earned\"),\n allocated: sumField(\"allocated\"),\n reclaimed: sumField(\"reclaimed\"),\n spent: sumField(\"spent\"),\n reversed: sumField(\"reversed\"),\n };\n assertWalletLifetimeTotals(totals);\n return {\n schemaVersion: ECONOMY_CONTRACT_VERSION,\n portfolioId: scope.portfolioId,\n subjectAccountId: scope.subjectAccountId,\n components: ordered,\n totals,\n asOf,\n };\n}\n\n/** Validates a portfolio lifetime read independently of its producing adapter. */\nexport function assertWalletPortfolioLifetime(\n lifetime: WalletPortfolioLifetimeV1,\n): void {\n const scope: WalletPortfolioReadScopeV1 = {\n schemaVersion: lifetime.schemaVersion,\n portfolioId: lifetime.portfolioId,\n subjectAccountId: lifetime.subjectAccountId,\n components: lifetime.components.map(\n ({ walletId, role, beneficiaryAccountId }) => ({\n walletId,\n role,\n ...(beneficiaryAccountId === undefined\n ? {}\n : { beneficiaryAccountId }),\n }),\n ),\n };\n const rebuilt = createWalletPortfolioLifetime(\n scope,\n lifetime.components,\n lifetime.asOf,\n );\n for (const field of [\n \"bought\",\n \"earned\",\n \"allocated\",\n \"reclaimed\",\n \"spent\",\n \"reversed\",\n ] as const) {\n economyAssert(\n lifetime.totals[field] === rebuilt.totals[field],\n \"INVALID_CONTRACT\",\n \"Portfolio lifetime totals must equal their component column sums\",\n );\n }\n}\n\n/** Validates the economic/workflow activity discriminant and safe display data. */\nexport function assertWalletActivityEntry(\n entry: WalletActivityEntryV1,\n): void {\n economyAssert(\n entry.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported wallet-activity contract version\",\n );\n assertEconomyIdentifier(entry.activityId, \"activityId\");\n assertEconomyIdentifier(entry.walletId, \"walletId\");\n economyAssert(\n ACTIVITY_TYPES.has(entry.activityType) &&\n ACTIVITY_STATUSES.has(entry.status) &&\n ACTIVITY_SOURCES.has(entry.source),\n \"INVALID_CONTRACT\",\n \"Wallet activity type, status, or source is unsupported\",\n );\n parseIsoTimestamp(entry.occurredAt);\n economyAssert(\n parseTokenSubunits(entry.amount) !== 0n,\n \"INVALID_AMOUNT\",\n \"Wallet activity amount cannot be zero\",\n );\n if (entry.beneficiaryAccountId !== undefined) {\n assertEconomyIdentifier(\n entry.beneficiaryAccountId,\n \"beneficiaryAccountId\",\n );\n }\n if (entry.maskedReference !== undefined) {\n assertSafeDisplayString(entry.maskedReference, \"Masked reference\");\n }\n assertSafeDisplayString(entry.sourceLabel, \"Source label\");\n economyAssert(\n entry.entryKind === \"economic\" || entry.entryKind === \"workflow\",\n \"INVALID_CONTRACT\",\n \"Wallet activity has an unsupported entry kind\",\n );\n if (entry.entryKind === \"economic\") {\n assertEconomyIdentifier(entry.transactionId, \"transactionId\");\n economyAssert(\n entry.status === \"held\" ||\n entry.status === \"settled\" ||\n entry.status === \"reversed\",\n \"INVALID_CONTRACT\",\n \"Economic activity cannot use a workflow status\",\n );\n } else {\n assertEconomyIdentifier(entry.commandId, \"commandId\");\n economyAssert(\n entry.status === \"pending\" || entry.status === \"failed\",\n \"INVALID_CONTRACT\",\n \"Workflow activity cannot use an economic status\",\n );\n }\n}\n\n/** Validates bounded filters and opaque cursor input. */\nexport function assertWalletActivityPageRequest(\n request: WalletActivityPageRequestV1,\n): void {\n economyAssert(\n Number.isSafeInteger(request.limit) &&\n request.limit >= 1 &&\n request.limit <= 100,\n \"INVALID_CONTRACT\",\n \"Activity page limit must be between one and 100\",\n );\n if (request.cursor !== undefined) {\n assertOpaqueCursor(request.cursor);\n }\n const filter = request.filter;\n if (filter === undefined) {\n return;\n }\n if (filter.activityTypes !== undefined) {\n assertUniqueValues(filter.activityTypes, ACTIVITY_TYPES, \"Activity types\");\n }\n if (filter.statuses !== undefined) {\n assertUniqueValues(filter.statuses, ACTIVITY_STATUSES, \"Activity statuses\");\n }\n if (filter.sources !== undefined) {\n assertUniqueValues(filter.sources, ACTIVITY_SOURCES, \"Activity sources\");\n }\n if (filter.beneficiaryAccountId !== undefined) {\n assertEconomyIdentifier(\n filter.beneficiaryAccountId,\n \"beneficiaryAccountId\",\n );\n }\n const from =\n filter.fromInclusive === undefined\n ? undefined\n : parseIsoTimestamp(filter.fromInclusive);\n const to =\n filter.toExclusive === undefined\n ? undefined\n : parseIsoTimestamp(filter.toExclusive);\n economyAssert(\n from === undefined || to === undefined || from < to,\n \"INVALID_TIME_WINDOW\",\n \"Activity filter start must precede its exclusive end\",\n );\n}\n\n/**\n * Validates stable descending `(occurredAt, activityId)` page order and cursor\n * presence. Cursors remain opaque to this provider-neutral package.\n */\nexport function assertWalletActivityPage(page: WalletActivityPageV1): void {\n economyAssert(\n page.schemaVersion === ECONOMY_CONTRACT_VERSION &&\n typeof page.hasMore === \"boolean\",\n \"INVALID_CONTRACT\",\n \"Unsupported wallet-activity-page contract\",\n );\n economyAssert(\n page.hasMore === (page.nextCursor !== undefined),\n \"INVALID_CONTRACT\",\n \"Activity page cursor must be present exactly when more rows exist\",\n );\n economyAssert(\n page.entries.length <= 100 && (!page.hasMore || page.entries.length > 0),\n \"INVALID_CONTRACT\",\n \"Activity pages are bounded and cannot advertise more rows from an empty page\",\n );\n if (page.nextCursor !== undefined) {\n assertOpaqueCursor(page.nextCursor);\n }\n const activityIds = new Set<string>();\n let previous: WalletActivityEntryV1 | undefined;\n for (const entry of page.entries) {\n assertWalletActivityEntry(entry);\n economyAssert(\n !activityIds.has(entry.activityId),\n \"DUPLICATE_IDENTIFIER\",\n \"Activity page cannot repeat an activity ID\",\n );\n activityIds.add(entry.activityId);\n if (previous !== undefined) {\n const previousTime = parseIsoTimestamp(previous.occurredAt);\n const currentTime = parseIsoTimestamp(entry.occurredAt);\n economyAssert(\n previousTime > currentTime ||\n (previousTime === currentTime &&\n previous.activityId.localeCompare(entry.activityId) > 0),\n \"INVALID_CONTRACT\",\n \"Activity page must use stable descending time and ID order\",\n );\n }\n previous = entry;\n }\n}\n\n/** Prevents an activity cursor/result from expanding an authorized portfolio. */\nexport function assertWalletActivityPageForPortfolio(\n page: WalletActivityPageV1,\n scope: WalletPortfolioReadScopeV1,\n): void {\n assertWalletActivityPage(page);\n assertWalletPortfolioReadScope(scope);\n const walletIds = new Set(scope.components.map((item) => item.walletId));\n economyAssert(\n page.entries.every((entry) => walletIds.has(entry.walletId)),\n \"INVALID_CONTRACT\",\n \"Portfolio activity contains a wallet outside its authorized read scope\",\n );\n}\n\n/** Read-only adapter boundary; authorization must precede scope construction. */\nexport interface EconomyQueryPortV1 {\n getWalletSummary(walletId: WalletId): Promise<WalletBalanceSummaryV1 | null>;\n getWalletLifetime(\n walletId: WalletId,\n ): Promise<WalletLifetimeSnapshotV1 | null>;\n listWalletActivity(\n walletId: WalletId,\n request: WalletActivityPageRequestV1,\n ): Promise<WalletActivityPageV1>;\n getPortfolioSummary(\n scope: WalletPortfolioReadScopeV1,\n ): Promise<WalletPortfolioSummaryV1>;\n getPortfolioLifetime(\n scope: WalletPortfolioReadScopeV1,\n ): Promise<WalletPortfolioLifetimeV1>;\n listPortfolioActivity(\n scope: WalletPortfolioReadScopeV1,\n request: WalletActivityPageRequestV1,\n ): Promise<WalletActivityPageV1>;\n}\n","import {\n assertPurchaseLimitPolicy,\n type PurchaseLimitPolicyV1,\n} from \"./acquisition.js\";\nimport { compareUnicodeCodeUnits } from \"./canonical-order.js\";\nimport {\n ECONOMY_CONTRACT_VERSION,\n assertEconomyIdentifier,\n parseIsoTimestamp,\n type AccountId,\n type EconomyContractVersion,\n type HouseholdId,\n type IsoTimestamp,\n} from \"./contracts.js\";\nimport { EconomyError, economyAssert } from \"./errors.js\";\n\ndeclare const gbpMinorUnitStringBrand: unique symbol;\n\n/** Canonical non-negative GBP minor-unit string used by cap contracts. */\nexport type GbpMinorUnitString = string & {\n readonly [gbpMinorUnitStringBrand]: \"GbpMinorUnitString\";\n};\n\nconst MAX_SIGNED_BIGINT = 2n ** 63n - 1n;\nconst CANONICAL_NON_NEGATIVE_INTEGER = /^(?:0|[1-9][0-9]*)$/u;\n\n/** Parses exact GBP minor units without floating point or coercion. */\nexport function parseGbpMinorUnits(value: string): bigint {\n economyAssert(\n typeof value === \"string\" && CANONICAL_NON_NEGATIVE_INTEGER.test(value),\n \"INVALID_AMOUNT\",\n \"GBP minor units must be a canonical non-negative integer string\",\n );\n try {\n const amount = BigInt(value);\n economyAssert(\n amount <= MAX_SIGNED_BIGINT,\n \"AMOUNT_OUT_OF_RANGE\",\n \"GBP minor units are outside the signed 64-bit range\",\n );\n return amount;\n } catch (error) {\n if (error instanceof EconomyError) {\n throw error;\n }\n throw new EconomyError(\"INVALID_AMOUNT\", \"GBP minor units are invalid\");\n }\n}\n\n/** Serializes exact GBP minor units using the canonical wire representation. */\nexport function serializeGbpMinorUnits(amount: bigint): GbpMinorUnitString {\n economyAssert(\n amount >= 0n && amount <= MAX_SIGNED_BIGINT,\n \"AMOUNT_OUT_OF_RANGE\",\n \"GBP minor units are outside the signed 64-bit range\",\n );\n return amount.toString(10) as GbpMinorUnitString;\n}\n\nexport type PurchaseCapScopeTypeV1 = \"payer\" | \"household\";\nexport type PurchaseCapReservationStatusV1 =\n | \"reserved\"\n | \"settled\"\n | \"released\"\n | \"expired\";\nexport type PurchaseCapReservationTransitionTypeV1 =\n | \"settle\"\n | \"release\"\n | \"expire\";\n\nexport interface PurchaseCapReservationTransitionV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly transitionId: string;\n readonly reservationId: string;\n readonly transitionType: PurchaseCapReservationTransitionTypeV1;\n readonly occurredAt: IsoTimestamp;\n}\n\n/** Append-only cap evidence; effectiveness is rebuilt from occurrence order. */\nexport interface PurchaseCapReservationTransitionReceiptV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly transition: PurchaseCapReservationTransitionV1;\n}\n\n/** One purchase amount mirrored into payer and household cap aggregates. */\nexport interface PurchaseCapReservationV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly reservationId: string;\n readonly payerAccountId: AccountId;\n readonly householdId: HouseholdId;\n readonly priceMinorUnits: GbpMinorUnitString;\n readonly status: PurchaseCapReservationStatusV1;\n readonly reservedAt: IsoTimestamp;\n readonly expiresAt: IsoTimestamp;\n /** Derived winning transition; every delivery remains in `transitionReceipts`. */\n readonly finalTransitionId?: string;\n readonly finalizedAt?: IsoTimestamp;\n readonly transitionReceipts: readonly PurchaseCapReservationTransitionReceiptV1[];\n}\n\n/** Optimistic aggregate for exactly one payer or household rolling ceiling. */\nexport interface RollingPurchaseCapStateV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly scopeType: PurchaseCapScopeTypeV1;\n readonly scopeId: string;\n readonly version: number;\n readonly reservations: readonly PurchaseCapReservationV1[];\n}\n\nexport interface ReservePurchaseCapsCommandV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly reservationId: string;\n readonly payerAccountId: AccountId;\n readonly householdId: HouseholdId;\n readonly priceMinorUnits: GbpMinorUnitString;\n readonly reservedAt: IsoTimestamp;\n readonly expiresAt: IsoTimestamp;\n readonly expectedPayerVersion: number;\n readonly expectedHouseholdVersion: number;\n}\n\nexport interface PurchaseCapMutationResultV1 {\n readonly payerState: RollingPurchaseCapStateV1;\n readonly householdState: RollingPurchaseCapStateV1;\n readonly reservation: PurchaseCapReservationV1;\n /** True when a reservation or transition receipt was newly recorded. */\n readonly applied: boolean;\n readonly stateChanged: boolean;\n readonly payerUsageMinorUnits: GbpMinorUnitString;\n readonly householdUsageMinorUnits: GbpMinorUnitString;\n}\n\ninterface ReservationBinding {\n readonly schemaVersion: EconomyContractVersion;\n readonly reservationId: string;\n readonly payerAccountId: AccountId;\n readonly householdId: HouseholdId;\n readonly priceMinorUnits: GbpMinorUnitString;\n readonly reservedAt: IsoTimestamp;\n readonly expiresAt: IsoTimestamp;\n}\n\nconst RESERVATION_STATUSES: readonly PurchaseCapReservationStatusV1[] = [\n \"reserved\",\n \"settled\",\n \"released\",\n \"expired\",\n];\n\nconst TRANSITION_PRECEDENCE: Readonly<\n Record<PurchaseCapReservationTransitionTypeV1, number>\n> = {\n settle: 0,\n release: 1,\n expire: 2,\n};\n\n/** Validates one rolling-cap transition envelope. */\nexport function assertPurchaseCapReservationTransition(\n transition: PurchaseCapReservationTransitionV1,\n): void {\n economyAssert(\n transition.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported purchase-cap transition contract version\",\n );\n assertEconomyIdentifier(transition.transitionId, \"transitionId\");\n assertEconomyIdentifier(transition.reservationId, \"reservationId\");\n economyAssert(\n [\"settle\", \"release\", \"expire\"].includes(transition.transitionType),\n \"INVALID_CONTRACT\",\n \"Purchase-cap transition type is unsupported\",\n );\n parseIsoTimestamp(transition.occurredAt);\n}\n\nfunction sameTransition(\n left: PurchaseCapReservationTransitionV1,\n right: PurchaseCapReservationTransitionV1,\n): boolean {\n return (\n left.schemaVersion === right.schemaVersion &&\n left.transitionId === right.transitionId &&\n left.reservationId === right.reservationId &&\n left.transitionType === right.transitionType &&\n left.occurredAt === right.occurredAt\n );\n}\n\nfunction compareTransitions(\n left: PurchaseCapReservationTransitionV1,\n right: PurchaseCapReservationTransitionV1,\n): number {\n const timeDifference =\n parseIsoTimestamp(left.occurredAt) - parseIsoTimestamp(right.occurredAt);\n if (timeDifference !== 0) {\n return timeDifference;\n }\n const precedenceDifference =\n TRANSITION_PRECEDENCE[left.transitionType] -\n TRANSITION_PRECEDENCE[right.transitionType];\n return precedenceDifference === 0\n ? compareUnicodeCodeUnits(left.transitionId, right.transitionId)\n : precedenceDifference;\n}\n\nfunction assertBinding(binding: ReservationBinding): void {\n economyAssert(\n binding.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported purchase-cap reservation contract version\",\n );\n assertEconomyIdentifier(binding.reservationId, \"reservationId\");\n assertEconomyIdentifier(binding.payerAccountId, \"payerAccountId\");\n assertEconomyIdentifier(binding.householdId, \"householdId\");\n economyAssert(\n parseGbpMinorUnits(binding.priceMinorUnits) > 0n,\n \"INVALID_AMOUNT\",\n \"Purchase-cap reservation amount must be positive\",\n );\n economyAssert(\n parseIsoTimestamp(binding.expiresAt) >\n parseIsoTimestamp(binding.reservedAt),\n \"INVALID_TIME_WINDOW\",\n \"Purchase-cap reservation expiry must follow its creation\",\n );\n}\n\nfunction bindingFromReservation(\n reservation: PurchaseCapReservationV1,\n): ReservationBinding {\n return {\n schemaVersion: reservation.schemaVersion,\n reservationId: reservation.reservationId,\n payerAccountId: reservation.payerAccountId,\n householdId: reservation.householdId,\n priceMinorUnits: reservation.priceMinorUnits,\n reservedAt: reservation.reservedAt,\n expiresAt: reservation.expiresAt,\n };\n}\n\nfunction projectReservation(\n binding: ReservationBinding,\n receipts: readonly PurchaseCapReservationTransitionReceiptV1[],\n): PurchaseCapReservationV1 {\n assertBinding(binding);\n const reservedAt = parseIsoTimestamp(binding.reservedAt);\n const expiresAt = parseIsoTimestamp(binding.expiresAt);\n const transitionIds = new Set<string>();\n for (const receipt of receipts) {\n economyAssert(\n receipt.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported purchase-cap transition receipt version\",\n );\n assertPurchaseCapReservationTransition(receipt.transition);\n economyAssert(\n receipt.transition.reservationId === binding.reservationId &&\n !transitionIds.has(receipt.transition.transitionId),\n \"DUPLICATE_IDENTIFIER\",\n \"Purchase-cap receipts must be unique and belong to the reservation\",\n );\n transitionIds.add(receipt.transition.transitionId);\n }\n\n let status: PurchaseCapReservationStatusV1 = \"reserved\";\n let finalTransitionId: string | undefined;\n let finalizedAt: IsoTimestamp | undefined;\n for (const receipt of [...receipts].sort((left, right) =>\n compareTransitions(left.transition, right.transition),\n )) {\n const transition = receipt.transition;\n const occurredAt = parseIsoTimestamp(transition.occurredAt);\n economyAssert(\n occurredAt >= reservedAt,\n \"INVALID_TIME_WINDOW\",\n \"Purchase-cap transition cannot precede reservation\",\n );\n if (transition.transitionType === \"settle\") {\n economyAssert(\n occurredAt < expiresAt,\n \"INVALID_TIME_WINDOW\",\n \"Purchase-cap settlement must use payment time before expiry\",\n );\n } else if (transition.transitionType === \"release\") {\n economyAssert(\n occurredAt < expiresAt,\n \"INVALID_TIME_WINDOW\",\n \"Purchase-cap release must precede reservation expiry\",\n );\n } else {\n economyAssert(\n occurredAt >= expiresAt,\n \"INVALID_TIME_WINDOW\",\n \"Purchase-cap reservation cannot expire before its deadline\",\n );\n }\n if (status === \"reserved\") {\n status =\n transition.transitionType === \"settle\"\n ? \"settled\"\n : transition.transitionType === \"release\"\n ? \"released\"\n : \"expired\";\n finalTransitionId = transition.transitionId;\n finalizedAt = transition.occurredAt;\n }\n }\n\n return {\n ...binding,\n status,\n ...(finalTransitionId === undefined\n ? {}\n : { finalTransitionId, finalizedAt: finalizedAt! }),\n transitionReceipts: receipts,\n };\n}\n\nfunction sameReservationFacts(\n left: PurchaseCapReservationV1,\n right: PurchaseCapReservationV1,\n): boolean {\n return (\n left.schemaVersion === right.schemaVersion &&\n left.reservationId === right.reservationId &&\n left.payerAccountId === right.payerAccountId &&\n left.householdId === right.householdId &&\n left.priceMinorUnits === right.priceMinorUnits &&\n left.status === right.status &&\n left.reservedAt === right.reservedAt &&\n left.expiresAt === right.expiresAt &&\n left.finalTransitionId === right.finalTransitionId &&\n left.finalizedAt === right.finalizedAt &&\n left.transitionReceipts.length === right.transitionReceipts.length &&\n left.transitionReceipts.every((receipt, index) => {\n const other = right.transitionReceipts[index];\n return (\n other !== undefined &&\n receipt.schemaVersion === other.schemaVersion &&\n sameTransition(receipt.transition, other.transition)\n );\n })\n );\n}\n\nfunction sameReservationBinding(\n reservation: PurchaseCapReservationV1,\n proposed: PurchaseCapReservationV1,\n): boolean {\n return (\n reservation.schemaVersion === proposed.schemaVersion &&\n reservation.reservationId === proposed.reservationId &&\n reservation.payerAccountId === proposed.payerAccountId &&\n reservation.householdId === proposed.householdId &&\n reservation.priceMinorUnits === proposed.priceMinorUnits &&\n reservation.reservedAt === proposed.reservedAt &&\n reservation.expiresAt === proposed.expiresAt\n );\n}\n\n/** Validates one mirrored rolling-cap reservation and its complete rebuild. */\nexport function assertPurchaseCapReservation(\n reservation: PurchaseCapReservationV1,\n): void {\n economyAssert(\n RESERVATION_STATUSES.includes(reservation.status),\n \"INVALID_CONTRACT\",\n \"Purchase-cap reservation status is unsupported\",\n );\n const projected = projectReservation(\n bindingFromReservation(reservation),\n reservation.transitionReceipts,\n );\n economyAssert(\n sameReservationFacts(projected, reservation),\n \"INVALID_CONTRACT\",\n \"Purchase-cap reservation does not match its immutable event rebuild\",\n );\n}\n\n/** Validates one payer or household rolling-cap aggregate. */\nexport function assertRollingPurchaseCapState(\n state: RollingPurchaseCapStateV1,\n): void {\n economyAssert(\n state.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported rolling purchase-cap contract version\",\n );\n economyAssert(\n state.scopeType === \"payer\" || state.scopeType === \"household\",\n \"INVALID_CONTRACT\",\n \"Purchase-cap scope type is unsupported\",\n );\n assertEconomyIdentifier(state.scopeId, \"scopeId\");\n const reservationIds = new Set<string>();\n const transitionIds = new Set<string>();\n let receiptCount = 0;\n for (const reservation of state.reservations) {\n assertPurchaseCapReservation(reservation);\n economyAssert(\n !reservationIds.has(reservation.reservationId),\n \"DUPLICATE_IDENTIFIER\",\n \"Purchase-cap state cannot repeat a reservation\",\n );\n reservationIds.add(reservation.reservationId);\n economyAssert(\n state.scopeType === \"payer\"\n ? reservation.payerAccountId === state.scopeId\n : reservation.householdId === state.scopeId,\n \"INVALID_CONTRACT\",\n \"Purchase-cap reservation belongs to another aggregate scope\",\n );\n for (const receipt of reservation.transitionReceipts) {\n economyAssert(\n !transitionIds.has(receipt.transition.transitionId),\n \"DUPLICATE_IDENTIFIER\",\n \"Purchase-cap state cannot repeat a transition ID\",\n );\n transitionIds.add(receipt.transition.transitionId);\n receiptCount += 1;\n }\n }\n economyAssert(\n Number.isSafeInteger(state.version) &&\n state.version === 1 + state.reservations.length + receiptCount,\n \"INVALID_CONTRACT\",\n \"Purchase-cap state version must match reservation and receipt counts\",\n );\n}\n\nfunction assertAggregatePair(\n payerState: RollingPurchaseCapStateV1,\n householdState: RollingPurchaseCapStateV1,\n payerAccountId: AccountId,\n householdId: HouseholdId,\n): void {\n assertRollingPurchaseCapState(payerState);\n assertRollingPurchaseCapState(householdState);\n economyAssert(\n payerState.scopeType === \"payer\" &&\n payerState.scopeId === payerAccountId &&\n householdState.scopeType === \"household\" &&\n householdState.scopeId === householdId,\n \"INVALID_CONTRACT\",\n \"Purchase-cap aggregate pair does not match payer and household\",\n );\n}\n\nfunction findMirroredReservation(\n payerState: RollingPurchaseCapStateV1,\n householdState: RollingPurchaseCapStateV1,\n reservationId: string,\n): PurchaseCapReservationV1 | undefined {\n const payerReservation = payerState.reservations.find(\n (reservation) => reservation.reservationId === reservationId,\n );\n const householdReservation = householdState.reservations.find(\n (reservation) => reservation.reservationId === reservationId,\n );\n economyAssert(\n (payerReservation === undefined) === (householdReservation === undefined),\n \"INVALID_CONTRACT\",\n \"Purchase-cap reservation must exist in both aggregate scopes atomically\",\n );\n if (payerReservation === undefined || householdReservation === undefined) {\n return undefined;\n }\n economyAssert(\n sameReservationFacts(payerReservation, householdReservation),\n \"INVALID_CONTRACT\",\n \"Payer and household purchase-cap reservations have diverged\",\n );\n return payerReservation;\n}\n\nfunction windowStart(checkedAt: number, rollingDays: number): number {\n return checkedAt - rollingDays * 24 * 60 * 60 * 1_000;\n}\n\n/** Returns the exact cap usage at one point in time. */\nexport function calculateRollingPurchaseCapUsage(\n state: RollingPurchaseCapStateV1,\n checkedAt: IsoTimestamp,\n policy: PurchaseLimitPolicyV1,\n): GbpMinorUnitString {\n assertRollingPurchaseCapState(state);\n assertPurchaseLimitPolicy(policy);\n const checkedAtValue = parseIsoTimestamp(checkedAt);\n const start = windowStart(checkedAtValue, policy.rollingDays);\n let total = 0n;\n for (const reservation of state.reservations) {\n if (\n reservation.status === \"reserved\" &&\n parseIsoTimestamp(reservation.reservedAt) <= checkedAtValue &&\n checkedAtValue < parseIsoTimestamp(reservation.expiresAt)\n ) {\n total += parseGbpMinorUnits(reservation.priceMinorUnits);\n } else if (\n reservation.status === \"settled\" &&\n reservation.finalizedAt !== undefined\n ) {\n const settledAt = parseIsoTimestamp(reservation.finalizedAt);\n if (settledAt >= start && settledAt <= checkedAtValue) {\n total += parseGbpMinorUnits(reservation.priceMinorUnits);\n }\n }\n economyAssert(\n total <= MAX_SIGNED_BIGINT,\n \"AMOUNT_OUT_OF_RANGE\",\n \"Rolling purchase-cap usage exceeds signed 64-bit range\",\n );\n }\n return serializeGbpMinorUnits(total);\n}\n\n/** Creates an empty compare-and-swap aggregate for one cap scope. */\nexport function createRollingPurchaseCapState(\n scopeType: PurchaseCapScopeTypeV1,\n scopeId: string,\n): RollingPurchaseCapStateV1 {\n economyAssert(\n scopeType === \"payer\" || scopeType === \"household\",\n \"INVALID_CONTRACT\",\n \"Purchase-cap scope type is unsupported\",\n );\n assertEconomyIdentifier(scopeId, \"scopeId\");\n return {\n schemaVersion: ECONOMY_CONTRACT_VERSION,\n scopeType,\n scopeId,\n version: 1,\n reservations: [],\n };\n}\n\nfunction sortedWithReservation(\n state: RollingPurchaseCapStateV1,\n reservation: PurchaseCapReservationV1,\n): readonly PurchaseCapReservationV1[] {\n return [...state.reservations, reservation].sort((left, right) =>\n compareUnicodeCodeUnits(left.reservationId, right.reservationId),\n );\n}\n\nfunction resultWithUsage(\n payerState: RollingPurchaseCapStateV1,\n householdState: RollingPurchaseCapStateV1,\n reservation: PurchaseCapReservationV1,\n applied: boolean,\n stateChanged: boolean,\n checkedAt: IsoTimestamp,\n policy: PurchaseLimitPolicyV1,\n): PurchaseCapMutationResultV1 {\n return {\n payerState,\n householdState,\n reservation,\n applied,\n stateChanged,\n payerUsageMinorUnits: calculateRollingPurchaseCapUsage(\n payerState,\n checkedAt,\n policy,\n ),\n householdUsageMinorUnits: calculateRollingPurchaseCapUsage(\n householdState,\n checkedAt,\n policy,\n ),\n };\n}\n\n/**\n * Atomically reserves the same amount in payer and household aggregates.\n * Adapters must compare-and-swap both returned versions in one transaction.\n */\nexport function reserveRollingPurchaseCaps(\n payerState: RollingPurchaseCapStateV1,\n householdState: RollingPurchaseCapStateV1,\n command: ReservePurchaseCapsCommandV1,\n policy: PurchaseLimitPolicyV1,\n): PurchaseCapMutationResultV1 {\n economyAssert(\n command.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported purchase-cap reservation command version\",\n );\n const binding: ReservationBinding = {\n schemaVersion: ECONOMY_CONTRACT_VERSION,\n reservationId: command.reservationId,\n payerAccountId: command.payerAccountId,\n householdId: command.householdId,\n priceMinorUnits: command.priceMinorUnits,\n reservedAt: command.reservedAt,\n expiresAt: command.expiresAt,\n };\n assertBinding(binding);\n assertAggregatePair(\n payerState,\n householdState,\n command.payerAccountId,\n command.householdId,\n );\n assertPurchaseLimitPolicy(policy);\n const proposed = projectReservation(binding, []);\n const replay = findMirroredReservation(\n payerState,\n householdState,\n command.reservationId,\n );\n if (replay !== undefined) {\n economyAssert(\n sameReservationBinding(replay, proposed),\n \"DUPLICATE_IDENTIFIER\",\n \"Purchase-cap reservation ID was reused with different facts\",\n );\n return resultWithUsage(\n payerState,\n householdState,\n replay,\n false,\n false,\n replay.finalizedAt ?? command.reservedAt,\n policy,\n );\n }\n\n economyAssert(\n command.expectedPayerVersion === payerState.version &&\n command.expectedHouseholdVersion === householdState.version,\n \"INVALID_CONTRACT\",\n \"Purchase-cap reservation has a stale aggregate version\",\n );\n const amount = parseGbpMinorUnits(command.priceMinorUnits);\n economyAssert(\n amount <= parseGbpMinorUnits(policy.maxOrderPriceMinorUnits),\n \"INSUFFICIENT_BALANCE\",\n \"Purchase amount exceeds the per-order ceiling\",\n );\n const payerUsage = parseGbpMinorUnits(\n calculateRollingPurchaseCapUsage(payerState, command.reservedAt, policy),\n );\n const householdUsage = parseGbpMinorUnits(\n calculateRollingPurchaseCapUsage(\n householdState,\n command.reservedAt,\n policy,\n ),\n );\n economyAssert(\n payerUsage + amount <=\n parseGbpMinorUnits(policy.rollingPayerPriceMinorUnits),\n \"INSUFFICIENT_BALANCE\",\n \"Purchase amount exceeds the rolling payer ceiling\",\n );\n economyAssert(\n householdUsage + amount <=\n parseGbpMinorUnits(policy.rollingHouseholdPriceMinorUnits),\n \"INSUFFICIENT_BALANCE\",\n \"Purchase amount exceeds the rolling household ceiling\",\n );\n\n const nextPayer: RollingPurchaseCapStateV1 = {\n ...payerState,\n version: payerState.version + 1,\n reservations: sortedWithReservation(payerState, proposed),\n };\n const nextHousehold: RollingPurchaseCapStateV1 = {\n ...householdState,\n version: householdState.version + 1,\n reservations: sortedWithReservation(householdState, proposed),\n };\n return resultWithUsage(\n nextPayer,\n nextHousehold,\n proposed,\n true,\n true,\n command.reservedAt,\n policy,\n );\n}\n\nfunction replaceReservation(\n state: RollingPurchaseCapStateV1,\n replacement: PurchaseCapReservationV1,\n): RollingPurchaseCapStateV1 {\n return {\n ...state,\n version: state.version + 1,\n reservations: state.reservations.map((reservation) =>\n reservation.reservationId === replacement.reservationId\n ? replacement\n : reservation,\n ),\n };\n}\n\nfunction findTransitionById(\n state: RollingPurchaseCapStateV1,\n transitionId: string,\n): {\n readonly reservationId: string;\n readonly transition: PurchaseCapReservationTransitionV1;\n} | undefined {\n for (const reservation of state.reservations) {\n const receipt = reservation.transitionReceipts.find(\n (candidate) => candidate.transition.transitionId === transitionId,\n );\n if (receipt !== undefined) {\n return { reservationId: reservation.reservationId, transition: receipt.transition };\n }\n }\n return undefined;\n}\n\n/**\n * Appends a settle/release/expiry receipt and rebuilds authoritative order. A\n * late-delivered pre-expiry settlement corrects a stored expiry while retaining\n * both receipts. Payer and household versions still advance atomically.\n */\nexport function transitionRollingPurchaseCapReservation(\n payerState: RollingPurchaseCapStateV1,\n householdState: RollingPurchaseCapStateV1,\n transition: PurchaseCapReservationTransitionV1,\n expectedPayerVersion: number,\n expectedHouseholdVersion: number,\n policy: PurchaseLimitPolicyV1,\n): PurchaseCapMutationResultV1 {\n assertPurchaseCapReservationTransition(transition);\n assertRollingPurchaseCapState(payerState);\n assertRollingPurchaseCapState(householdState);\n const current = findMirroredReservation(\n payerState,\n householdState,\n transition.reservationId,\n );\n economyAssert(\n current !== undefined,\n \"INVALID_CONTRACT\",\n \"Purchase-cap reservation does not exist in both aggregate scopes\",\n );\n assertAggregatePair(\n payerState,\n householdState,\n current.payerAccountId,\n current.householdId,\n );\n assertPurchaseLimitPolicy(policy);\n\n const payerExisting = findTransitionById(\n payerState,\n transition.transitionId,\n );\n const householdExisting = findTransitionById(\n householdState,\n transition.transitionId,\n );\n economyAssert(\n (payerExisting === undefined) === (householdExisting === undefined),\n \"INVALID_CONTRACT\",\n \"Purchase-cap transition must exist in both scopes atomically\",\n );\n if (payerExisting !== undefined && householdExisting !== undefined) {\n economyAssert(\n payerExisting.reservationId === transition.reservationId &&\n householdExisting.reservationId === transition.reservationId &&\n sameTransition(payerExisting.transition, transition) &&\n sameTransition(householdExisting.transition, transition),\n \"DUPLICATE_IDENTIFIER\",\n \"Purchase-cap transition ID was reused with different facts\",\n );\n return resultWithUsage(\n payerState,\n householdState,\n current,\n false,\n false,\n transition.occurredAt,\n policy,\n );\n }\n economyAssert(\n expectedPayerVersion === payerState.version &&\n expectedHouseholdVersion === householdState.version,\n \"INVALID_CONTRACT\",\n \"Purchase-cap transition has a stale aggregate version\",\n );\n\n const replacement = projectReservation(bindingFromReservation(current), [\n ...current.transitionReceipts,\n { schemaVersion: ECONOMY_CONTRACT_VERSION, transition },\n ]);\n const stateChanged =\n replacement.status !== current.status ||\n replacement.finalTransitionId !== current.finalTransitionId ||\n replacement.finalizedAt !== current.finalizedAt;\n const nextPayer = replaceReservation(payerState, replacement);\n const nextHousehold = replaceReservation(householdState, replacement);\n return resultWithUsage(\n nextPayer,\n nextHousehold,\n replacement,\n true,\n stateChanged,\n transition.occurredAt,\n policy,\n );\n}\n","import type { PurchaseIntentV1, TokenPackV1 } from \"./acquisition.js\";\nimport { assertPurchaseIntentBinding } from \"./acquisition.js\";\nimport { compareUnicodeCodeUnits } from \"./canonical-order.js\";\nimport {\n ECONOMY_CONTRACT_VERSION,\n assertEconomyIdentifier,\n parseIsoTimestamp,\n type EconomyContractVersion,\n type IsoTimestamp,\n} from \"./contracts.js\";\nimport { economyAssert } from \"./errors.js\";\n\nexport type PurchaseIntentTransitionTypeV1 =\n | \"checkout-bound\"\n | \"payment-observed\"\n | \"credit-recorded\"\n | \"expire\"\n | \"cancel\"\n | \"dispute-opened\"\n | \"dispute-won\"\n | \"dispute-lost\";\n\nexport type PurchaseIntentDisputeDispositionV1 =\n | \"none\"\n | \"open\"\n | \"won\"\n | \"lost\";\n\n/** Provider-neutral evidence for one requested purchase-intent transition. */\nexport interface PurchaseIntentTransitionV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly transitionId: string;\n readonly intentId: string;\n readonly transitionType: PurchaseIntentTransitionTypeV1;\n readonly occurredAt: IsoTimestamp;\n /** Sanitized binding; raw provider checkout references are adapter concerns. */\n readonly providerCheckoutReferenceHash?: string;\n}\n\n/** Append-only receipt. Whether it is effective is a rebuildable projection. */\nexport interface PurchaseIntentTransitionReceiptV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly transition: PurchaseIntentTransitionV1;\n}\n\n/**\n * Versioned lifecycle projection. `initialIntent` never changes; every delivery\n * is rebuilt from its append-only receipts in authoritative occurrence order.\n */\nexport interface PurchaseIntentLifecycleV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly initialIntent: PurchaseIntentV1;\n readonly intent: PurchaseIntentV1;\n readonly version: number;\n readonly creditRecorded: boolean;\n readonly disputeDisposition: PurchaseIntentDisputeDispositionV1;\n readonly receipts: readonly PurchaseIntentTransitionReceiptV1[];\n readonly effectiveTransitionIds: readonly string[];\n}\n\n/** Stable instruction identity for the one permitted purchase credit. */\nexport interface PurchaseCreditInstructionV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly intentId: string;\n readonly transitionId: string;\n readonly idempotencyKey: string;\n}\n\nexport interface PurchaseIntentTransitionResultV1 {\n readonly lifecycle: PurchaseIntentLifecycleV1;\n /** False only for an exact transition-ID replay already in `receipts`. */\n readonly recorded: boolean;\n readonly stateChanged: boolean;\n readonly creditInstruction?: PurchaseCreditInstructionV1;\n}\n\nexport interface PurchaseIntentReductionV1 {\n readonly lifecycle: PurchaseIntentLifecycleV1;\n readonly creditInstructions: readonly PurchaseCreditInstructionV1[];\n}\n\ninterface PurchaseIntentProjection {\n readonly intent: PurchaseIntentV1;\n readonly disputeDisposition: PurchaseIntentDisputeDispositionV1;\n readonly effectiveTransitionIds: readonly string[];\n readonly creditTransitionId?: string;\n}\n\nconst TRANSITION_TYPES: readonly PurchaseIntentTransitionTypeV1[] = [\n \"checkout-bound\",\n \"payment-observed\",\n \"credit-recorded\",\n \"expire\",\n \"cancel\",\n \"dispute-opened\",\n \"dispute-won\",\n \"dispute-lost\",\n];\n\nconst TRANSITION_PRECEDENCE: Readonly<\n Record<PurchaseIntentTransitionTypeV1, number>\n> = {\n \"checkout-bound\": 0,\n \"payment-observed\": 1,\n \"credit-recorded\": 2,\n \"dispute-opened\": 3,\n \"dispute-won\": 4,\n \"dispute-lost\": 4,\n cancel: 5,\n expire: 6,\n};\n\nfunction assertCheckoutHash(value: string): void {\n economyAssert(\n /^sha256:[a-f0-9]{64}$/u.test(value),\n \"INVALID_CONTRACT\",\n \"Checkout references must be stored as sanitized SHA-256 hashes\",\n );\n}\n\n/** Validates one provider-neutral purchase-intent transition envelope. */\nexport function assertPurchaseIntentTransition(\n transition: PurchaseIntentTransitionV1,\n): void {\n economyAssert(\n transition.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported purchase-intent transition contract version\",\n );\n assertEconomyIdentifier(transition.transitionId, \"transitionId\");\n assertEconomyIdentifier(transition.intentId, \"intentId\");\n economyAssert(\n TRANSITION_TYPES.includes(transition.transitionType),\n \"INVALID_CONTRACT\",\n \"Purchase-intent transition type is unsupported\",\n );\n parseIsoTimestamp(transition.occurredAt);\n if (transition.providerCheckoutReferenceHash !== undefined) {\n assertCheckoutHash(transition.providerCheckoutReferenceHash);\n }\n const requiresCheckoutHash =\n transition.transitionType === \"checkout-bound\" ||\n transition.transitionType === \"payment-observed\";\n economyAssert(\n requiresCheckoutHash ===\n (transition.providerCheckoutReferenceHash !== undefined),\n \"INVALID_CONTRACT\",\n \"Only checkout and payment transitions must carry a checkout binding\",\n );\n}\n\nfunction sameTransition(\n left: PurchaseIntentTransitionV1,\n right: PurchaseIntentTransitionV1,\n): boolean {\n return (\n left.schemaVersion === right.schemaVersion &&\n left.transitionId === right.transitionId &&\n left.intentId === right.intentId &&\n left.transitionType === right.transitionType &&\n left.occurredAt === right.occurredAt &&\n left.providerCheckoutReferenceHash ===\n right.providerCheckoutReferenceHash\n );\n}\n\nfunction sameIntent(left: PurchaseIntentV1, right: PurchaseIntentV1): boolean {\n return (\n left.schemaVersion === right.schemaVersion &&\n left.intentId === right.intentId &&\n left.payerAccountId === right.payerAccountId &&\n left.receivingHouseholdId === right.receivingHouseholdId &&\n left.receivingWalletId === right.receivingWalletId &&\n left.packId === right.packId &&\n left.catalogVersion === right.catalogVersion &&\n left.expectedCurrency === right.expectedCurrency &&\n left.expectedPriceMinorUnits === right.expectedPriceMinorUnits &&\n left.grantAmount === right.grantAmount &&\n left.status === right.status &&\n left.createdAt === right.createdAt &&\n left.expiresAt === right.expiresAt &&\n left.providerCheckoutReferenceHash ===\n right.providerCheckoutReferenceHash\n );\n}\n\nfunction compareTransitions(\n left: PurchaseIntentTransitionV1,\n right: PurchaseIntentTransitionV1,\n): number {\n const timeDifference =\n parseIsoTimestamp(left.occurredAt) - parseIsoTimestamp(right.occurredAt);\n if (timeDifference !== 0) {\n return timeDifference;\n }\n const precedenceDifference =\n TRANSITION_PRECEDENCE[left.transitionType] -\n TRANSITION_PRECEDENCE[right.transitionType];\n return precedenceDifference === 0\n ? compareUnicodeCodeUnits(left.transitionId, right.transitionId)\n : precedenceDifference;\n}\n\nfunction assertMatchingCheckoutBinding(\n intent: PurchaseIntentV1,\n checkoutHash: string,\n): void {\n economyAssert(\n intent.providerCheckoutReferenceHash === undefined ||\n intent.providerCheckoutReferenceHash === checkoutHash,\n \"INVALID_CONTRACT\",\n \"Purchase-intent transition conflicts with its checkout binding\",\n );\n}\n\nfunction projectPurchaseIntent(\n initialIntent: PurchaseIntentV1,\n transitions: readonly PurchaseIntentTransitionV1[],\n pack: TokenPackV1,\n): PurchaseIntentProjection {\n assertPurchaseIntentBinding(initialIntent, pack);\n economyAssert(\n initialIntent.status === \"created\" &&\n initialIntent.providerCheckoutReferenceHash === undefined,\n \"INVALID_CONTRACT\",\n \"Purchase-intent lifecycle requires immutable created intent facts\",\n );\n const createdAt = parseIsoTimestamp(initialIntent.createdAt);\n const expiresAt = parseIsoTimestamp(initialIntent.expiresAt);\n let intent = initialIntent;\n let disputeDisposition: PurchaseIntentDisputeDispositionV1 = \"none\";\n let creditTransitionId: string | undefined;\n const effectiveTransitionIds: string[] = [];\n\n for (const transition of [...transitions].sort(compareTransitions)) {\n assertPurchaseIntentTransition(transition);\n economyAssert(\n transition.intentId === initialIntent.intentId,\n \"INVALID_CONTRACT\",\n \"Purchase-intent transition belongs to another intent\",\n );\n const eventTime = parseIsoTimestamp(transition.occurredAt);\n economyAssert(\n eventTime >= createdAt,\n \"INVALID_TIME_WINDOW\",\n \"Purchase-intent transition cannot precede intent creation\",\n );\n let effective = false;\n\n if (transition.transitionType === \"checkout-bound\") {\n const checkoutHash = transition.providerCheckoutReferenceHash!;\n assertMatchingCheckoutBinding(intent, checkoutHash);\n if (intent.status === \"created\") {\n economyAssert(\n eventTime < expiresAt,\n \"INVALID_TIME_WINDOW\",\n \"Checkout cannot be bound after purchase-intent expiry\",\n );\n intent = {\n ...intent,\n status: \"checkout-created\",\n providerCheckoutReferenceHash: checkoutHash,\n };\n effective = true;\n } else {\n economyAssert(\n ![\"expired\", \"cancelled\"].includes(intent.status),\n \"INVALID_CONTRACT\",\n \"A terminal purchase intent cannot bind a checkout\",\n );\n }\n } else if (transition.transitionType === \"payment-observed\") {\n const checkoutHash = transition.providerCheckoutReferenceHash!;\n assertMatchingCheckoutBinding(intent, checkoutHash);\n economyAssert(\n eventTime < expiresAt,\n \"INVALID_TIME_WINDOW\",\n \"Authoritative payment time must precede purchase-intent expiry\",\n );\n if (intent.status === \"created\") {\n intent = {\n ...intent,\n status: \"paid-unreconciled\",\n providerCheckoutReferenceHash: checkoutHash,\n };\n effective = true;\n } else if (intent.status === \"checkout-created\") {\n intent = { ...intent, status: \"paid-unreconciled\" };\n effective = true;\n } else {\n economyAssert(\n ![\"expired\", \"cancelled\"].includes(intent.status),\n \"INVALID_CONTRACT\",\n \"A terminal purchase intent cannot observe payment\",\n );\n }\n } else if (transition.transitionType === \"credit-recorded\") {\n if (intent.status === \"paid-unreconciled\") {\n intent = { ...intent, status: \"credited\" };\n disputeDisposition = \"none\";\n creditTransitionId = transition.transitionId;\n effective = true;\n } else {\n economyAssert(\n intent.status === \"credited\" || intent.status === \"disputed\",\n \"INVALID_CONTRACT\",\n \"Purchase intent cannot be credited before authoritative payment\",\n );\n }\n } else if (transition.transitionType === \"dispute-opened\") {\n if (intent.status === \"credited\" && disputeDisposition === \"none\") {\n intent = { ...intent, status: \"disputed\" };\n disputeDisposition = \"open\";\n effective = true;\n } else {\n economyAssert(\n intent.status === \"disputed\" && disputeDisposition === \"open\",\n \"INVALID_CONTRACT\",\n \"Dispute can open only once after purchase credit\",\n );\n }\n } else if (transition.transitionType === \"dispute-won\") {\n if (intent.status === \"disputed\" && disputeDisposition === \"open\") {\n intent = { ...intent, status: \"credited\" };\n disputeDisposition = \"won\";\n effective = true;\n } else {\n economyAssert(\n intent.status === \"credited\" && disputeDisposition === \"won\",\n \"INVALID_CONTRACT\",\n \"Dispute-win transition requires one open dispute\",\n );\n }\n } else if (transition.transitionType === \"dispute-lost\") {\n if (intent.status === \"disputed\" && disputeDisposition === \"open\") {\n disputeDisposition = \"lost\";\n effective = true;\n } else {\n economyAssert(\n intent.status === \"disputed\" && disputeDisposition === \"lost\",\n \"INVALID_CONTRACT\",\n \"Dispute-loss transition requires one open dispute\",\n );\n }\n } else if (transition.transitionType === \"cancel\") {\n if (intent.status === \"created\" || intent.status === \"checkout-created\") {\n intent = { ...intent, status: \"cancelled\" };\n effective = true;\n }\n } else {\n economyAssert(\n eventTime >= expiresAt,\n \"INVALID_TIME_WINDOW\",\n \"Expiry transition cannot precede purchase-intent expiry\",\n );\n if (intent.status === \"created\" || intent.status === \"checkout-created\") {\n intent = { ...intent, status: \"expired\" };\n effective = true;\n }\n }\n\n if (effective) {\n effectiveTransitionIds.push(transition.transitionId);\n }\n }\n\n return {\n intent,\n disputeDisposition,\n effectiveTransitionIds,\n ...(creditTransitionId === undefined ? {} : { creditTransitionId }),\n };\n}\n\n/** Validates and deterministically rebuilds a lifecycle projection. */\nexport function assertPurchaseIntentLifecycle(\n lifecycle: PurchaseIntentLifecycleV1,\n pack: TokenPackV1,\n): void {\n economyAssert(\n lifecycle.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported purchase-intent lifecycle contract version\",\n );\n economyAssert(\n Number.isSafeInteger(lifecycle.version) &&\n lifecycle.version === lifecycle.receipts.length + 1,\n \"INVALID_CONTRACT\",\n \"Purchase-intent lifecycle version must match its receipt count\",\n );\n const transitionIds = new Set<string>();\n for (const receipt of lifecycle.receipts) {\n economyAssert(\n receipt.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Purchase-intent receipt is invalid\",\n );\n assertPurchaseIntentTransition(receipt.transition);\n economyAssert(\n receipt.transition.intentId === lifecycle.initialIntent.intentId &&\n !transitionIds.has(receipt.transition.transitionId),\n \"DUPLICATE_IDENTIFIER\",\n \"Purchase-intent receipts must be unique and belong to the intent\",\n );\n transitionIds.add(receipt.transition.transitionId);\n }\n const projection = projectPurchaseIntent(\n lifecycle.initialIntent,\n lifecycle.receipts.map((receipt) => receipt.transition),\n pack,\n );\n economyAssert(\n sameIntent(projection.intent, lifecycle.intent) &&\n lifecycle.creditRecorded ===\n (projection.intent.status === \"credited\" ||\n projection.intent.status === \"disputed\") &&\n lifecycle.disputeDisposition === projection.disputeDisposition &&\n lifecycle.effectiveTransitionIds.length ===\n projection.effectiveTransitionIds.length &&\n lifecycle.effectiveTransitionIds.every(\n (transitionId, index) =>\n transitionId === projection.effectiveTransitionIds[index],\n ),\n \"INVALID_CONTRACT\",\n \"Purchase-intent lifecycle does not match its immutable event rebuild\",\n );\n}\n\n/** Creates a lifecycle from immutable, server-created purchase-intent facts. */\nexport function createPurchaseIntentLifecycle(\n initialIntent: PurchaseIntentV1,\n pack: TokenPackV1,\n): PurchaseIntentLifecycleV1 {\n const projection = projectPurchaseIntent(initialIntent, [], pack);\n return {\n schemaVersion: ECONOMY_CONTRACT_VERSION,\n initialIntent,\n intent: projection.intent,\n version: 1,\n creditRecorded: false,\n disputeDisposition: projection.disputeDisposition,\n receipts: [],\n effectiveTransitionIds: [],\n };\n}\n\nfunction sameProjection(\n lifecycle: PurchaseIntentLifecycleV1,\n projection: PurchaseIntentProjection,\n): boolean {\n return (\n sameIntent(lifecycle.intent, projection.intent) &&\n lifecycle.disputeDisposition === projection.disputeDisposition &&\n lifecycle.effectiveTransitionIds.length ===\n projection.effectiveTransitionIds.length &&\n lifecycle.effectiveTransitionIds.every(\n (transitionId, index) =>\n transitionId === projection.effectiveTransitionIds[index],\n )\n );\n}\n\n/**\n * Appends one event and rebuilds all receipts by authoritative occurrence time.\n * A late pre-expiry payment can therefore correct a stored expiry without\n * deleting the expiry receipt. Exact retries succeed before version checking.\n */\nexport function applyPurchaseIntentTransition(\n lifecycle: PurchaseIntentLifecycleV1,\n transition: PurchaseIntentTransitionV1,\n expectedVersion: number,\n pack: TokenPackV1,\n): PurchaseIntentTransitionResultV1 {\n assertPurchaseIntentLifecycle(lifecycle, pack);\n assertPurchaseIntentTransition(transition);\n economyAssert(\n transition.intentId === lifecycle.initialIntent.intentId,\n \"INVALID_CONTRACT\",\n \"Purchase-intent transition belongs to another intent\",\n );\n const replay = lifecycle.receipts.find(\n (receipt) => receipt.transition.transitionId === transition.transitionId,\n );\n if (replay !== undefined) {\n economyAssert(\n sameTransition(replay.transition, transition),\n \"DUPLICATE_IDENTIFIER\",\n \"Purchase-intent transition ID was reused with different facts\",\n );\n return { lifecycle, recorded: false, stateChanged: false };\n }\n economyAssert(\n expectedVersion === lifecycle.version,\n \"INVALID_CONTRACT\",\n \"Purchase-intent transition has a stale expected version\",\n );\n\n const receipts: readonly PurchaseIntentTransitionReceiptV1[] = [\n ...lifecycle.receipts,\n { schemaVersion: ECONOMY_CONTRACT_VERSION, transition },\n ];\n const projection = projectPurchaseIntent(\n lifecycle.initialIntent,\n receipts.map((receipt) => receipt.transition),\n pack,\n );\n const stateChanged = !sameProjection(lifecycle, projection);\n const nextLifecycle: PurchaseIntentLifecycleV1 = {\n schemaVersion: ECONOMY_CONTRACT_VERSION,\n initialIntent: lifecycle.initialIntent,\n intent: projection.intent,\n version: lifecycle.version + 1,\n creditRecorded:\n projection.intent.status === \"credited\" ||\n projection.intent.status === \"disputed\",\n disputeDisposition: projection.disputeDisposition,\n receipts,\n effectiveTransitionIds: projection.effectiveTransitionIds,\n };\n assertPurchaseIntentLifecycle(nextLifecycle, pack);\n\n const producesCredit =\n projection.creditTransitionId === transition.transitionId &&\n !lifecycle.creditRecorded &&\n nextLifecycle.creditRecorded;\n const creditInstruction: PurchaseCreditInstructionV1 | undefined =\n producesCredit\n ? {\n schemaVersion: ECONOMY_CONTRACT_VERSION,\n intentId: nextLifecycle.intent.intentId,\n transitionId: transition.transitionId,\n idempotencyKey: nextLifecycle.intent.intentId,\n }\n : undefined;\n return {\n lifecycle: nextLifecycle,\n recorded: true,\n stateChanged,\n ...(creditInstruction === undefined ? {} : { creditInstruction }),\n };\n}\n\n/**\n * Reduces an unordered delivery batch in canonical event-time/type/ID order.\n * Exact duplicate IDs collapse; conflicting duplicate facts are rejected.\n */\nexport function reducePurchaseIntentTransitions(\n initialIntent: PurchaseIntentV1,\n transitions: readonly PurchaseIntentTransitionV1[],\n pack: TokenPackV1,\n): PurchaseIntentReductionV1 {\n const unique = new Map<string, PurchaseIntentTransitionV1>();\n for (const transition of transitions) {\n assertPurchaseIntentTransition(transition);\n const existing = unique.get(transition.transitionId);\n if (existing !== undefined) {\n economyAssert(\n sameTransition(existing, transition),\n \"DUPLICATE_IDENTIFIER\",\n \"Purchase-intent transition ID was reused with different facts\",\n );\n } else {\n unique.set(transition.transitionId, transition);\n }\n }\n\n let lifecycle = createPurchaseIntentLifecycle(initialIntent, pack);\n const creditInstructions: PurchaseCreditInstructionV1[] = [];\n for (const transition of [...unique.values()].sort(compareTransitions)) {\n const result = applyPurchaseIntentTransition(\n lifecycle,\n transition,\n lifecycle.version,\n pack,\n );\n lifecycle = result.lifecycle;\n if (result.creditInstruction !== undefined) {\n creditInstructions.push(result.creditInstruction);\n }\n }\n economyAssert(\n creditInstructions.length <= 1,\n \"DUPLICATE_TRANSACTION\",\n \"Purchase-intent reduction produced more than one credit\",\n );\n return { lifecycle, creditInstructions };\n}\n","import {\n ECONOMY_CONTRACT_VERSION,\n assertEconomyIdentifier,\n parseIsoTimestamp,\n type EconomyContractVersion,\n type IsoTimestamp,\n} from \"./contracts.js\";\nimport {\n isWholeTokenAmount,\n parseTokenSubunits,\n serializeTokenSubunits,\n type TokenSubunitString,\n} from \"./amount.js\";\nimport { economyAssert } from \"./errors.js\";\n\nexport type RecurrenceInterval = \"daily\" | \"weekly\" | \"monthly\";\n\n/** Provider-neutral subscription contract. Site policy controls enablement. */\nexport interface TokenSubscriptionPlanV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly planId: string;\n readonly catalogVersion: string;\n readonly interval: RecurrenceInterval;\n readonly priceMinorUnits: string;\n readonly currency: \"GBP\";\n readonly grantAmount: TokenSubunitString;\n readonly enabled: boolean;\n readonly effectiveFrom: IsoTimestamp;\n}\n\n/** Future convenience plan contract; disabled until public spend is live. */\nexport const BASELINE_MONTHLY_SUBSCRIPTION_PLAN: TokenSubscriptionPlanV1 =\n Object.freeze({\n schemaVersion: ECONOMY_CONTRACT_VERSION,\n planId: \"monthly-10-100-v1\",\n catalogVersion: \"gbp-subscriptions-v1\",\n interval: \"monthly\",\n priceMinorUnits: \"1000\",\n currency: \"GBP\",\n grantAmount: serializeTokenSubunits(100_000n),\n enabled: false,\n effectiveFrom: \"2026-07-15T00:00:00.000Z\",\n });\n\n/** Validates future provider-neutral recurrence without enabling it. */\nexport function assertTokenSubscriptionPlan(\n plan: TokenSubscriptionPlanV1,\n): void {\n economyAssert(\n plan.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported subscription-plan contract version\",\n );\n assertEconomyIdentifier(plan.planId, \"planId\");\n assertEconomyIdentifier(plan.catalogVersion, \"catalogVersion\");\n economyAssert(\n [\"daily\", \"weekly\", \"monthly\"].includes(plan.interval) &&\n plan.currency === \"GBP\" &&\n typeof plan.enabled === \"boolean\",\n \"INVALID_CONTRACT\",\n \"Subscription recurrence, currency, or enabled state is invalid\",\n );\n economyAssert(\n /^(?:0|[1-9][0-9]*)$/u.test(plan.priceMinorUnits) &&\n BigInt(plan.priceMinorUnits) > 0n,\n \"INVALID_AMOUNT\",\n \"Subscription price must be a positive integer minor-unit string\",\n );\n const grantAmount = parseTokenSubunits(plan.grantAmount);\n economyAssert(\n grantAmount > 0n && isWholeTokenAmount(grantAmount),\n \"AMOUNT_NOT_WHOLE_TOKEN\",\n \"Subscription grants must contain whole Tokens\",\n );\n parseIsoTimestamp(plan.effectiveFrom);\n}\n","import { parseTokenSubunits, type TokenSubunitString } from \"./amount.js\";\nimport {\n ECONOMY_CONTRACT_VERSION,\n assertEconomyIdentifier,\n parseIsoTimestamp,\n type AccountId,\n type AllocationId,\n type EconomyContractVersion,\n type IsoTimestamp,\n type TransactionId,\n} from \"./contracts.js\";\nimport { economyAssert } from \"./errors.js\";\n\nexport type SpendRequestPurpose = \"gameplay-conversion\" | \"non-gameplay\";\nexport type SpendRequestStatus =\n | \"requested\"\n | \"approved\"\n | \"rejected\"\n | \"expired\"\n | \"executed\"\n | \"cancelled\";\n\n/** Future child request; baseline adapters must reject creation while disabled. */\nexport interface SpendRequestV1 {\n readonly schemaVersion: EconomyContractVersion;\n readonly requestId: string;\n readonly childAccountId: AccountId;\n readonly allocationId: AllocationId;\n readonly purpose: SpendRequestPurpose;\n readonly amount: TokenSubunitString;\n readonly status: SpendRequestStatus;\n readonly requestedAt: IsoTimestamp;\n readonly expiresAt: IsoTimestamp;\n readonly decidedByAccountId?: AccountId;\n readonly decidedAt?: IsoTimestamp;\n readonly approvalNonceHash?: string;\n readonly resultingTransactionId?: TransactionId;\n}\n\n/** Validates future child requests while creation remains policy-disabled. */\nexport function assertSpendRequest(request: SpendRequestV1): void {\n economyAssert(\n request.schemaVersion === ECONOMY_CONTRACT_VERSION,\n \"INVALID_CONTRACT\",\n \"Unsupported spend-request contract version\",\n );\n assertEconomyIdentifier(request.requestId, \"requestId\");\n assertEconomyIdentifier(request.childAccountId, \"childAccountId\");\n assertEconomyIdentifier(request.allocationId, \"allocationId\");\n economyAssert(\n request.purpose === \"gameplay-conversion\" ||\n request.purpose === \"non-gameplay\",\n \"INVALID_CONTRACT\",\n \"Spend request has an unsupported purpose\",\n );\n economyAssert(\n [\n \"requested\",\n \"approved\",\n \"rejected\",\n \"expired\",\n \"executed\",\n \"cancelled\",\n ].includes(request.status),\n \"INVALID_CONTRACT\",\n \"Spend request has an unsupported status\",\n );\n economyAssert(\n parseTokenSubunits(request.amount) > 0n,\n \"INVALID_AMOUNT\",\n \"Spend-request amount must be positive\",\n );\n const requestedAt = parseIsoTimestamp(request.requestedAt);\n const expiresAt = parseIsoTimestamp(request.expiresAt);\n economyAssert(\n expiresAt > requestedAt,\n \"INVALID_TIME_WINDOW\",\n \"Spend-request expiry must follow creation\",\n );\n\n const decisionRequired = [\"approved\", \"rejected\", \"executed\"].includes(\n request.status,\n );\n economyAssert(\n !decisionRequired ||\n (request.decidedByAccountId !== undefined &&\n request.decidedAt !== undefined),\n \"INVALID_CONTRACT\",\n \"Decided spend requests require a guardian actor and timestamp\",\n );\n if (request.decidedByAccountId !== undefined) {\n assertEconomyIdentifier(request.decidedByAccountId, \"decidedByAccountId\");\n }\n if (request.decidedAt !== undefined) {\n const decidedAt = parseIsoTimestamp(request.decidedAt);\n economyAssert(\n decidedAt >= requestedAt && decidedAt <= expiresAt,\n \"INVALID_TIME_WINDOW\",\n \"Spend-request decision must occur before expiry\",\n );\n }\n if (request.approvalNonceHash !== undefined) {\n economyAssert(\n /^sha256:[a-f0-9]{64}$/u.test(request.approvalNonceHash),\n \"INVALID_CONTRACT\",\n \"Approval nonces must be stored as SHA-256 hashes\",\n );\n }\n if (request.status === \"approved\" || request.status === \"executed\") {\n economyAssert(\n request.approvalNonceHash !== undefined,\n \"INVALID_CONTRACT\",\n \"Approved spend requests require a one-time approval nonce hash\",\n );\n }\n if (request.resultingTransactionId !== undefined) {\n assertEconomyIdentifier(\n request.resultingTransactionId,\n \"resultingTransactionId\",\n );\n economyAssert(\n request.status === \"executed\",\n \"INVALID_CONTRACT\",\n \"Only executed spend requests may reference a ledger transaction\",\n );\n }\n}\n"],"mappings":"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","names":["assertCanonicalHash","assertWholePositive","ACTIVITY_TYPES","ACTIVITY_STATUSES","ACTIVITY_SOURCES","hasControlCharacters","TRANSITION_PRECEDENCE","sameTransition","compareTransitions"]}