import { BankTransaction } from './tink.classes.banktransaction.js'; import { TinkUser } from './tink.classes.tinkuser.js'; import * as plugins from './tink.plugins.js'; import * as tinkHelpers from './helpers/index.js'; export interface ITinkBankAccountData { balances: { booked: { amount: { currencyCode: string; value: { scale: string; unscaledValue: string; }; }; }; available: { amount: { currencyCode: string; value: { scale: string; unscaledValue: string; }; }; }; }; customerSegment: string; dates: { lastRefreshed: string; }; financialInstitutionId: string; id: string; identifiers: { iban?: { bban: string; iban: string; }; pan: { masked: string; }; financialInstitution: { accountNumber: string; referenceNumbers: unknown }; }; name: string; type: string; } export class BankAccount { // STATIC public static async getAccountUserAccessToken(tinkUserArg: TinkUser) { const authorizationCode = await tinkUserArg.tinkAccountRef.getUserAuthorizationCode( tinkUserArg.externalUserIdArg, tinkUserArg.tinkAccountRef.clientId, 'accounts:read,balances:read,transactions:read,provider-consents:read' ); const accessToken = await tinkUserArg.tinkAccountRef.getUserAccessToken(authorizationCode); return accessToken; } public static async getBankAccountsForUser(tinkUserArg: TinkUser) { const userAccessToken = await this.getAccountUserAccessToken(tinkUserArg); const returnBankAccounts: BankAccount[] = []; const getBankAccountRecursively = async (nextPageToken?: string) => { const searchParams = new URLSearchParams(); searchParams.set('pageSize', '200'); if (nextPageToken) { searchParams.set('pageToken', nextPageToken); } const response = await tinkUserArg.tinkAccountRef.request({ urlArg: `/data/v2/accounts?${searchParams.toString()}`, accessToken: userAccessToken, methodArg: 'GET', payloadArg: null, }); for (const account of response.accounts) { returnBankAccounts.push(new BankAccount(tinkUserArg, account)); } if (response.nextPageToken.length > 0) { await getBankAccountRecursively(response.nextPageToken); } }; await getBankAccountRecursively(); return returnBankAccounts; } // INSTANCE tinkUserRef: TinkUser; data: ITinkBankAccountData; constructor(tinkUserRefArg: TinkUser, dataArg: ITinkBankAccountData) { this.tinkUserRef = tinkUserRefArg; this.data = dataArg; } /** * updates the account and tries to get the latest state from bunq */ public async update() { const bankAccounts = await BankAccount.getBankAccountsForUser(this.tinkUserRef); const matchingAccount = bankAccounts.find( (bankAccountArg) => bankAccountArg.data.id === this.data.id ); if (matchingAccount) { this.data = matchingAccount.data; } } /** * gets normalized data */ public getNormalizedData() { return { id: this.data.id, name: this.data.name, accountNumber: this.data.identifiers.iban?.iban || this.data.identifiers?.financialInstitution?.accountNumber || null, bookedValue: tinkHelpers.getNormalizedAmount(this.data.balances.booked?.amount), availableValue: tinkHelpers.getNormalizedAmount(this.data.balances.available?.amount), }; } /** * gets the transactions for the bank account */ public async getTransactions() { const transactions = await BankTransaction.getBankTransactions(this); return transactions; } }