filter by selections (now all working), add cache for plans

This commit is contained in:
2024-04-06 14:01:18 -06:00
parent e3696e3ac5
commit 3fbf68b117
15 changed files with 384 additions and 107 deletions

View File

@@ -1,9 +1,11 @@
import { Axios, AxiosResponse, RawAxiosRequestHeaders } from "axios";
import * as didJwt from "did-jwt";
import { LRUCache } from "lru-cache";
import * as R from "ramda";
import { IIdentifier } from "@veramo/core";
import { accessToken, SimpleSigner } from "@/libs/crypto";
import * as didJwt from "did-jwt";
import { Axios, AxiosResponse } from "axios";
import { Contact } from "@/db/tables/contacts";
import { accessToken, SimpleSigner } from "@/libs/crypto";
export const SCHEMA_ORG_CONTEXT = "https://schema.org";
// the object in RegisterAction claims
@@ -49,7 +51,7 @@ export interface GenericVerifiableCredential {
[key: string]: any; // eslint-disable-line @typescript-eslint/no-explicit-any
}
export interface GenericServerRecord extends GenericVerifiableCredential {
export interface GenericCredWrapper extends GenericVerifiableCredential {
handleId?: string;
id: string;
issuedAt: string;
@@ -58,7 +60,7 @@ export interface GenericServerRecord extends GenericVerifiableCredential {
claim: Record<string, any>;
claimType?: string;
}
export const BLANK_GENERIC_SERVER_RECORD: GenericServerRecord = {
export const BLANK_GENERIC_SERVER_RECORD: GenericCredWrapper = {
"@context": SCHEMA_ORG_CONTEXT,
"@type": "",
claim: {},
@@ -68,7 +70,7 @@ export const BLANK_GENERIC_SERVER_RECORD: GenericServerRecord = {
};
// a summary record; the VC is found the fullClaim field
export interface GiveServerRecord {
export interface GiveSummaryRecord {
agentDid: string;
amount: number;
amountConfirmed: number;
@@ -83,7 +85,7 @@ export interface GiveServerRecord {
}
// a summary record; the VC is found the fullClaim field
export interface OfferServerRecord {
export interface OfferSummaryRecord {
amount: number;
amountGiven: number;
amountGivenConfirmed: number;
@@ -101,7 +103,7 @@ export interface OfferServerRecord {
}
// a summary record; the VC is not currently part of this record
export interface PlanServerRecord {
export interface PlanSummaryRecord {
agentDid?: string; // optional, if the issuer wants someone else to manage as well
description: string;
endTime?: string;
@@ -256,6 +258,10 @@ export type CreateAndSubmitClaimResult = SuccessResult | ErrorResult;
// See https://github.com/trentlarson/endorser-ch/blob/0cb626f803028e7d9c67f095858a9fc8542e3dbd/server/api/services/util.js#L6
const HIDDEN_DID = "did:none:HIDDEN";
const planCache: LRUCache<string, PlanSummaryRecord> = new LRUCache({
max: 500,
});
export function isDid(did: string) {
return did.startsWith("did:");
}
@@ -269,7 +275,7 @@ export function isEmptyOrHiddenDid(did?: string) {
}
/**
* @return true for any nested string where func(input) === true
* @return true for any string within this primitive/object/array where func(input) === true
*
* Similar logic is found in endorser-mobile.
*/
@@ -304,6 +310,12 @@ export function containsHiddenDid(obj: any) {
return testRecursivelyOnStrings(isHiddenDid, obj);
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const containsNonHiddenDid = (obj: any) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return testRecursivelyOnStrings((s: any) => isDid(s) && !isHiddenDid(s), obj);
};
export function stripEndorserPrefix(claimId: string) {
if (claimId && claimId.startsWith(ENDORSER_CH_HANDLE_PREFIX)) {
return claimId.substring(ENDORSER_CH_HANDLE_PREFIX.length);
@@ -423,6 +435,62 @@ export function didInfo(
return didInfoForContact(did, activeDid, contact, allMyDids).displayName;
}
async function getHeaders(identity: IIdentifier) {
const headers: RawAxiosRequestHeaders = {
"Content-Type": "application/json",
};
if (identity) {
const token = await accessToken(identity);
headers["Authorization"] = "Bearer " + token;
}
return headers;
}
export async function getPlanFromCache(
handleId: string,
identity: IIdentifier,
axios: Axios,
apiServer: string,
) {
let cred = planCache.get(handleId);
if (!cred) {
const url =
apiServer +
"/api/v2/report/plans?handleId=" +
encodeURIComponent(handleId);
const headers = await getHeaders(identity);
try {
const resp = await axios.get(url, { headers });
if (resp.status === 200 && resp.data?.data?.length > 0) {
cred = resp.data.data[0];
planCache.set(handleId, cred);
} else {
console.log(
"Failed to load plan with handle",
handleId,
" Got data:",
resp.data,
);
}
} catch (error) {
console.log(
"Failed to load plan with handle",
handleId,
" Got error:",
error,
);
}
}
return cred;
}
export async function setPlanInCache(
handleId: string,
planSummary: PlanSummaryRecord,
) {
planCache.set(handleId, planSummary);
}
/**
* For result, see https://api.endorser.ch/api-docs/#/claims/post_api_v2_claim
*
@@ -475,7 +543,7 @@ export async function createAndSubmitGive(
vcClaim.image = imageUrl;
}
return createAndSubmitClaim(
vcClaim as GenericServerRecord,
vcClaim as GenericCredWrapper,
identity,
apiServer,
axios,
@@ -524,7 +592,7 @@ export async function createAndSubmitOffer(
};
}
return createAndSubmitClaim(
vcClaim as GenericServerRecord,
vcClaim as GenericCredWrapper,
identity,
apiServer,
axios,
@@ -695,7 +763,7 @@ const claimSummary = (claim: Record<string, any>) => {
similar code is also contained in endorser-mobile
**/
export const claimSpecialDescription = (
record: GenericServerRecord,
record: GenericCredWrapper,
activeDid: string,
identifiers: Array<string>,
contacts: Array<Contact>,
@@ -789,7 +857,7 @@ export const claimSpecialDescription = (
"...]"
);
} else {
return issuer + " declared " + claimSummary(claim as GenericServerRecord);
return issuer + " declared " + claimSummary(claim as GenericCredWrapper);
}
};

View File

@@ -9,7 +9,7 @@ import { accountsDB, db } from "@/db/index";
import { Account } from "@/db/tables/accounts";
import { MASTER_SETTINGS_KEY } from "@/db/tables/settings";
import { deriveAddress, generateSeed, newIdentifier } from "@/libs/crypto";
import { GenericServerRecord, containsHiddenDid } from "@/libs/endorserServer";
import { GenericCredWrapper, containsHiddenDid } from "@/libs/endorserServer";
import * as serverUtil from "@/libs/endorserServer";
// eslint-disable-next-line @typescript-eslint/no-var-requires
@@ -69,7 +69,7 @@ export const isGlobalUri = (uri: string) => {
return uri && uri.match(new RegExp(/^[A-Za-z][A-Za-z0-9+.-]+:/));
};
export const giveIsConfirmable = (veriClaim: GenericServerRecord) => {
export const giveIsConfirmable = (veriClaim: GenericCredWrapper) => {
return veriClaim.claimType === "GiveAction";
};
@@ -85,7 +85,7 @@ export const doCopyTwoSecRedo = (text: string, fn: () => void) => {
* @param veriClaim is expected to have fields: claim, claimType, and issuer
*/
export const isGiveRecordTheUserCanConfirm = (
veriClaim: GenericServerRecord,
veriClaim: GenericCredWrapper,
activeDid: string,
confirmerIdList: string[] = [],
) => {
@@ -101,9 +101,9 @@ export const isGiveRecordTheUserCanConfirm = (
* @returns the DID of the person who offered, or undefined if hidden
* @param veriClaim is expected to have fields: claim and issuer
*/
export const offerGiverDid: (
arg0: GenericServerRecord,
) => string | undefined = (veriClaim) => {
export const offerGiverDid: (arg0: GenericCredWrapper) => string | undefined = (
veriClaim,
) => {
let giver;
if (
veriClaim.claim.offeredBy?.identifier &&
@@ -120,7 +120,7 @@ export const offerGiverDid: (
* @returns true if the user can fulfill the offer
* @param veriClaim is expected to have fields: claim, claimType, and issuer
*/
export const canFulfillOffer = (veriClaim: GenericServerRecord) => {
export const canFulfillOffer = (veriClaim: GenericCredWrapper) => {
return !!(veriClaim.claimType === "Offer" && offerGiverDid(veriClaim));
};