import { sql, type Selectable } from 'kysely' import type * as Db from '../Db.js' import type * as db_Schema from '../Schema.js' /** Columns of the `funding_deposit_request_observations` table. */ export type Table = db_Schema.FundingDepositRequestObservation /** First Tempo observations of one provider request. */ export type Record = Selectable /** Gets observation timestamps for one provider request. */ export function get(db: Db.Db, options: get.Options): Promise { return db.kysely .selectFrom('funding_deposit_request_observations') .selectAll() .where('depositAddressId', '=', options.depositAddressId) .where('providerRequestId', '=', options.providerRequestId) .executeTakeFirst() } export declare namespace get { /** Provider request identity scoped to one reusable address. */ type Options = { /** Funding deposit address id (`fda_…`). */ depositAddressId: string /** Provider request identifier. */ providerRequestId: string } } /** Records when polling first observed each provider request. */ export async function observePoll(db: Db.Db, options: observePoll.Options): Promise { const providerRequestIds = [...new Set(options.providerRequestIds)] if (providerRequestIds.length === 0) return [] return db.kysely .insertInto('funding_deposit_request_observations') .values( providerRequestIds.map((providerRequestId) => ({ depositAddressId: options.depositAddressId, pollObservedAt: options.observedAt, providerRequestId, webhookReceivedAt: null, })), ) .onConflict((oc) => oc.columns(['depositAddressId', 'providerRequestId']).doUpdateSet({ pollObservedAt: sql`LEAST(COALESCE(funding_deposit_request_observations.poll_observed_at, excluded.poll_observed_at), excluded.poll_observed_at)`, }), ) .returningAll() .execute() } export declare namespace observePoll { /** Provider requests observed in one successful poll response. */ type Options = { /** Funding deposit address id (`fda_…`). */ depositAddressId: string /** When Tempo observed the provider requests. */ observedAt: string /** Provider request identifiers returned by the poll. */ providerRequestIds: readonly string[] } } /** Records when Tempo first received an authenticated webhook for a provider request. */ export function observeWebhook( db: Db.Db, options: observeWebhook.Options, ): Promise { return db.kysely .insertInto('funding_deposit_request_observations') .values({ depositAddressId: options.depositAddressId, pollObservedAt: null, providerRequestId: options.providerRequestId, webhookReceivedAt: options.receivedAt, }) .onConflict((oc) => oc.columns(['depositAddressId', 'providerRequestId']).doUpdateSet({ webhookReceivedAt: sql`LEAST(COALESCE(funding_deposit_request_observations.webhook_received_at, excluded.webhook_received_at), excluded.webhook_received_at)`, }), ) .returningAll() .executeTakeFirst() } export declare namespace observeWebhook { /** Authenticated webhook observation for one provider request. */ type Options = { /** Funding deposit address id (`fda_…`). */ depositAddressId: string /** Provider request identifier. */ providerRequestId: string /** When Tempo received the webhook. */ receivedAt: string } }