UNPKG

asseton

Version:
157 lines (127 loc) 4.04 kB
import crypto from "crypto"; import { ServerApiError } from "src/errors"; import { DatabaseTypes } from "database"; import { IProviderAuthentication, IProviderAuthenticationInput, AuthenticatedProvider, IProviderInput, } from "../Provider"; import { NordigenClient } from "./NordigenClient"; import { NordginenApiTypes } from "./NordigenApi"; import { findProviderRequisition } from "./utils"; interface IRequisition { id: string; status: "CREATED" | "AUTHENTICATED"; authenticationUrl: string; accountIDs: Array<string>; } export class NordigenProvider extends AuthenticatedProvider { private client: NordigenClient; constructor(input: IProviderInput) { super(input); this.client = new NordigenClient(); this.ensureToken(); } private ensureToken = async (): Promise<void> => { await this.client.generateToken(); }; getDataSnapshot = async (): Promise<DatabaseTypes.IProviderData> => { const requisition = await this.getExistingRequisition(); if (!requisition || requisition.status === "CREATED") { throw ServerApiError.AuthenticationRequired(); } const result: DatabaseTypes.IProviderData = { id: this.id, createdAt: new Date().toISOString(), accounts: [], }; for (let accountID of requisition.accountIDs) { const { balances }: NordginenApiTypes.IBalances = await this.client .account(accountID) .getBalances(); const account: DatabaseTypes.IAccount = { assets: [], }; balances.forEach((it) => { account.assets.push({ symbol: it.balanceAmount.currency, amount: Number(it.balanceAmount.amount), }); }); result.accounts.push(account); } return result; }; createAuthentication = async ( input: IProviderAuthenticationInput ): Promise<IProviderAuthentication> => { let requisition = await this.getExistingRequisition(); if (!requisition) { const agreement: NordginenApiTypes.IAgreement = await this.client.createAgreement({ institutionId: this.id, maxHistoricalDays: 30, accessValidForDays: 1, }); const req: NordginenApiTypes.IRequisition = await this.client.createRequisition({ redirectUrl: input.redirectUrl, institutionId: this.id, reference: crypto.randomUUID(), agreement: agreement.id, }); requisition = this.transformRequisition(req); } if (requisition.status === "AUTHENTICATED") { throw ServerApiError.AuthenticationExists(); } return { authenticationUrl: requisition.authenticationUrl, }; }; deleteAuthentication = async (): Promise<void> => { const requisition = await this.getExistingRequisition(); if (!requisition) { throw ServerApiError.AuthenticationNotFound(); } await this.client.deleteRequisition(requisition.id); }; private getExistingRequisition = async (): Promise< IRequisition | undefined > => { const allAgreements: NordginenApiTypes.IAgreements = await this.client.getAgreements(); const allRequisitions: NordginenApiTypes.IRequisitions = await this.client.getRequisitions(); const result = findProviderRequisition({ providerID: this.id, agreements: allAgreements, requisitions: allRequisitions, }); if (result) { return this.transformRequisition(result); } return result; }; private transformRequisition = ( requisition: NordginenApiTypes.IRequisition ): IRequisition => { function transformStatus( status: NordginenApiTypes.IRequisition["status"] ): IRequisition["status"] { switch (status) { case "CR": return "CREATED"; case "LN": return "AUTHENTICATED"; } } return { id: requisition.id, authenticationUrl: requisition.link, status: transformStatus(requisition.status), accountIDs: requisition.accounts, }; }; }