@cobre-npm/library-portal-core 0.56.0 → 0.58.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.
Files changed (54) hide show
  1. package/README.md +75 -7
  2. package/dist/cjs/blockchains/catalog.d.ts +25 -0
  3. package/dist/cjs/blockchains/catalog.js +12 -0
  4. package/dist/cjs/blockchains/index.d.ts +2 -0
  5. package/dist/cjs/blockchains/index.js +17 -0
  6. package/dist/cjs/blockchains/locales/en.json +11 -0
  7. package/dist/cjs/blockchains/locales/es-mex.json +11 -0
  8. package/dist/cjs/blockchains/utils/blockchain.utils.d.ts +13 -0
  9. package/dist/cjs/blockchains/utils/blockchain.utils.js +27 -0
  10. package/dist/cjs/canonicalTransactions/index.d.ts +4 -0
  11. package/dist/cjs/canonicalTransactions/index.js +2 -0
  12. package/dist/cjs/canonicalTransactions/interfaces/response.interface.d.ts +4 -2
  13. package/dist/cjs/canonicalTransactions/nature/catalog.d.ts +22 -0
  14. package/dist/cjs/canonicalTransactions/nature/catalog.js +11 -0
  15. package/dist/cjs/canonicalTransactions/nature/locales/en.json +10 -0
  16. package/dist/cjs/canonicalTransactions/nature/locales/es-mex.json +10 -0
  17. package/dist/cjs/canonicalTransactions/nature/utils/nature.utils.d.ts +6 -0
  18. package/dist/cjs/canonicalTransactions/nature/utils/nature.utils.js +19 -0
  19. package/dist/cjs/canonicalTransactions/productType/catalog.d.ts +19 -0
  20. package/dist/cjs/canonicalTransactions/productType/catalog.js +18 -0
  21. package/dist/cjs/canonicalTransactions/productType/locales/en.json +9 -0
  22. package/dist/cjs/canonicalTransactions/productType/locales/es-mex.json +9 -0
  23. package/dist/cjs/canonicalTransactions/productType/utils/product-type.utils.d.ts +6 -0
  24. package/dist/cjs/canonicalTransactions/productType/utils/product-type.utils.js +19 -0
  25. package/dist/cjs/filterClassification/interfaces/filter-classification.interface.d.ts +2 -2
  26. package/dist/cjs/filterClassification/utils/type-group.utils.d.ts +6 -2
  27. package/dist/cjs/filterClassification/utils/type-group.utils.js +4 -1
  28. package/dist/cjs/transactions/index.d.ts +1 -1
  29. package/dist/cjs/transactions/types/catalog.d.ts +108 -0
  30. package/dist/cjs/transactions/types/catalog.js +101 -0
  31. package/dist/cjs/transactions/types/locales/en.json +9 -0
  32. package/dist/cjs/transactions/types/locales/es-mex.json +9 -0
  33. package/dist/cjs/transactions/types/utils/transaction-type.utils.d.ts +12 -1
  34. package/dist/cjs/transactions/types/utils/transaction-type.utils.js +30 -1
  35. package/dist/esm/blockchains/catalog.js +9 -0
  36. package/dist/esm/blockchains/index.js +1 -0
  37. package/dist/esm/blockchains/locales/en.json +11 -0
  38. package/dist/esm/blockchains/locales/es-mex.json +11 -0
  39. package/dist/esm/blockchains/utils/blockchain.utils.js +19 -0
  40. package/dist/esm/canonicalTransactions/index.js +2 -0
  41. package/dist/esm/canonicalTransactions/nature/catalog.js +8 -0
  42. package/dist/esm/canonicalTransactions/nature/locales/en.json +10 -0
  43. package/dist/esm/canonicalTransactions/nature/locales/es-mex.json +10 -0
  44. package/dist/esm/canonicalTransactions/nature/utils/nature.utils.js +12 -0
  45. package/dist/esm/canonicalTransactions/productType/catalog.js +15 -0
  46. package/dist/esm/canonicalTransactions/productType/locales/en.json +9 -0
  47. package/dist/esm/canonicalTransactions/productType/locales/es-mex.json +9 -0
  48. package/dist/esm/canonicalTransactions/productType/utils/product-type.utils.js +12 -0
  49. package/dist/esm/filterClassification/utils/type-group.utils.js +2 -0
  50. package/dist/esm/transactions/types/catalog.js +101 -0
  51. package/dist/esm/transactions/types/locales/en.json +9 -0
  52. package/dist/esm/transactions/types/locales/es-mex.json +9 -0
  53. package/dist/esm/transactions/types/utils/transaction-type.utils.js +28 -0
  54. package/package.json +6 -1
