Skip to content
← Public packages

@kentcdodds/wise

Call Wise profiles, balances, quotes, recipients, and transfers with wiseApiToken.

src/create-quote.ts

77 lines · 2.6 KB · TypeScript
import { clean, resolveProfileId, wiseRequest, type ProfileRef } from './core.ts'

export type CreateQuoteInput = ProfileRef & {
	sourceCurrency: string
	targetCurrency: string
	sourceAmount?: number
	targetAmount?: number
	payOut?: string
	preferredPayIn?: string
	/** When true, validate and return the would-be request without calling Wise. */
	dryRun?: boolean
	/** Required true to create a real quote (unless dryRun). */
	confirm?: boolean
}

/**
 * Create a Wise transfer quote for a profile.
 * Requires confirm: true for a live POST, or dryRun: true to preview the payload.
 * Uses POST /v3/profiles/{profileId}/quotes.
 *
 * @param input.sourceCurrency - Source currency code (e.g. USD).
 * @param input.targetCurrency - Target currency code.
 * @param input.sourceAmount - Amount in source currency (mutually exclusive with targetAmount).
 * @param input.targetAmount - Amount in target currency.
 * @param input.dryRun - Preview without calling Wise.
 * @param input.confirm - Must be true for a live quote.
 *
 * @example
 * import createQuote from 'kody:@kentcdodds/wise/create-quote'
 * const preview = await createQuote({
 *   sourceCurrency: 'USD',
 *   targetCurrency: 'EUR',
 *   sourceAmount: 100,
 *   dryRun: true,
 * })
 */
export default async function createQuote(input: CreateQuoteInput) {
	const sourceCurrency = clean(input.sourceCurrency).toUpperCase()
	const targetCurrency = clean(input.targetCurrency).toUpperCase()
	if (!sourceCurrency || !targetCurrency) {
		throw new Error('sourceCurrency and targetCurrency are required')
	}
	const hasSource = input.sourceAmount !== undefined && input.sourceAmount !== null
	const hasTarget = input.targetAmount !== undefined && input.targetAmount !== null
	if (hasSource === hasTarget) {
		throw new Error('Provide exactly one of sourceAmount or targetAmount')
	}
	const profileId = await resolveProfileId(input)
	const body: Record<string, unknown> = {
		sourceCurrency,
		targetCurrency,
		payOut: clean(input.payOut) || 'BANK_TRANSFER',
	}
	if (hasSource) body.sourceAmount = Number(input.sourceAmount)
	if (hasTarget) body.targetAmount = Number(input.targetAmount)
	if (clean(input.preferredPayIn)) body.preferredPayIn = clean(input.preferredPayIn)

	if (input.dryRun) {
		return {
			dryRun: true,
			profileId,
			path: `/v3/profiles/${profileId}/quotes`,
			body,
		}
	}
	if (input.confirm !== true) {
		throw new Error('Pass confirm: true to create a live quote, or dryRun: true to preview')
	}

	const quote = await wiseRequest({
		method: 'POST',
		path: `/v3/profiles/${profileId}/quotes`,
		body,
		label: 'Wise create quote',
	})
	return { dryRun: false, profileId, quote }
}