Trent Larson
3bf8fd0c22
|
1 year ago | |
---|---|---|
public | 1 year ago | |
src | 1 year ago | |
sw_scripts | 1 year ago | |
.browserslistrc | 2 years ago | |
.eslintrc.js | 2 years ago | |
.gitignore | 1 year ago | |
CHANGELOG.md | 1 year ago | |
README.md | 1 year ago | |
babel.config.js | 2 years ago | |
openssl_signing_console.rst | 1 year ago | |
openssl_signing_console.sh | 1 year ago | |
package-lock.json | 1 year ago | |
package.json | 1 year ago | |
postcss.config.js | 2 years ago | |
project.task.yaml | 1 year ago | |
sample.txt | 1 year ago | |
tailwind.config.js | 2 years ago | |
tsconfig.json | 1 year ago | |
vue.config.js | 1 year ago | |
web-push.md | 1 year 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
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
, anddanger
. 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!
- Máximo Fernández for the 3D code and explanatory post
- Many tools & libraries such as Nodejs.org, IntelliJ Idea, Veramo.io, Vuejs.org, threejs.org
- Bush 3D model
- Forest floor image