@kasufinance/kasu-sdk 2.10.2 → 2.11.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.
@@ -24217,9 +24217,10 @@ class SdkConfig {
24217
24217
  }
24218
24218
 
24219
24219
  /**
24220
- * The single-call `LendingPoolManager` requests a sponsored relay may carry,
24221
- * encoded by the SDK so no application hand-builds calldata or hand-maps the
24222
- * relay's `kind` for them.
24220
+ * The single-call requests a sponsored relay may carry — the four
24221
+ * `LendingPoolManager` requests, plus the stable asset's own `transfer` (P2P
24222
+ * Send) — encoded by the SDK so no application hand-builds calldata or
24223
+ * hand-maps the relay's `kind` for them.
24223
24224
  *
24224
24225
  * Every function here is PURE: addresses and ids in, `{ kind, call }` out.
24225
24226
  * Reading the chain (the shares a withdrawal is for) is the facade's job —
@@ -24247,6 +24248,11 @@ const SPONSORED_CALL_KINDS = [
24247
24248
  'cancel_withdrawal',
24248
24249
  /** `LendingPoolManager.requestFixedTermDepositWithdrawal(pool, lockId)`. */
24249
24250
  'withdraw_at_expiry',
24251
+ /**
24252
+ * `stableAsset.transfer(to, amount)` — P2P Send, to the chain's stable
24253
+ * asset rather than the manager. See {@link encodeStableTransfer}.
24254
+ */
24255
+ 'transfer',
24250
24256
  ];
24251
24257
  /**
24252
24258
  * Widened to the plain `Interface`: the typechain one overloads
@@ -24254,7 +24260,9 @@ const SPONSORED_CALL_KINDS = [
24254
24260
  * `FUNCTION_OF`.
24255
24261
  */
24256
24262
  const LENDING_POOL_MANAGER$2 = ILendingPoolManagerAbi__factory.createInterface();
