diff --git a/src/libs/endorserServer.ts b/src/libs/endorserServer.ts index a06d8fa2..cab9cf8e 100644 --- a/src/libs/endorserServer.ts +++ b/src/libs/endorserServer.ts @@ -70,7 +70,7 @@ export interface RegisterVerifiableCredential { "@type": string; agent: { identifier: string }; object: string; - recipient: { identifier: string }; + participant: { identifier: string }; } export interface InternalError { @@ -122,7 +122,7 @@ interface ErrorResult { error: InternalError; } -type CreateAndSubmitGiveResult = SuccessResult | ErrorResult; +export type CreateAndSubmitGiveResult = SuccessResult | ErrorResult; /** * For result, see https://api.endorser.ch/api-docs/#/claims/post_api_v2_claim diff --git a/src/views/AccountViewView.vue b/src/views/AccountViewView.vue index c69968e2..9dbdd18a 100644 --- a/src/views/AccountViewView.vue +++ b/src/views/AccountViewView.vue @@ -517,7 +517,7 @@ export default class AccountViewView extends Vue { if (resp.status === 200) { this.limits = resp.data; } - } catch (error: unknown) { + } catch (error: any) { if ( error.message === "Attempted to load Give records with no identity available." @@ -528,13 +528,9 @@ export default class AccountViewView extends Vue { const serverError = error as AxiosError; console.error("Bad response retrieving limits: ", serverError); - const data: ErrorResponse | undefined = - serverError.response && serverError.response.data; - if (data && data.error && data.error.message) { - this.limitsMessage = data.error.message; - } else { - this.limitsMessage = "Bad server response."; - } + const data = (serverError.response && + serverError.response.data) as ErrorResponse; + this.limitsMessage = data?.error?.message || "Bad server response."; } } diff --git a/src/views/ContactAmountsView.vue b/src/views/ContactAmountsView.vue index 9c956b31..cafd495e 100644 --- a/src/views/ContactAmountsView.vue +++ b/src/views/ContactAmountsView.vue @@ -190,7 +190,7 @@ export default class ContactsView extends Vue { async loadGives(activeDid: string, contact: Contact) { try { const identity = await this.getIdentity(this.activeDid); - let result = []; + let result: Array = []; const url = this.apiServer + "/api/v2/report/gives?agentDid=" + diff --git a/src/views/ContactGiftingView.vue b/src/views/ContactGiftingView.vue index b3bf0be5..0888c9d8 100644 --- a/src/views/ContactGiftingView.vue +++ b/src/views/ContactGiftingView.vue @@ -88,10 +88,10 @@ import { MASTER_SETTINGS_KEY } from "@/db/tables/settings"; import { accessToken } from "@/libs/crypto"; import { createAndSubmitGive, + CreateAndSubmitGiveResult, GiverInputInfo, GiverOutputInfo, } from "@/libs/endorserServer"; -import { Account } from "@/db/tables/accounts"; import { Contact } from "@/db/tables/contacts"; import QuickNav from "@/components/QuickNav"; import EntityIcon from "@/components/EntityIcon"; @@ -112,18 +112,14 @@ export default class HomeView extends Vue { $notify!: (notification: Notification, timeout?: number) => void; activeDid = ""; - allAccounts: Array = []; allContacts: Array = []; apiServer = ""; - feedLastViewedId = ""; - isHiddenSpinner = true; accounts: typeof AccountsSchema; numAccounts = 0; async beforeCreate() { accountsDB.open(); - this.accounts = accountsDB.accounts; - this.numAccounts = await this.accounts.count(); + this.numAccounts = await accountsDB.accounts.count(); } public async getIdentity(activeDid: string) { @@ -153,15 +149,11 @@ export default class HomeView extends Vue { async created() { try { - await accountsDB.open(); - this.allAccounts = await accountsDB.accounts.toArray(); await db.open(); const settings = await db.settings.get(MASTER_SETTINGS_KEY); this.apiServer = settings?.apiServer || ""; this.activeDid = settings?.activeDid || ""; this.allContacts = await db.contacts.toArray(); - this.feedLastViewedId = settings?.lastViewedClaimId; - this.updateAllFeed(); } catch (err) { this.$notify( { @@ -177,30 +169,6 @@ export default class HomeView extends Vue { } } - public async buildHeaders() { - const headers: RawAxiosRequestHeaders = { - "Content-Type": "application/json", - }; - - if (this.activeDid) { - await accountsDB.open(); - const allAccounts = await accountsDB.accounts.toArray(); - const account = allAccounts.find((acc) => acc.did === this.activeDid); - const identity = JSON.parse(account?.identity || "null"); - - if (!identity) { - throw new Error( - "An ID is chosen but there are no keys for it so it cannot be used to talk with the service.", - ); - } - - headers["Authorization"] = "Bearer " + (await accessToken(identity)); - } else { - // it's OK without auth... we just won't get any identifiers - } - return headers; - } - openDialog(giver: GiverInputInfo) { this.$refs.customDialog.open(giver); } @@ -208,8 +176,13 @@ export default class HomeView extends Vue { handleDialogResult(result: GiverOutputInfo) { if (result.action === "confirm") { return new Promise((resolve) => { - this.recordGive(result.contact?.did, result.description, result.hours); - resolve(); + this.recordGive( + result.giver?.did, + result.description, + result.hours, + ).then(() => { + resolve(null); + }); }); } else { // action was "cancel" so do nothing @@ -288,7 +261,7 @@ export default class HomeView extends Vue { -1, ); } - } catch (error) { + } catch (error: any) { console.log("Error with give caught:", error); this.$notify( { @@ -306,15 +279,15 @@ export default class HomeView extends Vue { // Helper functions for readability - isGiveCreationError(result) { - return result.status !== 201 || result.data?.error; + isGiveCreationError(result: CreateAndSubmitGiveResult) { + return result.response?.status !== 201 || result.response?.data?.error; } - getGiveCreationErrorMessage(result) { - return result.data?.error?.message; + getGiveCreationErrorMessage(result: CreateAndSubmitGiveResult) { + return result.response?.data?.error?.message; } - getGiveErrorMessage(error) { + getGiveErrorMessage(error: any) { return error.userMessage || error.response?.data?.error?.message; } } diff --git a/src/views/ContactQRScanShowView.vue b/src/views/ContactQRScanShowView.vue index cdcb9f6f..66c2de64 100644 --- a/src/views/ContactQRScanShowView.vue +++ b/src/views/ContactQRScanShowView.vue @@ -54,7 +54,7 @@ export default class ContactQRScanShow extends Vue { apiServer = ""; qrValue = ""; - public async getIdentity(activeDid) { + public async getIdentity(activeDid: string) { await accountsDB.open(); const accounts = await accountsDB.accounts.toArray(); const account: Account | undefined = R.find( diff --git a/src/views/ContactsView.vue b/src/views/ContactsView.vue index e8b8f04e..e878d25f 100644 --- a/src/views/ContactsView.vue +++ b/src/views/ContactsView.vue @@ -215,6 +215,7 @@ import { Contact } from "@/db/tables/contacts"; import { MASTER_SETTINGS_KEY } from "@/db/tables/settings"; import { accessToken, SimpleSigner } from "@/libs/crypto"; import { + GiveServerRecord, GiveVerifiableCredential, RegisterVerifiableCredential, SERVICE_ID, @@ -310,11 +311,11 @@ export default class ContactsView extends Vue { async loadGives() { const handleResponse = ( - resp, - descriptions, - confirmed, - unconfirmed, - useRecipient, + resp: { status: number; data: { data: GiveServerRecord[] } }, + descriptions: Record, + confirmed: Record, + unconfirmed: Record, + useRecipient: boolean, ) => { if (resp.status === 200) { const allData = resp.data.data; @@ -346,9 +347,8 @@ export default class ContactsView extends Vue { title: "Error With Server", text: "Got an error retrieving your " + - resp.config.url.includes("recipientDid") - ? "received" - : "given" + " time from the server.", + (useRecipient ? "given" : "received") + + " time from the server.", }, -1, ); @@ -610,6 +610,8 @@ export default class ContactsView extends Vue { this.apiServer + "/api/report/canDidExplicitlySeeMe?did=" + encodeURIComponent(contact.did); + const identity = await this.getIdentity(this.activeDid); + const headers = await this.getHeaders(identity); try { const resp = await this.axios.get(url, { headers }); diff --git a/src/views/DiscoverView.vue b/src/views/DiscoverView.vue index a893ffe3..9def8ceb 100644 --- a/src/views/DiscoverView.vue +++ b/src/views/DiscoverView.vue @@ -202,6 +202,7 @@ import { didInfo, ProjectData } from "@/libs/endorserServer"; import QuickNav from "@/components/QuickNav"; import InfiniteScroll from "@/components/InfiniteScroll"; import EntityIcon from "@/components/EntityIcon"; +import { RawAxiosRequestHeaders } from "axios"; const DEFAULT_LAT_LONG_DIFF = 0.01; const WORLD_ZOOM = 2; @@ -268,8 +269,10 @@ export default class DiscoverView extends Vue { this.searchLocal(); } - public async buildHeaders() { - const headers = { "Content-Type": "application/json" }; + public async buildHeaders(): Promise { + const headers: HeadersInit = { + "Content-Type": "application/json", + }; if (this.activeDid) { await accountsDB.open(); @@ -327,8 +330,8 @@ export default class DiscoverView extends Vue { const plans: ProjectData[] = results.data; if (plans) { for (const plan of plans) { - const { name, description, handleId, rowid, issuerDid } = plan; - this.projects.push({ name, description, handleId, rowid, issuerDid }); + const { name, description, handleId, rowid } = plan; + this.projects.push({ name, description, handleId, rowid }); } this.remoteCount = this.projects.length; } else { diff --git a/src/views/HomeView.vue b/src/views/HomeView.vue index d0e3688d..273e5719 100644 --- a/src/views/HomeView.vue +++ b/src/views/HomeView.vue @@ -210,6 +210,7 @@ import { didInfo, GiverInputInfo, GiverOutputInfo, + GiveServerRecord, } from "@/libs/endorserServer"; import { Contact } from "@/db/tables/contacts"; import QuickNav from "@/components/QuickNav"; @@ -236,7 +237,7 @@ export default class HomeView extends Vue { apiServer = ""; feedAllLoaded = false; feedData = []; - feedPreviousOldestId = null; + feedPreviousOldestId?: string; feedLastViewedId?: string; isHiddenSpinner = true; numAccounts = 0; @@ -300,7 +301,7 @@ export default class HomeView extends Vue { } public async buildHeaders() { - const headers: RawAxiosRequestHeaders = { + const headers: HeadersInit = { "Content-Type": "application/json", }; @@ -325,7 +326,7 @@ export default class HomeView extends Vue { public async updateAllFeed() { this.isHiddenSpinner = false; - await this.retrieveClaims(this.apiServer, null, this.feedPreviousOldestId) + await this.retrieveClaims(this.apiServer, this.feedPreviousOldestId) .then(async (results) => { if (results.data.length > 0) { this.feedData = this.feedData.concat(results.data); @@ -360,7 +361,7 @@ export default class HomeView extends Vue { this.isHiddenSpinner = true; } - public async retrieveClaims(endorserApiServer, identifier, beforeId) { + public async retrieveClaims(endorserApiServer: string, beforeId?: string) { const beforeQuery = beforeId == null ? "" : "&beforeId=" + beforeId; const response = await fetch( endorserApiServer + "/api/v2/report/gives?" + beforeQuery, @@ -383,13 +384,14 @@ export default class HomeView extends Vue { } } - giveDescription(giveRecord) { + giveDescription(giveRecord: GiveServerRecord) { let claim = giveRecord.fullClaim; - if (claim.claim) { - claim = claim.claim; + if ((claim as any).claim) { + // can happen for some claims wrapped in a Verifiable Credential + claim = (claim as any).claim; } // agent.did is for legacy data, before March 2023 - const giverDid = claim.agent?.identifier || claim.agent?.did; + const giverDid = claim.agent?.identifier || (claim.agent as any)?.did; const giverInfo = didInfo( giverDid, this.activeDid, @@ -400,7 +402,8 @@ export default class HomeView extends Vue { ? this.displayAmount(claim.object.unitCode, claim.object.amountOfThisGood) : claim.description || "something unknown"; // recipient.did is for legacy data, before March 2023 - const gaveRecipientId = claim.recipient?.identifier || claim.recipient?.did; + const gaveRecipientId = + claim.recipient?.identifier || (claim.recipient as any)?.did; const gaveRecipientInfo = gaveRecipientId ? " to " + didInfo( @@ -417,7 +420,7 @@ export default class HomeView extends Vue { return "" + amt + " " + this.currencyShortWordForCode(code, amt === 1); } - currencyShortWordForCode(unitCode: string, single: number) { + currencyShortWordForCode(unitCode: string, single: boolean) { return unitCode === "HUR" ? (single ? "hour" : "hours") : unitCode; } @@ -425,11 +428,16 @@ export default class HomeView extends Vue { this.$refs.customDialog.open(giver); } - handleDialogResult(result: GiverInputInfo) { + handleDialogResult(result: GiverOutputInfo) { if (result.action === "confirm") { return new Promise((resolve) => { - this.recordGive(result.giver?.did, result.description, result.hours); - resolve(); + this.recordGive( + result.giver?.did, + result.description, + result.hours, + ).then(() => { + resolve(null); + }); }); } else { // action was "cancel" so do nothing @@ -445,7 +453,7 @@ export default class HomeView extends Vue { public async recordGive( giverDid?: string, description?: string, - hours?: string, + hours?: number, ) { if (!this.activeDid) { this.$notify( @@ -482,7 +490,7 @@ export default class HomeView extends Vue { giverDid, this.activeDid, description, - hours ? parseFloat(hours) : undefined, + hours, ); if (this.isGiveCreationError(result)) { diff --git a/src/views/IdentitySwitcherView.vue b/src/views/IdentitySwitcherView.vue index 2ab28e7c..34eff21e 100644 --- a/src/views/IdentitySwitcherView.vue +++ b/src/views/IdentitySwitcherView.vue @@ -84,11 +84,14 @@ export default class IdentitySwitcherView extends Vue { $notify!: (notification: Notification, timeout?: number) => void; Constants = AppString; - public accounts: AccountsSchema; + public accounts: typeof AccountsSchema; public activeDid = ""; + public apiServer = ""; + public apiServerInput = ""; public firstName = ""; public lastName = ""; - public otherIdentities = []; + public otherIdentities: Array<{ did: string }> = []; + public showContactGives = false; public async getIdentity(activeDid: string) { await accountsDB.open(); @@ -127,27 +130,16 @@ export default class IdentitySwitcherView extends Vue { } } } catch (err) { - if ( - err?.message === - "Attempted to load account records with no identity available." - ) { - this.limitsMessage = "No identity."; - this.loadingLimits = false; - } else { - this.$notify( - { - group: "alert", - type: "danger", - title: "Error Creating Account", - text: "Clear your cache and start over (after data backup).", - }, - -1, - ); - console.error( - "Telling user to clear cache at page create because:", - err, - ); - } + this.$notify( + { + group: "alert", + type: "danger", + title: "Error Loading Accounts", + text: "Clear your cache and start over (after data backup).", + }, + -1, + ); + console.error("Telling user to clear cache at page create because:", err); } } @@ -160,7 +152,7 @@ export default class IdentitySwitcherView extends Vue { db.settings.update(MASTER_SETTINGS_KEY, { activeDid: did, }); - this.activeDid = did; + this.activeDid = did || ""; this.otherIdentities = []; await accountsDB.open(); const accounts = await accountsDB.accounts.toArray(); diff --git a/src/views/ImportDerivedAccountView.vue b/src/views/ImportDerivedAccountView.vue index 7155acd0..b542a565 100644 --- a/src/views/ImportDerivedAccountView.vue +++ b/src/views/ImportDerivedAccountView.vue @@ -87,7 +87,7 @@ export default class ImportAccountView extends Vue { async mounted() { await accountsDB.open(); const accounts = await accountsDB.accounts.toArray(); - const seedDids = {}; + const seedDids: Record> = {}; accounts.forEach((account) => { const prevDids: Array = seedDids[account.mnemonic] || []; seedDids[account.mnemonic] = prevDids.concat([account.did]);