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.
 
 
 
Matthew Raymer 2b8cd180a1 Refactored last viewed notification code. Appears to work now. 10 months ago
public remove old texture image that's been replaced 1 year ago
src Alert dialog for odd edge-case 10 months ago
sw_scripts Refactored last viewed notification code. Appears to work now. 10 months ago
.browserslistrc init 2 years ago
.eslintrc.js In transition ... experimenting 2 years ago
.gitignore Some updates and nudging toward notification ui 11 months ago
CHANGELOG.md fix display of given items; bump version to 0.1.2 11 months ago
README.md add some instructions and other tasks 11 months ago
babel.config.js init 2 years ago
openssl_signing_console.rst Small fix 1 year ago
openssl_signing_console.sh Added a quick fix to console signing. Need to edit text later 1 year ago
package-lock.json Beefing up registration and activation of the service worker. 10 months ago
package.json Beefing up registration and activation of the service worker. 10 months ago
postcss.config.js Adding Tailwind and start application views 2 years ago
project.task.yaml tweak some more tasks (so it's clear which ones require UI expertise) 11 months ago
sample.txt Fix typing errors from the refactoring 1 year ago
tailwind.config.js Fix config 2 years ago
tsconfig.json fix the last of the type annotations (still have to fix no-explicit-any warnings) 1 year ago
vue.config.js Beefing up registration and activation of the service worker. 10 months ago
web-push.md Minor formatting changes 11 months ago

README.md

kickstart-for-time-pwa

Project setup

We have pkgx.dev set up in package.json, so you can use dev to set up the dev environment.

npm install

Compiles and hot-reloads for development

npm run serve

Compiles and minifies for production

If you are deploying in a subdirectory, add it to publicPath in vue.config.js, eg: publicPath: "/app/time-tracker/",

npm run build

Lints and fixes files

npm run lint

Tests

For your own web-push tests, change the 'vapid' URL in App.vue, and install apps on the same domain.

Test key contents

See this page

Register new user on test server

New users require registration. This can be done with a claim payload like this by an existing user:

  const vcClaim = {
    "@context": "https://schema.org",
    "@type": "RegisterAction",
    agent: { identifier: identity0.did },
    object: SERVICE_ID,
    participant: { identifier: newIdentity.did },
  };

On the test server, User #0 has rights to register others, so you can start playing one of two ways:

  • Import the keys for the test User did:ethr:0x000Ee5654b9742f6Fe18ea970e32b97ee2247B51 by importing this seed phrase: seminar accuse mystery assist delay law thing deal image undo guard initial shallow wrestle list fragile borrow velvet tomorrow awake explain test offer control (Other test users are found here.)

  • Alternatively, register someone else under User #0 automatically:

    • In the src/views/AccountViewView.vue file, uncomment the lines referring to "testServerRegisterUser".

    • Visit the /account page.

Create multiple identifiers

Go to /start and create or import a new one. Then switch identifiers on the bottom of the Your Identity page.

Create keys with alternate tools

See this page

Customize Vue configuration

See Configuration Reference.

Scenarios

  • Create a new identity as prompted. Go to "Your Identity" screen and copy the ID to the clipboard.

  • Go back to /start and import test User did:ethr:0x000Ee5654b9742f6Fe18ea970e32b97ee2247B51 with this this seed phrase: seminar accuse mystery assist delay law thing deal image undo guard initial shallow wrestle list fragile borrow velvet tomorrow awake explain test offer control (Other test users are found here.)

  • Go to "Your Contacts" screen and add the ID you copied to the clipboard, and hit "+" to add them.

  • Click on the "Registration Unknown" button and register that person to be able to make claims as them.

Clear data & restart

Clear cache for localhost, then go to http://localhost:8080/start (because it'll generate a new one automatically if you start on the /account page).

Other

Reference Material

  • Notifications can be type of toast (self-dismiss), info, success, warning, and danger. They are done via notiwind and set up in App.vue.
// reference material from https://github.com/trentlarson/endorser-mobile/blob/8dc8e0353e0cc80ffa7ed89ded15c8b0da92726b/src/utility/idUtility.ts#L83

// Import an existing ID
export const importAndStoreIdentifier = async (mnemonic: string, mnemonicPassword: string, toLowercase: boolean, previousIdentifiers: Array<IIdentifier>) => {

  // just to get rid of variability that might cause an error
  mnemonic = mnemonic.trim().toLowerCase()

  /**
  // an approach I pieced together
  // requires: yarn add elliptic
  // ... plus:
  // const EC = require('elliptic').ec
  // const secp256k1 = new EC('secp256k1')
  //
  const keyHex: string = bip39.mnemonicToEntropy(mnemonic)
  // returns a KeyPair from the elliptic.ec library
  const keyPair = secp256k1.keyFromPrivate(keyHex, 'hex')
  // this code is from did-provider-eth createIdentifier
  const privateHex = keyPair.getPrivate('hex')
  const publicHex = keyPair.getPublic('hex')
  const address = didJwt.toEthereumAddress(publicHex)
  **/

  /**
  // from https://github.com/uport-project/veramo/discussions/346#discussioncomment-302234
  // ... which almost works but the didJwt.toEthereumAddress is wrong
  // requires: yarn add bip32
  // ... plus: import * as bip32 from 'bip32'
  //
  const seed: Buffer = await bip39.mnemonicToSeed(mnemonic)
  const root = bip32.fromSeed(seed)
  const node = root.derivePath(UPORT_ROOT_DERIVATION_PATH)
  const privateHex = node.privateKey.toString("hex")
  const publicHex = node.publicKey.toString("hex")
  const address = didJwt.toEthereumAddress('0x' + publicHex)
  **/

  /**
  // from https://github.com/uport-project/veramo/discussions/346#discussioncomment-302234
  // requires: yarn add @ethersproject/hdnode
  // ... plus: import { HDNode } from '@ethersproject/hdnode'
  **/
  const hdnode: HDNode = HDNode.fromMnemonic(mnemonic)
  const rootNode: HDNode = hdnode.derivePath(UPORT_ROOT_DERIVATION_PATH)
  const privateHex = rootNode.privateKey.substring(2) // original starts with '0x'
  const publicHex = rootNode.publicKey.substring(2) // original starts with '0x'
  let address = rootNode.address

  const prevIds = previousIdentifiers || [];

  if (toLowercase) {
    const foundEqual = R.find(
      (id) => utility.rawAddressOfDid(id.did) === address,
      prevIds
    )
    if (foundEqual) {
      // They're trying to create a lowercase version of one that exists in normal case.
      // (We really should notify the user.)
      appStore.dispatch(appSlice.actions.addLog({log: true, msg: "Will create a normal-case version of the DID since a regular version exists."}))
    } else {
      address = address.toLowerCase()
    }
  } else {
    // They're not trying to convert to lowercase.
    const foundLower = R.find((id) =>
      utility.rawAddressOfDid(id.did) === address.toLowerCase(),
      prevIds
    )
    if (foundLower) {
      // They're trying to create a normal case version of one that exists in lowercase.
      // (We really should notify the user.)
      appStore.dispatch(appSlice.actions.addLog({log: true, msg: "Will create a lowercase version of the DID since a lowercase version exists."}))
      address = address.toLowerCase()
    }
  }

  appStore.dispatch(appSlice.actions.addLog({log: false, msg: "... derived keys and address..."}))

  const newId = newIdentifier(address, publicHex, privateHex, UPORT_ROOT_DERIVATION_PATH)
  appStore.dispatch(appSlice.actions.addLog({log: false, msg: "... created new ID..."}))

  // awaiting because otherwise the UI may not see that a mnemonic was created
  const savedId = await storeIdentifier(newId, mnemonic, mnemonicPassword)
  appStore.dispatch(appSlice.actions.addLog({log: false, msg: "... stored new ID..."}))
  return savedId
}

// Create a totally new ID
export const createAndStoreIdentifier = async (mnemonicPassword) => {

  // This doesn't give us the entropy/seed.
  //const id = await agent.didManagerCreate()

  const entropy = crypto.randomBytes(32)
  const mnemonic = bip39.entropyToMnemonic(entropy)
  appStore.dispatch(appSlice.actions.addLog({log: false, msg: "... generated mnemonic..."}))

  return importAndStoreIdentifier(mnemonic, mnemonicPassword, false, [])
}

Kudos

Gifts make the world go 'round!