package/README.md CHANGED
@@ -4,6 +4,10 @@ Shared catalogs, configuration and interfaces for Cobre's Portal MFEs (Vue 3 + T
4
4
  It is a **static data** library (no app runtime): account types, counterparties, countries, currencies,
5
5
  movement types, document types, etc., together with their translated labels.
6
6
 
7
+ The vocabulary these catalogs share with the Portal and the BFF (rail, movement type, line, business category,
8
+ product type, nature, …) is defined in [`GLOSSARY.md`](./GLOSSARY.md); [`GLOSSARY-MAP.md`](./GLOSSARY-MAP.md)
9
+ lists it together with the glossary local to `canonicalTransactions`.
10
+
7
11
  - No runtime dependencies (only `devDependencies`).
8
12
  - Published compiled to `dist/` (CommonJS + `.d.ts`).
9
13
  - Managed with **pnpm**; built with plain `tsc`.
@@ -43,8 +47,9 @@ import { getCountries } from "@cobre-npm/library-portal-core/countries"
43
47
  | `@cobre-npm/library-portal-core/subclients` | Subclient statuses + `Subclient`/`SubclientPerson` interfaces |
44
48
  | `@cobre-npm/library-portal-core/documentTypes` | Document types (definition + per-country applicability) |
45
49
  | `@cobre-npm/library-portal-core/currencies` | Currencies |
50
+ | `@cobre-npm/library-portal-core/blockchains` | Blockchains (chains of the counterparty dropdown) |
46
51
  | `@cobre-npm/library-portal-core/transactions` | Transaction types + interfaces |
47
- | `@cobre-npm/library-portal-core/canonicalTransactions` | Canonical transaction/money-movement detail interfaces |
52
+ | `@cobre-npm/library-portal-core/canonicalTransactions` | Canonical transaction/money-movement detail interfaces + product type and nature catalogs |
48
53
  | `@cobre-npm/library-portal-core/search` | Search / aggregation interfaces |
49
54
  | `@cobre-npm/library-portal-core/filterClassification` | Grouped type-filter vocabulary (families, sections, categories), `splitTypeLabel`, group-selection helpers |
50
55
  | `@cobre-npm/library-portal-core/trustedSessions` | Trusted session (OTP elevation window) interfaces + constants |
@@ -145,7 +150,7 @@ one-off predicates even where `queryX()` exists.
145
150
 
146
151
  | Class | When | Signature | Examples |
147
152
  |---|---|---|---|
148
- | **With i18n** | the label depends on the language | `getX(lang)` | accountTypes, counterpartyTypes, movementTypes, transactionTypes, countries, countriesISO, documentTypes |
153
+ | **With i18n** | the label depends on the language | `getX(lang)` | accountTypes, counterpartyTypes, movementTypes, transactionTypes, countries, countriesISO, documentTypes, blockchains, productTypes, natures |
149
154
  | **Without i18n** | the label is fixed (or there is none) | `getX()` | currencies (inline label), accountProviders |
150
155
 
151
156
  `currencies`/`providers` **don't take `lang`** because there's no translation — the signature is honest.
