/* This file is part of GNU Taler (C) 2022 Taler Systems S.A. GNU Taler is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU Taler; see the file COPYING. If not, see */ import { AccessToken, TalerBankIntegrationResultByMethod, TalerCoreBankResultByMethod, TalerHttpError, WithdrawalOperationStatus } from "@gnu-taler/taler-util"; import { useEffect, useState } from "preact/hooks"; import { MAX_RESULT_SIZE, PAGE_SIZE } from "../utils.js"; import { useBackendState } from "./backend.js"; // FIX default import https://github.com/microsoft/TypeScript/issues/49189 import _useSWR, { SWRHook } from "swr"; import { useBankCoreApiContext } from "../context/config.js"; const useSWR = _useSWR as unknown as SWRHook; export interface InstanceTemplateFilter { //FIXME: add filter to the template list position?: string; } export function useAccountDetails(account: string) { const { state: credentials } = useBackendState(); const { api } = useBankCoreApiContext(); async function fetcher([username, token]: [string, AccessToken]) { return await api.getAccount({ username, token }) } const token = credentials.status !== "loggedIn" ? undefined : credentials.token const { data, error } = useSWR, TalerHttpError>( [account, token, "getAccount"], fetcher, { refreshInterval: 0, refreshWhenHidden: false, revalidateOnFocus: false, revalidateOnReconnect: false, refreshWhenOffline: false, errorRetryCount: 0, errorRetryInterval: 1, shouldRetryOnError: false, keepPreviousData: true, }); if (data) return data if (error) return error; return undefined; } export function useWithdrawalDetails(wid: string) { const { api } = useBankCoreApiContext(); const [latestStatus, setLatestStatus] = useState() async function fetcher([wid, old_state]: [string, WithdrawalOperationStatus | undefined]) { return await api.getWithdrawalById(wid, old_state === undefined ? undefined : { old_state, timeoutMs: 15000 }) } const { data, error } = useSWR, TalerHttpError>( [wid, latestStatus, "getWithdrawalById"], fetcher, { refreshInterval: 3000, refreshWhenHidden: false, revalidateOnFocus: false, revalidateOnReconnect: false, refreshWhenOffline: false, errorRetryCount: 0, errorRetryInterval: 1, shouldRetryOnError: false, keepPreviousData: true, }); const currentStatus = data !== undefined && data.type === "ok" ? data.body.status : undefined; useEffect(() => { if (currentStatus !== undefined && currentStatus !== latestStatus) { setLatestStatus(currentStatus) } }, [currentStatus]) if (data) return data; if (error) return error; return undefined; } export function useTransactionDetails(account: string, tid: number) { const { state: credentials } = useBackendState(); const token = credentials.status !== "loggedIn" ? undefined : credentials.token const { api } = useBankCoreApiContext(); async function fetcher([username, token, txid]: [string, AccessToken, number]) { return await api.getTransactionById({ username, token }, txid) } const { data, error } = useSWR, TalerHttpError>( [account, token, tid, "getTransactionById"], fetcher, { refreshInterval: 0, refreshWhenHidden: false, revalidateOnFocus: false, revalidateOnReconnect: false, refreshWhenOffline: false, errorRetryCount: 0, errorRetryInterval: 1, shouldRetryOnError: false, keepPreviousData: true, }); if (data) return data; if (error) return error; return undefined; } export function usePublicAccounts(filterAccount: string | undefined, initial?: number) { const [offset, setOffset] = useState(initial); const { api } = useBankCoreApiContext(); async function fetcher([account, txid]: [string | undefined, number | undefined]) { return await api.getPublicAccounts({ account }, { limit: MAX_RESULT_SIZE, offset: txid ? String(txid) : undefined, order: "asc" }) } const { data, error } = useSWR, TalerHttpError>( [filterAccount, offset, "getPublicAccounts"], fetcher, { refreshInterval: 0, refreshWhenHidden: false, revalidateOnFocus: false, revalidateOnReconnect: false, refreshWhenOffline: false, errorRetryCount: 0, errorRetryInterval: 1, shouldRetryOnError: false, keepPreviousData: true, }); const isLastPage = data && data.body.public_accounts.length < PAGE_SIZE; const isFirstPage = !initial; const pagination = { isLastPage, isFirstPage, loadMore: () => { if (isLastPage || data?.type !== "ok") return; const list = data.body.public_accounts if (list.length < MAX_RESULT_SIZE) { // setOffset(list[list.length-1].account_name); } }, loadMorePrev: () => { null; }, }; // const public_accountslist = data?.type !== "ok" ? [] : data.body.public_accounts; if (data) { return { ok: true, data: data.body, ...pagination } } if (error) { return error; } return undefined; } /** * @param account * @param args * @returns */ export function useTransactions(account: string, initial?: number) { const { state: credentials } = useBackendState(); const token = credentials.status !== "loggedIn" ? undefined : credentials.token const [offset, setOffset] = useState(initial); const { api } = useBankCoreApiContext(); async function fetcher([username, token, txid]: [string, AccessToken, number | undefined]) { return await api.getTransactions({ username, token }, { limit: MAX_RESULT_SIZE, offset: txid ? String(txid) : undefined, order: "dec" }) } const { data, error } = useSWR, TalerHttpError>( [account, token, offset, "getTransactions"], fetcher, { refreshInterval: 0, refreshWhenHidden: false, refreshWhenOffline: false, // revalidateOnMount: false, revalidateIfStale: false, revalidateOnFocus: false, revalidateOnReconnect: false, } ); const isLastPage = data && data.type === "ok" && data.body.transactions.length < PAGE_SIZE; const isFirstPage = true; const pagination = { isLastPage, isFirstPage, loadMore: () => { if (isLastPage || data?.type !== "ok") return; const list = data.body.transactions if (list.length < MAX_RESULT_SIZE) { setOffset(list[list.length - 1].row_id); } }, loadMorePrev: () => { null; }, }; if (data) { return { ok: true, data, ...pagination } } if (error) { return error; } return undefined; }