Browse Source

fix some errors and correct recent type duplications & bloat

pull/134/head
Trent Larson 7 days ago
parent
commit
d8f2587d1c
  1. 106
      src/interfaces/claims.ts
  2. 89
      src/interfaces/common.ts
  3. 6
      src/interfaces/index.ts
  4. 8
      src/interfaces/records.ts
  5. 4
      src/libs/crypto/vc/index.ts
  6. 212
      src/libs/endorserServer.ts
  7. 105
      src/libs/util.ts
  8. 8
      src/views/ClaimView.vue
  9. 4
      src/views/ContactAmountsView.vue
  10. 8
      src/views/DIDView.vue
  11. 8
      src/views/GiftedDetailsView.vue
  12. 11
      src/views/IdentitySwitcherView.vue
  13. 8
      src/views/OfferDetailsView.vue
  14. 12
      src/views/ProjectViewView.vue
  15. 4
      src/views/ShareMyContactInfoView.vue
  16. 1
      test-playwright/60-new-activity.spec.ts

106
src/interfaces/claims.ts

@ -1,14 +1,24 @@
import { GenericVerifiableCredential } from "./common"; /**
* Types of Claims
*
* Note that these are for the claims that get signed.
* Records that are the latest edited entities are in the records.ts file.
*
*/
export interface AgreeVerifiableCredential { import { ClaimObject } from "./common";
"@context": string;
export interface AgreeActionClaim extends ClaimObject {
"@context": "https://schema.org";
"@type": string; "@type": string;
object: Record<string, unknown>; object: Record<string, unknown>;
} }
// Note that previous VCs may have additional fields. // Note that previous VCs may have additional fields.
// https://endorser.ch/doc/html/transactions.html#id4 // https://endorser.ch/doc/html/transactions.html#id4
export interface GiveVerifiableCredential extends GenericVerifiableCredential { export interface GiveActionClaim extends ClaimObject {
// context is optional because it might be embedded in another claim, eg. an AgreeAction
"@context"?: "https://schema.org";
"@type": "GiveAction"; "@type": "GiveAction";
agent?: { identifier: string }; agent?: { identifier: string };
description?: string; description?: string;
@ -16,43 +26,21 @@ export interface GiveVerifiableCredential extends GenericVerifiableCredential {
identifier?: string; identifier?: string;
image?: string; image?: string;
object?: { amountOfThisGood: number; unitCode: string }; object?: { amountOfThisGood: number; unitCode: string };
provider?: GenericVerifiableCredential; provider?: ClaimObject;
recipient?: { identifier: string }; recipient?: { identifier: string };
type: string[]; }
issuer: string;
issuanceDate: string; export interface JoinActionClaim extends ClaimObject {
credentialSubject: { agent?: { identifier: string };
id: string; event?: { organizer?: { name: string }; name?: string; startTime?: string };
type: "GiveAction";
offeredBy?: {
type: "Person";
identifier: string;
};
offeredTo?: {
type: "Person";
identifier: string;
};
offeredToProject?: {
type: "Project";
identifier: string;
};
offeredToProjectVisibleToDids?: string[];
offeredToVisibleToDids?: string[];
offeredByVisibleToDids?: string[];
amount: {
type: "QuantitativeValue";
value: number;
unitCode: string;
};
startTime?: string;
endTime?: string;
};
} }
// Note that previous VCs may have additional fields. // Note that previous VCs may have additional fields.
// https://endorser.ch/doc/html/transactions.html#id8 // https://endorser.ch/doc/html/transactions.html#id8
export interface OfferVerifiableCredential extends GenericVerifiableCredential { export interface OfferClaim extends ClaimObject {
"@context": "https://schema.org";
"@type": "Offer"; "@type": "Offer";
agent?: { identifier: string };
description?: string; description?: string;
fulfills?: { "@type": string; identifier?: string; lastClaimId?: string }[]; fulfills?: { "@type": string; identifier?: string; lastClaimId?: string }[];
identifier?: string; identifier?: string;
@ -67,43 +55,18 @@ export interface OfferVerifiableCredential extends GenericVerifiableCredential {
name?: string; name?: string;
}; };
}; };
provider?: GenericVerifiableCredential;
recipient?: { identifier: string };
validThrough?: string;
type: string[];
issuer: string;
issuanceDate: string;
credentialSubject: {
id: string;
type: "Offer";
offeredBy?: { offeredBy?: {
type: "Person"; type?: "Person";
identifier: string;
};
offeredTo?: {
type: "Person";
identifier: string;
};
offeredToProject?: {
type: "Project";
identifier: string; identifier: string;
}; };
offeredToProjectVisibleToDids?: string[]; provider?: ClaimObject;
offeredToVisibleToDids?: string[]; recipient?: { identifier: string };
offeredByVisibleToDids?: string[]; validThrough?: string;
amount: {
type: "QuantitativeValue";
value: number;
unitCode: string;
};
startTime?: string;
endTime?: string;
};
} }
// Note that previous VCs may have additional fields. // Note that previous VCs may have additional fields.
// https://endorser.ch/doc/html/transactions.html#id7 // https://endorser.ch/doc/html/transactions.html#id7
export interface PlanVerifiableCredential extends GenericVerifiableCredential { export interface PlanActionClaim extends ClaimObject {
"@context": "https://schema.org"; "@context": "https://schema.org";
"@type": "PlanAction"; "@type": "PlanAction";
name: string; name: string;
@ -117,11 +80,18 @@ export interface PlanVerifiableCredential extends GenericVerifiableCredential {
} }
// AKA Registration & RegisterAction // AKA Registration & RegisterAction
export interface RegisterVerifiableCredential { export interface RegisterActionClaim extends ClaimObject {
"@context": string; "@context": "https://schema.org";
"@type": "RegisterAction"; "@type": "RegisterAction";
agent: { identifier: string }; agent: { identifier: string };
identifier?: string; identifier?: string;
object: string; object?: string;
participant?: { identifier: string }; participant?: { identifier: string };
} }
export interface TenureClaim extends ClaimObject {
"@context": "https://endorser.ch";
"@type": "Tenure";
party?: { identifier: string };
spatialUnit?: { geo?: { polygon?: string } };
}

89
src/interfaces/common.ts

@ -37,15 +37,19 @@ export interface ErrorResult extends ResultWithType {
export interface KeyMeta { export interface KeyMeta {
did: string; did: string;
name?: string;
publicKeyHex: string; publicKeyHex: string;
mnemonic: string; derivationPath?: string;
derivationPath: string;
registered?: boolean;
profileImageUrl?: string;
identity?: string; // Stringified IIdentifier object from Veramo
passkeyCredIdHex?: string; // The Webauthn credential ID in hex, if this is from a passkey passkeyCredIdHex?: string; // The Webauthn credential ID in hex, if this is from a passkey
[key: string]: unknown; }
export interface KeyMetaMaybeWithPrivate extends KeyMeta {
mnemonic?: string; // 12 or 24 words encoding the seed
identity?: string; // Stringified IIdentifier object from Veramo
}
export interface KeyMetaWithPrivate extends KeyMeta {
mnemonic: string; // 12 or 24 words encoding the seed
identity: string; // Stringified IIdentifier object from Veramo
} }
export interface QuantitativeValue extends GenericVerifiableCredential { export interface QuantitativeValue extends GenericVerifiableCredential {
@ -53,7 +57,6 @@ export interface QuantitativeValue extends GenericVerifiableCredential {
"@context"?: string; "@context"?: string;
amountOfThisGood: number; amountOfThisGood: number;
unitCode: string; unitCode: string;
[key: string]: unknown;
} }
export interface AxiosErrorResponse { export interface AxiosErrorResponse {
@ -87,34 +90,14 @@ export interface CreateAndSubmitClaimResult {
handleId?: string; handleId?: string;
} }
export interface PlanSummaryRecord {
handleId: string;
issuer: string;
claim: GenericVerifiableCredential;
[key: string]: unknown;
}
export interface Agent { export interface Agent {
identifier?: string; identifier?: string;
did?: string; did?: string;
[key: string]: unknown;
} }
export interface ClaimObject { export interface ClaimObject {
"@type": string; "@type": string;
"@context"?: string; "@context"?: string;
fulfills?: Array<{
"@type": string;
identifier?: string;
[key: string]: unknown;
}>;
object?: GenericVerifiableCredential;
agent?: Agent;
participant?: {
identifier?: string;
[key: string]: unknown;
};
identifier?: string;
[key: string]: unknown; [key: string]: unknown;
} }
@ -125,53 +108,3 @@ export interface VerifiableCredentialClaim {
credentialSubject: ClaimObject; credentialSubject: ClaimObject;
[key: string]: unknown; [key: string]: unknown;
} }
export interface GiveVerifiableCredential extends GenericVerifiableCredential {
"@type": "GiveAction";
object?: GenericVerifiableCredential;
agent?: Agent;
participant?: {
identifier?: string;
[key: string]: unknown;
};
fulfills?: Array<{
"@type": string;
identifier?: string;
[key: string]: unknown;
}>;
[key: string]: unknown;
}
export interface OfferVerifiableCredential extends GenericVerifiableCredential {
"@type": "Offer";
object?: GenericVerifiableCredential;
agent?: Agent;
participant?: {
identifier?: string;
[key: string]: unknown;
};
itemOffered?: {
description?: string;
isPartOf?: {
"@type": string;
identifier: string;
[key: string]: unknown;
};
[key: string]: unknown;
};
[key: string]: unknown;
}
export interface RegisterVerifiableCredential
extends GenericVerifiableCredential {
"@type": "RegisterAction";
agent: {
identifier: string;
};
object: string;
participant?: {
identifier: string;
};
identifier?: string;
[key: string]: unknown;
}

6
src/interfaces/index.ts

@ -13,9 +13,9 @@ export type {
export type { export type {
// From claims.ts // From claims.ts
GiveVerifiableCredential, GiveActionClaim,
OfferVerifiableCredential, OfferClaim,
RegisterVerifiableCredential, RegisterActionClaim,
} from "./claims"; } from "./claims";
export type { export type {

8
src/interfaces/records.ts

@ -1,14 +1,14 @@
import { GiveVerifiableCredential, OfferVerifiableCredential } from "./claims"; import { GiveActionClaim, OfferClaim } from "./claims";
// a summary record; the VC is found the fullClaim field // a summary record; the VC is found the fullClaim field
export interface GiveSummaryRecord { export interface GiveSummaryRecord {
[x: string]: PropertyKey | undefined | GiveVerifiableCredential; [x: string]: PropertyKey | undefined | GiveActionClaim;
type?: string; type?: string;
agentDid: string; agentDid: string;
amount: number; amount: number;
amountConfirmed: number; amountConfirmed: number;
description: string; description: string;
fullClaim: GiveVerifiableCredential; fullClaim: GiveActionClaim;
fulfillsHandleId: string; fulfillsHandleId: string;
fulfillsPlanHandleId?: string; fulfillsPlanHandleId?: string;
fulfillsType?: string; fulfillsType?: string;
@ -26,7 +26,7 @@ export interface OfferSummaryRecord {
amount: number; amount: number;
amountGiven: number; amountGiven: number;
amountGivenConfirmed: number; amountGivenConfirmed: number;
fullClaim: OfferVerifiableCredential; fullClaim: OfferClaim;
fulfillsPlanHandleId: string; fulfillsPlanHandleId: string;
handleId: string; handleId: string;
issuerDid: string; issuerDid: string;

4
src/libs/crypto/vc/index.ts

@ -17,7 +17,7 @@ import { didEthLocalResolver } from "./did-eth-local-resolver";
import { PEER_DID_PREFIX, verifyPeerSignature } from "./didPeer"; import { PEER_DID_PREFIX, verifyPeerSignature } from "./didPeer";
import { base64urlDecodeString, createDidPeerJwt } from "./passkeyDidPeer"; import { base64urlDecodeString, createDidPeerJwt } from "./passkeyDidPeer";
import { urlBase64ToUint8Array } from "./util"; import { urlBase64ToUint8Array } from "./util";
import { KeyMeta } from "../../../interfaces/common"; import { KeyMeta, KeyMetaWithPrivate } from "../../../interfaces/common";
export const ETHR_DID_PREFIX = "did:ethr:"; export const ETHR_DID_PREFIX = "did:ethr:";
export const JWT_VERIFY_FAILED_CODE = "JWT_VERIFY_FAILED"; export const JWT_VERIFY_FAILED_CODE = "JWT_VERIFY_FAILED";
@ -34,7 +34,7 @@ export function isFromPasskey(keyMeta?: KeyMeta): boolean {
} }
export async function createEndorserJwtForKey( export async function createEndorserJwtForKey(
account: KeyMeta, account: KeyMetaWithPrivate,
payload: object, payload: object,
expiresIn?: number, expiresIn?: number,
) { ) {

212
src/libs/endorserServer.ts

@ -38,7 +38,14 @@ import {
getPasskeyExpirationSeconds, getPasskeyExpirationSeconds,
} from "../libs/util"; } from "../libs/util";
import { createEndorserJwtForKey } from "../libs/crypto/vc"; import { createEndorserJwtForKey } from "../libs/crypto/vc";
import { KeyMeta } from "../interfaces/common"; import {
GiveActionClaim,
JoinActionClaim,
OfferClaim,
PlanActionClaim,
RegisterActionClaim,
TenureClaim,
} from "../interfaces/claims";
import { import {
GenericCredWrapper, GenericCredWrapper,
@ -46,15 +53,13 @@ import {
AxiosErrorResponse, AxiosErrorResponse,
UserInfo, UserInfo,
CreateAndSubmitClaimResult, CreateAndSubmitClaimResult,
PlanSummaryRecord,
GiveVerifiableCredential,
OfferVerifiableCredential,
RegisterVerifiableCredential,
ClaimObject, ClaimObject,
VerifiableCredentialClaim, VerifiableCredentialClaim,
Agent,
QuantitativeValue, QuantitativeValue,
KeyMetaWithPrivate,
KeyMetaMaybeWithPrivate,
} from "../interfaces/common"; } from "../interfaces/common";
import { PlanSummaryRecord } from "../interfaces/records";
import { logger } from "../utils/logger"; import { logger } from "../utils/logger";
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory"; import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
@ -650,7 +655,7 @@ export async function getNewOffersToUserProjects(
* @param lastClaimId supplied when editing a previous claim * @param lastClaimId supplied when editing a previous claim
*/ */
export function hydrateGive( export function hydrateGive(
vcClaimOrig?: GiveVerifiableCredential, vcClaimOrig?: GiveActionClaim,
fromDid?: string, fromDid?: string,
toDid?: string, toDid?: string,
description?: string, description?: string,
@ -662,8 +667,8 @@ export function hydrateGive(
imageUrl?: string, imageUrl?: string,
providerPlanHandleId?: string, providerPlanHandleId?: string,
lastClaimId?: string, lastClaimId?: string,
): GiveVerifiableCredential { ): GiveActionClaim {
const vcClaim: GiveVerifiableCredential = vcClaimOrig const vcClaim: GiveActionClaim = vcClaimOrig
? R.clone(vcClaimOrig) ? R.clone(vcClaimOrig)
: { : {
"@context": SCHEMA_ORG_CONTEXT, "@context": SCHEMA_ORG_CONTEXT,
@ -694,7 +699,7 @@ export function hydrateGive(
// Initialize fulfills array if not present // Initialize fulfills array if not present
if (!Array.isArray(vcClaim.fulfills)) { if (!Array.isArray(vcClaim.fulfills)) {
vcClaim.fulfills = []; vcClaim.fulfills = vcClaim.fulfills ? [vcClaim.fulfills] : [];
} }
// Filter and add fulfills elements // Filter and add fulfills elements
@ -797,7 +802,7 @@ export async function createAndSubmitGive(
export async function editAndSubmitGive( export async function editAndSubmitGive(
axios: Axios, axios: Axios,
apiServer: string, apiServer: string,
fullClaim: GenericCredWrapper<GiveVerifiableCredential>, fullClaim: GenericCredWrapper<GiveActionClaim>,
issuerDid: string, issuerDid: string,
fromDid?: string, fromDid?: string,
toDid?: string, toDid?: string,
@ -838,7 +843,7 @@ export async function editAndSubmitGive(
* @param lastClaimId supplied when editing a previous claim * @param lastClaimId supplied when editing a previous claim
*/ */
export function hydrateOffer( export function hydrateOffer(
vcClaimOrig?: OfferVerifiableCredential, vcClaimOrig?: OfferClaim,
fromDid?: string, fromDid?: string,
toDid?: string, toDid?: string,
itemDescription?: string, itemDescription?: string,
@ -848,8 +853,8 @@ export function hydrateOffer(
fulfillsProjectHandleId?: string, fulfillsProjectHandleId?: string,
validThrough?: string, validThrough?: string,
lastClaimId?: string, lastClaimId?: string,
): OfferVerifiableCredential { ): OfferClaim {
const vcClaim: OfferVerifiableCredential = vcClaimOrig const vcClaim: OfferClaim = vcClaimOrig
? R.clone(vcClaimOrig) ? R.clone(vcClaimOrig)
: { : {
"@context": SCHEMA_ORG_CONTEXT, "@context": SCHEMA_ORG_CONTEXT,
@ -857,12 +862,13 @@ export function hydrateOffer(
}; };
if (lastClaimId) { if (lastClaimId) {
// this is an edit
vcClaim.lastClaimId = lastClaimId; vcClaim.lastClaimId = lastClaimId;
delete vcClaim.identifier; delete vcClaim.identifier;
} }
if (fromDid) { if (fromDid) {
vcClaim.agent = { identifier: fromDid }; vcClaim.offeredBy = { identifier: fromDid };
} }
if (toDid) { if (toDid) {
vcClaim.recipient = { identifier: toDid }; vcClaim.recipient = { identifier: toDid };
@ -870,12 +876,10 @@ export function hydrateOffer(
vcClaim.description = conditionDescription || undefined; vcClaim.description = conditionDescription || undefined;
if (amount && !isNaN(amount)) { if (amount && !isNaN(amount)) {
const quantitativeValue: QuantitativeValue = { vcClaim.includesObject = {
"@type": "QuantitativeValue",
amountOfThisGood: amount, amountOfThisGood: amount,
unitCode: unitCode || "HUR", unitCode: unitCode || "HUR",
}; };
vcClaim.object = quantitativeValue;
} }
if (itemDescription || fulfillsProjectHandleId) { if (itemDescription || fulfillsProjectHandleId) {
@ -928,7 +932,7 @@ export async function createAndSubmitOffer(
undefined, undefined,
); );
return createAndSubmitClaim( return createAndSubmitClaim(
vcClaim as OfferVerifiableCredential, vcClaim as OfferClaim,
issuerDid, issuerDid,
apiServer, apiServer,
axios, axios,
@ -938,7 +942,7 @@ export async function createAndSubmitOffer(
export async function editAndSubmitOffer( export async function editAndSubmitOffer(
axios: Axios, axios: Axios,
apiServer: string, apiServer: string,
fullClaim: GenericCredWrapper<OfferVerifiableCredential>, fullClaim: GenericCredWrapper<OfferClaim>,
issuerDid: string, issuerDid: string,
itemDescription: string, itemDescription: string,
amount?: number, amount?: number,
@ -961,7 +965,7 @@ export async function editAndSubmitOffer(
fullClaim.id, fullClaim.id,
); );
return createAndSubmitClaim( return createAndSubmitClaim(
vcClaim as OfferVerifiableCredential, vcClaim as OfferClaim,
issuerDid, issuerDid,
apiServer, apiServer,
axios, axios,
@ -1036,7 +1040,7 @@ export async function createAndSubmitClaim(
} }
export async function generateEndorserJwtUrlForAccount( export async function generateEndorserJwtUrlForAccount(
account: KeyMeta, account: KeyMetaMaybeWithPrivate,
isRegistered: boolean, isRegistered: boolean,
givenName: string, givenName: string,
profileImageUrl: string, profileImageUrl: string,
@ -1060,7 +1064,7 @@ export async function generateEndorserJwtUrlForAccount(
} }
// Add the next key -- not recommended for the QR code for such a high resolution // Add the next key -- not recommended for the QR code for such a high resolution
if (isContact) { if (isContact && account.derivationPath && account.mnemonic) {
const newDerivPath = nextDerivationPath(account.derivationPath); const newDerivPath = nextDerivationPath(account.derivationPath);
const nextPublicHex = deriveAddress(account.mnemonic, newDerivPath)[2]; const nextPublicHex = deriveAddress(account.mnemonic, newDerivPath)[2];
const nextPublicEncKey = Buffer.from(nextPublicHex, "hex"); const nextPublicEncKey = Buffer.from(nextPublicHex, "hex");
@ -1082,7 +1086,11 @@ export async function createEndorserJwtForDid(
expiresIn?: number, expiresIn?: number,
) { ) {
const account = await retrieveFullyDecryptedAccount(issuerDid); const account = await retrieveFullyDecryptedAccount(issuerDid);
return createEndorserJwtForKey(account as KeyMeta, payload, expiresIn); return createEndorserJwtForKey(
account as KeyMetaWithPrivate,
payload,
expiresIn,
);
} }
/** /**
@ -1179,102 +1187,118 @@ export const claimSpecialDescription = (
identifiers: Array<string>, identifiers: Array<string>,
contacts: Array<Contact>, contacts: Array<Contact>,
) => { ) => {
let claim = record.claim; let claim:
| GenericVerifiableCredential
| GenericCredWrapper<GenericVerifiableCredential> = record.claim;
if ("claim" in claim) { if ("claim" in claim) {
// it's a nested GenericCredWrapper
claim = claim.claim as GenericVerifiableCredential; claim = claim.claim as GenericVerifiableCredential;
} }
const issuer = didInfo(record.issuer, activeDid, identifiers, contacts); const issuer = didInfo(record.issuer, activeDid, identifiers, contacts);
const claimObj = claim as ClaimObject; const type = claim["@type"] || "UnknownType";
const type = claimObj["@type"] || "UnknownType";
if (type === "AgreeAction") { if (type === "AgreeAction") {
return ( return (
issuer + issuer +
" agreed with " + " agreed with " +
claimSummary(claimObj.object as GenericVerifiableCredential) claimSummary(claim.object as GenericVerifiableCredential)
); );
} else if (isAccept(claim)) { } else if (isAccept(claim)) {
return ( return (
issuer + issuer +
" accepted " + " accepted " +
claimSummary(claimObj.object as GenericVerifiableCredential) claimSummary(claim.object as GenericVerifiableCredential)
); );
} else if (type === "GiveAction") { } else if (type === "GiveAction") {
const giveClaim = claim as GiveVerifiableCredential; const giveClaim = claim as GiveActionClaim;
const agent: Agent = giveClaim.agent || { // @ts-expect-error because .did may be found in legacy data, before March 2023
identifier: undefined, const legacyGiverDid = giveClaim.agent?.did;
did: undefined, const giver = giveClaim.agent?.identifier || legacyGiverDid;
}; const giverInfo = didInfo(giver, activeDid, identifiers, contacts);
const agentDid = agent.did || agent.identifier; let gaveAmount = giveClaim.object?.amountOfThisGood
const contactInfo = agentDid ? displayAmount(
? didInfo(agentDid, activeDid, identifiers, contacts) giveClaim.object.unitCode as string,
: "someone"; giveClaim.object.amountOfThisGood as number,
const offering = giveClaim.object )
? " " + claimSummary(giveClaim.object)
: ""; : "";
const recipient = giveClaim.participant?.identifier; if (giveClaim.description) {
const recipientInfo = recipient if (gaveAmount) {
? " to " + didInfo(recipient, activeDid, identifiers, contacts) gaveAmount = gaveAmount + ", and also: ";
}
gaveAmount = gaveAmount + giveClaim.description;
}
if (!gaveAmount) {
gaveAmount = "something not described";
}
// @ts-expect-error because .did may be found in legacy data, before March 2023
const legacyRecipDid = giveClaim.recipient?.did;
const gaveRecipientId = giveClaim.recipient?.identifier || legacyRecipDid;
const gaveRecipientInfo = gaveRecipientId
? " to " + didInfo(gaveRecipientId, activeDid, identifiers, contacts)
: ""; : "";
return contactInfo + " gave" + offering + recipientInfo; return giverInfo + " gave" + gaveRecipientInfo + ": " + gaveAmount;
} else if (type === "JoinAction") { } else if (type === "JoinAction") {
const joinClaim = claim as ClaimObject; const joinClaim = claim as JoinActionClaim;
const agent: Agent = joinClaim.agent || { // @ts-expect-error because .did may be found in legacy data, before March 2023
identifier: undefined, const legacyDid = joinClaim.agent?.did;
did: undefined, const agent = joinClaim.agent?.identifier || legacyDid;
}; const contactInfo = didInfo(agent, activeDid, identifiers, contacts);
const agentDid = agent.did || agent.identifier;
const contactInfo = agentDid let eventOrganizer =
? didInfo(agentDid, activeDid, identifiers, contacts) joinClaim.event &&
: "someone"; joinClaim.event.organizer &&
const object = joinClaim.object as GenericVerifiableCredential; joinClaim.event.organizer.name;
const objectInfo = object ? " " + claimSummary(object) : ""; eventOrganizer = eventOrganizer || "";
return contactInfo + " joined" + objectInfo; let eventName = joinClaim.event && joinClaim.event.name;
eventName = eventName ? " " + eventName : "";
let fullEvent = eventOrganizer + eventName;
fullEvent = fullEvent ? " attended the " + fullEvent : "";
let eventDate = joinClaim.event && joinClaim.event.startTime;
eventDate = eventDate ? " at " + eventDate : "";
return contactInfo + fullEvent + eventDate;
} else if (isOffer(claim)) { } else if (isOffer(claim)) {
const offerClaim = claim as OfferVerifiableCredential; const offerClaim = claim as OfferClaim;
const agent: Agent = offerClaim.agent || { const offerer = offerClaim.offeredBy?.identifier;
identifier: undefined, const contactInfo = didInfo(offerer, activeDid, identifiers, contacts);
did: undefined, let offering = "";
}; if (offerClaim.includesObject) {
const agentDid = agent.did || agent.identifier; offering +=
const contactInfo = agentDid " " +
? didInfo(agentDid, activeDid, identifiers, contacts) displayAmount(
: "someone"; offerClaim.includesObject.unitCode,
const offering = offerClaim.object offerClaim.includesObject.amountOfThisGood,
? " " + claimSummary(offerClaim.object) );
: ""; }
const offerRecipientId = offerClaim.participant?.identifier; if (offerClaim.itemOffered?.description) {
offering += ", saying: " + offerClaim.itemOffered?.description;
}
// @ts-expect-error because .did may be found in legacy data, before March 2023
const legacyDid = offerClaim.recipient?.did;
const offerRecipientId = offerClaim.recipient?.identifier || legacyDid;
const offerRecipientInfo = offerRecipientId const offerRecipientInfo = offerRecipientId
? " to " + didInfo(offerRecipientId, activeDid, identifiers, contacts) ? " to " + didInfo(offerRecipientId, activeDid, identifiers, contacts)
: ""; : "";
return contactInfo + " offered" + offering + offerRecipientInfo; return contactInfo + " offered" + offering + offerRecipientInfo;
} else if (type === "PlanAction") { } else if (type === "PlanAction") {
const planClaim = claim as ClaimObject; const planClaim = claim as PlanActionClaim;
const agent: Agent = planClaim.agent || { const claimer = planClaim.agent?.identifier || record.issuer;
identifier: undefined, const claimerInfo = didInfo(claimer, activeDid, identifiers, contacts);
did: undefined, return claimerInfo + " announced a project: " + planClaim.name;
};
const agentDid = agent.did || agent.identifier;
const contactInfo = agentDid
? didInfo(agentDid, activeDid, identifiers, contacts)
: "someone";
const object = planClaim.object as GenericVerifiableCredential;
const objectInfo = object ? " " + claimSummary(object) : "";
return contactInfo + " planned" + objectInfo;
} else if (type === "Tenure") { } else if (type === "Tenure") {
const tenureClaim = claim as ClaimObject; const tenureClaim = claim as TenureClaim;
const agent: Agent = tenureClaim.agent || { // @ts-expect-error because .did may be found in legacy data, before March 2023
identifier: undefined, const legacyDid = tenureClaim.party?.did;
did: undefined, const claimer = tenureClaim.party?.identifier || legacyDid;
}; const contactInfo = didInfo(claimer, activeDid, identifiers, contacts);
const agentDid = agent.did || agent.identifier; const polygon = tenureClaim.spatialUnit?.geo?.polygon || "";
const contactInfo = agentDid return (
? didInfo(agentDid, activeDid, identifiers, contacts) contactInfo +
: "someone"; " possesses [" +
const object = tenureClaim.object as GenericVerifiableCredential; polygon.substring(0, polygon.indexOf(" ")) +
const objectInfo = object ? " " + claimSummary(object) : ""; "...]"
return contactInfo + " has tenure" + objectInfo; );
} else { } else {
return issuer + " declared " + claimSummary(claim); return issuer + " declared " + claimSummary(claim);
} }
@ -1331,7 +1355,7 @@ export async function createInviteJwt(
identifier?: string, identifier?: string,
expiresIn?: number, // in seconds expiresIn?: number, // in seconds
): Promise<string> { ): Promise<string> {
const vcClaim: RegisterVerifiableCredential = { const vcClaim: RegisterActionClaim = {
"@context": SCHEMA_ORG_CONTEXT, "@context": SCHEMA_ORG_CONTEXT,
"@type": "RegisterAction", "@type": "RegisterAction",
agent: { identifier: activeDid }, agent: { identifier: activeDid },

105
src/libs/util.ts

@ -34,10 +34,10 @@ import { containsHiddenDid } from "../libs/endorserServer";
import { import {
GenericCredWrapper, GenericCredWrapper,
GenericVerifiableCredential, GenericVerifiableCredential,
KeyMetaWithPrivate,
} from "../interfaces/common"; } from "../interfaces/common";
import { GiveSummaryRecord } from "../interfaces/records"; import { GiveSummaryRecord } from "../interfaces/records";
import { OfferVerifiableCredential } from "../interfaces/claims"; import { OfferClaim } from "../interfaces/claims";
import { KeyMeta } from "../interfaces/common";
import { createPeerDid } from "../libs/crypto/vc/didPeer"; import { createPeerDid } from "../libs/crypto/vc/didPeer";
import { registerCredential } from "../libs/crypto/vc/passkeyDidPeer"; import { registerCredential } from "../libs/crypto/vc/passkeyDidPeer";
import { logger } from "../utils/logger"; import { logger } from "../utils/logger";
@ -378,17 +378,19 @@ export function base64ToBlob(base64DataUrl: string, sliceSize = 512) {
* @param veriClaim is expected to have fields: claim and issuer * @param veriClaim is expected to have fields: claim and issuer
*/ */
export function offerGiverDid( export function offerGiverDid(
veriClaim: GenericCredWrapper<GenericVerifiableCredential>, veriClaim: GenericCredWrapper<OfferClaim>,
): string | undefined { ): string | undefined {
let giver; const innerClaim = veriClaim.claim as OfferClaim;
const claim = veriClaim.claim as OfferVerifiableCredential; let giver: string | undefined = undefined;
if (
claim.credentialSubject.offeredBy?.identifier && giver = innerClaim.offeredBy?.identifier;
!serverUtil.isHiddenDid(claim.credentialSubject.offeredBy.identifier) if (giver && !serverUtil.isHiddenDid(giver)) {
) { return giver;
giver = claim.credentialSubject.offeredBy.identifier; }
} else if (veriClaim.issuer && !serverUtil.isHiddenDid(veriClaim.issuer)) {
giver = veriClaim.issuer; giver = veriClaim.issuer;
if (giver && !serverUtil.isHiddenDid(giver)) {
return giver;
} }
return giver; return giver;
} }
@ -400,7 +402,10 @@ export function offerGiverDid(
export const canFulfillOffer = ( export const canFulfillOffer = (
veriClaim: GenericCredWrapper<GenericVerifiableCredential>, veriClaim: GenericCredWrapper<GenericVerifiableCredential>,
) => { ) => {
return veriClaim.claimType === "Offer" && !!offerGiverDid(veriClaim); return (
veriClaim.claimType === "Offer" &&
!!offerGiverDid(veriClaim as GenericCredWrapper<OfferClaim>)
);
}; };
// return object with paths and arrays of DIDs for any keys ending in "VisibleToDid" // return object with paths and arrays of DIDs for any keys ending in "VisibleToDid"
@ -469,11 +474,7 @@ export function findAllVisibleToDids(
* *
**/ **/
export interface AccountKeyInfo export type AccountKeyInfo = Account & KeyMetaWithPrivate;
extends Omit<Account, "derivationPath">,
Omit<KeyMeta, "derivationPath"> {
derivationPath?: string; // Make it optional to match Account type
}
export const retrieveAccountCount = async (): Promise<number> => { export const retrieveAccountCount = async (): Promise<number> => {
let result = 0; let result = 0;
@ -510,12 +511,16 @@ export const retrieveAccountDids = async (): Promise<string[]> => {
return allDids; return allDids;
}; };
// This is provided and recommended when the full key is not necessary so that /**
// future work could separate this info from the sensitive key material. * This is provided and recommended when the full key is not necessary so that
* future work could separate this info from the sensitive key material.
*
* If you need the private key data, use retrieveFullyDecryptedAccount instead.
*/
export const retrieveAccountMetadata = async ( export const retrieveAccountMetadata = async (
activeDid: string, activeDid: string,
): Promise<AccountKeyInfo | undefined> => { ): Promise<Account | undefined> => {
let result: AccountKeyInfo | undefined = undefined; let result: Account | undefined = undefined;
const platformService = PlatformServiceFactory.getInstance(); const platformService = PlatformServiceFactory.getInstance();
const dbAccount = await platformService.dbQuery( const dbAccount = await platformService.dbQuery(
`SELECT * FROM accounts WHERE did = ?`, `SELECT * FROM accounts WHERE did = ?`,
@ -547,32 +552,16 @@ export const retrieveAccountMetadata = async (
return result; return result;
}; };
export const retrieveAllAccountsMetadata = async (): Promise<Account[]> => { /**
const platformService = PlatformServiceFactory.getInstance(); * This contains sensitive data. If possible, use retrieveAccountMetadata instead.
const dbAccounts = await platformService.dbQuery(`SELECT * FROM accounts`); *
const accounts = databaseUtil.mapQueryResultToValues(dbAccounts) as Account[]; * @param activeDid
let result = accounts.map((account) => { * @returns account info with private key data decrypted
// eslint-disable-next-line @typescript-eslint/no-unused-vars */
const { identity, mnemonic, ...metadata } = account;
return metadata as Account;
});
if (USE_DEXIE_DB) {
// one of the few times we use accountsDBPromise directly; try to avoid more usage
const accountsDB = await accountsDBPromise;
const array = await accountsDB.accounts.toArray();
result = array.map((account) => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { identity, mnemonic, ...metadata } = account;
return metadata as Account;
});
}
return result;
};
export const retrieveFullyDecryptedAccount = async ( export const retrieveFullyDecryptedAccount = async (
activeDid: string, activeDid: string,
): Promise<AccountKeyInfo | undefined> => { ): Promise<Account | undefined> => {
let result: AccountKeyInfo | undefined = undefined; let result: Account | undefined = undefined;
const platformService = PlatformServiceFactory.getInstance(); const platformService = PlatformServiceFactory.getInstance();
const dbSecrets = await platformService.dbQuery( const dbSecrets = await platformService.dbQuery(
`SELECT secretBase64 from secret`, `SELECT secretBase64 from secret`,
@ -620,20 +609,26 @@ export const retrieveFullyDecryptedAccount = async (
return result; return result;
}; };
// let's try and eliminate this export const retrieveAllAccountsMetadata = async (): Promise<Account[]> => {
export const retrieveAllFullyDecryptedAccounts = async (): Promise<
Array<AccountEncrypted>
> => {
const platformService = PlatformServiceFactory.getInstance(); const platformService = PlatformServiceFactory.getInstance();
const queryResult = await platformService.dbQuery("SELECT * FROM accounts"); const dbAccounts = await platformService.dbQuery(`SELECT * FROM accounts`);
let allAccounts = databaseUtil.mapQueryResultToValues( const accounts = databaseUtil.mapQueryResultToValues(dbAccounts) as Account[];
queryResult, let result = accounts.map((account) => {
) as unknown as AccountEncrypted[]; // eslint-disable-next-line @typescript-eslint/no-unused-vars
const { identity, mnemonic, ...metadata } = account;
return metadata as Account;
});
if (USE_DEXIE_DB) { if (USE_DEXIE_DB) {
// one of the few times we use accountsDBPromise directly; try to avoid more usage
const accountsDB = await accountsDBPromise; const accountsDB = await accountsDBPromise;
allAccounts = (await accountsDB.accounts.toArray()) as AccountEncrypted[]; const array = await accountsDB.accounts.toArray();
result = array.map((account) => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { identity, mnemonic, ...metadata } = account;
return metadata as Account;
});
} }
return allAccounts; return result;
}; };
/** /**

8
src/views/ClaimView.vue

@ -548,11 +548,7 @@ import { db } from "../db/index";
import { logConsoleAndDb } from "../db/databaseUtil"; import { logConsoleAndDb } from "../db/databaseUtil";
import { Contact } from "../db/tables/contacts"; import { Contact } from "../db/tables/contacts";
import * as serverUtil from "../libs/endorserServer"; import * as serverUtil from "../libs/endorserServer";
import { import { GenericCredWrapper, OfferClaim, ProviderInfo } from "../interfaces";
GenericCredWrapper,
OfferVerifiableCredential,
ProviderInfo,
} from "../interfaces";
import * as libsUtil from "../libs/util"; import * as libsUtil from "../libs/util";
import { logger } from "../utils/logger"; import { logger } from "../utils/logger";
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory"; import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
@ -978,7 +974,7 @@ export default class ClaimView extends Vue {
openFulfillGiftDialog() { openFulfillGiftDialog() {
const giver: libsUtil.GiverReceiverInputInfo = { const giver: libsUtil.GiverReceiverInputInfo = {
did: libsUtil.offerGiverDid( did: libsUtil.offerGiverDid(
this.veriClaim as GenericCredWrapper<OfferVerifiableCredential>, this.veriClaim as GenericCredWrapper<OfferClaim>,
), ),
}; };
(this.$refs.customGiveDialog as GiftedDialog).open( (this.$refs.customGiveDialog as GiftedDialog).open(

4
src/views/ContactAmountsView.vue

@ -124,7 +124,7 @@ import * as databaseUtil from "../db/databaseUtil";
import { import {
AgreeVerifiableCredential, AgreeVerifiableCredential,
GiveSummaryRecord, GiveSummaryRecord,
GiveVerifiableCredential, GiveActionClaim,
} from "../interfaces"; } from "../interfaces";
import { import {
createEndorserJwtVcFromClaim, createEndorserJwtVcFromClaim,
@ -276,7 +276,7 @@ export default class ContactAmountssView extends Vue {
// Make claim // Make claim
// I use clone here because otherwise it gets a Proxy object. // I use clone here because otherwise it gets a Proxy object.
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
const origClaim: GiveVerifiableCredential = R.clone(record.fullClaim); const origClaim: GiveActionClaim = R.clone(record.fullClaim);
if (record.fullClaim["@context"] == SCHEMA_ORG_CONTEXT) { if (record.fullClaim["@context"] == SCHEMA_ORG_CONTEXT) {
delete origClaim["@context"]; delete origClaim["@context"];
} }

8
src/views/DIDView.vue

@ -240,8 +240,8 @@ import * as databaseUtil from "../db/databaseUtil";
import { import {
GenericCredWrapper, GenericCredWrapper,
GenericVerifiableCredential, GenericVerifiableCredential,
GiveVerifiableCredential, GiveActionClaim,
OfferVerifiableCredential, OfferClaim,
} from "../interfaces"; } from "../interfaces";
import { import {
capitalizeAndInsertSpacesBeforeCaps, capitalizeAndInsertSpacesBeforeCaps,
@ -657,7 +657,7 @@ export default class DIDView extends Vue {
*/ */
public claimAmount(claim: GenericVerifiableCredential) { public claimAmount(claim: GenericVerifiableCredential) {
if (claim.claimType === "GiveAction") { if (claim.claimType === "GiveAction") {
const giveClaim = claim.claim as GiveVerifiableCredential; const giveClaim = claim.claim as GiveActionClaim;
if (giveClaim.object?.unitCode && giveClaim.object?.amountOfThisGood) { if (giveClaim.object?.unitCode && giveClaim.object?.amountOfThisGood) {
return displayAmount( return displayAmount(
giveClaim.object.unitCode, giveClaim.object.unitCode,
@ -667,7 +667,7 @@ export default class DIDView extends Vue {
return ""; return "";
} }
} else if (claim.claimType === "Offer") { } else if (claim.claimType === "Offer") {
const offerClaim = claim.claim as OfferVerifiableCredential; const offerClaim = claim.claim as OfferClaim;
if ( if (
offerClaim.includesObject?.unitCode && offerClaim.includesObject?.unitCode &&
offerClaim.includesObject?.amountOfThisGood offerClaim.includesObject?.amountOfThisGood

8
src/views/GiftedDetailsView.vue

@ -268,7 +268,7 @@ import {
} from "../constants/app"; } from "../constants/app";
import { db, retrieveSettingsForActiveAccount } from "../db/index"; import { db, retrieveSettingsForActiveAccount } from "../db/index";
import * as databaseUtil from "../db/databaseUtil"; import * as databaseUtil from "../db/databaseUtil";
import { GenericCredWrapper, GiveVerifiableCredential } from "../interfaces"; import { GenericCredWrapper, GiveActionClaim } from "../interfaces";
import { import {
createAndSubmitGive, createAndSubmitGive,
didInfo, didInfo,
@ -311,7 +311,7 @@ export default class GiftedDetails extends Vue {
imageUrl = ""; imageUrl = "";
message = ""; message = "";
offerId = ""; offerId = "";
prevCredToEdit?: GenericCredWrapper<GiveVerifiableCredential>; prevCredToEdit?: GenericCredWrapper<GiveActionClaim>;
providerProjectId = ""; providerProjectId = "";
providerProjectName = "a project"; providerProjectName = "a project";
providedByProject = false; // basically static, based on input; if we allow changing then let's fix things (see below) providedByProject = false; // basically static, based on input; if we allow changing then let's fix things (see below)
@ -328,7 +328,7 @@ export default class GiftedDetails extends Vue {
this.prevCredToEdit = (this.$route.query["prevCredToEdit"] as string) this.prevCredToEdit = (this.$route.query["prevCredToEdit"] as string)
? (JSON.parse( ? (JSON.parse(
this.$route.query["prevCredToEdit"] as string, this.$route.query["prevCredToEdit"] as string,
) as GenericCredWrapper<GiveVerifiableCredential>) ) as GenericCredWrapper<GiveActionClaim>)
: undefined; : undefined;
} catch (error) { } catch (error) {
this.$notify( this.$notify(
@ -883,7 +883,7 @@ export default class GiftedDetails extends Vue {
? this.fulfillsProjectId ? this.fulfillsProjectId
: undefined; : undefined;
const giveClaim = hydrateGive( const giveClaim = hydrateGive(
this.prevCredToEdit?.claim as GiveVerifiableCredential, this.prevCredToEdit?.claim as GiveActionClaim,
giverDid, giverDid,
recipientDid, recipientDid,
this.description, this.description,

11
src/views/IdentitySwitcherView.vue

@ -115,6 +115,7 @@ import { MASTER_SETTINGS_KEY } from "../db/tables/settings";
import * as databaseUtil from "../db/databaseUtil"; import * as databaseUtil from "../db/databaseUtil";
import { retrieveAllAccountsMetadata } from "../libs/util"; import { retrieveAllAccountsMetadata } from "../libs/util";
import { logger } from "../utils/logger"; import { logger } from "../utils/logger";
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
@Component({ components: { QuickNav } }) @Component({ components: { QuickNav } })
export default class IdentitySwitcherView extends Vue { export default class IdentitySwitcherView extends Vue {
@ -167,10 +168,13 @@ export default class IdentitySwitcherView extends Vue {
if (did === "0") { if (did === "0") {
did = undefined; did = undefined;
} }
await databaseUtil.updateDefaultSettings({ activeDid: did });
if (USE_DEXIE_DB) {
await db.open(); await db.open();
await db.settings.update(MASTER_SETTINGS_KEY, { await db.settings.update(MASTER_SETTINGS_KEY, {
activeDid: did, activeDid: did,
}); });
}
this.$router.push({ name: "account" }); this.$router.push({ name: "account" });
} }
@ -182,9 +186,16 @@ export default class IdentitySwitcherView extends Vue {
title: "Delete Identity?", title: "Delete Identity?",
text: "Are you sure you want to erase this identity? (There is no undo. You may want to select it and back it up just in case.)", text: "Are you sure you want to erase this identity? (There is no undo. You may want to select it and back it up just in case.)",
onYes: async () => { onYes: async () => {
const platformService = PlatformServiceFactory.getInstance();
await platformService.dbExec(
`DELETE FROM accounts WHERE id = ?`,
[id],
);
if (USE_DEXIE_DB) {
// one of the few times we use accountsDBPromise directly; try to avoid more usage // one of the few times we use accountsDBPromise directly; try to avoid more usage
const accountsDB = await accountsDBPromise; const accountsDB = await accountsDBPromise;
await accountsDB.accounts.delete(id); await accountsDB.accounts.delete(id);
}
this.otherIdentities = this.otherIdentities.filter( this.otherIdentities = this.otherIdentities.filter(
(ident) => ident.id !== id, (ident) => ident.id !== id,
); );

8
src/views/OfferDetailsView.vue

@ -182,7 +182,7 @@ import QuickNav from "../components/QuickNav.vue";
import TopMessage from "../components/TopMessage.vue"; import TopMessage from "../components/TopMessage.vue";
import { NotificationIface, USE_DEXIE_DB } from "../constants/app"; import { NotificationIface, USE_DEXIE_DB } from "../constants/app";
import { db, retrieveSettingsForActiveAccount } from "../db/index"; import { db, retrieveSettingsForActiveAccount } from "../db/index";
import { GenericCredWrapper, OfferVerifiableCredential } from "../interfaces"; import { GenericCredWrapper, OfferClaim } from "../interfaces";
import { import {
createAndSubmitOffer, createAndSubmitOffer,
didInfo, didInfo,
@ -268,7 +268,7 @@ export default class OfferDetailsView extends Vue {
/** Offer ID for editing */ /** Offer ID for editing */
offerId = ""; offerId = "";
/** Previous offer data for editing */ /** Previous offer data for editing */
prevCredToEdit?: GenericCredWrapper<OfferVerifiableCredential>; prevCredToEdit?: GenericCredWrapper<OfferClaim>;
/** Project ID if offer is for project */ /** Project ID if offer is for project */
projectId = ""; projectId = "";
/** Project name display */ /** Project name display */
@ -330,7 +330,7 @@ export default class OfferDetailsView extends Vue {
this.prevCredToEdit = (this.$route.query["prevCredToEdit"] as string) this.prevCredToEdit = (this.$route.query["prevCredToEdit"] as string)
? (JSON.parse( ? (JSON.parse(
this.$route.query["prevCredToEdit"] as string, this.$route.query["prevCredToEdit"] as string,
) as GenericCredWrapper<OfferVerifiableCredential>) ) as GenericCredWrapper<OfferClaim>)
: undefined; : undefined;
} catch (error: unknown) { } catch (error: unknown) {
this.$notify( this.$notify(
@ -768,7 +768,7 @@ export default class OfferDetailsView extends Vue {
: undefined; : undefined;
const projectId = this.offeredToProject ? this.projectId : undefined; const projectId = this.offeredToProject ? this.projectId : undefined;
const offerClaim = hydrateOffer( const offerClaim = hydrateOffer(
this.prevCredToEdit?.claim as OfferVerifiableCredential, this.prevCredToEdit?.claim as OfferClaim,
this.activeDid, this.activeDid,
recipientDid, recipientDid,
this.descriptionOfItem, this.descriptionOfItem,

12
src/views/ProjectViewView.vue

@ -613,9 +613,9 @@ import {
GenericVerifiableCredential, GenericVerifiableCredential,
GenericCredWrapper, GenericCredWrapper,
GiveSummaryRecord, GiveSummaryRecord,
GiveVerifiableCredential, GiveActionClaim,
OfferSummaryRecord, OfferSummaryRecord,
OfferVerifiableCredential, OfferClaim,
PlanSummaryRecord, PlanSummaryRecord,
} from "../interfaces"; } from "../interfaces";
import GiftedDialog from "../components/GiftedDialog.vue"; import GiftedDialog from "../components/GiftedDialog.vue";
@ -1269,7 +1269,7 @@ export default class ProjectViewView extends Vue {
} }
checkIsFulfillable(offer: OfferSummaryRecord) { checkIsFulfillable(offer: OfferSummaryRecord) {
const offerRecord: GenericCredWrapper<OfferVerifiableCredential> = { const offerRecord: GenericCredWrapper<OfferClaim> = {
...serverUtil.BLANK_GENERIC_SERVER_RECORD, ...serverUtil.BLANK_GENERIC_SERVER_RECORD,
claim: offer.fullClaim, claim: offer.fullClaim,
claimType: "Offer", claimType: "Offer",
@ -1279,13 +1279,13 @@ export default class ProjectViewView extends Vue {
} }
onClickFulfillGiveToOffer(offer: OfferSummaryRecord) { onClickFulfillGiveToOffer(offer: OfferSummaryRecord) {
const offerRecord: GenericCredWrapper<OfferVerifiableCredential> = { const offerClaimCred: GenericCredWrapper<OfferClaim> = {
...serverUtil.BLANK_GENERIC_SERVER_RECORD, ...serverUtil.BLANK_GENERIC_SERVER_RECORD,
claim: offer.fullClaim, claim: offer.fullClaim,
issuer: offer.offeredByDid, issuer: offer.offeredByDid,
}; };
const giver: libsUtil.GiverReceiverInputInfo = { const giver: libsUtil.GiverReceiverInputInfo = {
did: libsUtil.offerGiverDid(offerRecord), did: libsUtil.offerGiverDid(offerClaimCred),
}; };
(this.$refs.giveDialogToThis as GiftedDialog).open( (this.$refs.giveDialogToThis as GiftedDialog).open(
giver, giver,
@ -1327,7 +1327,7 @@ export default class ProjectViewView extends Vue {
* @param confirmerIdList optional list of DIDs who confirmed; if missing, doesn't do a full server check * @param confirmerIdList optional list of DIDs who confirmed; if missing, doesn't do a full server check
*/ */
checkIsConfirmable(give: GiveSummaryRecord, confirmerIdList?: string[]) { checkIsConfirmable(give: GiveSummaryRecord, confirmerIdList?: string[]) {
const giveDetails: GenericCredWrapper<GiveVerifiableCredential> = { const giveDetails: GenericCredWrapper<GiveActionClaim> = {
...serverUtil.BLANK_GENERIC_SERVER_RECORD, ...serverUtil.BLANK_GENERIC_SERVER_RECORD,
claim: give.fullClaim, claim: give.fullClaim,
claimType: "GiveAction", claimType: "GiveAction",

4
src/views/ShareMyContactInfoView.vue

@ -49,7 +49,7 @@ import TopMessage from "../components/TopMessage.vue";
import { NotificationIface, APP_SERVER, USE_DEXIE_DB } from "../constants/app"; import { NotificationIface, APP_SERVER, USE_DEXIE_DB } from "../constants/app";
import * as databaseUtil from "../db/databaseUtil"; import * as databaseUtil from "../db/databaseUtil";
import { db, retrieveSettingsForActiveAccount } from "../db/index"; import { db, retrieveSettingsForActiveAccount } from "../db/index";
import { retrieveAccountMetadata } from "../libs/util"; import { retrieveFullyDecryptedAccount } from "../libs/util";
import { generateEndorserJwtUrlForAccount } from "../libs/endorserServer"; import { generateEndorserJwtUrlForAccount } from "../libs/endorserServer";
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory"; import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
import { logger } from "../utils/logger"; import { logger } from "../utils/logger";
@ -75,7 +75,7 @@ export default class ShareMyContactInfoView extends Vue {
const isRegistered = !!settings.isRegistered; const isRegistered = !!settings.isRegistered;
const profileImageUrl = settings.profileImageUrl || ""; const profileImageUrl = settings.profileImageUrl || "";
const account = await retrieveAccountMetadata(activeDid); const account = await retrieveFullyDecryptedAccount(activeDid);
const platformService = PlatformServiceFactory.getInstance(); const platformService = PlatformServiceFactory.getInstance();
const contactQueryResult = await platformService.dbQuery( const contactQueryResult = await platformService.dbQuery(

1
test-playwright/60-new-activity.spec.ts

@ -44,7 +44,6 @@ test('New offers for another user', async ({ page }) => {
// as user 1, go to the home page and check that two offers are shown as new // as user 1, go to the home page and check that two offers are shown as new
await switchToUser(page, user01Did); await switchToUser(page, user01Did);
await page.goto('./'); await page.goto('./');
// await page.getByTestId('closeOnboardingAndFinish').click();
let offerNumElem = page.getByTestId('newDirectOffersActivityNumber'); let offerNumElem = page.getByTestId('newDirectOffersActivityNumber');
await expect(offerNumElem).toHaveText('2'); await expect(offerNumElem).toHaveText('2');

Loading…
Cancel
Save