@@ -440,8 +445,10 @@ And two on rule 1: `{ minAmount: 1 }` is equality, not `>=`, which is rarely wha
440
445
  ```ts
441
446
  import {
442
447
  getTransactionTypes, queryTransactionTypes, type TransactionType, type TransactionTypeQuery,
448
+ collapseTransactionTypes, type TransactionTypeGroup, type TransactionTypeGroupOption,
443
449
  type Transaction, type EnrichedTransaction, /* ...interfaces */
444
450
  } from "@cobre-npm/library-portal-core/transactions"
451
+ import { isGroupOption, expandGroupSelection } from "@cobre-npm/library-portal-core/filterClassification"
445
452
 
446
453
  getTransactionTypes("en").spei_debit.label // "Outgoing transfer · SPEI"
447
454
  getTransactionTypes("es-mex").spei_debit.label // "Transferencia enviada · SPEI"
@@ -458,6 +465,33 @@ queryTransactionTypes({ lang: "en", category: "top_up" }) // col_top_up_credit
458
465
  "· débito" / "· crédito" (en "· debit" / "· credit") suffix, except `offramp_treasury_credit`, whose label has none; elsewhere the direction is in the verb
459
466
  ("Outgoing transfer", "Incoming transfer"). `col_cb_*` keeps "Cobre Balance" in its label. `misc_*`,
460
467
  `internal_*` and `adjustment_*` have `line: "unclassified"`, and `misc_*` also `category: "unclassified"`.
468
+ Each type also carries a required `section: FilterClassificationSection`, the heading it is listed under in the
469
+ grouped filter (group members take their group's section; `internal_spei_*`, `col_cb_debit` → `internal`,
470
+ `misc_*` → `connected_account`).
471
+ - **conditional marker**: five rarely used types (`misc_debit`, `misc_credit`, `col_cb_debit`, `internal_spei_debit`,
472
+ `internal_spei_credit`) carry `filterDisplay: "when_present"`: the grouped filter should list them only when the
473
+ data has them. It is descriptive, not a visibility switch: there is no default, `queryTransactionTypes()` still
474
+ returns them and their labels are unchanged, so flat filters see no difference. The field is absent on every
475
+ other type, so read it with `"filterDisplay" in type`.
476
+ - **group**: every type carries a required `group: TransactionTypeGroup | null`. The 14 debit/credit legs name
477
+ one of 7 UI-only groups (`cbmm`, `global_pay_to_usa`, `usa_pay_to_global`, `on_ramp`, `off_ramp`,
478
+ `stable_payout`, `internal`); every other type is `null`. A group code is **never** a transaction type and is
479
+ never sent to the API: selecting a group means selecting its member codes (`expandGroupSelection`). There is no
480
+ separate groups catalog; group labels come out of `collapseTransactionTypes`.
481
+ - **collapse** (i18n): `collapseTransactionTypes({ lang, ...filters })` takes the same query as
482
+ `queryTransactionTypes`, filters first, then folds each group into one `TransactionTypeGroupOption`
483
+ `{ code, members, line, category, section, label }`, placed at its first member's position. A group collapses
484
+ only if **all** its legs survive the filter; otherwise the surviving legs come out as plain options. Tell the
485
+ two apart with `isGroupOption` (from [`filterClassification`](#filterclassification)), which also feeds
486
+ `expandGroupSelection` / `getGroupSelectionState`:
487
+
488
+ ```ts
489
+ collapseTransactionTypes({ lang: "en", category: "conversions" }).map(option => option.code)
490
+ // 7 conversion types → 4 options: ["on_ramp", "off_ramp", "stable_payout", "offramp_treasury_credit"]
491
+ collapseTransactionTypes({ lang: "en", creditDebitType: "debit" }) // no group survives: plain legs only
492
+ const groups = collapseTransactionTypes({ lang: "en" }).filter(isGroupOption)
493
+ expandGroupSelection(["cbmm", "spei_debit"], groups) // ["cbmm_debit", "cbmm_credit", "spei_debit"]
494
+ ```
461
495
  - **types query** (i18n `queryX()`): `queryTransactionTypes({ lang, ...filters })` — `lang` is **required inside
462
496
  the query object**, not a separate argument, so the result is already localized. There is no default field
463
497
  (unlike `currencies`' `scope`): every transaction type comes back when only `lang` is given.
@@ -483,7 +517,7 @@ the headings inside a chip, and **types** (movement / transaction types) are the
483
517
  ```ts
484
518
  import {
485
519
  getFilterClassificationCategoryFamilies, getFilterClassificationSections, splitTypeLabel,
486
- expandGroupSelection, getGroupSelectionState,
520
+ expandGroupSelection, getGroupSelectionState, isGroupOption,
487
521
  type FilterClassificationCategoryFamily, type FilterClassificationSection,
488
522
  type FilterClassificationCategory, type FilterClassificationRecord,
489
523
  } from "@cobre-npm/library-portal-core/filterClassification"
@@ -493,6 +527,7 @@ declare const record: { section: FilterClassificationSection } // one of tho
493
527
  declare const groups: FilterClassificationRecord<string>[] // the UI's group records
494
528
  declare const group: FilterClassificationRecord<string> // one of them
