You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
163 lines
5.5 KiB
163 lines
5.5 KiB
// many of these are also found in endorser-mobile utility.ts
|
|
|
|
import axios, { AxiosResponse } from "axios";
|
|
|
|
import { DEFAULT_PUSH_SERVER } from "@/constants/app";
|
|
import { accountsDB, db } from "@/db/index";
|
|
import { MASTER_SETTINGS_KEY } from "@/db/tables/settings";
|
|
import { deriveAddress, generateSeed, newIdentifier } from "@/libs/crypto";
|
|
import { GenericServerRecord, containsHiddenDid } from "@/libs/endorserServer";
|
|
import * as serverUtil from "@/libs/endorserServer";
|
|
import { useClipboard } from "@vueuse/core";
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
const Buffer = require("buffer/").Buffer;
|
|
|
|
export const isGlobalUri = (uri: string) => {
|
|
return uri && uri.match(new RegExp(/^[A-Za-z][A-Za-z0-9+.-]+:/));
|
|
};
|
|
|
|
// If you edit this, check that the numbers still line up on the side in the alert (on mobile, too),
|
|
// and make sure they can take all actions while the notification shows.
|
|
export const ONBOARD_MESSAGE =
|
|
"1) Check that they have entered their name on the profile page in their device. 2) Add them to your Contacts by scanning with the QR icon that is by the input box. 3) Click the person icon to register them. 4) Have them go to their Contact page and scan your QR to add you to their list.";
|
|
|
|
export const giveIsConfirmable = (veriClaim: GenericServerRecord) => {
|
|
return veriClaim.claimType === "GiveAction";
|
|
};
|
|
|
|
export const doCopyTwoSecRedo = (text: string, fn: () => void) => {
|
|
fn();
|
|
useClipboard()
|
|
.copy(text)
|
|
.then(() => setTimeout(fn, 2000));
|
|
};
|
|
|
|
/**
|
|
* @returns true if the user can confirm the claim
|
|
* @param veriClaim is expected to have fields: claim, claimType, and issuer
|
|
*/
|
|
export const giveRecordTheUserCanConfirm = (
|
|
veriClaim: GenericServerRecord,
|
|
activeDid: string,
|
|
confirmerIdList: string[] = [],
|
|
) => {
|
|
return (
|
|
giveIsConfirmable(veriClaim) &&
|
|
!confirmerIdList.includes(activeDid) &&
|
|
veriClaim.issuer !== activeDid &&
|
|
!containsHiddenDid(veriClaim.claim)
|
|
);
|
|
};
|
|
|
|
/**
|
|
* @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) => {
|
|
let giver;
|
|
if (
|
|
veriClaim.claim.offeredBy?.identifier &&
|
|
!serverUtil.isHiddenDid(veriClaim.claim.offeredBy.identifier as string)
|
|
) {
|
|
giver = veriClaim.claim.offeredBy.identifier;
|
|
} else if (veriClaim.issuer && !serverUtil.isHiddenDid(veriClaim.issuer)) {
|
|
giver = veriClaim.issuer;
|
|
}
|
|
return giver;
|
|
};
|
|
|
|
/**
|
|
* @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) => {
|
|
return !!(veriClaim.claimType === "Offer" && offerGiverDid(veriClaim));
|
|
};
|
|
|
|
/**
|
|
* Generates a new identity, saves it to the database, and sets it as the active identity.
|
|
* @return {Promise<string>} with the DID of the new identity
|
|
*/
|
|
export const generateSaveAndActivateIdentity = async (): Promise<string> => {
|
|
const mnemonic = generateSeed();
|
|
// address is 0x... ETH address, without "did:eth:"
|
|
const [address, privateHex, publicHex, derivationPath] =
|
|
deriveAddress(mnemonic);
|
|
|
|
const newId = newIdentifier(address, publicHex, privateHex, derivationPath);
|
|
const identity = JSON.stringify(newId);
|
|
|
|
await accountsDB.open();
|
|
await accountsDB.accounts.add({
|
|
dateCreated: new Date().toISOString(),
|
|
derivationPath: derivationPath,
|
|
did: newId.did,
|
|
identity: identity,
|
|
mnemonic: mnemonic,
|
|
publicKeyHex: newId.keys[0].publicKeyHex,
|
|
});
|
|
|
|
await db.settings.update(MASTER_SETTINGS_KEY, {
|
|
activeDid: newId.did,
|
|
});
|
|
|
|
return newId.did;
|
|
};
|
|
|
|
export const sendTestThroughPushServer = async (
|
|
subscription: PushSubscription,
|
|
skipFilter: boolean,
|
|
): Promise<AxiosResponse> => {
|
|
await db.open();
|
|
const settings = await db.settings.get(MASTER_SETTINGS_KEY);
|
|
let pushUrl: string = DEFAULT_PUSH_SERVER as string;
|
|
if (settings?.webPushServer) {
|
|
pushUrl = settings.webPushServer;
|
|
}
|
|
|
|
// This is a special value that tells the service worker to send a direct notification to the device, skipping filters.
|
|
// This is shared with the service worker and should be a constant. Look for the same name in additional-scripts.js
|
|
// Use something other than "Daily Update" https://gitea.anomalistdesign.com/trent_larson/py-push-server/src/commit/3c0e196c11bc98060ec5934e99e7dbd591b5da4d/app.py#L213
|
|
const DIRECT_PUSH_TITLE = "DIRECT_NOTIFICATION";
|
|
|
|
const auth = Buffer.from(subscription.getKey("auth"));
|
|
const authB64 = auth
|
|
.toString("base64")
|
|
.replace(/\+/g, "-")
|
|
.replace(/\//g, "_")
|
|
.replace(/=+$/, "");
|
|
const p256dh = Buffer.from(subscription.getKey("p256dh"));
|
|
const p256dhB64 = p256dh
|
|
.toString("base64")
|
|
.replace(/\+/g, "-")
|
|
.replace(/\//g, "_")
|
|
.replace(/=+$/, "");
|
|
const newPayload = {
|
|
endpoint: subscription.endpoint,
|
|
keys: {
|
|
auth: authB64,
|
|
p256dh: p256dhB64,
|
|
},
|
|
message: `Test, where you will see this message ${
|
|
skipFilter ? "un" : ""
|
|
}filtered.`,
|
|
title: skipFilter ? DIRECT_PUSH_TITLE : "Your Web Push",
|
|
};
|
|
console.log("Sending a test web push message:", newPayload);
|
|
const payloadStr = JSON.stringify(newPayload);
|
|
const response = await axios.post(
|
|
pushUrl + "/web-push/send-test",
|
|
payloadStr,
|
|
{
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
},
|
|
},
|
|
);
|
|
|
|
console.log("Got response from web push server:", response);
|
|
return response;
|
|
};
|
|
|