|
|
|
# kickstart-for-time-pwa
|
|
|
|
|
|
|
|
## Project setup
|
|
|
|
```
|
|
|
|
npm install
|
|
|
|
```
|
|
|
|
|
|
|
|
### Compiles and hot-reloads for development
|
|
|
|
```
|
|
|
|
npm run serve
|
|
|
|
```
|
|
|
|
|
|
|
|
### Compiles and minifies for production
|
|
|
|
```
|
|
|
|
npm run build
|
|
|
|
```
|
|
|
|
|
|
|
|
### Lints and fixes files
|
|
|
|
```
|
|
|
|
npm run lint
|
|
|
|
```
|
|
|
|
|
|
|
|
### Customize configuration
|
|
|
|
See [Configuration Reference](https://cli.vuejs.org/config/).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## Other
|
|
|
|
|
|
|
|
```
|
|
|
|
// 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, [])
|
|
|
|
}
|
|
|
|
```
|