495
529
  declare const selectedCodes: string[] // what the user has ticked
530
+ declare const options: ({ code: string } | FilterClassificationRecord<string>)[] // a mixed list: plain and group options
496
531
 
497
532
  const families = getFilterClassificationCategoryFamilies("en")
498
533
  families.between_accounts.label // "Between accounts"
@@ -503,6 +538,7 @@ splitTypeLabel("Transfer · ACH") // { title: "Transfe
503
538
  splitTypeLabel("International") // { title: "International" } — no empty rail
504
539
  expandGroupSelection(["stablecoin_group", "ach"], groups) // member codes + "ach"; the group code is never returned
505
540
  getGroupSelectionState(group, selectedCodes) // "checked" | "indeterminate" | "unchecked"
541
+ options.filter(isGroupOption) // only the group options, typed as such
506
542
  ```
507
543
 
508
544
  - **Family** (`FilterClassificationCategoryFamily`): the chips of the grouped type filter, in chip order: `payments`, `collections`,
@@ -517,9 +553,9 @@ getGroupSelectionState(group, selectedCodes) // "checked" | "indet
517
553
  never sent to an API. `getFilterClassificationSections(lang)`. `internal` and `connected_account` exist but no movement type uses
518
554
  them yet.
519
555
  - **`splitTypeLabel(label)`**: splits at the first `" · "` into `{ title, rail? }` for two-line options.
520
- - **group helpers**: `FilterClassificationRecord<Code>` (`code`, `members`, `line`, `category`, `section`). A group code is a UI
521
- identifier: `expandGroupSelection` swaps it for its members before calling an API, and `getGroupSelectionState`
522
- gives the checkbox state from the selected member codes.
556
+ - **group helpers**: `FilterClassificationRecord<Code, Member = Code>` (`code`, `members`, `line`, `category`, `section`). A group code is a UI
557
+ identifier: `expandGroupSelection` swaps it for its members before calling an API, `getGroupSelectionState`
558
+ gives the checkbox state from the selected member codes, and `isGroupOption` tells group options from plain ones in a mixed list.
523
559
 
524
560
  ### `trustedSessions`
525
561
 
@@ -536,9 +572,30 @@ caller stop attaching an `otp_token` per request while the window is active.
536
572
  `constants/trustedSessions.constants.ts` — the pattern for a domain that needs standalone constants
537
573
  (no catalog, no i18n): a `constants/<domain>.constants.ts` file, re-exported from the barrel.
538
574
 
575
+ ### `blockchains`
576
+
577
+ ```ts
578
+ import {
579
+ getBlockchains, queryBlockchains,
580
+ type Blockchain, type BlockchainOption, type BlockchainQuery,
581
+ } from "@cobre-npm/library-portal-core/blockchains"
582
+
583
+ getBlockchains("en").stellar.label // "Stellar" → point lookup of a chain code
584
+ queryBlockchains({ lang: "en" }) // the 7 chains as a list → dropdowns
585
+ queryBlockchains({ lang: "en", code: ["tron", "base"] }) // [ tron, base ]
586
+ ```
587
+
588
+ - Single i18n catalog (`code` + `label`), 7 chains: `ethereum`, `tron`, `solana`, `polygon`, `base`, `xrpl`, `stellar`.
589
+ Labels are proper names, so `en` and `es-mex` match today.
590
+ - No logo field: the logo is a presentation concern of the consumer (Portal derives it from `code`).
591
+ - `counterparty_chain` / `chain` stay `string` in the counterparties and accounts interfaces — a `string` from
592
+ the backend may not be a `Blockchain`, so consumers narrow it themselves before indexing `getBlockchains()`.
593
+ - No visibility field, so `queryBlockchains({ lang })` returns all 7 (same rule as every `queryX()`: a key that is
594
+ present always filters, so `{ code: undefined }` returns `[]`).
595
+
539
596
  ### `canonicalTransactions`
540
597
 
541
- Interfaces only (pure types). This is the single source of truth for the canonical money-movement /
598
+ Interfaces plus two small i18n catalogs (`productType`, `nature`). The interfaces are the single source of truth for the canonical money-movement /
542
599
  transaction detail — built by `core-portal-bff`'s transaction-canonical BFF, consumed as-is by the
543
600
  `portal` MFE (`CanonicalMoneyMovement`), and narrowed with `Pick` by the receipts-generation service:
544
601
 
@@ -560,6 +617,17 @@ import type {
560
617
  consumers (`portal`, `core-portal-bff`, `util-portal-receipts`) — see `ICanonicalApprovalEvent`'s
561
618
  doc comment for one case that's a superset of two non-overlapping shapes rather than a clean merge,
562
619
  and revisit it once the real payload is confirmed.
620
+ - **productType / nature** (i18n): `getProductTypes(lang)` / `getNatures(lang)` cover the 5 `product_type` and 6
621
+ `nature` values of the BFF's `rail-mapper.interface.ts` (the source of truth), and `CanonicalProductType` /
622
+ `CanonicalNature` are derived from them — `conversion`, `on_ramp` and `off_ramp` used to be missing. `en` labels
623
+ are the humanized code in Title Case (`on_ramp` → "On Ramp"); `es-mex` labels are Design's copy (`payout` →
624
+ "Transferencia", `payin` → "Depósito", `cross_border` → "Internacional", `payment` → "Pago", `collection` →
625
+ "Recaudo", `return` → "Reversión", `on_ramp` → "Conversión a stablecoin", `off_ramp` → "Conversión a moneda
626
+ local"). Only `getX()` for now (no `queryX()`).
627
+ They are not duplicates of `businessLines` or `movements/types`: `product_type` is the BFF's per-transaction class
628
+ and flips with the ledger direction (`payin` ↔ `payout`), whereas a `BusinessLine` is fixed per movement type;
629
+ the value sets differ (`internal_transfer`, `conversion` vs `cbmm`, `stable`, `unclassified`) and
630
+ `movements/types` has 26 rail codes, not 5 classes. The only shared label is `cross_border`.
563
631
 
564
632
  ### `exports`
565
633
 
@@ -0,0 +1,25 @@
1
+ export declare const BLOCKCHAINS: {
2
+ readonly ethereum: {
3
+ readonly code: "ethereum";
4
+ };
5
+ readonly tron: {
6
+ readonly code: "tron";
7
+ };
8
+ readonly solana: {
9
+ readonly code: "solana";
10
+ };
11
+ readonly polygon: {
12
+ readonly code: "polygon";
13
+ };
14
+ readonly base: {
15
+ readonly code: "base";
16
+ };
17
+ readonly xrpl: {
18
+ readonly code: "xrpl";
19
+ };
20
+ readonly stellar: {
21
+ readonly code: "stellar";
22
+ };
23
+ };
24
+ export type Blockchain = keyof typeof BLOCKCHAINS;
25
+ export type BlockchainRecord = (typeof BLOCKCHAINS)[Blockchain];
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BLOCKCHAINS = void 0;
4
+ exports.BLOCKCHAINS = {
5
+ ethereum: { code: "ethereum" },
6
+ tron: { code: "tron" },
7
+ solana: { code: "solana" },
8
+ polygon: { code: "polygon" },
9
+ base: { code: "base" },
10
+ xrpl: { code: "xrpl" },
11
+ stellar: { code: "stellar" },
12
+ };
@@ -0,0 +1,2 @@
1
+ export type { Blockchain } from "./catalog";
2
+ export * from "./utils/blockchain.utils";
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./utils/blockchain.utils"), exports);
@@ -0,0 +1,11 @@
1
+ {
2
+ "blockchains": {
3
+ "ethereum": "Ethereum",
4
+ "tron": "Tron",
5
+ "solana": "Solana",
6
+ "polygon": "Polygon",
7
+ "base": "Base",
8
+ "xrpl": "XRP Ledger",
9
+ "stellar": "Stellar"
10
+ }
11
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "blockchains": {
3
+ "ethereum": "Ethereum",
4
+ "tron": "Tron",
5
+ "solana": "Solana",
6
+ "polygon": "Polygon",
7
+ "base": "Base",
8
+ "xrpl": "XRP Ledger",
9
+ "stellar": "Stellar"
10
+ }
11
+ }
@@ -0,0 +1,13 @@
1
+ import type { Blockchain, BlockchainRecord } from "../catalog";
2
+ import type { Locale } from "../../lang";
3
+ import type { CatalogQuery } from "../../utils/catalog-query.utils";
4
+ export type BlockchainOption = BlockchainRecord & {
5
+ label: string;
6
+ };
7
+ export declare const getBlockchains: (lang: Locale) => Record<Blockchain, BlockchainOption>;
8
+ /** `lang` is required (i18n domain, no default) and travels inside the query object, never positional. */
9
+ export type BlockchainQuery = CatalogQuery<BlockchainRecord> & {
10
+ lang: Locale;
11
+ };
12
+ /** The catalog as a list, narrowed by the query — see `matchesQuery` for the matching rules. */
13
+ export declare const queryBlockchains: (query: BlockchainQuery) => BlockchainOption[];
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.queryBlockchains = exports.getBlockchains = void 0;
7
+ const catalog_1 = require("../catalog");
8
+ const en_json_1 = __importDefault(require("../locales/en.json"));
9
+ const es_mex_json_1 = __importDefault(require("../locales/es-mex.json"));
10
+ const catalog_query_utils_1 = require("../../utils/catalog-query.utils");
11
+ const locales = { en: en_json_1.default, "es-mex": es_mex_json_1.default };
12
+ const getBlockchains = (lang) => {
13
+ const locale = locales[lang];
14
+ const result = {};
15
+ for (const record of Object.values(catalog_1.BLOCKCHAINS)) {
16
+ result[record.code] = { ...record, label: locale.blockchains[record.code] };
17
+ }
18
+ return result;
19
+ };
20
+ exports.getBlockchains = getBlockchains;
21
+ /** The catalog as a list, narrowed by the query — see `matchesQuery` for the matching rules. */
22
+ const queryBlockchains = (query) => {
23
+ const { lang, ...criteria } = query;
24
+ const blockchains = (0, exports.getBlockchains)(lang);
25
+ return Object.values(blockchains).filter(blockchain => (0, catalog_query_utils_1.matchesQuery)(blockchain, criteria));
26
+ };
27
+ exports.queryBlockchains = queryBlockchains;
@@ -1,2 +1,6 @@
1
1
  export * from "./interfaces/response.interface";
2
2
  export * from "./interfaces/request.interface";
3
+ export type { ProductType } from "./productType/catalog";
4
+ export * from "./productType/utils/product-type.utils";
5
+ export type { Nature } from "./nature/catalog";
6
+ export * from "./nature/utils/nature.utils";
@@ -16,3 +16,5 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./interfaces/response.interface"), exports);
18
18
  __exportStar(require("./interfaces/request.interface"), exports);
19
+ __exportStar(require("./productType/utils/product-type.utils"), exports);
20
+ __exportStar(require("./nature/utils/nature.utils"), exports);
@@ -3,9 +3,11 @@ import type { CounterpartyType } from "../../counterparties/types/catalog";
3
3
  import type { Currency } from "../../currencies/catalog";
4
4
  import type { DocumentType } from "../../documentTypes/catalog";
5
5
  import type { MovementStatus } from "../../movements/status/catalog";
6
+ import type { Nature } from "../nature/catalog";
7
+ import type { ProductType } from "../productType/catalog";
6
8
  export type CanonicalDirection = "credit" | "debit";
7
- export type CanonicalProductType = "payout" | "payin" | "internal_transfer" | "cross_border";
8
- export type CanonicalNature = "payment" | "collection" | "return" | "fx_conversion";
9
+ export type CanonicalProductType = ProductType;
10
+ export type CanonicalNature = Nature;
9
11
  export type CanonicalStatusPresentationType = "status-pending" | "info" | "success" | "error" | "neutral" | "warning";
10
12
  export type CanonicalAlertType = "danger" | "success" | "warning" | "info";
11
13
  export type CanonicalAlertActionType = "open_drawer" | "copy_to_clipboard";
@@ -0,0 +1,22 @@
1
+ export declare const NATURES: {
2
+ readonly payment: {
3
+ readonly code: "payment";
4
+ };
5
+ readonly collection: {
6
+ readonly code: "collection";
7
+ };
8
+ readonly return: {
9
+ readonly code: "return";
10
+ };
11
+ readonly fx_conversion: {
12
+ readonly code: "fx_conversion";
13
+ };
14
+ readonly on_ramp: {
15
+ readonly code: "on_ramp";
16
+ };
17
+ readonly off_ramp: {
18
+ readonly code: "off_ramp";
19
+ };
20
+ };
21
+ export type Nature = keyof typeof NATURES;
22
+ export type NatureRecord = (typeof NATURES)[Nature];
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.NATURES = void 0;
4
+ exports.NATURES = {
5
+ payment: { code: "payment" },
6
+ collection: { code: "collection" },
7
+ return: { code: "return" },
8
+ fx_conversion: { code: "fx_conversion" },
9
+ on_ramp: { code: "on_ramp" },
10
+ off_ramp: { code: "off_ramp" },
11
+ };
@@ -0,0 +1,10 @@
1
+ {
2
+ "natures": {
3
+ "payment": "Payment",
4
+ "collection": "Collection",
5
+ "return": "Return",
6
+ "fx_conversion": "FX Conversion",
7
+ "on_ramp": "On Ramp",
8
+ "off_ramp": "Off Ramp"
9
+ }
10
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "natures": {
3
+ "payment": "Pago",
4
+ "collection": "Recaudo",
5
+ "return": "Reversión",
6
+ "fx_conversion": "Conversión FX",
7
+ "on_ramp": "Conversión a stablecoin",
8
+ "off_ramp": "Conversión a moneda local"
9
+ }
10
+ }
@@ -0,0 +1,6 @@
1
+ import type { Nature, NatureRecord } from "../catalog";
2
+ import type { Locale } from "../../../lang";
3
+ export type NatureOption = NatureRecord & {
4
+ label: string;
5
+ };
6
+ export declare const getNatures: (lang: Locale) => Record<Nature, NatureOption>;
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.getNatures = void 0;
7
+ const catalog_1 = require("../catalog");
8
+ const en_json_1 = __importDefault(require("../locales/en.json"));
9
+ const es_mex_json_1 = __importDefault(require("../locales/es-mex.json"));
10
+ const locales = { en: en_json_1.default, "es-mex": es_mex_json_1.default };
11
+ const getNatures = (lang) => {
12
+ const locale = locales[lang];
13
+ const result = {};
14
+ for (const record of Object.values(catalog_1.NATURES)) {
15
+ result[record.code] = { ...record, label: locale.natures[record.code] };
16
+ }
17
+ return result;
18
+ };
19
+ exports.getNatures = getNatures;
@@ -0,0 +1,19 @@
1
+ export declare const PRODUCT_TYPES: {
2
+ readonly payout: {
3
+ readonly code: "payout";
4
+ };
5
+ readonly payin: {
6
+ readonly code: "payin";
7
+ };
8
+ readonly internal_transfer: {
9
+ readonly code: "internal_transfer";
10
+ };
11
+ readonly cross_border: {
12
+ readonly code: "cross_border";
13
+ };
14
+ readonly conversion: {
15
+ readonly code: "conversion";
16
+ };
17
+ };
18
+ export type ProductType = keyof typeof PRODUCT_TYPES;
19
+ export type ProductTypeRecord = (typeof PRODUCT_TYPES)[ProductType];
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PRODUCT_TYPES = void 0;
4
+ /*
5
+ The BFF's `classification.product_type` (core-portal-bff `rail-mapper.interface.ts`). Not a BusinessLine and not
6
+ a MovementType, even though `payin`/`payout` share a name with the former:
7
+ - It is assigned per rail and flips with the ledger direction (a debit `payin` becomes `payout` and a credit
8
+ `payout` becomes `payin`), while a BusinessLine is a fixed property of each movement type.
9
+ - It has values a BusinessLine lacks (`internal_transfer`, `conversion`, `cross_border`) and vice versa
10
+ (`cbmm`, `stable`, `unclassified`), and it needs labels, which `businessLines` does not have.
11
+ */
12
+ exports.PRODUCT_TYPES = {
13
+ payout: { code: "payout" },
14
+ payin: { code: "payin" },
15
+ internal_transfer: { code: "internal_transfer" },
16
+ cross_border: { code: "cross_border" },
17
+ conversion: { code: "conversion" },
18
+ };
@@ -0,0 +1,9 @@
1
+ {
2
+ "productTypes": {
3
+ "payout": "Payout",
4
+ "payin": "Payin",
5
+ "internal_transfer": "Internal Transfer",
6
+ "cross_border": "Cross Border",
7
+ "conversion": "Conversion"
8
+ }
9
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "productTypes": {
3
+ "payout": "Transferencia",
4
+ "payin": "Depósito",
5
+ "internal_transfer": "Transferencia interna",
6
+ "cross_border": "Internacional",
7
+ "conversion": "Conversión"
8
+ }
9
+ }
@@ -0,0 +1,6 @@
1
+ import type { ProductType, ProductTypeRecord } from "../catalog";
2
+ import type { Locale } from "../../../lang";
3
+ export type ProductTypeOption = ProductTypeRecord & {
4
+ label: string;
5
+ };
6
+ export declare const getProductTypes: (lang: Locale) => Record<ProductType, ProductTypeOption>;
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.getProductTypes = void 0;
7
+ const catalog_1 = require("../catalog");
8
+ const en_json_1 = __importDefault(require("../locales/en.json"));
9
+ const es_mex_json_1 = __importDefault(require("../locales/es-mex.json"));
10
+ const locales = { en: en_json_1.default, "es-mex": es_mex_json_1.default };
11
+ const getProductTypes = (lang) => {
12
+ const locale = locales[lang];
13
+ const result = {};
14
+ for (const record of Object.values(catalog_1.PRODUCT_TYPES)) {
15
+ result[record.code] = { ...record, label: locale.productTypes[record.code] };
16
+ }
17
+ return result;
18
+ };
19
+ exports.getProductTypes = getProductTypes;
@@ -5,9 +5,9 @@ import type { FilterClassificationSection } from "../sections/catalog";
5
5
  * A selectable group of type codes (one checkbox that stands for several types). The group `code` is a UI
6
6
  * identifier: it is never sent to an API, only its `members` are — see `expandGroupSelection`.
7
7
  */
8
- export type FilterClassificationRecord<Code extends string> = {
8
+ export type FilterClassificationRecord<Code extends string, Member extends string = Code> = {
9
9
  readonly code: Code;
10
- readonly members: readonly Code[];
10
+ readonly members: readonly Member[];
11
11
  readonly line: BusinessLine;
12
12
  readonly category: FilterClassificationCategory;
13
13
  readonly section: FilterClassificationSection;
@@ -1,9 +1,13 @@
1
1
  import type { FilterClassificationRecord } from "../interfaces/filter-classification.interface";
2
2
  export type GroupSelectionState = "checked" | "indeterminate" | "unchecked";
3
+ /** Tells a group option (it has `members`) from a plain option, narrowing a mixed list of both. */
4
+ export declare const isGroupOption: <Option extends object>(option: Option) => option is Extract<Option, {
5
+ readonly members: readonly string[];
6
+ }>;
3
7
  /**
4
8
  * The codes to send to an API: each selected group code is replaced by its members, anything else passes
5
9
  * through. The group code itself never appears in the output, and repeated codes are dropped.
6
10
  */
7
- export declare const expandGroupSelection: <Code extends string>(selected: readonly Code[], groups: readonly FilterClassificationRecord<Code>[]) => Code[];
11
+ export declare const expandGroupSelection: <Code extends string, Member extends string = Code>(selected: readonly (Code | Member)[], groups: readonly FilterClassificationRecord<Code, Member>[]) => Member[];
8
12
  /** checked = every member selected, indeterminate = some, unchecked = none (or a group without members). */
9
- export declare const getGroupSelectionState: <Code extends string>(group: FilterClassificationRecord<Code>, selected: readonly Code[]) => GroupSelectionState;
13
+ export declare const getGroupSelectionState: <Code extends string, Member extends string = Code>(group: FilterClassificationRecord<Code, Member>, selected: readonly Member[]) => GroupSelectionState;
@@ -1,6 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getGroupSelectionState = exports.expandGroupSelection = void 0;
3
+ exports.getGroupSelectionState = exports.expandGroupSelection = exports.isGroupOption = void 0;
4
+ /** Tells a group option (it has `members`) from a plain option, narrowing a mixed list of both. */
5
+ const isGroupOption = (option) => "members" in option;
6
+ exports.isGroupOption = isGroupOption;
4
7
  /**
5
8
  * The codes to send to an API: each selected group code is replaced by its members, anything else passes
6
9
  * through. The group code itself never appears in the output, and repeated codes are dropped.
@@ -1,3 +1,3 @@
1
- export type { TransactionType } from "./types/catalog";
1
+ export type { TransactionType, TransactionTypeGroup } from "./types/catalog";
2
2
  export * from "./types/utils/transaction-type.utils";
3
3
  export * from "./interfaces/response.interface";