@voyantjs/finance 0.80.3 → 0.80.5

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.
package/README.md CHANGED
@@ -150,9 +150,12 @@ createFinanceHonoModule({
150
150
  })
151
151
  ```
152
152
 
153
- The default data resolver calls the Voyant Data FX pair route
154
- `/data/fx/v1/fx/pair/{invoiceCurrency}/{baseCurrency}`. If the invoice currency
155
- matches the operator base currency, no FX fields are emitted.
153
+ The default data resolver uses `@voyantjs/data-sdk` to call the Voyant Data FX
154
+ pair route `/data/fx/v1/fx/pair/{invoiceCurrency}/{baseCurrency}`. SDK
155
+ responses can add provenance metadata such as `source`, `quotedAt`, and
156
+ `validUntil`; invoice-issued events expose those as `fxRateSource`,
157
+ `fxRateQuotedAt`, and `fxRateValidUntil`. If the invoice currency matches the
158
+ operator base currency, no FX fields are emitted.
156
159
 
157
160
  The same resolver also backs `GET /v1/finance/invoice-fx-rate`, which lets
158
161
  operator UI surfaces auto-fill cross-currency payment rates without exposing
@@ -0,0 +1,17 @@
1
+ import type { PostgresJsDatabase } from "drizzle-orm/postgres-js";
2
+ import type { InvoiceFxOptions } from "./invoice-fx.js";
3
+ export type FxMoneyInput = {
4
+ amountCents: number;
5
+ currency: string;
6
+ baseCurrency?: string | null;
7
+ baseAmountCents?: number | null;
8
+ fxRateSetId?: string | null;
9
+ };
10
+ export type ResolveFxMoneyBaseAmountOptions = InvoiceFxOptions & {
11
+ targetBaseCurrency?: string | null;
12
+ fallbackFxRateSetId?: string | null;
13
+ date?: string | Date | null;
14
+ setBaseCurrencyWhenUnresolved?: boolean;
15
+ };
16
+ export declare function resolveFxMoneyBaseAmount<T extends FxMoneyInput>(db: PostgresJsDatabase, input: T, options?: ResolveFxMoneyBaseAmountOptions): Promise<T>;
17
+ //# sourceMappingURL=fx-money.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fx-money.d.ts","sourceRoot":"","sources":["../src/fx-money.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAEjE,OAAO,KAAK,EAEV,gBAAgB,EAGjB,MAAM,iBAAiB,CAAA;AAGxB,MAAM,MAAM,YAAY,GAAG;IACzB,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,EAAE,MAAM,CAAA;IAChB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/B,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAC5B,CAAA;AAED,MAAM,MAAM,+BAA+B,GAAG,gBAAgB,GAAG;IAC/D,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAClC,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACnC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAAA;IAC3B,6BAA6B,CAAC,EAAE,OAAO,CAAA;CACxC,CAAA;AAOD,wBAAsB,wBAAwB,CAAC,CAAC,SAAS,YAAY,EACnE,EAAE,EAAE,kBAAkB,EACtB,KAAK,EAAE,CAAC,EACR,OAAO,GAAE,+BAAoC,GAC5C,OAAO,CAAC,CAAC,CAAC,CA0EZ"}
@@ -0,0 +1,194 @@
1
+ import { and, asc, desc, eq, isNull, lte, or } from "drizzle-orm";
2
+ import { exchangeRatesRef } from "./markets-ref.js";
3
+ export async function resolveFxMoneyBaseAmount(db, input, options = {}) {
4
+ const settings = await resolveConfiguredFxSettings(db, options);
5
+ const currency = normalizeCurrency(input.currency) ?? input.currency;
6
+ const configuredBaseCurrency = normalizeCurrency(settings?.baseCurrency);
7
+ const targetBaseCurrency = normalizeCurrency(input.baseCurrency) ??
8
+ normalizeCurrency(options.targetBaseCurrency) ??
9
+ configuredBaseCurrency;
10
+ if (!targetBaseCurrency) {
11
+ return {
12
+ ...input,
13
+ currency,
14
+ baseCurrency: normalizeCurrency(input.baseCurrency) ?? input.baseCurrency ?? null,
15
+ fxRateSetId: normalizeOptionalText(input.fxRateSetId) ?? input.fxRateSetId ?? null,
16
+ };
17
+ }
18
+ const existingBaseAmountCents = normalizeAmount(input.baseAmountCents);
19
+ const fallbackFxRateSetId = normalizeOptionalText(input.fxRateSetId) ??
20
+ normalizeOptionalText(options.fallbackFxRateSetId) ??
21
+ null;
22
+ if (existingBaseAmountCents !== null) {
23
+ return {
24
+ ...input,
25
+ currency,
26
+ baseCurrency: targetBaseCurrency,
27
+ baseAmountCents: existingBaseAmountCents,
28
+ fxRateSetId: currency === targetBaseCurrency ? null : fallbackFxRateSetId,
29
+ };
30
+ }
31
+ if (currency === targetBaseCurrency) {
32
+ return {
33
+ ...input,
34
+ currency,
35
+ baseCurrency: targetBaseCurrency,
36
+ baseAmountCents: input.amountCents,
37
+ fxRateSetId: null,
38
+ };
39
+ }
40
+ const persistedRate = await resolvePersistedExchangeRate(db, currency, targetBaseCurrency, {
41
+ fxRateSetId: fallbackFxRateSetId,
42
+ date: options.date,
43
+ });
44
+ const resolvedRate = persistedRate
45
+ ? { rate: persistedRate.rate, fxRateSetId: persistedRate.fxRateSetId }
46
+ : await resolveRuntimeExchangeRate(currency, targetBaseCurrency, options);
47
+ if (!resolvedRate) {
48
+ return {
49
+ ...input,
50
+ currency,
51
+ baseCurrency: options.setBaseCurrencyWhenUnresolved
52
+ ? targetBaseCurrency
53
+ : (normalizeCurrency(input.baseCurrency) ?? input.baseCurrency ?? null),
54
+ baseAmountCents: input.baseAmountCents ?? null,
55
+ fxRateSetId: fallbackFxRateSetId,
56
+ };
57
+ }
58
+ const fxCommissionBps = normalizeBasisPoints(settings?.fxCommissionBps);
59
+ const effectiveRate = resolvedRate.rate * (1 + fxCommissionBps / 10_000);
60
+ return {
61
+ ...input,
62
+ currency,
63
+ baseCurrency: targetBaseCurrency,
64
+ baseAmountCents: Math.round(input.amountCents * effectiveRate),
65
+ fxRateSetId: resolvedRate.fxRateSetId ?? null,
66
+ };
67
+ }
68
+ async function resolveConfiguredFxSettings(db, options) {
69
+ if (options.invoiceFxSettings !== undefined)
70
+ return options.invoiceFxSettings;
71
+ return (await options.resolveInvoiceFxSettings?.(db)) ?? null;
72
+ }
73
+ async function resolveRuntimeExchangeRate(baseCurrency, quoteCurrency, options) {
74
+ if (!options.resolveInvoiceExchangeRate)
75
+ return null;
76
+ const input = {
77
+ baseCurrency,
78
+ quoteCurrency,
79
+ date: toDateString(options.date),
80
+ };
81
+ try {
82
+ return normalizeExchangeRateResolution(await options.resolveInvoiceExchangeRate(input));
83
+ }
84
+ catch (error) {
85
+ try {
86
+ await options.onInvoiceFxResolutionError?.(error, input);
87
+ }
88
+ catch {
89
+ // FX resolution failure hooks should not mask the original write path.
90
+ }
91
+ return null;
92
+ }
93
+ }
94
+ async function resolvePersistedExchangeRate(db, baseCurrency, quoteCurrency, options) {
95
+ if (options.fxRateSetId) {
96
+ return ((await queryPersistedExchangeRate(db, baseCurrency, quoteCurrency, {
97
+ fxRateSetId: options.fxRateSetId,
98
+ })) ??
99
+ (await queryPersistedExchangeRate(db, quoteCurrency, baseCurrency, {
100
+ fxRateSetId: options.fxRateSetId,
101
+ inverse: true,
102
+ })));
103
+ }
104
+ const asOf = toDateEnd(options.date);
105
+ return ((await queryPersistedExchangeRate(db, baseCurrency, quoteCurrency, { asOf })) ??
106
+ (await queryPersistedExchangeRate(db, quoteCurrency, baseCurrency, {
107
+ asOf,
108
+ inverse: true,
109
+ })) ??
110
+ (await queryPersistedExchangeRate(db, baseCurrency, quoteCurrency, {})) ??
111
+ (await queryPersistedExchangeRate(db, quoteCurrency, baseCurrency, { inverse: true })));
112
+ }
113
+ async function queryPersistedExchangeRate(db, baseCurrency, quoteCurrency, options) {
114
+ const conditions = [
115
+ eq(exchangeRatesRef.baseCurrency, baseCurrency),
116
+ eq(exchangeRatesRef.quoteCurrency, quoteCurrency),
117
+ ];
118
+ if (options.fxRateSetId) {
119
+ conditions.push(eq(exchangeRatesRef.fxRateSetId, options.fxRateSetId));
120
+ }
121
+ if (options.asOf) {
122
+ const asOfCondition = or(isNull(exchangeRatesRef.observedAt), lte(exchangeRatesRef.observedAt, options.asOf));
123
+ if (asOfCondition)
124
+ conditions.push(asOfCondition);
125
+ }
126
+ const [row] = await db
127
+ .select({
128
+ fxRateSetId: exchangeRatesRef.fxRateSetId,
129
+ rateDecimal: exchangeRatesRef.rateDecimal,
130
+ inverseRateDecimal: exchangeRatesRef.inverseRateDecimal,
131
+ })
132
+ .from(exchangeRatesRef)
133
+ .where(and(...conditions))
134
+ .orderBy(asc(isNull(exchangeRatesRef.observedAt)), desc(exchangeRatesRef.observedAt), desc(exchangeRatesRef.createdAt))
135
+ .limit(1);
136
+ if (!row)
137
+ return null;
138
+ const rate = options.inverse
139
+ ? (normalizeRate(row.inverseRateDecimal) ?? inverseRate(row.rateDecimal))
140
+ : normalizeRate(row.rateDecimal);
141
+ return rate ? { rate, fxRateSetId: row.fxRateSetId } : null;
142
+ }
143
+ function normalizeExchangeRateResolution(resolution) {
144
+ if (typeof resolution === "number") {
145
+ return Number.isFinite(resolution) && resolution > 0 ? { rate: resolution } : null;
146
+ }
147
+ if (!resolution || typeof resolution !== "object")
148
+ return null;
149
+ if (typeof resolution.rate !== "number" || !Number.isFinite(resolution.rate))
150
+ return null;
151
+ if (resolution.rate <= 0)
152
+ return null;
153
+ const fxRateSetId = normalizeOptionalText(resolution.fxRateSetId);
154
+ return {
155
+ rate: resolution.rate,
156
+ ...(fxRateSetId ? { fxRateSetId } : {}),
157
+ };
158
+ }
159
+ function normalizeAmount(value) {
160
+ return typeof value === "number" && Number.isFinite(value) ? Math.round(value) : null;
161
+ }
162
+ function normalizeRate(value) {
163
+ const parsed = typeof value === "number" ? value : Number.parseFloat(value ?? "");
164
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : null;
165
+ }
166
+ function inverseRate(value) {
167
+ const rate = normalizeRate(value);
168
+ return rate ? 1 / rate : null;
169
+ }
170
+ function normalizeBasisPoints(value) {
171
+ return typeof value === "number" && Number.isFinite(value) && value > 0 ? Math.round(value) : 0;
172
+ }
173
+ function normalizeCurrency(value) {
174
+ const normalized = value?.trim().toUpperCase();
175
+ return normalized ? normalized : null;
176
+ }
177
+ function normalizeOptionalText(value) {
178
+ return typeof value === "string" && value.trim().length > 0 ? value.trim() : undefined;
179
+ }
180
+ function toDateString(value) {
181
+ if (value instanceof Date)
182
+ return value.toISOString().slice(0, 10);
183
+ return typeof value === "string" && value.length > 0 ? value : undefined;
184
+ }
185
+ function toDateEnd(value) {
186
+ if (value instanceof Date)
187
+ return value;
188
+ if (!value)
189
+ return null;
190
+ const parsed = /^\d{4}-\d{2}-\d{2}$/.test(value)
191
+ ? new Date(`${value}T23:59:59.999Z`)
192
+ : new Date(value);
193
+ return Number.isNaN(parsed.getTime()) ? null : parsed;
194
+ }
package/dist/index.d.ts CHANGED
@@ -22,7 +22,7 @@ export declare function createFinanceHonoModule(options?: FinanceHonoModuleOptio
22
22
  export declare const financeHonoModule: HonoModule;
23
23
  export { type BookingTaxRouteOptions, type BookingTaxSettings, computeBookingItemTaxLine, createBookingTaxHonoExtension, createBookingTaxRoutes, loadProductTaxFacts, matchesTaxPolicyCondition, mountBookingTaxRoutes, type ProductTaxFacts, type ResolveBookingSellTaxRateOptions, type ResolveBookingTaxSettings, type ResolvedBookingSellTaxRate, resolveBookingSellTaxRate, type TaxPolicyCondition, type UpdateBookingTaxSettings, } from "./booking-tax.js";
24
24
  export { type DocumentDownloadEnvelope, type DocumentDownloadResolution, type DocumentDownloadResolver, resolveStoredDocumentDownload, type StoredDocumentReference, } from "./document-download.js";
25
- export { createInvoiceFxHonoExtension, createInvoiceFxRoutes, createVoyantDataFxExchangeRateResolver, type InvoiceFxContext, type InvoiceFxOptions, type InvoiceFxRouteOptions, type InvoiceFxSettings, mountInvoiceFxRoutes, type ResolvedInvoiceFxSettings, type ResolveInvoiceExchangeRate, type ResolveInvoiceExchangeRateInput, type ResolveInvoiceFxSettings, resolveInvoiceFxContext, resolveInvoiceFxSettingsOrDefault, type UpdateInvoiceFxSettings, type VoyantDataFxResolverOptions, } from "./invoice-fx.js";
25
+ export { createInvoiceFxHonoExtension, createInvoiceFxRoutes, createVoyantDataFxExchangeRateResolver, type InvoiceExchangeRateResolution, type InvoiceFxContext, type InvoiceFxOptions, type InvoiceFxRouteOptions, type InvoiceFxSettings, mountInvoiceFxRoutes, type ResolvedInvoiceFxSettings, type ResolveInvoiceExchangeRate, type ResolveInvoiceExchangeRateInput, type ResolveInvoiceFxSettings, resolveInvoiceFxContext, resolveInvoiceFxSettingsOrDefault, type UpdateInvoiceFxSettings, type VoyantDataFxResolverOptions, } from "./invoice-fx.js";
26
26
  export type { ComputedScheduleEntry, ComputeScheduleInput, DepositKind, DepositRule, PaymentPolicy, PaymentPolicyCascadeLayers, PaymentPolicySource, PaymentScheduleEntryType, ResolvedPaymentPolicy, } from "./payment-policy.js";
27
27
  export { computePaymentSchedule, isPaymentPolicyEmpty, noDepositPolicy, policyShouldRequireFullPayment, resolveEffectivePaymentPolicy, } from "./payment-policy.js";
28
28
  export { buildFinanceRouteRuntime, FINANCE_ROUTE_RUNTIME_CONTAINER_KEY, type FinanceRouteRuntime, type FinanceRuntimeOptions, } from "./route-runtime.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -17,7 +17,14 @@ export type ResolveInvoiceExchangeRateInput = {
17
17
  quoteCurrency: string;
18
18
  date?: string;
19
19
  };
20
- export type ResolveInvoiceExchangeRate = (input: ResolveInvoiceExchangeRateInput) => number | null | undefined | Promise<number | null | undefined>;
20
+ export type InvoiceExchangeRateResolution = {
21
+ rate: number;
22
+ fxRateSetId?: string;
23
+ source?: string;
24
+ quotedAt?: string;
25
+ validUntil?: string;
26
+ };
27
+ export type ResolveInvoiceExchangeRate = (input: ResolveInvoiceExchangeRateInput) => number | InvoiceExchangeRateResolution | null | undefined | Promise<number | InvoiceExchangeRateResolution | null | undefined>;
21
28
  export type HandleInvoiceFxResolutionError = (error: unknown, input: ResolveInvoiceExchangeRateInput) => void | Promise<void>;
22
29
  export interface InvoiceFxOptions {
23
30
  invoiceFxSettings?: InvoiceFxSettings | null;
@@ -36,7 +43,11 @@ export type InvoiceFxInvoice = {
36
43
  };
37
44
  export type InvoiceFxContext = {
38
45
  baseCurrency: string;
46
+ fxRateSetId?: string;
39
47
  fxRate: number;
48
+ fxRateSource?: string;
49
+ fxRateQuotedAt?: string;
50
+ fxRateValidUntil?: string;
40
51
  fxCommissionBps: number;
41
52
  effectiveRate: number;
42
53
  fxCommissionInvoiceMention?: string;
@@ -52,6 +63,8 @@ export type VoyantDataFxResolverOptions = {
52
63
  authHeader?: string;
53
64
  authScheme?: string | null;
54
65
  fetch?: typeof fetch;
66
+ headers?: HeadersInit;
67
+ userAgent?: string;
55
68
  };
56
69
  type InvoiceFxRouteEnv = Env & {
57
70
  Variables: Env["Variables"] & {
@@ -97,6 +110,10 @@ export declare function createInvoiceFxRoutes(options?: InvoiceFxRouteOptions):
97
110
  input: {};
98
111
  output: {
99
112
  data: {
113
+ validUntil?: string | undefined;
114
+ quotedAt?: string | undefined;
115
+ source?: string | undefined;
116
+ fxRateSetId?: string | undefined;
100
117
  rate: number;
101
118
  baseCurrency: string;
102
119
  quoteCurrency: string;
@@ -1 +1 @@
1
- {"version":3,"file":"invoice-fx.d.ts","sourceRoot":"","sources":["../src/invoice-fx.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"invoice-fx.d.ts","sourceRoot":"","sources":["../src/invoice-fx.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,8 @@
1
+ import { createVoyantDataClient } from "@voyantjs/data-sdk";
1
2
  import { ApiHttpError, parseJsonBody, parseQuery } from "@voyantjs/hono";
2
3
  import { Hono as HonoApp } from "hono";
3
4
  import { z } from "zod";
4
5
  import { buildFinanceRouteRuntime, FINANCE_ROUTE_RUNTIME_CONTAINER_KEY, } from "./route-runtime.js";
5
- const DEFAULT_DATA_BASE_URL = "https://api.voyantjs.com";
6
6
  const invoiceFxSettingsPatchSchema = z.object({
7
7
  baseCurrency: z.string().min(3).max(8).nullable().optional(),
8
8
  fxCommissionBps: z.number().int().min(0).max(100_000).nullable().optional(),
@@ -39,21 +39,26 @@ export async function resolveInvoiceFxContext(db, invoice, options = {}) {
39
39
  quoteCurrency: baseCurrency,
40
40
  date: toDateString(invoice.issueDate),
41
41
  };
42
- let fxRate;
42
+ let fxResolution;
43
43
  try {
44
- fxRate = await options.resolveInvoiceExchangeRate(rateInput);
44
+ fxResolution = await options.resolveInvoiceExchangeRate(rateInput);
45
45
  }
46
46
  catch (error) {
47
47
  await notifyInvoiceFxResolutionError(options, error, rateInput);
48
48
  return null;
49
49
  }
50
- if (typeof fxRate !== "number" || !Number.isFinite(fxRate) || fxRate <= 0)
50
+ const resolvedRate = normalizeInvoiceExchangeRateResolution(fxResolution);
51
+ if (!resolvedRate)
51
52
  return null;
52
53
  const fxCommissionBps = normalizeBasisPoints(settings?.fxCommissionBps);
53
- const effectiveRate = roundRate(fxRate * (1 + fxCommissionBps / 10_000));
54
+ const effectiveRate = roundRate(resolvedRate.rate * (1 + fxCommissionBps / 10_000));
54
55
  return {
55
56
  baseCurrency,
56
- fxRate: roundRate(fxRate),
57
+ ...(resolvedRate.fxRateSetId ? { fxRateSetId: resolvedRate.fxRateSetId } : {}),
58
+ fxRate: roundRate(resolvedRate.rate),
59
+ ...(resolvedRate.source ? { fxRateSource: resolvedRate.source } : {}),
60
+ ...(resolvedRate.quotedAt ? { fxRateQuotedAt: resolvedRate.quotedAt } : {}),
61
+ ...(resolvedRate.validUntil ? { fxRateValidUntil: resolvedRate.validUntil } : {}),
57
62
  fxCommissionBps,
58
63
  effectiveRate,
59
64
  ...(fxCommissionBps > 0 && normalizeOptionalText(settings?.fxCommissionInvoiceMention)
@@ -62,22 +67,29 @@ export async function resolveInvoiceFxContext(db, invoice, options = {}) {
62
67
  };
63
68
  }
64
69
  export function createVoyantDataFxExchangeRateResolver(options) {
65
- const fetchImpl = options.fetch ?? fetch;
66
- const baseUrl = options.baseUrl ?? DEFAULT_DATA_BASE_URL;
67
- const authHeader = options.authHeader ?? "authorization";
68
- const authScheme = options.authScheme === undefined ? "Bearer" : options.authScheme;
70
+ const client = createVoyantDataClient({
71
+ apiKey: options.apiKey,
72
+ ...(options.baseUrl ? { baseUrl: options.baseUrl } : {}),
73
+ ...(options.authHeader ? { authHeader: options.authHeader } : {}),
74
+ ...(options.authScheme !== undefined ? { authScheme: options.authScheme } : {}),
75
+ ...(options.fetch ? { fetch: options.fetch } : {}),
76
+ ...(options.headers ? { headers: options.headers } : {}),
77
+ userAgent: options.userAgent ?? "voyant-finance",
78
+ });
69
79
  return async ({ baseCurrency, quoteCurrency }) => {
70
- const url = new URL(`/data/fx/v1/fx/pair/${encodeURIComponent(baseCurrency)}/${encodeURIComponent(quoteCurrency)}`, baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`);
71
- const headers = new Headers();
72
- headers.set(authHeader, authScheme ? `${authScheme} ${options.apiKey}` : options.apiKey);
73
- headers.set("x-voyant-sdk", "voyant-finance");
74
- const response = await fetchImpl(url, { headers });
75
- const body = (await response.json());
76
- if (!response.ok) {
77
- throw new Error(`Voyant Data FX request failed with status ${response.status}`);
80
+ const quote = await client.fx.pair(baseCurrency, quoteCurrency);
81
+ if (typeof quote.conversionRate !== "number" || !Number.isFinite(quote.conversionRate)) {
82
+ return null;
78
83
  }
79
- const rate = body.conversionRate ?? body.conversion_rate;
80
- return typeof rate === "number" && Number.isFinite(rate) ? rate : null;
84
+ const source = normalizeOptionalText(quote.source);
85
+ const quotedAt = normalizeOptionalText(quote.timeLastUpdateUtc);
86
+ const validUntil = normalizeOptionalText(quote.timeNextUpdateUtc);
87
+ return {
88
+ rate: quote.conversionRate,
89
+ ...(source ? { source } : {}),
90
+ ...(quotedAt ? { quotedAt } : {}),
91
+ ...(validUntil ? { validUntil } : {}),
92
+ };
81
93
  };
