UNPKG

split-expense-ynab-venmo-shared

Version:

Shared library code the app Expo+Firebase app 'Split Expense: YNAB + Venmo'

64 lines (52 loc) 1.68 kB
import { z } from 'zod'; import { objectKeys } from 'ts-extras'; export class VenmoClient { #accessToken: string; #defaultChargeeUserId: string; constructor(config: VenmoConfig) { this.#accessToken = config.accessToken; this.#defaultChargeeUserId = config.defaultChargeeId; } async requestPayment(details: PaymentDetails) { try { const chargeResponse = await fetch('https://api.venmo.com/v1/payments', { method: 'POST', headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${this.#accessToken}`, }, body: JSON.stringify({ note: details.note, metadata: { quasi_cash_disclaimer_viewed: false, }, amount: details.cents * -0.01, user_id: this.#defaultChargeeUserId, audience: 'private', }), }); if (!chargeResponse.ok) { throw new Error(`Venmo charge failed with status ${chargeResponse.status}`); } } catch (e) { console.error('Venmo charge error: ', e); throw e; } } } const ChargeeIdSchema = z.string(); export const VenmoEnvVarsSchema = z.object({ DEFAULT_VENMO_CHARGEE_ID: ChargeeIdSchema, VENMO_API_ACCESS_TOKEN: z.string(), }); export const VENMO_ENV_VAR_NAMES = objectKeys(VenmoEnvVarsSchema.keyof().Values); export const VenmoConfigSchema = z.object({ accessToken: z.string(), defaultChargeeId: ChargeeIdSchema, }); type VenmoConfig = z.infer<typeof VenmoConfigSchema>; export const PaymentDetailsSchema = z.object({ cents: z.number(), note: z.string(), }); export type PaymentDetails = z.infer<typeof PaymentDetailsSchema>;