| 
						
						
							
								
							
						
						
					 | 
				
				 | 
				
					@ -34,7 +34,11 @@ | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      </p> | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    </div> | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    <div @click="onCopyToClipboard()" v-if="activeDid" class="text-center"> | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    <div | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      @click="onCopyUrlToClipboard()" | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      v-if="activeDid && activeDid.startsWith(ETHR_DID_PREFIX)" | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      class="text-center" | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    > | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      <!-- | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        Play with display options: https://qr-code-styling.com/ | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        See docs: https://www.npmjs.com/package/qr-code-generator-vue3 | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				
					@ -45,8 +49,18 @@ | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        :dotsOptions="{ type: 'square' }" | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        class="flex justify-center" | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      /> | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      <span> Click that QR to copy your contact URL to your clipboard. </span> | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      <div>Not scanning? Show it in pieces.</div> | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      <span> | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        Click this or QR code to copy your contact URL to your clipboard. | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      </span> | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    </div> | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    <div v-else-if="activeDid" class="text-center"> | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      <!-- Not an ETHR DID so force them to paste it. (Passkey Peer DIDs are too big.) --> | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      <span @click="onCopyDidToClipboard()" class="text-blue-500"> | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        Click here to copy your DID to your clipboard. | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      </span> | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      <span> | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        Then give it to them so they can paste it in their list of People. | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      </span> | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    </div> | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    <div class="text-center" v-else> | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      You have no identitifiers yet, so | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
				 | 
				
					@ -92,13 +106,14 @@ import { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					  nextDerivationPath, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					} from "@/libs/crypto"; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					import { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					  CONTACT_URL_PREFIX, createEndorserJwtForDid, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					  CONTACT_URL_PREFIX, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					  createEndorserJwtForDid, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					  ENDORSER_JWT_URL_LOCATION, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					  isDid, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					  register, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					  setVisibilityUtil, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					} from "@/libs/endorserServer"; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					import * as libsUtil from "@/libs/util"; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					import { ETHR_DID_PREFIX } from "@/libs/crypto/vc"; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					@Component({ | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					  components: { | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				
					@ -117,6 +132,8 @@ export default class ContactQRScanShow extends Vue { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					  isRegistered = false; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					  qrValue = ""; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					  ETHR_DID_PREFIX = ETHR_DID_PREFIX; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					  async created() { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    await db.open(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    const settings = await db.settings.get(MASTER_SETTINGS_KEY); | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				
					@ -131,20 +148,9 @@ export default class ContactQRScanShow extends Vue { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    const accounts = await accountsDB.accounts.toArray(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    const account = R.find((acc) => acc.did === this.activeDid, accounts); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    if (account) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      const identity = await libsUtil.getIdentity(this.activeDid); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      const publicKeyHex = identity.keys[0].publicKeyHex; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      const publicKeyHex = account.publicKeyHex; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      const publicEncKey = Buffer.from(publicKeyHex, "hex").toString("base64"); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      const newDerivPath = nextDerivationPath(account.derivationPath as string); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      const nextPublicHex = deriveAddress( | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        account.mnemonic as string, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        newDerivPath, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      )[2]; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      const nextPublicEncKey = Buffer.from(nextPublicHex, "hex"); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      const nextPublicEncKeyHash = sha256(nextPublicEncKey); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      const nextPublicEncKeyHashBase64 = | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        Buffer.from(nextPublicEncKeyHash).toString("base64"); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      const contactInfo = { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        iat: Date.now(), | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        iss: this.activeDid, | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				
					@ -153,13 +159,28 @@ export default class ContactQRScanShow extends Vue { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            (settings?.firstName || "") + | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            (settings?.lastName ? ` ${settings.lastName}` : ""), // deprecated, pre v 0.1.3 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					          publicEncKey, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					          nextPublicEncKeyHash: nextPublicEncKeyHashBase64, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					          profileImageUrl: settings?.profileImageUrl, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					          registered: settings?.isRegistered, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        }, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      }; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      const vcJwt: string = await createEndorserJwtForDid(identity.did, contactInfo); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      if (account?.mnemonic && account?.derivationPath) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        const newDerivPath = nextDerivationPath( | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					          account.derivationPath as string, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        const nextPublicHex = deriveAddress( | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					          account.mnemonic as string, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					          newDerivPath, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        )[2]; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        const nextPublicEncKey = Buffer.from(nextPublicHex, "hex"); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        const nextPublicEncKeyHash = sha256(nextPublicEncKey); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        const nextPublicEncKeyHashBase64 = | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					          Buffer.from(nextPublicEncKeyHash).toString("base64"); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        contactInfo.own.nextPublicEncKeyHash = nextPublicEncKeyHashBase64; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      const vcJwt = await createEndorserJwtForDid(this.activeDid, contactInfo); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      const viewPrefix = CONTACT_URL_PREFIX + ENDORSER_JWT_URL_LOCATION; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      this.qrValue = viewPrefix + vcJwt; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    } | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
				 | 
				
					@ -409,7 +430,7 @@ export default class ContactQRScanShow extends Vue { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					  } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					  onCopyToClipboard() { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					  onCopyUrlToClipboard() { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    //this.onScanDetect([{ rawValue: this.qrValue }]); // good for testing | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    useClipboard() | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      .copy(this.qrValue) | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				
					@ -426,5 +447,22 @@ export default class ContactQRScanShow extends Vue { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      }); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					  } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					  onCopyDidToClipboard() { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    //this.onScanDetect([{ rawValue: this.qrValue }]); // good for testing | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    useClipboard() | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      .copy(this.activeDid) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      .then(() => { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        this.$notify( | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					          { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            group: "alert", | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            type: "info", | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            title: "Copied", | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            text: "Your DID was copied to the clipboard. Have them paste it on their 'People' screen to add you.", | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					          }, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					          10000, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      }); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					  } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					</script> | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
					 | 
				
				 | 
				
					
  |