24257
- /** The `LendingPoolManager` function behind each kind. */
24263
+ /** The generated ERC-20 interface — the `transfer` kind's one function. */
24264
+ const ERC20$2 = IERC20MetadataAbi__factory.createInterface();
24265
+ /** The `LendingPoolManager` function behind each manager kind. */
24258
24266
  const FUNCTION_OF = Object.freeze({
24259
24267
  withdrawal: 'requestWithdrawal',
24260
24268
  cancel_deposit: 'cancelDepositRequest',
@@ -24263,14 +24271,16 @@ const FUNCTION_OF = Object.freeze({
24263
24271
  });
24264
24272
  /**
24265
24273
  * The 4-byte selector of each kind's function, DERIVED from the generated
24266
- * `ILendingPoolManager` ABI — never typed in by hand, so an ABI change moves
24267
- * it and the cross-check spec against the relay's own pins goes red.
24274
+ * ABIs (`ILendingPoolManager`, and `IERC20Metadata` for `transfer`) — never
24275
+ * typed in by hand, so an ABI change moves it and the cross-check spec
24276
+ * against the relay's own pins goes red.
24268
24277
  */
24269
24278
  const SPONSORED_CALL_SELECTORS = Object.freeze({
24270
24279
  withdrawal: LENDING_POOL_MANAGER$2.getSighash(FUNCTION_OF.withdrawal),
24271
24280
  cancel_deposit: LENDING_POOL_MANAGER$2.getSighash(FUNCTION_OF.cancel_deposit),
24272
24281
  cancel_withdrawal: LENDING_POOL_MANAGER$2.getSighash(FUNCTION_OF.cancel_withdrawal),
24273
24282
  withdraw_at_expiry: LENDING_POOL_MANAGER$2.getSighash(FUNCTION_OF.withdraw_at_expiry),
24283
+ transfer: ERC20$2.getSighash('transfer'),
24274
24284
  });
24275
24285
  /**
24276
24286
  * What an encoder throws for an input it will not encode. `code` names the
@@ -24369,6 +24379,53 @@ function encodeWithdrawAtExpiryCall(lendingPoolManager, poolId, fixedTermDeposit
24369
24379
  toUint256(fixedTermDepositId, 'lock-id'),
24370
24380
  ]);
24371
24381
  }
24382
+ /**
24383
+ * `stableAsset.transfer(to, amount)` — `transfer`: P2P Send of the chain's
24384
+ * stable asset from the sender's own account (`msg.sender`) to `to`.
24385
+ *
24386
+ * `amount` is in the token's BASE units (6 decimals for USDC), and must be
24387
+ * greater than zero. `to` must be a well-formed, non-zero address (a
24388
+ * mixed-case one with a valid EIP-55 checksum). That is
24389
+ * ALL this encoder judges, because it is all a pure function can know.
24390
+ *
24391
+ * The recipient POLICY is the relay's job and is deliberately not restated
24392
+ * here: it refuses the sender's own account, the stable asset, the
24393
+ * `LendingPoolManager`, the precompile range, any address with contract code
24394
+ * (read on chain at submission), a sender our identity store does not hold
24395
+ * as verified, and anything over the sender's daily count and amount caps.
24396
+ * A call this encoder accepts can therefore still be refused — the app maps
24397
+ * the relay's refusal codes to its own words.
24398
+ *
24399
+ * Pass `stableAsset` from the chain config (`CHAIN_CONFIGS[chain].stableAsset
24400
+ * .address`) — the relay compares `to` against its own configured token and
24401
+ * refuses any other contract.
24402
+ */
24403
+ function encodeStableTransfer(input) {
24404
+ assertAddress(input.stableAsset, 'stable-asset');
24405
+ assertAddress(input.to, 'recipient');
24406
+ // A mixed-case recipient carries an EIP-55 checksum, and one that does not
24407
+ // match is a mistyped address: refuse it as `recipient` here rather than
24408
+ // let the ABI coder throw its own error at the encode below.
24409
+ try {
24410
+ utils$2.getAddress(input.to);
24411
+ }
24412
+ catch (_a) {
24413
+ throw new SponsoredCallInputError('recipient');
24414
+ }
24415
+ if (BigNumber.from(input.to).isZero()) {
24416
+ throw new SponsoredCallInputError('zero-recipient');
24417
+ }
24418
+ const amount = toUint256(input.amount, 'amount');
24419
+ if (amount.isZero())
24420
+ throw new SponsoredCallInputError('zero-amount');
24421
+ return {
24422
+ kind: 'transfer',
24423
+ call: {
24424
+ to: input.stableAsset,
24425
+ data: ERC20$2.encodeFunctionData('transfer', [input.to, amount]),
24426
+ },
24427
+ };
24428
+ }
24372
24429
 
24373
24430
  const ADDRESS_RE$1 = /^0x[0-9a-fA-F]{40}$/;
24374
24431
  /**
@@ -25600,7 +25657,10 @@ function checkBatchOutcome(transactionId, expect, ports) {
25600
25657
  }
25601
25658
  if (read.kind === 'reverted')
25602
25659
  return 'not-deposited';
25603
- if (read.kind !== 'mined' || typeof read.txHash !== 'string') {
25660
+ // An empty hash is not an answer — `waitForMined` reads it the same way.
25661
+ if (read.kind !== 'mined' ||
25662
+ typeof read.txHash !== 'string' ||
25663
+ read.txHash === '') {
25604
25664
  return 'unknown';
25605
25665
  }
25606
25666
  try {
@@ -25617,10 +25677,60 @@ function checkBatchOutcome(transactionId, expect, ports) {
25617
25677
  }
25618
25678
  });
25619
25679
  }
25680
+ // ---------------------------------------------------------------------------
25681
+ // One sponsored call — withdraw, cancel, withdraw at expiry, transfer
25682
+ // ---------------------------------------------------------------------------
25683
+ /**
25684
+ * `checkBatchOutcome` for ONE sponsored call — ONE status read, no polling —
25685
+ * for an app's guard against sending the same request twice (a P2P transfer
25686
+ * whose earlier submission ended PENDING, say):
25687
+ *
25688
+ * - `executed` — mined, and the receipt proves the sender's operation
25689
+ * succeeded (`proveUserOperationInReceipt`);
25690
+ * - `not-executed` — definitively reverted (vendor status or the operation's
25691
+ * own flag);
25692
+ * - `unknown` — anything else, including a read or receipt that failed, or a
25693
+ * receipt that does not show the sender's operation.
25694
+ *
25695
+ * Only `not-executed` may let a new attempt proceed unprompted; `executed`
25696
+ * means the earlier one landed and the user should be told.
25697
+ */
25698
+ function checkSponsoredCallOutcome(transactionId, expect, ports) {
25699
+ return __awaiter(this, void 0, void 0, function* () {
25700
+ var _a;
25701
+ let read;
25702
+ try {
25703
+ read = yield ports.getStatus(transactionId);
25704
+ }
25705
+ catch (_b) {
25706
+ return 'unknown';
25707
+ }
25708
+ if (read.kind === 'reverted')
25709
+ return 'not-executed';
25710
+ // An empty hash is not an answer — `waitForMined` reads it the same way.
25711
+ if (read.kind !== 'mined' ||
25712
+ typeof read.txHash !== 'string' ||
25713
+ read.txHash === '') {
25714
+ return 'unknown';
25715
+ }
25716
+ try {
25717
+ const receipt = yield ports.getReceipt(read.txHash);
25718
+ const proof = proveUserOperationInReceipt(receipt, Object.assign(Object.assign({}, expect), { userOperationHash: (_a = read.userOperationHash) !== null && _a !== void 0 ? _a : null }));
25719
+ if (proof.kind === 'executed')
25720
+ return 'executed';
25721
+ if (proof.kind === 'reverted')
25722
+ return 'not-executed';
25723
+ return 'unknown';
25724
+ }
25725
+ catch (_c) {
25726
+ return 'unknown';
25727
+ }
25728
+ });
25729
+ }
25620
25730
  /**
25621
- * `submitBatch` for ONE sponsored `LendingPoolManager` call — the body of a
25622
- * `WithdrawFlow` `submitCall` port, and of an app's cancel or
25623
- * withdraw-at-expiry action. Same post, same polling policy, same outcome
25731
+ * `submitBatch` for ONE sponsored call — the body of a `WithdrawFlow`
25732
+ * `submitCall` port, of an app's cancel or withdraw-at-expiry action, and of
25733
+ * a P2P transfer (`encodeStableTransfer`). Same post, same polling policy, same outcome
25624
25734
  * table; the proof is `proveUserOperationInReceipt` (the sender's operation
25625
25735
  * succeeded) instead of the deposit proof, and an unproven receipt is
25626
25736
  * `call_unproven:<reason>`.
@@ -25636,7 +25746,8 @@ function checkBatchOutcome(transactionId, expect, ports) {
25636
25746
  * The call is checked against its kind before anything is posted — a known
25637
25747
  * kind, exactly `{ to, data }`, and `data` opening with that kind's selector —
25638
25748
  * and a mismatch is `BatchSubmissionError('call_mismatch', 'failed')`: nothing
25639
- * was sent. Build calls with `kasu.calls`, and this never fires.
25749
+ * was sent. Build calls with `kasu.calls` (or `encodeStableTransfer`), and
25750
+ * this never fires.
25640
25751
  *
25641
25752
  * As on the deposit path, nothing after the post ever produces `failed`.
25642
25753
  */
@@ -27432,6 +27543,82 @@ function maxNetRateCeiling(pools, feePercent) {
27432
27543
  return rate;
27433
27544
  }
27434
27545
 
27546
+ /**
27547
+ * A strategy's SHORT blurb, as plain text: the CMS `liteDescription` first,
27548
+ * else the first paragraph of the long `description`, else nothing.
27549
+ *
27550
+ * Lifted from kasu-ui (`pickShortDescription`, its deposit dialog and landing
27551
+ * strategy card) so every app shows the same line, and pinned to its output
27552
+ * for every live CMS row. The rules are facts about how the CMS is authored,
27553
+ * not formatting preferences:
27554
+ *
27555
+ * - `liteDescription` IS THE SHORT ONE. `description` is the credit
27556
+ * originator's several-paragraph profile; on a card it is a wall.
27557
+ * - `"Not Available"` IS A PLACEHOLDER, not editorial. Several rows carry it
27558
+ * verbatim, and it must read as missing, not print. Matched on the whole
27559
+ * trimmed value, case-insensitively. It applies to `liteDescription` only.
27560
+ * - EMPTY OR BLANK IS MISSING. The service maps a pool with no CMS record to
27561
+ * `''`.
27562
+ * - THE FIELDS HOLD MARKDOWN. `liteDescription` can open with a `**bold**`
27563
+ * lead, and the surfaces this feeds render plain text, so the markers are
27564
+ * stripped (bold, then italic, then inline code).
27565
+ * - AND HARD NEWLINES. Every run of whitespace becomes one space, so a
27566
+ * paragraph break inside the value is not a gap in a one-line slot.
27567
+ * - NOT SANITISED. "Plain text" means text to render AS text. HTML tags,
27568
+ * entities and link syntax (`<script>`, `&lt;`, `[a](javascript:…)`) pass
27569
+ * through unchanged, and removing markers can join fragments into a tag
27570
+ * (`<scr**i**pt>` becomes `<script>`). Render it as a text node, never as
27571
+ * HTML or markdown.
27572
+ *
27573
+ * Two refinements over the kasu-ui original, neither reachable by any live
27574
+ * row: the cleaned text is trimmed (a CRLF value no longer ends in a space),
27575
+ * and a `liteDescription` that cleans to nothing (`** **`) counts as missing,
27576
+ * so the result is never a blank string.
27577
+ *
27578
+ * This authors no string of its own. It selects and cleans editorial the CMS
27579
+ * already holds, and an absent blurb is `undefined`, never a fallback sentence:
27580
+ * what "no blurb" means is the render site's decision.
27581
+ *
27582
+ * Pure. A value that is not a string reads as missing.
27583
+ */
27584
+ function pickShortDescription(source) {
27585
+ var _a;
27586
+ const lite = asTrimmed(source.liteDescription);
27587
+ if (lite && !NOT_AVAILABLE.test(lite)) {
27588
+ const summary = toOneLine(lite);
27589
+ if (summary)
27590
+ return summary;
27591
+ }
27592
+ const long = asTrimmed(source.description);
27593
+ if (long) {
27594
+ const firstParagraph = (_a = long.split(PARAGRAPH_BREAK, 1)[0]) !== null && _a !== void 0 ? _a : long;
27595
+ return toOneLine(firstParagraph) || undefined;
27596
+ }
27597
+ return undefined;
27598
+ }
27599
+ const NOT_AVAILABLE = /^not available$/i;
27600
+ const PARAGRAPH_BREAK = /\n\s*\n/;
27601
+ function asTrimmed(value) {
27602
+ return typeof value === 'string' ? value.trim() : '';
27603
+ }
27604
+ /** Markers off, whitespace runs to one space, ends trimmed. `''` when nothing is left. */
27605
+ function toOneLine(text) {
27606
+ return stripInlineMarkdown(text).replace(/\s+/gu, ' ').trim();
27607
+ }
27608
+ /**
27609
+ * Inline markdown markers off, in the order bold → italic → code. The bold
27610
+ * passes consume every `**` / `__` pair first, so the italic patterns can match
27611
+ * a lone `*` / `_` without lookarounds.
27612
+ */
27613
+ function stripInlineMarkdown(input) {
27614
+ return input
27615
+ .replace(/\*\*(.+?)\*\*/g, '$1')
27616
+ .replace(/__(.+?)__/g, '$1')
27617
+ .replace(/\*(.+?)\*/g, '$1')
27618
+ .replace(/_(.+?)_/g, '$1')
27619
+ .replace(/`([^`]+)`/g, '$1');
27620
+ }
27621
+
27435
27622
  /**
27436
27623
  * High-level facade for browsing Kasu lending strategies (pools).
27437
27624
  *
@@ -27615,7 +27802,10 @@ class StrategiesFacade {
27615
27802
  return {
27616
27803
  id: pool.id,
27617
27804
  name: pool.poolName,
27805
+ subheading: nonEmptyOrUndefined(pool.subheading),
27618
27806
  description: pool.description,
27807
+ liteDescription: nonEmptyOrUndefined(pool.liteDescription),
27808
+ summary: pickShortDescription(pool),
27619
27809
  isActive: pool.isActive,
27620
27810
  apy: pool.apy,
27621
27811
  tvl: pool.totalValueLocked,
@@ -27630,6 +27820,16 @@ class StrategiesFacade {
27630
27820
  };
27631
27821
  }
27632
27822
  }
27823
+ /**
27824
+ * A CMS text field as a string, or `undefined` when it is absent, not a
27825
+ * string, or empty (blank included) — the CMS stores an emptied field as `''`, and an empty
27826
+ * subheading must read as "none", not render an empty line.
27827
+ */
27828
+ function nonEmptyOrUndefined(value) {
27829
+ return typeof value === 'string' && value.trim().length > 0
27830
+ ? value
27831
+ : undefined;
27832
+ }
27633
27833
  /**
27634
27834
  * A CMS "numeric" field as a finite number, or `null`. An empty or blank
27635
27835
  * string is UNAUTHORED, not zero.
@@ -28970,4 +29170,4 @@ function weightedAverageApy(slices) {
28970
29170
  return weighted / totalBalance;
28971
29171
  }
28972
29172
 
28973
- export { APXIUM, AU_ALPHA3, AU_MIN_CUMULATIVE_BY_STABLE, BatchPendingError, BatchRevertedError, BatchSubmissionError, CHAIN_CONFIGS, CLEARING_WINDOW_SECONDS, CONTRACT_TTL_MS, CallsFacade, DAYS_PER_EPOCH, DAYS_PER_MONTH, DEFAULT_BATCH_POLLING_POLICY, DepositBatchMismatchError, DepositFlow, DepositsFacade, ENTRY_POINT_V07, EPOCHS_IN_YEAR, Flow, FlowStore, FlowsFacade, INVALID_ACCEPTANCE_SIGNATURE_MESSAGE, INVALID_AUTH_SIGNATURE_MESSAGE, INVOICEMATE, Kasu, KasuSdk, MAX_LENDING_AMOUNT_FALLBACK, MIN_DAYS_FOR_MONTHS, MIN_LENDING_AMOUNT_FALLBACK, MIN_TRANCHE_CAPACITY, NOT_A_WITHDRAWAL_CALL_MESSAGE, NO_DIRECTUS_URL_MESSAGE, NO_KYC_PARAMS_MESSAGE, NO_SPENDER_MESSAGE, NO_WITHDRAWAL_ENCODER_MESSAGE, PortfolioFacade, READ_ONLY_MESSAGE, RIXON_CAPITAL, SECONDS_PER_WEEK, SPONSORED_CALL_KINDS, SPONSORED_CALL_SELECTORS, SdkConfig, SponsoredCallInputError, StrategiesFacade, UPPER_MEZZANINE, WithdrawFlow, accruedInterest, apyToEpochRate, asContractType, auMinimumRemaining, auThresholdFor, availableFixedTermConfigs, batchOutcomeOf, buildContractVersionType, buildFullNameRequestMessage, buildLegacyContractRequestMessage, buildLoanAgreementSignMessage, cancelDeadline, ceilToCents, checkBatchOutcome, classifyWalletFailure, compareTrancheSeniority, computeSettlementWindow, countSubmissions, dailyInterest, decodeRevert, deriveCycleDates, derivePoolStatus, deriveRequestState, encodeCancelDepositCall, encodeCancelWithdrawalCall, encodeDepositData, encodeRequestWithdrawalCall, encodeWithdrawAtExpiryCall, epochRateToApy, explorerAddressUrl, explorerTxUrl, extractRevertData, fetchUnusedPoolIds, firstSubmissionTimestamp, floorToCents, formatSignTimestampUtc, getCreditOriginator, getInstitutionalLender, getStrategyRegion, getTrancheDisplayName, isAuMinimumExempt, isAustralianKyc, isBelowMinimumCapacity, isCycleClosed, isDefinitivelyNotSubmitted, isFixedTermConfigId, isUnpredictableGas, isUserRejected, lastEventTimestamp, lockDurationDays, lockDurationMonths, maxNetRateCeiling, netEffectiveApy, netTrancheApyBounds, nextCycleBoundary, parseFormattedMessage, parseMinorUnits, parseTrancheBound, pickDefaultTrancheId, pickHighestYieldTranche, poolAllTranchesFull, poolMaxApy, projectedAnnualEarnings, proveDepositInReceipt, proveUserOperationInReceipt, resolveBoundShortcuts, resolveDepositBounds, selectVisiblePools, submissionEvents, submitBatch, submitSponsoredCall, trancheApyBounds, trancheHasCapacity, trancheRiskRank, validateDepositBatchCalls, weeklyInterest, weightedAverageApy };
29173
+ export { APXIUM, AU_ALPHA3, AU_MIN_CUMULATIVE_BY_STABLE, BatchPendingError, BatchRevertedError, BatchSubmissionError, CHAIN_CONFIGS, CLEARING_WINDOW_SECONDS, CONTRACT_TTL_MS, CallsFacade, DAYS_PER_EPOCH, DAYS_PER_MONTH, DEFAULT_BATCH_POLLING_POLICY, DepositBatchMismatchError, DepositFlow, DepositsFacade, ENTRY_POINT_V07, EPOCHS_IN_YEAR, Flow, FlowStore, FlowsFacade, INVALID_ACCEPTANCE_SIGNATURE_MESSAGE, INVALID_AUTH_SIGNATURE_MESSAGE, INVOICEMATE, Kasu, KasuSdk, MAX_LENDING_AMOUNT_FALLBACK, MIN_DAYS_FOR_MONTHS, MIN_LENDING_AMOUNT_FALLBACK, MIN_TRANCHE_CAPACITY, NOT_A_WITHDRAWAL_CALL_MESSAGE, NO_DIRECTUS_URL_MESSAGE, NO_KYC_PARAMS_MESSAGE, NO_SPENDER_MESSAGE, NO_WITHDRAWAL_ENCODER_MESSAGE, PortfolioFacade, READ_ONLY_MESSAGE, RIXON_CAPITAL, SECONDS_PER_WEEK, SPONSORED_CALL_KINDS, SPONSORED_CALL_SELECTORS, SdkConfig, SponsoredCallInputError, StrategiesFacade, UPPER_MEZZANINE, WithdrawFlow, accruedInterest, apyToEpochRate, asContractType, auMinimumRemaining, auThresholdFor, availableFixedTermConfigs, batchOutcomeOf, buildContractVersionType, buildFullNameRequestMessage, buildLegacyContractRequestMessage, buildLoanAgreementSignMessage, cancelDeadline, ceilToCents, checkBatchOutcome, checkSponsoredCallOutcome, classifyWalletFailure, compareTrancheSeniority, computeSettlementWindow, countSubmissions, dailyInterest, decodeRevert, deriveCycleDates, derivePoolStatus, deriveRequestState, encodeCancelDepositCall, encodeCancelWithdrawalCall, encodeDepositData, encodeRequestWithdrawalCall, encodeStableTransfer, encodeWithdrawAtExpiryCall, epochRateToApy, explorerAddressUrl, explorerTxUrl, extractRevertData, fetchUnusedPoolIds, firstSubmissionTimestamp, floorToCents, formatSignTimestampUtc, getCreditOriginator, getInstitutionalLender, getStrategyRegion, getTrancheDisplayName, isAuMinimumExempt, isAustralianKyc, isBelowMinimumCapacity, isCycleClosed, isDefinitivelyNotSubmitted, isFixedTermConfigId, isUnpredictableGas, isUserRejected, lastEventTimestamp, lockDurationDays, lockDurationMonths, maxNetRateCeiling, netEffectiveApy, netTrancheApyBounds, nextCycleBoundary, parseFormattedMessage, parseMinorUnits, parseTrancheBound, pickDefaultTrancheId, pickHighestYieldTranche, pickShortDescription, poolAllTranchesFull, poolMaxApy, projectedAnnualEarnings, proveDepositInReceipt, proveUserOperationInReceipt, resolveBoundShortcuts, resolveDepositBounds, selectVisiblePools, submissionEvents, submitBatch, submitSponsoredCall, trancheApyBounds, trancheHasCapacity, trancheRiskRank, validateDepositBatchCalls, weeklyInterest, weightedAverageApy };
@@ -16,6 +16,10 @@
16
16
  * reconstructs byte-for-byte to verify a lender's signature. Those are not
17
17
  * copy: nobody may reword them, in any language, without a matching backend
18
18
  * change, which is exactly why they belong in one place.
19
+ *
20
+ * `pickShortDescription` returns a string but AUTHORS none: it selects and
21
+ * cleans editorial the CMS already holds, and an absent blurb is
22
+ * `undefined`, never a sentence of its own.
19
23
  * 2. **Pure.** No network, no clock, no environment. Anything with I/O belongs
20
24
  * in `facade/` (see `fetchUnusedPoolIds`).
21
25
  */
@@ -42,8 +46,10 @@ export { decodeRevert, extractRevertData } from './revert-errors';
42
46
  export type { DecodedRevert, RevertFamily } from './revert-errors';
43
47
  export { CLEARING_WINDOW_SECONDS, computeSettlementWindow, deriveCycleDates, nextCycleBoundary, } from './settlement';
44
48
  export type { CycleDates, SettlementWindowInput, SettlementWindowState, } from './settlement';
45
- export { encodeCancelDepositCall, encodeCancelWithdrawalCall, encodeRequestWithdrawalCall, encodeWithdrawAtExpiryCall, SPONSORED_CALL_KINDS, SPONSORED_CALL_SELECTORS, SponsoredCallInputError, } from './sponsored-calls';
49
+ export { encodeCancelDepositCall, encodeCancelWithdrawalCall, encodeRequestWithdrawalCall, encodeStableTransfer, encodeWithdrawAtExpiryCall, SPONSORED_CALL_KINDS, SPONSORED_CALL_SELECTORS, SponsoredCallInputError, } from './sponsored-calls';
46
50
  export type { SponsoredCall, SponsoredCallKind } from './sponsored-calls';
51
+ export { pickShortDescription } from './strategy-summary';
52
+ export type { ShortDescriptionSource } from './strategy-summary';
47
53
  export { getTrancheDisplayName, UPPER_MEZZANINE } from './tranche-display-name';
48
54
  export { compareTrancheSeniority, derivePoolStatus, MIN_TRANCHE_CAPACITY, netTrancheApyBounds, pickDefaultTrancheId, poolAllTranchesFull, trancheApyBounds, trancheHasCapacity, trancheRiskRank, } from './tranches';
49
55
  export type { ApyBounds, PoolStatus, TrancheCapacitySignal, } from './tranches';
@@ -16,6 +16,10 @@
16
16
  * reconstructs byte-for-byte to verify a lender's signature. Those are not
17
17
  * copy: nobody may reword them, in any language, without a matching backend
18
18
  * change, which is exactly why they belong in one place.
19
+ *
20
+ * `pickShortDescription` returns a string but AUTHORS none: it selects and
21
+ * cleans editorial the CMS already holds, and an absent blurb is
22
+ * `undefined`, never a sentence of its own.
19
23
  * 2. **Pure.** No network, no clock, no environment. Anything with I/O belongs
20
24
  * in `facade/` (see `fetchUnusedPoolIds`).
21
25
  */
@@ -31,7 +35,8 @@ export { maxNetRateCeiling, pickHighestYieldTranche, poolMaxApy, selectVisiblePo
31
35
  export { cancelDeadline, countSubmissions, deriveRequestState, firstSubmissionTimestamp, isCycleClosed, lastEventTimestamp, submissionEvents, } from './requests';
32
36
  export { decodeRevert, extractRevertData } from './revert-errors';
33
37
  export { CLEARING_WINDOW_SECONDS, computeSettlementWindow, deriveCycleDates, nextCycleBoundary, } from './settlement';
34
- export { encodeCancelDepositCall, encodeCancelWithdrawalCall, encodeRequestWithdrawalCall, encodeWithdrawAtExpiryCall, SPONSORED_CALL_KINDS, SPONSORED_CALL_SELECTORS, SponsoredCallInputError, } from './sponsored-calls';
38
+ export { encodeCancelDepositCall, encodeCancelWithdrawalCall, encodeRequestWithdrawalCall, encodeStableTransfer, encodeWithdrawAtExpiryCall, SPONSORED_CALL_KINDS, SPONSORED_CALL_SELECTORS, SponsoredCallInputError, } from './sponsored-calls';
39
+ export { pickShortDescription } from './strategy-summary';
35
40
  export { getTrancheDisplayName, UPPER_MEZZANINE } from './tranche-display-name';
36
41
  export { compareTrancheSeniority, derivePoolStatus, MIN_TRANCHE_CAPACITY, netTrancheApyBounds, pickDefaultTrancheId, poolAllTranchesFull, trancheApyBounds, trancheHasCapacity, trancheRiskRank, } from './tranches';
37
42
  export { classifyWalletFailure, isUnpredictableGas, isUserRejected, } from './wallet-errors';
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/domain/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,OAAO,EACH,cAAc,EACd,cAAc,EACd,cAAc,EACd,eAAe,GAClB,MAAM,SAAS,CAAC;AAEjB,OAAO,EACH,SAAS,EACT,2BAA2B,EAC3B,kBAAkB,EAClB,cAAc,EACd,iBAAiB,EACjB,eAAe,EACf,eAAe,GAClB,MAAM,cAAc,CAAC;AAGtB,OAAO,EACH,yBAAyB,EACzB,eAAe,EACf,qBAAqB,EACrB,2BAA2B,EAC3B,yBAAyB,GAC5B,MAAM,eAAe,CAAC;AAavB,OAAO,EACH,WAAW,EACX,YAAY,EACZ,sBAAsB,EACtB,2BAA2B,EAC3B,2BAA2B,EAC3B,iBAAiB,EACjB,qBAAqB,EACrB,oBAAoB,GACvB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAGpE,OAAO,EACH,yBAAyB,EACzB,cAAc,EACd,cAAc,EACd,mBAAmB,EACnB,gBAAgB,EAChB,kBAAkB,EAClB,mBAAmB,GACtB,MAAM,cAAc,CAAC;AAGtB,OAAO,EACH,MAAM,EACN,mBAAmB,EACnB,sBAAsB,EACtB,iBAAiB,EACjB,WAAW,EACX,aAAa,GAChB,MAAM,YAAY,CAAC;AAGpB,OAAO,EACH,cAAc,EACd,wBAAwB,EACxB,2BAA2B,EAC3B,iCAAiC,EACjC,6BAA6B,EAC7B,iBAAiB,EACjB,sBAAsB,EACtB,qBAAqB,GACxB,MAAM,iBAAiB,CAAC;AAYzB,OAAO,EACH,iBAAiB,EACjB,uBAAuB,EACvB,UAAU,EACV,kBAAkB,GACrB,MAAM,SAAS,CAAC;AAGjB,OAAO,EACH,cAAc,EACd,gBAAgB,EAChB,kBAAkB,EAClB,wBAAwB,EACxB,aAAa,EACb,kBAAkB,EAClB,gBAAgB,GACnB,MAAM,YAAY,CAAC;AAOpB,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAGlE,OAAO,EACH,uBAAuB,EACvB,uBAAuB,EACvB,gBAAgB,EAChB,iBAAiB,GACpB,MAAM,cAAc,CAAC;AAOtB,OAAO,EACH,uBAAuB,EACvB,0BAA0B,EAC1B,2BAA2B,EAC3B,0BAA0B,EAC1B,oBAAoB,EACpB,wBAAwB,EACxB,uBAAuB,GAC1B,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEhF,OAAO,EACH,uBAAuB,EACvB,gBAAgB,EAChB,oBAAoB,EACpB,mBAAmB,EACnB,oBAAoB,EACpB,mBAAmB,EACnB,gBAAgB,EAChB,kBAAkB,EAClB,eAAe,GAClB,MAAM,YAAY,CAAC;AAOpB,OAAO,EACH,qBAAqB,EACrB,kBAAkB,EAClB,cAAc,GACjB,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EACH,eAAe,EACf,aAAa,EACb,uBAAuB,EACvB,gBAAgB,EAChB,cAAc,EACd,kBAAkB,GACrB,MAAM,UAAU,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/domain/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,OAAO,EACH,cAAc,EACd,cAAc,EACd,cAAc,EACd,eAAe,GAClB,MAAM,SAAS,CAAC;AAEjB,OAAO,EACH,SAAS,EACT,2BAA2B,EAC3B,kBAAkB,EAClB,cAAc,EACd,iBAAiB,EACjB,eAAe,EACf,eAAe,GAClB,MAAM,cAAc,CAAC;AAGtB,OAAO,EACH,yBAAyB,EACzB,eAAe,EACf,qBAAqB,EACrB,2BAA2B,EAC3B,yBAAyB,GAC5B,MAAM,eAAe,CAAC;AAavB,OAAO,EACH,WAAW,EACX,YAAY,EACZ,sBAAsB,EACtB,2BAA2B,EAC3B,2BAA2B,EAC3B,iBAAiB,EACjB,qBAAqB,EACrB,oBAAoB,GACvB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAGpE,OAAO,EACH,yBAAyB,EACzB,cAAc,EACd,cAAc,EACd,mBAAmB,EACnB,gBAAgB,EAChB,kBAAkB,EAClB,mBAAmB,GACtB,MAAM,cAAc,CAAC;AAGtB,OAAO,EACH,MAAM,EACN,mBAAmB,EACnB,sBAAsB,EACtB,iBAAiB,EACjB,WAAW,EACX,aAAa,GAChB,MAAM,YAAY,CAAC;AAGpB,OAAO,EACH,cAAc,EACd,wBAAwB,EACxB,2BAA2B,EAC3B,iCAAiC,EACjC,6BAA6B,EAC7B,iBAAiB,EACjB,sBAAsB,EACtB,qBAAqB,GACxB,MAAM,iBAAiB,CAAC;AAYzB,OAAO,EACH,iBAAiB,EACjB,uBAAuB,EACvB,UAAU,EACV,kBAAkB,GACrB,MAAM,SAAS,CAAC;AAGjB,OAAO,EACH,cAAc,EACd,gBAAgB,EAChB,kBAAkB,EAClB,wBAAwB,EACxB,aAAa,EACb,kBAAkB,EAClB,gBAAgB,GACnB,MAAM,YAAY,CAAC;AAOpB,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAGlE,OAAO,EACH,uBAAuB,EACvB,uBAAuB,EACvB,gBAAgB,EAChB,iBAAiB,GACpB,MAAM,cAAc,CAAC;AAOtB,OAAO,EACH,uBAAuB,EACvB,0BAA0B,EAC1B,2BAA2B,EAC3B,oBAAoB,EACpB,0BAA0B,EAC1B,oBAAoB,EACpB,wBAAwB,EACxB,uBAAuB,GAC1B,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAG1D,OAAO,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEhF,OAAO,EACH,uBAAuB,EACvB,gBAAgB,EAChB,oBAAoB,EACpB,mBAAmB,EACnB,oBAAoB,EACpB,mBAAmB,EACnB,gBAAgB,EAChB,kBAAkB,EAClB,eAAe,GAClB,MAAM,YAAY,CAAC;AAOpB,OAAO,EACH,qBAAqB,EACrB,kBAAkB,EAClB,cAAc,GACjB,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EACH,eAAe,EACf,aAAa,EACb,uBAAuB,EACvB,gBAAgB,EAChB,cAAc,EACd,kBAAkB,GACrB,MAAM,UAAU,CAAC"}
@@ -1,8 +1,9 @@
1
1
  import { BigNumberish } from 'ethers';
2
2
  /**
3
- * The single-call `LendingPoolManager` requests a sponsored relay may carry,
4
- * encoded by the SDK so no application hand-builds calldata or hand-maps the
5
- * relay's `kind` for them.
3
+ * The single-call requests a sponsored relay may carry — the four
4
+ * `LendingPoolManager` requests, plus the stable asset's own `transfer` (P2P
5
+ * Send) — encoded by the SDK so no application hand-builds calldata or
6
+ * hand-maps the relay's `kind` for them.
6
7
  *
7
8
  * Every function here is PURE: addresses and ids in, `{ kind, call }` out.
8
9
  * Reading the chain (the shares a withdrawal is for) is the facade's job —
@@ -21,7 +22,7 @@ import { BigNumberish } from 'ethers';
21
22
  * wrong kind is refused (`invalid_calls`), so a hand-mapped table that drifts
22
23
  * turns into a lender who cannot withdraw.
23
24
  */
24
- export declare const SPONSORED_CALL_KINDS: readonly ["withdrawal", "cancel_deposit", "cancel_withdrawal", "withdraw_at_expiry"];
25
+ export declare const SPONSORED_CALL_KINDS: readonly ["withdrawal", "cancel_deposit", "cancel_withdrawal", "withdraw_at_expiry", "transfer"];
25
26
  export type SponsoredCallKind = (typeof SPONSORED_CALL_KINDS)[number];
26
27
  /** One encoded call and the relay `kind` that names its shape. */
27
28
  export interface SponsoredCall {
@@ -37,8 +38,9 @@ export interface SponsoredCall {
37
38
  }
38
39
  /**
39
40
  * The 4-byte selector of each kind's function, DERIVED from the generated
40
- * `ILendingPoolManager` ABI — never typed in by hand, so an ABI change moves
41
- * it and the cross-check spec against the relay's own pins goes red.
41
+ * ABIs (`ILendingPoolManager`, and `IERC20Metadata` for `transfer`) — never
42
+ * typed in by hand, so an ABI change moves it and the cross-check spec
43
+ * against the relay's own pins goes red.
42
44
  */
43
45
  export declare const SPONSORED_CALL_SELECTORS: Readonly<Record<SponsoredCallKind, string>>;
44
46
  /**
@@ -72,3 +74,29 @@ export declare function encodeCancelWithdrawalCall(lendingPoolManager: string, p
72
74
  * lender's behalf, which knows the lock's tranche.
73
75
  */
74
76
  export declare function encodeWithdrawAtExpiryCall(lendingPoolManager: string, poolId: string, fixedTermDepositId: BigNumberish): SponsoredCall;
77
+ /**
78
+ * `stableAsset.transfer(to, amount)` — `transfer`: P2P Send of the chain's
79
+ * stable asset from the sender's own account (`msg.sender`) to `to`.
80
+ *
81
+ * `amount` is in the token's BASE units (6 decimals for USDC), and must be
82
+ * greater than zero. `to` must be a well-formed, non-zero address (a
83
+ * mixed-case one with a valid EIP-55 checksum). That is
84
+ * ALL this encoder judges, because it is all a pure function can know.
85
+ *
86
+ * The recipient POLICY is the relay's job and is deliberately not restated
87
+ * here: it refuses the sender's own account, the stable asset, the
88
+ * `LendingPoolManager`, the precompile range, any address with contract code
89
+ * (read on chain at submission), a sender our identity store does not hold
90
+ * as verified, and anything over the sender's daily count and amount caps.
91
+ * A call this encoder accepts can therefore still be refused — the app maps
92
+ * the relay's refusal codes to its own words.
93
+ *
94
+ * Pass `stableAsset` from the chain config (`CHAIN_CONFIGS[chain].stableAsset
95
+ * .address`) — the relay compares `to` against its own configured token and
96
+ * refuses any other contract.
97
+ */
98
+ export declare function encodeStableTransfer(input: {
99
+ stableAsset: string;
100
+ to: string;
101
+ amount: BigNumberish;
102
+ }): SponsoredCall;
@@ -1,9 +1,11 @@
1
- import { BigNumber, constants } from 'ethers';
1
+ import { BigNumber, constants, utils } from 'ethers';
2
+ import { IERC20MetadataAbi__factory } from '../contracts/factories/IERC20MetadataAbi__factory';
2
3
  import { ILendingPoolManagerAbi__factory } from '../contracts/factories/ILendingPoolManagerAbi__factory';
3
4
  /**
4
- * The single-call `LendingPoolManager` requests a sponsored relay may carry,
5
- * encoded by the SDK so no application hand-builds calldata or hand-maps the
6
- * relay's `kind` for them.
5
+ * The single-call requests a sponsored relay may carry — the four
6
+ * `LendingPoolManager` requests, plus the stable asset's own `transfer` (P2P
7
+ * Send) — encoded by the SDK so no application hand-builds calldata or
8
+ * hand-maps the relay's `kind` for them.
7
9
  *
8
10
  * Every function here is PURE: addresses and ids in, `{ kind, call }` out.
9
11
  * Reading the chain (the shares a withdrawal is for) is the facade's job —
@@ -31,6 +33,11 @@ export const SPONSORED_CALL_KINDS = [
31
33
  'cancel_withdrawal',
32
34
  /** `LendingPoolManager.requestFixedTermDepositWithdrawal(pool, lockId)`. */
33
35
  'withdraw_at_expiry',
36
+ /**
37
+ * `stableAsset.transfer(to, amount)` — P2P Send, to the chain's stable
38
+ * asset rather than the manager. See {@link encodeStableTransfer}.
39
+ */
40
+ 'transfer',
34
41
  ];
35
42
  /**
36
43
  * Widened to the plain `Interface`: the typechain one overloads
@@ -38,7 +45,9 @@ export const SPONSORED_CALL_KINDS = [
38
45
  * `FUNCTION_OF`.
39
46
  */
40
47
  const LENDING_POOL_MANAGER = ILendingPoolManagerAbi__factory.createInterface();
41
- /** The `LendingPoolManager` function behind each kind. */
48
+ /** The generated ERC-20 interface — the `transfer` kind's one function. */
49
+ const ERC20 = IERC20MetadataAbi__factory.createInterface();
50
+ /** The `LendingPoolManager` function behind each manager kind. */
42
51
  const FUNCTION_OF = Object.freeze({
43
52
  withdrawal: 'requestWithdrawal',
44
53
  cancel_deposit: 'cancelDepositRequest',
@@ -47,14 +56,16 @@ const FUNCTION_OF = Object.freeze({
47
56
  });
48
57
  /**
49
58
  * The 4-byte selector of each kind's function, DERIVED from the generated
50
- * `ILendingPoolManager` ABI — never typed in by hand, so an ABI change moves
51
- * it and the cross-check spec against the relay's own pins goes red.
59
+ * ABIs (`ILendingPoolManager`, and `IERC20Metadata` for `transfer`) — never
60
+ * typed in by hand, so an ABI change moves it and the cross-check spec
61
+ * against the relay's own pins goes red.
52
62
  */
53
63
  export const SPONSORED_CALL_SELECTORS = Object.freeze({
54
64
  withdrawal: LENDING_POOL_MANAGER.getSighash(FUNCTION_OF.withdrawal),
55
65
  cancel_deposit: LENDING_POOL_MANAGER.getSighash(FUNCTION_OF.cancel_deposit),
56
66
  cancel_withdrawal: LENDING_POOL_MANAGER.getSighash(FUNCTION_OF.cancel_withdrawal),
57
67
  withdraw_at_expiry: LENDING_POOL_MANAGER.getSighash(FUNCTION_OF.withdraw_at_expiry),
68
+ transfer: ERC20.getSighash('transfer'),
58
69
  });
59
70
  /**
60
71
  * What an encoder throws for an input it will not encode. `code` names the
@@ -153,4 +164,51 @@ export function encodeWithdrawAtExpiryCall(lendingPoolManager, poolId, fixedTerm
153
164
  toUint256(fixedTermDepositId, 'lock-id'),
154
165
  ]);
155
166
  }
167
+ /**
168
+ * `stableAsset.transfer(to, amount)` — `transfer`: P2P Send of the chain's
169
+ * stable asset from the sender's own account (`msg.sender`) to `to`.
170
+ *
171
+ * `amount` is in the token's BASE units (6 decimals for USDC), and must be
172
+ * greater than zero. `to` must be a well-formed, non-zero address (a
173
+ * mixed-case one with a valid EIP-55 checksum). That is
174
+ * ALL this encoder judges, because it is all a pure function can know.
175
+ *
176
+ * The recipient POLICY is the relay's job and is deliberately not restated
177
+ * here: it refuses the sender's own account, the stable asset, the
178
+ * `LendingPoolManager`, the precompile range, any address with contract code
179
+ * (read on chain at submission), a sender our identity store does not hold
180
+ * as verified, and anything over the sender's daily count and amount caps.
181
+ * A call this encoder accepts can therefore still be refused — the app maps
182
+ * the relay's refusal codes to its own words.
183
+ *
184
+ * Pass `stableAsset` from the chain config (`CHAIN_CONFIGS[chain].stableAsset
185
+ * .address`) — the relay compares `to` against its own configured token and
186
+ * refuses any other contract.
187
+ */
188
+ export function encodeStableTransfer(input) {
189
+ assertAddress(input.stableAsset, 'stable-asset');
190
+ assertAddress(input.to, 'recipient');
191
+ // A mixed-case recipient carries an EIP-55 checksum, and one that does not
192
+ // match is a mistyped address: refuse it as `recipient` here rather than
193
+ // let the ABI coder throw its own error at the encode below.
194
+ try {
195
+ utils.getAddress(input.to);
196
+ }
197
+ catch (_a) {
198
+ throw new SponsoredCallInputError('recipient');
199
+ }
200
+ if (BigNumber.from(input.to).isZero()) {
201
+ throw new SponsoredCallInputError('zero-recipient');
202
+ }
203
+ const amount = toUint256(input.amount, 'amount');
204
+ if (amount.isZero())
205
+ throw new SponsoredCallInputError('zero-amount');
206
+ return {
207
+ kind: 'transfer',
208
+ call: {
209
+ to: input.stableAsset,
210
+ data: ERC20.encodeFunctionData('transfer', [input.to, amount]),
211
+ },
212
+ };
213
+ }
156
214
  //# sourceMappingURL=sponsored-calls.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"sponsored-calls.js","sourceRoot":"","sources":["../../src/domain/sponsored-calls.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sponsored-calls.js","sourceRoot":"","sources":["../../src/domain/sponsored-calls.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * A strategy's SHORT blurb, as plain text: the CMS `liteDescription` first,
3
+ * else the first paragraph of the long `description`, else nothing.
4
+ *
5
+ * Lifted from kasu-ui (`pickShortDescription`, its deposit dialog and landing
6
+ * strategy card) so every app shows the same line, and pinned to its output
7
+ * for every live CMS row. The rules are facts about how the CMS is authored,
8
+ * not formatting preferences:
9
+ *
10
+ * - `liteDescription` IS THE SHORT ONE. `description` is the credit
11
+ * originator's several-paragraph profile; on a card it is a wall.
12
+ * - `"Not Available"` IS A PLACEHOLDER, not editorial. Several rows carry it
13
+ * verbatim, and it must read as missing, not print. Matched on the whole
14
+ * trimmed value, case-insensitively. It applies to `liteDescription` only.
15
+ * - EMPTY OR BLANK IS MISSING. The service maps a pool with no CMS record to
16
+ * `''`.
17
+ * - THE FIELDS HOLD MARKDOWN. `liteDescription` can open with a `**bold**`
18
+ * lead, and the surfaces this feeds render plain text, so the markers are
19
+ * stripped (bold, then italic, then inline code).
20
+ * - AND HARD NEWLINES. Every run of whitespace becomes one space, so a
21
+ * paragraph break inside the value is not a gap in a one-line slot.
22
+ * - NOT SANITISED. "Plain text" means text to render AS text. HTML tags,
23
+ * entities and link syntax (`<script>`, `&lt;`, `[a](javascript:…)`) pass
24
+ * through unchanged, and removing markers can join fragments into a tag
25
+ * (`<scr**i**pt>` becomes `<script>`). Render it as a text node, never as
26
+ * HTML or markdown.
27
+ *
28
+ * Two refinements over the kasu-ui original, neither reachable by any live
29
+ * row: the cleaned text is trimmed (a CRLF value no longer ends in a space),
30
+ * and a `liteDescription` that cleans to nothing (`** **`) counts as missing,
31
+ * so the result is never a blank string.
32
+ *
33
+ * This authors no string of its own. It selects and cleans editorial the CMS
34
+ * already holds, and an absent blurb is `undefined`, never a fallback sentence:
35
+ * what "no blurb" means is the render site's decision.
36
+ *
37
+ * Pure. A value that is not a string reads as missing.
38
+ */
39
+ export declare function pickShortDescription(source: ShortDescriptionSource): string | undefined;
40
+ /**
41
+ * The two CMS fields `pickShortDescription` reads. A `PoolOverview` and a
42
+ * facade `Strategy` both satisfy it.
43
+ */
44
+ export interface ShortDescriptionSource {
45
+ liteDescription?: string | null;
46
+ description?: string | null;
47
+ }