diff --git a/graphql-contracts b/graphql-contracts index 1526ffc..d8f6796 160000 --- a/graphql-contracts +++ b/graphql-contracts @@ -1 +1 @@ -Subproject commit 1526ffc3b94547ae9d792528ad1a4e2aac0b1bc4 +Subproject commit d8f6796b68b3906eeba3ed8ddbafda784bbe87a5 diff --git a/src/m2m-schema.ts b/src/m2m-schema.ts index 41d0603..0ce7d3a 100644 --- a/src/m2m-schema.ts +++ b/src/m2m-schema.ts @@ -15,6 +15,12 @@ type LockCurrencyPriceInput = { rateDate?: string | null } +type ConvertCurrencyForDisplayInput = { + amount: number + sourceCurrency: string + displayCurrency: string +} + export const m2mTypeDefs = `#graphql input LockCurrencyPriceInput { sourceAmount: Float! @@ -24,6 +30,24 @@ export const m2mTypeDefs = `#graphql rateDate: String } + input ConvertCurrencyForDisplayInput { + amount: Float! + sourceCurrency: String! + displayCurrency: String! + } + + type DisplayCurrencyConversion { + sourceAmount: Float! + sourceCurrency: String! + displayAmount: Float! + displayCurrency: String! + exchangeRate: Float! + rateSnapshotUuid: String + rateEffectiveDate: String! + rateQuotedAt: String! + provider: String! + } + type LockedCurrencyPrice { sourceAmount: Float! sourceCurrency: String! @@ -41,6 +65,7 @@ export const m2mTypeDefs = `#graphql type Query { health: String! + convertCurrencyForDisplay(input: ConvertCurrencyForDisplayInput!): DisplayCurrencyConversion! } type Mutation { @@ -118,9 +143,49 @@ async function lockCurrencyPrice( } } +async function convertCurrencyForDisplay( + _: unknown, + args: { input: ConvertCurrencyForDisplayInput }, +) { + const sourceAmount = Number(args.input.amount) + if (!Number.isFinite(sourceAmount) || sourceAmount < 0) { + throw new GraphQLError('amount must be a non-negative finite number') + } + const sourceCurrency = currencyCode(args.input.sourceCurrency) + const displayCurrency = currencyCode(args.input.displayCurrency) + if (sourceCurrency === displayCurrency) { + const quotedAt = new Date() + return { + sourceAmount, + sourceCurrency, + displayAmount: sourceAmount, + displayCurrency, + exchangeRate: 1, + rateSnapshotUuid: null, + rateEffectiveDate: quotedAt.toISOString().slice(0, 10), + rateQuotedAt: quotedAt.toISOString(), + provider: 'identity', + } + } + const snapshot = await latestCurrencyRatesSnapshot() + const exchangeRate = convertMoney(1, sourceCurrency, displayCurrency, snapshot) + return { + sourceAmount, + sourceCurrency, + displayAmount: sourceAmount * exchangeRate, + displayCurrency, + exchangeRate, + rateSnapshotUuid: snapshot.uuid, + rateEffectiveDate: snapshot.effectiveDate.toISOString().slice(0, 10), + rateQuotedAt: snapshot.updatedAt.toISOString(), + provider: snapshot.provider, + } +} + export const m2mResolvers = { Query: { health: () => 'ok', + convertCurrencyForDisplay, }, Mutation: { lockCurrencyPrice,