82
94
  }
83
95
  export function createInvoiceFxRoutes(options = {}) {
@@ -120,9 +132,9 @@ export function createInvoiceFxRoutes(options = {}) {
120
132
  quoteCurrency: normalizeCurrency(query.quoteCurrency) ?? query.quoteCurrency,
121
133
  date: query.date,
122
134
  };
123
- let rate;
135
+ let rateResolution;
124
136
  try {
125
- rate = await runtime.resolveInvoiceExchangeRate(input);
137
+ rateResolution = await runtime.resolveInvoiceExchangeRate(input);
126
138
  }
127
139
  catch (error) {
128
140
  await notifyInvoiceFxResolutionError(runtime, error, input);
@@ -131,7 +143,8 @@ export function createInvoiceFxRoutes(options = {}) {
131
143
  code: "invoice_fx_rate_resolution_failed",
132
144
  });
133
145
  }
134
- if (typeof rate !== "number" || !Number.isFinite(rate) || rate <= 0) {
146
+ const resolvedRate = normalizeInvoiceExchangeRateResolution(rateResolution);
147
+ if (!resolvedRate) {
135
148
  throw new ApiHttpError("Invoice FX rate was not found", {
136
149
  status: 404,
137
150
  code: "invoice_fx_rate_not_found",
@@ -140,7 +153,11 @@ export function createInvoiceFxRoutes(options = {}) {
140
153
  return c.json({
141
154
  data: {
142
155
  ...input,
143
- rate: roundRate(rate),
156
+ rate: roundRate(resolvedRate.rate),
157
+ ...(resolvedRate.fxRateSetId ? { fxRateSetId: resolvedRate.fxRateSetId } : {}),
158
+ ...(resolvedRate.source ? { source: resolvedRate.source } : {}),
159
+ ...(resolvedRate.quotedAt ? { quotedAt: resolvedRate.quotedAt } : {}),
160
+ ...(resolvedRate.validUntil ? { validUntil: resolvedRate.validUntil } : {}),
144
161
  },
145
162
  });
146
163
  });
@@ -180,6 +197,28 @@ async function notifyInvoiceFxResolutionError(options, error, input) {
180
197
  function normalizeBasisPoints(value) {
181
198
  return typeof value === "number" && Number.isFinite(value) && value > 0 ? Math.round(value) : 0;
182
199
  }
200
+ function normalizeInvoiceExchangeRateResolution(resolution) {
201
+ if (typeof resolution === "number") {
202
+ return Number.isFinite(resolution) && resolution > 0 ? { rate: resolution } : null;
203
+ }
204
+ if (!resolution || typeof resolution !== "object")
205
+ return null;
206
+ if (typeof resolution.rate !== "number" || !Number.isFinite(resolution.rate))
207
+ return null;
208
+ if (resolution.rate <= 0)
209
+ return null;
210
+ const source = normalizeOptionalText(resolution.source);
211
+ const fxRateSetId = normalizeOptionalText(resolution.fxRateSetId);
212
+ const quotedAt = normalizeOptionalText(resolution.quotedAt);
213
+ const validUntil = normalizeOptionalText(resolution.validUntil);
214
+ return {
215
+ rate: resolution.rate,
216
+ ...(fxRateSetId ? { fxRateSetId } : {}),
217
+ ...(source ? { source } : {}),
218
+ ...(quotedAt ? { quotedAt } : {}),
219
+ ...(validUntil ? { validUntil } : {}),
220
+ };
221
+ }
183
222
  function normalizeOptionalText(value) {
184
223
  return typeof value === "string" && value.trim().length > 0 ? value.trim() : undefined;
185
224
  }
@@ -0,0 +1,149 @@
1
+ /**
2
+ * Local reference to `markets.exchange_rates`. Finance stores plain-text
3
+ * `fx_rate_set_id` links and reads this table opportunistically to normalize
4
+ * cross-currency payment/document amounts without taking a hard markets dep.
5
+ */
6
+ export declare const exchangeRatesRef: import("drizzle-orm/pg-core").PgTableWithColumns<{
7
+ name: "exchange_rates";
8
+ schema: undefined;
9
+ columns: {
10
+ id: import("drizzle-orm/pg-core").PgColumn<{
11
+ name: string;
12
+ tableName: "exchange_rates";
13
+ dataType: "string";
14
+ columnType: "PgText";
15
+ data: string;
16
+ driverParam: string;
17
+ notNull: true;
18
+ hasDefault: true;
19
+ isPrimaryKey: true;
20
+ isAutoincrement: false;
21
+ hasRuntimeDefault: true;
22
+ enumValues: [string, ...string[]];
23
+ baseColumn: never;
24
+ identity: undefined;
25
+ generated: undefined;
26
+ }, {}, {}>;
27
+ fxRateSetId: import("drizzle-orm/pg-core").PgColumn<{
28
+ name: string;
29
+ tableName: "exchange_rates";
30
+ dataType: "string";
31
+ columnType: "PgText";
32
+ data: string;
33
+ driverParam: string;
34
+ notNull: true;
35
+ hasDefault: false;
36
+ isPrimaryKey: false;
37
+ isAutoincrement: false;
38
+ hasRuntimeDefault: false;
39
+ enumValues: [string, ...string[]];
40
+ baseColumn: never;
41
+ identity: undefined;
42
+ generated: undefined;
43
+ }, {}, {}>;
44
+ baseCurrency: import("drizzle-orm/pg-core").PgColumn<{
45
+ name: "base_currency";
46
+ tableName: "exchange_rates";
47
+ dataType: "string";
48
+ columnType: "PgText";
49
+ data: string;
50
+ driverParam: string;
51
+ notNull: true;
52
+ hasDefault: false;
53
+ isPrimaryKey: false;
54
+ isAutoincrement: false;
55
+ hasRuntimeDefault: false;
56
+ enumValues: [string, ...string[]];
57
+ baseColumn: never;
58
+ identity: undefined;
59
+ generated: undefined;
60
+ }, {}, {}>;
61
+ quoteCurrency: import("drizzle-orm/pg-core").PgColumn<{
62
+ name: "quote_currency";
63
+ tableName: "exchange_rates";
64
+ dataType: "string";
65
+ columnType: "PgText";
66
+ data: string;
67
+ driverParam: string;
68
+ notNull: true;
69
+ hasDefault: false;
70
+ isPrimaryKey: false;
71
+ isAutoincrement: false;
72
+ hasRuntimeDefault: false;
73
+ enumValues: [string, ...string[]];
74
+ baseColumn: never;
75
+ identity: undefined;
76
+ generated: undefined;
77
+ }, {}, {}>;
78
+ rateDecimal: import("drizzle-orm/pg-core").PgColumn<{
79
+ name: "rate_decimal";
80
+ tableName: "exchange_rates";
81
+ dataType: "string";
82
+ columnType: "PgNumeric";
83
+ data: string;
84
+ driverParam: string;
85
+ notNull: true;
86
+ hasDefault: false;
87
+ isPrimaryKey: false;
88
+ isAutoincrement: false;
89
+ hasRuntimeDefault: false;
90
+ enumValues: undefined;
91
+ baseColumn: never;
92
+ identity: undefined;
93
+ generated: undefined;
94
+ }, {}, {}>;
95
+ inverseRateDecimal: import("drizzle-orm/pg-core").PgColumn<{
96
+ name: "inverse_rate_decimal";
97
+ tableName: "exchange_rates";
98
+ dataType: "string";
99
+ columnType: "PgNumeric";
100
+ data: string;
101
+ driverParam: string;
102
+ notNull: false;
103
+ hasDefault: false;
104
+ isPrimaryKey: false;
105
+ isAutoincrement: false;
106
+ hasRuntimeDefault: false;
107
+ enumValues: undefined;
108
+ baseColumn: never;
109
+ identity: undefined;
110
+ generated: undefined;
111
+ }, {}, {}>;
112
+ observedAt: import("drizzle-orm/pg-core").PgColumn<{
113
+ name: "observed_at";
114
+ tableName: "exchange_rates";
115
+ dataType: "date";
116
+ columnType: "PgTimestamp";
117
+ data: Date;
118
+ driverParam: string;
119
+ notNull: false;
120
+ hasDefault: false;
121
+ isPrimaryKey: false;
122
+ isAutoincrement: false;
123
+ hasRuntimeDefault: false;
124
+ enumValues: undefined;
125
+ baseColumn: never;
126
+ identity: undefined;
127
+ generated: undefined;
128
+ }, {}, {}>;
129
+ createdAt: import("drizzle-orm/pg-core").PgColumn<{
130
+ name: "created_at";
131
+ tableName: "exchange_rates";
132
+ dataType: "date";
133
+ columnType: "PgTimestamp";
134
+ data: Date;
135
+ driverParam: string;
136
+ notNull: true;
137
+ hasDefault: false;
138
+ isPrimaryKey: false;
139
+ isAutoincrement: false;
140
+ hasRuntimeDefault: false;
141
+ enumValues: undefined;
142
+ baseColumn: never;
143
+ identity: undefined;
144
+ generated: undefined;
145
+ }, {}, {}>;
146
+ };
147
+ dialect: "pg";
148
+ }>;
149
+ //# sourceMappingURL=markets-ref.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markets-ref.d.ts","sourceRoot":"","sources":["../src/markets-ref.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AACH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAS3B,CAAA"}
@@ -0,0 +1,17 @@
1
+ import { typeId, typeIdRef } from "@voyantjs/db/lib/typeid-column";
2
+ import { numeric, pgTable, text, timestamp } from "drizzle-orm/pg-core";
3
+ /**
4
+ * Local reference to `markets.exchange_rates`. Finance stores plain-text
5
+ * `fx_rate_set_id` links and reads this table opportunistically to normalize
6
+ * cross-currency payment/document amounts without taking a hard markets dep.
7
+ */
8
+ export const exchangeRatesRef = pgTable("exchange_rates", {
9
+ id: typeId("exchange_rates").primaryKey(),
10
+ fxRateSetId: typeIdRef("fx_rate_set_id").notNull(),
11
+ baseCurrency: text("base_currency").notNull(),
12
+ quoteCurrency: text("quote_currency").notNull(),
13
+ rateDecimal: numeric("rate_decimal", { precision: 18, scale: 8 }).notNull(),
14
+ inverseRateDecimal: numeric("inverse_rate_decimal", { precision: 18, scale: 8 }),
15
+ observedAt: timestamp("observed_at", { withTimezone: true }),
16
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull(),
17
+ });