Compare commits
9 Commits
experiment
...
tmp
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cf4375164f | ||
|
|
bdb9da2b87 | ||
|
|
6fc070b45d | ||
|
|
55ba4f0154 | ||
|
|
38d04566a4 | ||
|
|
4b8466fb04 | ||
|
|
f45a528f43 | ||
|
|
d25f8f45bd | ||
|
|
fee0c08f76 |
@@ -15,6 +15,5 @@ module.exports = {
|
|||||||
rules: {
|
rules: {
|
||||||
"no-console": process.env.NODE_ENV === "production" ? "warn" : "off",
|
"no-console": process.env.NODE_ENV === "production" ? "warn" : "off",
|
||||||
"no-debugger": process.env.NODE_ENV === "production" ? "warn" : "off",
|
"no-debugger": process.env.NODE_ENV === "production" ? "warn" : "off",
|
||||||
"@typescript-eslint/no-unnecessary-type-constraint": "off",
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
101
README.md
101
README.md
@@ -22,104 +22,3 @@ npm run lint
|
|||||||
|
|
||||||
### Customize configuration
|
### Customize configuration
|
||||||
See [Configuration Reference](https://cli.vuejs.org/config/).
|
See [Configuration Reference](https://cli.vuejs.org/config/).
|
||||||
|
|
||||||
```
|
|
||||||
// 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, [])
|
|
||||||
}
|
|
||||||
```
|
|
||||||
13974
package-lock.json
generated
13974
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
30
package.json
30
package.json
@@ -8,45 +8,17 @@
|
|||||||
"lint": "vue-cli-service lint"
|
"lint": "vue-cli-service lint"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ethersproject/hdnode": "^5.7.0",
|
|
||||||
"@fortawesome/fontawesome-svg-core": "^6.2.1",
|
"@fortawesome/fontawesome-svg-core": "^6.2.1",
|
||||||
"@fortawesome/free-solid-svg-icons": "^6.2.1",
|
"@fortawesome/free-solid-svg-icons": "^6.2.1",
|
||||||
"@fortawesome/vue-fontawesome": "^3.0.2",
|
"@fortawesome/vue-fontawesome": "^3.0.2",
|
||||||
"@pvermeer/dexie-encrypted-addon": "^2.0.2",
|
|
||||||
"@veramo/core": "^4.1.1",
|
|
||||||
"@veramo/credential-w3c": "^4.1.1",
|
|
||||||
"@veramo/data-store": "^4.1.1",
|
|
||||||
"@veramo/did-manager": "^4.1.1",
|
|
||||||
"@veramo/did-provider-ethr": "^4.1.2",
|
|
||||||
"@veramo/did-resolver": "^4.1.1",
|
|
||||||
"@veramo/key-manager": "^4.1.1",
|
|
||||||
"@vueuse/core": "^9.6.0",
|
|
||||||
"@zxing/text-encoding": "^0.9.0",
|
|
||||||
"class-transformer": "^0.5.1",
|
|
||||||
"core-js": "^3.26.1",
|
"core-js": "^3.26.1",
|
||||||
"dexie": "^3.2.2",
|
|
||||||
"ethereum-cryptography": "^1.1.2",
|
|
||||||
"ethereumjs-util": "^7.1.5",
|
|
||||||
"ethr-did-resolver": "^8.0.0",
|
|
||||||
"js-generate-password": "^0.1.7",
|
|
||||||
"localstorage-slim": "^2.3.0",
|
|
||||||
"luxon": "^3.1.1",
|
|
||||||
"merkletreejs": "^0.3.9",
|
|
||||||
"papaparse": "^5.3.2",
|
|
||||||
"pina": "^0.20.2204228",
|
|
||||||
"pinia-plugin-persistedstate": "^3.0.1",
|
|
||||||
"ramda": "^0.28.0",
|
|
||||||
"readable-stream": "^4.2.0",
|
|
||||||
"reflect-metadata": "^0.1.13",
|
|
||||||
"register-service-worker": "^1.7.2",
|
"register-service-worker": "^1.7.2",
|
||||||
"vue": "^3.2.45",
|
"vue": "^3.2.45",
|
||||||
"vue-class-component": "^8.0.0-0",
|
"vue-class-component": "^8.0.0-0",
|
||||||
"vue-property-decorator": "^9.1.2",
|
|
||||||
"vue-router": "^4.1.6",
|
"vue-router": "^4.1.6",
|
||||||
"web-did-resolver": "^2.0.21"
|
"vuex": "^4.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/ramda": "^0.28.20",
|
|
||||||
"@typescript-eslint/eslint-plugin": "^5.44.0",
|
"@typescript-eslint/eslint-plugin": "^5.44.0",
|
||||||
"@typescript-eslint/parser": "^5.44.0",
|
"@typescript-eslint/parser": "^5.44.0",
|
||||||
"@vue/cli-plugin-babel": "~5.0.8",
|
"@vue/cli-plugin-babel": "~5.0.8",
|
||||||
|
|||||||
@@ -3,5 +3,3 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style></style>
|
<style></style>
|
||||||
|
|
||||||
<script lang="ts"></script>
|
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
/**
|
|
||||||
* Generic strings that could be used throughout the app.
|
|
||||||
*/
|
|
||||||
export enum AppString {
|
|
||||||
APP_NAME = "Kickstart for time",
|
|
||||||
VERSION = "0.1",
|
|
||||||
}
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
import BaseDexie from "dexie";
|
|
||||||
import { encrypted, Encryption } from "@pvermeer/dexie-encrypted-addon";
|
|
||||||
import { accountsSchema, AccountsTable } from "./tables/accounts";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* In order to make the next line be acceptable, the program needs to have its linter suppress a rule:
|
|
||||||
* https://typescript-eslint.io/rules/no-unnecessary-type-constraint/
|
|
||||||
*
|
|
||||||
* and change *any* to *unknown*
|
|
||||||
*
|
|
||||||
* https://9to5answer.com/how-to-bypass-warning-unexpected-any-specify-a-different-type-typescript-eslint-no-explicit-any
|
|
||||||
*/
|
|
||||||
type DexieTables = AccountsTable;
|
|
||||||
export type Dexie<T extends unknown = DexieTables> = BaseDexie & T;
|
|
||||||
export const db = new BaseDexie("kickStarter") as Dexie;
|
|
||||||
const schema = Object.assign({}, accountsSchema);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Needed to enable a special webpack setting to allow *await* below:
|
|
||||||
* https://stackoverflow.com/questions/72474803/error-the-top-level-await-experiment-is-not-enabled-set-experiments-toplevelaw
|
|
||||||
*/
|
|
||||||
|
|
||||||
// create password and place password in localStorage
|
|
||||||
const secret =
|
|
||||||
localStorage.getItem("secret") || Encryption.createRandomEncryptionKey();
|
|
||||||
|
|
||||||
if (localStorage.getItem("secret") == null) {
|
|
||||||
localStorage.setItem("secret", secret);
|
|
||||||
}
|
|
||||||
console.log(secret);
|
|
||||||
encrypted(db, { secretKey: secret });
|
|
||||||
db.version(1).stores(schema);
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
import { Table } from "dexie";
|
|
||||||
|
|
||||||
export type Account = {
|
|
||||||
id?: number;
|
|
||||||
publicKey: string;
|
|
||||||
mnemonic: string;
|
|
||||||
identity: string;
|
|
||||||
dateCreated: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type AccountsTable = {
|
|
||||||
accounts: Table<Account>;
|
|
||||||
};
|
|
||||||
|
|
||||||
// mark encrypted field by starting with a $ character
|
|
||||||
export const accountsSchema = {
|
|
||||||
accounts: "++id, publicKey, $mnemonic, $identity, dateCreated",
|
|
||||||
};
|
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
import { IIdentifier } from "@veramo/core";
|
|
||||||
import { DEFAULT_DID_PROVIDER_NAME } from "../veramo/setup";
|
|
||||||
import { getRandomBytesSync } from "ethereum-cryptography/random";
|
|
||||||
import { entropyToMnemonic } from "ethereum-cryptography/bip39";
|
|
||||||
import { wordlist } from "ethereum-cryptography/bip39/wordlists/english";
|
|
||||||
import { HDNode } from "@ethersproject/hdnode";
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param {string} address
|
|
||||||
* @param {string} publicHex
|
|
||||||
* @param {string} privateHex
|
|
||||||
* @param {string} derivationPath
|
|
||||||
* @return {*} {Omit<IIdentifier, 'provider'>}
|
|
||||||
*/
|
|
||||||
export const newIdentifier = (
|
|
||||||
address: string,
|
|
||||||
publicHex: string,
|
|
||||||
privateHex: string,
|
|
||||||
derivationPath: string
|
|
||||||
): Omit<IIdentifier, keyof "provider"> => {
|
|
||||||
return {
|
|
||||||
did: DEFAULT_DID_PROVIDER_NAME + ":" + address,
|
|
||||||
keys: [
|
|
||||||
{
|
|
||||||
kid: publicHex,
|
|
||||||
kms: "local",
|
|
||||||
meta: { derivationPath: derivationPath },
|
|
||||||
privateKeyHex: privateHex,
|
|
||||||
publicKeyHex: publicHex,
|
|
||||||
type: "Secp256k1",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
provider: DEFAULT_DID_PROVIDER_NAME,
|
|
||||||
services: [],
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export const deriveAddress = (
|
|
||||||
mnemonic: string
|
|
||||||
): [string, string, string, string] => {
|
|
||||||
const UPORT_ROOT_DERIVATION_PATH = "m/7696500'/0'/0'/0'";
|
|
||||||
mnemonic = mnemonic.trim().toLowerCase();
|
|
||||||
|
|
||||||
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'
|
|
||||||
const address = rootNode.address;
|
|
||||||
|
|
||||||
return [address, privateHex, publicHex, UPORT_ROOT_DERIVATION_PATH];
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @return {*} {string}
|
|
||||||
*/
|
|
||||||
export const createIdentifier = (): string => {
|
|
||||||
const entropy: Uint8Array = getRandomBytesSync(32);
|
|
||||||
const mnemonic = entropyToMnemonic(entropy, wordlist);
|
|
||||||
|
|
||||||
return mnemonic;
|
|
||||||
};
|
|
||||||
@@ -1,100 +0,0 @@
|
|||||||
/* import * as R from "ramda";
|
|
||||||
import { configureStore, createSlice } from "@reduxjs/toolkit";
|
|
||||||
import { IIdentifier } from "@veramo/core";
|
|
||||||
|
|
||||||
import { Contact } from "../entity/contact";
|
|
||||||
import { Settings } from "../entity/settings";
|
|
||||||
import * as utility from "../utility/utility";
|
|
||||||
|
|
||||||
const MAX_LOG_LENGTH = 2000000;
|
|
||||||
|
|
||||||
export const DEFAULT_ENDORSER_API_SERVER = "https://endorser.ch:3000";
|
|
||||||
export const DEFAULT_ENDORSER_VIEW_SERVER = "https://endorser.ch";
|
|
||||||
export const LOCAL_ENDORSER_API_SERVER = "http://127.0.0.1:3000";
|
|
||||||
export const LOCAL_ENDORSER_VIEW_SERVER = "http://127.0.0.1:3001";
|
|
||||||
export const TEST_ENDORSER_API_SERVER = "https://test.endorser.ch:8000";
|
|
||||||
export const TEST_ENDORSER_VIEW_SERVER = "https://test.endorser.ch:8080";
|
|
||||||
|
|
||||||
// for contents set in reducers
|
|
||||||
interface Payload<T> {
|
|
||||||
type: string;
|
|
||||||
payload: T;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface LogMsg {
|
|
||||||
log: boolean;
|
|
||||||
msg: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const appSlice = createSlice({
|
|
||||||
name: "app",
|
|
||||||
initialState: {
|
|
||||||
// This is nullable because it is cached state from the DB...
|
|
||||||
// it'll be null if we haven't even loaded from the DB yet.
|
|
||||||
settings: null as Settings,
|
|
||||||
|
|
||||||
// This is nullable because it is cached state from the DB...
|
|
||||||
// it'll be null if we haven't even loaded from the DB yet.
|
|
||||||
identifiers: null as Array<IIdentifier> | null,
|
|
||||||
|
|
||||||
// This is nullable because it is cached state from the DB...
|
|
||||||
// it'll be null if we haven't even loaded from the DB yet.
|
|
||||||
contacts: null as Array<Contact> | null,
|
|
||||||
|
|
||||||
viewServer: DEFAULT_ENDORSER_VIEW_SERVER,
|
|
||||||
|
|
||||||
logMessage: "",
|
|
||||||
|
|
||||||
advancedMode: false,
|
|
||||||
testMode: false,
|
|
||||||
},
|
|
||||||
reducers: {
|
|
||||||
addIdentifier: (state, contents: Payload<IIdentifier>) => {
|
|
||||||
state.identifiers = state.identifiers.concat([contents.payload]);
|
|
||||||
},
|
|
||||||
addLog: (state, contents: Payload<LogMsg>) => {
|
|
||||||
if (state.logMessage.length > MAX_LOG_LENGTH) {
|
|
||||||
state.logMessage =
|
|
||||||
"<truncated>\n..." +
|
|
||||||
state.logMessage.substring(
|
|
||||||
state.logMessage.length - MAX_LOG_LENGTH / 2
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (contents.payload.log) {
|
|
||||||
console.log(contents.payload.msg);
|
|
||||||
state.logMessage += "\n" + contents.payload.msg;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
setAdvancedMode: (state, contents: Payload<boolean>) => {
|
|
||||||
state.advancedMode = contents.payload;
|
|
||||||
},
|
|
||||||
setContacts: (state, contents: Payload<Array<Contact>>) => {
|
|
||||||
state.contacts = contents.payload;
|
|
||||||
},
|
|
||||||
setContact: (state, contents: Payload<Contact>) => {
|
|
||||||
const index = R.findIndex(
|
|
||||||
(c) => c.did === contents.payload.did,
|
|
||||||
state.contacts
|
|
||||||
);
|
|
||||||
state.contacts[index] = contents.payload;
|
|
||||||
},
|
|
||||||
setHomeScreen: (state, contents: Payload<string>) => {
|
|
||||||
state.settings.homeScreen = contents.payload;
|
|
||||||
},
|
|
||||||
setIdentifiers: (state, contents: Payload<Array<IIdentifier>>) => {
|
|
||||||
state.identifiers = contents.payload;
|
|
||||||
},
|
|
||||||
setSettings: (state, contents: Payload<Settings>) => {
|
|
||||||
state.settings = contents.payload;
|
|
||||||
},
|
|
||||||
setTestMode: (state, contents: Payload<boolean>) => {
|
|
||||||
state.testMode = contents.payload;
|
|
||||||
},
|
|
||||||
setViewServer: (state, contents: Payload<string>) => {
|
|
||||||
state.viewServer = contents.payload;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const appStore = configureStore({ reducer: appSlice.reducer });
|
|
||||||
*/
|
|
||||||
@@ -1,151 +0,0 @@
|
|||||||
// Created from the setup in https://veramo.io/docs/guides/react_native
|
|
||||||
|
|
||||||
// Core interfaces
|
|
||||||
/* import {
|
|
||||||
createAgent,
|
|
||||||
IDIDManager,
|
|
||||||
IResolver,
|
|
||||||
IDataStore,
|
|
||||||
IKeyManager,
|
|
||||||
} from "@veramo/core";
|
|
||||||
*/
|
|
||||||
// Core identity manager plugin
|
|
||||||
//import { DIDManager } from "@veramo/did-manager";
|
|
||||||
|
|
||||||
// Ethr did identity provider
|
|
||||||
//import { EthrDIDProvider } from "@veramo/did-provider-ethr";
|
|
||||||
|
|
||||||
// Core key manager plugin
|
|
||||||
//import { KeyManager } from "@veramo/key-manager";
|
|
||||||
|
|
||||||
// Custom key management system for RN
|
|
||||||
//import { KeyManagementSystem } from '@veramo/kms-local-react-native'
|
|
||||||
|
|
||||||
// Custom resolver
|
|
||||||
// Custom resolvers
|
|
||||||
//import { DIDResolverPlugin } from "@veramo/did-resolver";
|
|
||||||
/* import { Resolver } from "did-resolver";
|
|
||||||
import { getResolver as ethrDidResolver } from "ethr-did-resolver";
|
|
||||||
import { getResolver as webDidResolver } from "web-did-resolver";
|
|
||||||
*/
|
|
||||||
// for VCs and VPs https://veramo.io/docs/api/credential-w3c
|
|
||||||
//import { CredentialIssuer } from '@veramo/credential-w3c'
|
|
||||||
|
|
||||||
// Storage plugin using TypeOrm
|
|
||||||
/* import {
|
|
||||||
Entities,
|
|
||||||
KeyStore,
|
|
||||||
DIDStore,
|
|
||||||
IDataStoreORM,
|
|
||||||
} from "@veramo/data-store";
|
|
||||||
*/
|
|
||||||
// TypeORM is installed with @veramo/typeorm
|
|
||||||
//import { createConnection } from 'typeorm'
|
|
||||||
|
|
||||||
//import * as R from "ramda";
|
|
||||||
|
|
||||||
/*
|
|
||||||
import { Contact } from '../entity/contact'
|
|
||||||
import { Settings } from '../entity/settings'
|
|
||||||
import { PrivateData } from '../entity/privateData'
|
|
||||||
|
|
||||||
import { Initial1616938713828 } from '../migration/1616938713828-initial'
|
|
||||||
import { SettingsContacts1616967972293 } from '../migration/1616967972293-settings-contacts'
|
|
||||||
import { EncryptedSeed1637856484788 } from '../migration/1637856484788-EncryptedSeed'
|
|
||||||
import { HomeScreenConfig1639947962124 } from '../migration/1639947962124-HomeScreenConfig'
|
|
||||||
import { HandlePublicKeys1652142819353 } from '../migration/1652142819353-HandlePublicKeys'
|
|
||||||
import { LastClaimsSeen1656811846836 } from '../migration/1656811846836-LastClaimsSeen'
|
|
||||||
import { ContactRegistered1662256903367 }from '../migration/1662256903367-ContactRegistered'
|
|
||||||
import { PrivateData1663080623479 } from '../migration/1663080623479-PrivateData'
|
|
||||||
|
|
||||||
const ALL_ENTITIES = Entities.concat([Contact, Settings, PrivateData])
|
|
||||||
|
|
||||||
// Create react native DB connection configured by ormconfig.js
|
|
||||||
|
|
||||||
export const dbConnection = createConnection({
|
|
||||||
database: 'endorser-mobile.sqlite',
|
|
||||||
entities: ALL_ENTITIES,
|
|
||||||
location: 'default',
|
|
||||||
logging: ['error', 'info', 'warn'],
|
|
||||||
migrations: [ Initial1616938713828, SettingsContacts1616967972293, EncryptedSeed1637856484788, HomeScreenConfig1639947962124, HandlePublicKeys1652142819353, LastClaimsSeen1656811846836, ContactRegistered1662256903367, PrivateData1663080623479 ],
|
|
||||||
migrationsRun: true,
|
|
||||||
type: 'react-native',
|
|
||||||
})
|
|
||||||
*/
|
|
||||||
function didProviderName(netName: string) {
|
|
||||||
return "did:ethr" + (netName === "mainnet" ? "" : ":" + netName);
|
|
||||||
}
|
|
||||||
|
|
||||||
//const NETWORK_NAMES = ["mainnet", "rinkeby"];
|
|
||||||
|
|
||||||
const DEFAULT_DID_PROVIDER_NETWORK_NAME = "mainnet";
|
|
||||||
|
|
||||||
export const DEFAULT_DID_PROVIDER_NAME = didProviderName(
|
|
||||||
DEFAULT_DID_PROVIDER_NETWORK_NAME
|
|
||||||
);
|
|
||||||
|
|
||||||
export const HANDY_APP = false;
|
|
||||||
|
|
||||||
// this is used as the object in RegisterAction claims
|
|
||||||
export const SERVICE_ID = "endorser.ch";
|
|
||||||
|
|
||||||
//const INFURA_PROJECT_ID = "INFURA_PROJECT_ID";
|
|
||||||
/*
|
|
||||||
const providers = {}
|
|
||||||
NETWORK_NAMES.forEach((networkName) => {
|
|
||||||
providers[didProviderName(networkName)] = new EthrDIDProvider({
|
|
||||||
defaultKms: 'local',
|
|
||||||
network: networkName,
|
|
||||||
rpcUrl: 'https://' + networkName + '.infura.io/v3/' + INFURA_PROJECT_ID,
|
|
||||||
gas: 1000001,
|
|
||||||
ttl: 60 * 60 * 24 * 30 * 12 + 1,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
const didManager = new DIDManager({
|
|
||||||
store: new DIDStore(dbConnection),
|
|
||||||
defaultProvider: DEFAULT_DID_PROVIDER_NAME,
|
|
||||||
providers: providers,
|
|
||||||
})
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* const basicDidResolvers = NETWORK_NAMES.map((networkName) => [
|
|
||||||
networkName,
|
|
||||||
new Resolver({
|
|
||||||
ethr: ethrDidResolver({
|
|
||||||
networks: [
|
|
||||||
{
|
|
||||||
name: networkName,
|
|
||||||
rpcUrl:
|
|
||||||
"https://" + networkName + ".infura.io/v3/" + INFURA_PROJECT_ID,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}).ethr,
|
|
||||||
web: webDidResolver().web,
|
|
||||||
}),
|
|
||||||
]);
|
|
||||||
|
|
||||||
const basicResolverMap = R.fromPairs(basicDidResolvers)
|
|
||||||
|
|
||||||
export const DEFAULT_BASIC_RESOLVER = basicResolverMap[DEFAULT_DID_PROVIDER_NETWORK_NAME]
|
|
||||||
|
|
||||||
const agentDidResolvers = NETWORK_NAMES.map((networkName) => {
|
|
||||||
return new DIDResolverPlugin({
|
|
||||||
resolver: basicResolverMap[networkName],
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
let allPlugins = [
|
|
||||||
new CredentialIssuer(),
|
|
||||||
new KeyManager({
|
|
||||||
store: new KeyStore(dbConnection),
|
|
||||||
kms: {
|
|
||||||
local: new KeyManagementSystem(),
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
didManager,
|
|
||||||
].concat(agentDidResolvers)
|
|
||||||
*/
|
|
||||||
|
|
||||||
//export const agent = createAgent<IDIDManager & IKeyManager & IDataStore & IDataStoreORM & IResolver>({ plugins: allPlugins })
|
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
import { VueDexiePlugin } from "@/plugins/dexieVuePlugin";
|
|
||||||
import { createPinia } from "pinia";
|
|
||||||
import { createApp } from "vue";
|
import { createApp } from "vue";
|
||||||
import App from "./App.vue";
|
import App from "./App.vue";
|
||||||
import "./registerServiceWorker";
|
import "./registerServiceWorker";
|
||||||
import router from "./router";
|
import router from "./router";
|
||||||
|
import store from "./store";
|
||||||
|
|
||||||
import "./assets/styles/tailwind.css";
|
import "./assets/styles/tailwind.css";
|
||||||
|
|
||||||
import { library } from "@fortawesome/fontawesome-svg-core";
|
import { library } from "@fortawesome/fontawesome-svg-core";
|
||||||
@@ -49,7 +49,6 @@ import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
|
|||||||
|
|
||||||
createApp(App)
|
createApp(App)
|
||||||
.component("fa", FontAwesomeIcon)
|
.component("fa", FontAwesomeIcon)
|
||||||
.use(VueDexiePlugin())
|
.use(store)
|
||||||
.use(createPinia())
|
|
||||||
.use(router)
|
.use(router)
|
||||||
.mount("#app");
|
.mount("#app");
|
||||||
|
|||||||
@@ -1,18 +0,0 @@
|
|||||||
import Vue from 'vue'
|
|
||||||
import { PluginObject } from 'vue'
|
|
||||||
|
|
||||||
// define the plugin class
|
|
||||||
class VueDexiePlugin implements PluginObject<{}> {
|
|
||||||
// the install method is called when the plugin is installed
|
|
||||||
public static install(app: typeof Vue): void {
|
|
||||||
// define a custom property
|
|
||||||
app.$myProperty = 'Hello, World!'
|
|
||||||
|
|
||||||
// define a custom method
|
|
||||||
app.prototype.$myMethod = (): string => {
|
|
||||||
return this.$myProperty
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default new VueDexiePlugin()
|
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
import { createRouter, createWebHistory, RouteRecordRaw } from "vue-router";
|
import { createRouter, createWebHistory, RouteRecordRaw } from "vue-router";
|
||||||
import { useAppStore } from "../store/app";
|
|
||||||
import HomeView from "../views/HomeView.vue";
|
import HomeView from "../views/HomeView.vue";
|
||||||
|
|
||||||
const routes: Array<RouteRecordRaw> = [
|
const routes: Array<RouteRecordRaw> = [
|
||||||
@@ -89,20 +88,6 @@ const routes: Array<RouteRecordRaw> = [
|
|||||||
component: () =>
|
component: () =>
|
||||||
import(/* webpackChunkName: "project" */ "../views/ProjectViewView.vue"),
|
import(/* webpackChunkName: "project" */ "../views/ProjectViewView.vue"),
|
||||||
},
|
},
|
||||||
{
|
|
||||||
path: "/projects",
|
|
||||||
name: "projects",
|
|
||||||
component: () =>
|
|
||||||
import(/* webpackChunkName: "projects" */ "../views/ProjectsView.vue"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: "/commitments",
|
|
||||||
name: "commitments",
|
|
||||||
component: () =>
|
|
||||||
import(
|
|
||||||
/* webpackChunkName: "commitments" */ "../views/CommitmentsView.vue"
|
|
||||||
),
|
|
||||||
},
|
|
||||||
];
|
];
|
||||||
|
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
@@ -110,32 +95,4 @@ const router = createRouter({
|
|||||||
routes,
|
routes,
|
||||||
});
|
});
|
||||||
|
|
||||||
router.beforeEach(async (to) => {
|
|
||||||
const publicPages = ["/start", "/account", "/import-account"];
|
|
||||||
const isPublic = publicPages.includes(to.path);
|
|
||||||
const appStore = useAppStore();
|
|
||||||
let return_path = "/start";
|
|
||||||
|
|
||||||
if (isPublic) {
|
|
||||||
switch (appStore.condition) {
|
|
||||||
case "uninitialized":
|
|
||||||
return_path = "";
|
|
||||||
break;
|
|
||||||
case "registering":
|
|
||||||
return_path = to.path;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
switch (appStore.condition) {
|
|
||||||
case "registered":
|
|
||||||
return_path = to.path;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (return_path == "") {
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
return return_path;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
export default router;
|
export default router;
|
||||||
|
|||||||
@@ -1,22 +0,0 @@
|
|||||||
// @ts-check
|
|
||||||
import { defineStore } from "pinia";
|
|
||||||
|
|
||||||
export const useAccountStore = defineStore({
|
|
||||||
id: "account",
|
|
||||||
state: () => ({
|
|
||||||
account: JSON.parse(
|
|
||||||
typeof localStorage["account"] == "undefined"
|
|
||||||
? null
|
|
||||||
: localStorage["account"]
|
|
||||||
),
|
|
||||||
}),
|
|
||||||
getters: {
|
|
||||||
firstName: (state) => state.account.firstName,
|
|
||||||
lastName: (state) => state.account.lastName,
|
|
||||||
},
|
|
||||||
actions: {
|
|
||||||
reset() {
|
|
||||||
localStorage.removeItem("account");
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
// @ts-check
|
|
||||||
import { defineStore } from "pinia";
|
|
||||||
|
|
||||||
export const useAppStore = defineStore({
|
|
||||||
id: "app",
|
|
||||||
state: () => ({
|
|
||||||
_condition:
|
|
||||||
typeof localStorage["condition"] == "undefined"
|
|
||||||
? "uninitialized"
|
|
||||||
: localStorage["condition"],
|
|
||||||
_lastView:
|
|
||||||
typeof localStorage["lastView"] == "undefined"
|
|
||||||
? "/start"
|
|
||||||
: localStorage["lastView"],
|
|
||||||
}),
|
|
||||||
getters: {
|
|
||||||
condition: (state) => state._condition,
|
|
||||||
},
|
|
||||||
actions: {
|
|
||||||
reset() {
|
|
||||||
localStorage.removeItem("condition");
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
9
src/store/index.ts
Normal file
9
src/store/index.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import { createStore } from "vuex";
|
||||||
|
|
||||||
|
export default createStore({
|
||||||
|
state: {},
|
||||||
|
getters: {},
|
||||||
|
mutations: {},
|
||||||
|
actions: {},
|
||||||
|
modules: {},
|
||||||
|
});
|
||||||
@@ -4,45 +4,33 @@
|
|||||||
<ul class="flex text-2xl p-2 gap-2">
|
<ul class="flex text-2xl p-2 gap-2">
|
||||||
<!-- Home Feed -->
|
<!-- Home Feed -->
|
||||||
<li class="basis-1/5 rounded-md text-slate-500">
|
<li class="basis-1/5 rounded-md text-slate-500">
|
||||||
<router-link :to="{ name: 'home' }" class="block text-center py-3 px-1">
|
<a href="" class="block text-center py-3 px-1"
|
||||||
<fa icon="house-chimney" class="fa-fw"></fa>
|
><fa icon="house-chimney" class="fa-fw"></fa
|
||||||
</router-link>
|
></a>
|
||||||
</li>
|
</li>
|
||||||
<!-- Search -->
|
<!-- Search -->
|
||||||
<li class="basis-1/5 rounded-md text-slate-500">
|
<li class="basis-1/5 rounded-md text-slate-500">
|
||||||
<router-link
|
<a href="search.html" class="block text-center py-3 px-1"
|
||||||
:to="{ name: 'discover' }"
|
><fa icon="magnifying-glass" class="fa-fw"></fa
|
||||||
class="block text-center py-3 px-1"
|
></a>
|
||||||
>
|
|
||||||
<fa icon="magnifying-glass" class="fa-fw"></fa>
|
|
||||||
</router-link>
|
|
||||||
</li>
|
</li>
|
||||||
<!-- Projects -->
|
<!-- Projects -->
|
||||||
<li class="basis-1/5 rounded-md text-slate-500">
|
<li class="basis-1/5 rounded-md text-slate-500">
|
||||||
<router-link
|
<a href="" class="block text-center py-3 px-1"
|
||||||
:to="{ name: 'projects' }"
|
><fa icon="folder-open" class="fa-fw"></fa
|
||||||
class="block text-center py-3 px-1"
|
></a>
|
||||||
>
|
|
||||||
<fa icon="folder-open" class="fa-fw"></fa>
|
|
||||||
</router-link>
|
|
||||||
</li>
|
</li>
|
||||||
<!-- Commitments -->
|
<!-- Commitments -->
|
||||||
<li class="basis-1/5 rounded-md text-slate-500">
|
<li class="basis-1/5 rounded-md text-slate-500">
|
||||||
<router-link
|
<a href="" class="block text-center py-3 px-1"
|
||||||
:to="{ name: 'commitments' }"
|
><fa icon="hand" class="fa-fw"></fa
|
||||||
class="block text-center py-3 px-1"
|
></a>
|
||||||
>
|
|
||||||
<fa icon="hand" class="fa-fw"></fa>
|
|
||||||
</router-link>
|
|
||||||
</li>
|
</li>
|
||||||
<!-- Profile -->
|
<!-- Profile -->
|
||||||
<li class="basis-1/5 rounded-md bg-slate-400 text-white">
|
<li class="basis-1/5 rounded-md bg-slate-400 text-white">
|
||||||
<router-link
|
<a href="account-view.html" class="block text-center py-3 px-1"
|
||||||
:to="{ name: 'account' }"
|
><fa icon="circle-user" class="fa-fw"></fa
|
||||||
class="block text-center py-3 px-1"
|
></a>
|
||||||
>
|
|
||||||
<fa icon="circle-user" class="fa-fw"></fa>
|
|
||||||
</router-link>
|
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
@@ -79,9 +67,9 @@
|
|||||||
class="text-sm text-slate-500 flex justify-between items-center mb-1"
|
class="text-sm text-slate-500 flex justify-between items-center mb-1"
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
><code>{{ address }}</code>
|
><code>did:peer:kl45kj41lk451kl3</code>
|
||||||
<fa icon="copy" class="text-slate-400 fa-fw ml-1"></fa>
|
<fa icon="copy" class="text-slate-400 fa-fw ml-1"></fa
|
||||||
</span>
|
></span>
|
||||||
<span>
|
<span>
|
||||||
<button
|
<button
|
||||||
class="text-xs uppercase bg-slate-500 text-white px-1.5 py-1 rounded-md"
|
class="text-xs uppercase bg-slate-500 text-white px-1.5 py-1 rounded-md"
|
||||||
@@ -99,24 +87,24 @@
|
|||||||
<div class="text-slate-500 text-sm font-bold">Public Key</div>
|
<div class="text-slate-500 text-sm font-bold">Public Key</div>
|
||||||
<div class="text-sm text-slate-500 mb-1">
|
<div class="text-sm text-slate-500 mb-1">
|
||||||
<span
|
<span
|
||||||
><code>{{ publicHex }}</code>
|
><code>dyIgKepL19trfrFu5jzkoNhI</code>
|
||||||
<fa icon="copy" class="text-slate-400 fa-fw ml-1"></fa>
|
<fa icon="copy" class="text-slate-400 fa-fw ml-1"></fa
|
||||||
</span>
|
></span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="text-slate-500 text-sm font-bold">Derivation Path</div>
|
<div class="text-slate-500 text-sm font-bold">Derivation Path</div>
|
||||||
<div class="text-sm text-slate-500 mb-1">
|
<div class="text-sm text-slate-500 mb-1">
|
||||||
<span
|
<span
|
||||||
><code>{{ UPORT_ROOT_DERIVATION_PATH }}</code>
|
><code>m/44'/0'/0'/0/0</code>
|
||||||
<fa icon="copy" class="text-slate-400 fa-fw ml-1"></fa>
|
<fa icon="copy" class="text-slate-400 fa-fw ml-1"></fa
|
||||||
</span>
|
></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<router-link
|
<a
|
||||||
:to="{ name: 'new-edit-account' }"
|
href="account-edit.html"
|
||||||
class="block text-center text-lg font-bold uppercase bg-blue-600 text-white px-2 py-3 rounded-md mb-8"
|
class="block text-center text-lg font-bold uppercase bg-blue-600 text-white px-2 py-3 rounded-md mb-8"
|
||||||
>Edit Identity</router-link
|
>Edit Identity</a
|
||||||
>
|
>
|
||||||
|
|
||||||
<h3 class="text-sm uppercase font-semibold mb-3">Contact Actions</h3>
|
<h3 class="text-sm uppercase font-semibold mb-3">Contact Actions</h3>
|
||||||
@@ -167,86 +155,9 @@
|
|||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Options, Vue } from "vue-class-component";
|
import { Options, Vue } from "vue-class-component";
|
||||||
import { createIdentifier, deriveAddress, newIdentifier } from "../libs/crypto";
|
|
||||||
import { IIdentifier } from "@veramo/core";
|
|
||||||
import * as R from "ramda";
|
|
||||||
import { db } from "../db";
|
|
||||||
|
|
||||||
@Options({
|
@Options({
|
||||||
components: {},
|
components: {},
|
||||||
})
|
})
|
||||||
export default class AccountViewView extends Vue {
|
export default class AccountViewView extends Vue {}
|
||||||
mnemonic = "";
|
|
||||||
address = "";
|
|
||||||
privateHex = "";
|
|
||||||
publicHex = "";
|
|
||||||
UPORT_ROOT_DERIVATION_PATH = "";
|
|
||||||
async created() {
|
|
||||||
const previousIdentifiers: Array<IIdentifier> = [];
|
|
||||||
const toLowercase = true;
|
|
||||||
this.mnemonic = createIdentifier();
|
|
||||||
[
|
|
||||||
this.address,
|
|
||||||
this.privateHex,
|
|
||||||
this.publicHex,
|
|
||||||
this.UPORT_ROOT_DERIVATION_PATH,
|
|
||||||
] = deriveAddress(this.mnemonic);
|
|
||||||
//appStore.dispatch(appSlice.actions.addLog({log: false, msg: "... derived keys and address..."}))
|
|
||||||
const prevIds = previousIdentifiers || [];
|
|
||||||
if (toLowercase) {
|
|
||||||
const foundEqual = R.find(
|
|
||||||
(id: IIdentifier) => id.did.split(":")[2] === this.address,
|
|
||||||
prevIds
|
|
||||||
);
|
|
||||||
if (foundEqual) {
|
|
||||||
// appStore.dispatch(appSlice.actions.addLog({log: true, msg: "Will create a normal-case version of the DID since a regular version exists."}))
|
|
||||||
} else {
|
|
||||||
this.address = this.address.toLowerCase();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// They're not trying to convert to lowercase.
|
|
||||||
const foundLower = R.find(
|
|
||||||
(id: IIdentifier) =>
|
|
||||||
id.did.split(":")[2] === this.address.toLowerCase(),
|
|
||||||
prevIds
|
|
||||||
);
|
|
||||||
if (foundLower) {
|
|
||||||
// appStore.dispatch(appSlice.actions.addLog({log: true, msg: "Will create a lowercase version of the DID since a lowercase version exists."}))
|
|
||||||
this.address = this.address.toLowerCase();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const newId = newIdentifier(
|
|
||||||
this.address,
|
|
||||||
this.publicHex,
|
|
||||||
this.privateHex,
|
|
||||||
this.UPORT_ROOT_DERIVATION_PATH
|
|
||||||
);
|
|
||||||
try {
|
|
||||||
await db.open();
|
|
||||||
const num_accounts = await db.accounts.count();
|
|
||||||
if (num_accounts === 0) {
|
|
||||||
console.log("...");
|
|
||||||
await db.accounts.add({
|
|
||||||
publicKey: newId.keys[0].publicKeyHex,
|
|
||||||
mnemonic: this.mnemonic,
|
|
||||||
identity: JSON.stringify(newId),
|
|
||||||
dateCreated: new Date().getTime(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
const accounts = await db.accounts.toArray();
|
|
||||||
console.log(accounts[0]);
|
|
||||||
const identity = JSON.parse(accounts[0].identity);
|
|
||||||
|
|
||||||
this.address = identity.did;
|
|
||||||
this.publicHex = identity.keys[0].publicKeyHex;
|
|
||||||
|
|
||||||
//appStore.dispatch(appSlice.actions.addLog({log: false, msg: "... created new ID..."}))
|
|
||||||
//appStore.dispatch(appSlice.actions.addLog({log: false, msg: "... stored new ID..."}))
|
|
||||||
} catch (err) {
|
|
||||||
console.log("Error!");
|
|
||||||
console.log(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
<template>
|
|
||||||
<section id="Content" class="p-6 pb-24"></section>
|
|
||||||
</template>
|
|
||||||
@@ -5,11 +5,11 @@
|
|||||||
<div id="ViewBreadcrumb" class="mb-8">
|
<div id="ViewBreadcrumb" class="mb-8">
|
||||||
<h1 class="text-lg text-center font-light relative px-7">
|
<h1 class="text-lg text-center font-light relative px-7">
|
||||||
<!-- Cancel -->
|
<!-- Cancel -->
|
||||||
<router-link
|
<a
|
||||||
:to="{ name: 'account' }"
|
href="account-view.html"
|
||||||
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
|
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
|
||||||
><fa icon="chevron-left" class="fa-fw"></fa
|
><fa icon="chevron-left" class="fa-fw"></fa
|
||||||
></router-link>
|
></a>
|
||||||
|
|
||||||
Confirm Contact
|
Confirm Contact
|
||||||
</h1>
|
</h1>
|
||||||
|
|||||||
@@ -4,11 +4,11 @@
|
|||||||
<div id="ViewBreadcrumb" class="mb-8">
|
<div id="ViewBreadcrumb" class="mb-8">
|
||||||
<h1 class="text-lg text-center font-light relative px-7">
|
<h1 class="text-lg text-center font-light relative px-7">
|
||||||
<!-- Cancel -->
|
<!-- Cancel -->
|
||||||
<router-link
|
<a
|
||||||
:to="{ name: 'account' }"
|
href="account-view.html"
|
||||||
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
|
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
|
||||||
><fa icon="chevron-left" class="fa-fw"></fa
|
><fa icon="chevron-left" class="fa-fw"></fa
|
||||||
></router-link>
|
></a>
|
||||||
|
|
||||||
Scan Contact
|
Scan Contact
|
||||||
</h1>
|
</h1>
|
||||||
|
|||||||
@@ -4,39 +4,33 @@
|
|||||||
<ul class="flex text-2xl p-2 gap-2">
|
<ul class="flex text-2xl p-2 gap-2">
|
||||||
<!-- Home Feed -->
|
<!-- Home Feed -->
|
||||||
<li class="basis-1/5 rounded-md text-slate-500">
|
<li class="basis-1/5 rounded-md text-slate-500">
|
||||||
<router-link :to="{ name: 'home' }" class="block text-center py-3 px-1"
|
<a href="" class="block text-center py-3 px-1"
|
||||||
><fa icon="house-chimney" class="fa-fw"></fa
|
><fa icon="house-chimney" class="fa-fw"></fa
|
||||||
></router-link>
|
></a>
|
||||||
</li>
|
</li>
|
||||||
<!-- Search -->
|
<!-- Search -->
|
||||||
<li class="basis-1/5 rounded-md bg-slate-400 text-white">
|
<li class="basis-1/5 rounded-md bg-slate-400 text-white">
|
||||||
<router-link
|
<a href="search.html" class="block text-center py-3 px-1"
|
||||||
:to="{ name: 'discover' }"
|
|
||||||
class="block text-center py-3 px-1"
|
|
||||||
><fa icon="magnifying-glass" class="fa-fw"></fa
|
><fa icon="magnifying-glass" class="fa-fw"></fa
|
||||||
></router-link>
|
></a>
|
||||||
</li>
|
</li>
|
||||||
<!-- Projects -->
|
<!-- Projects -->
|
||||||
<li class="basis-1/5 rounded-md text-slate-500">
|
<li class="basis-1/5 rounded-md text-slate-500">
|
||||||
<router-link
|
<a href="" class="block text-center py-3 px-1"
|
||||||
:to="{ name: 'project' }"
|
|
||||||
class="block text-center py-3 px-1"
|
|
||||||
><fa icon="folder-open" class="fa-fw"></fa
|
><fa icon="folder-open" class="fa-fw"></fa
|
||||||
></router-link>
|
></a>
|
||||||
</li>
|
</li>
|
||||||
<!-- Commitments -->
|
<!-- Commitments -->
|
||||||
<li class="basis-1/5 rounded-md text-slate-500">
|
<li class="basis-1/5 rounded-md text-slate-500">
|
||||||
<router-link :to="{ name: '' }" class="block text-center py-3 px-1"
|
<a href="" class="block text-center py-3 px-1"
|
||||||
><fa icon="hand" class="fa-fw"></fa
|
><fa icon="hand" class="fa-fw"></fa
|
||||||
></router-link>
|
></a>
|
||||||
</li>
|
</li>
|
||||||
<!-- Profile -->
|
<!-- Profile -->
|
||||||
<li class="basis-1/5 rounded-md text-slate-500">
|
<li class="basis-1/5 rounded-md text-slate-500">
|
||||||
<router-link
|
<a href="account-view.html" class="block text-center py-3 px-1"
|
||||||
:to="{ name: 'account' }"
|
|
||||||
class="block text-center py-3 px-1"
|
|
||||||
><fa icon="circle-user" class="fa-fw"></fa
|
><fa icon="circle-user" class="fa-fw"></fa
|
||||||
></router-link>
|
></a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
|
|||||||
@@ -4,12 +4,11 @@
|
|||||||
<div id="ViewBreadcrumb" class="mb-8">
|
<div id="ViewBreadcrumb" class="mb-8">
|
||||||
<h1 class="text-lg text-center font-light relative px-7">
|
<h1 class="text-lg text-center font-light relative px-7">
|
||||||
<!-- Cancel -->
|
<!-- Cancel -->
|
||||||
<button
|
<a
|
||||||
@click="$router.go(-1)"
|
href="start.html"
|
||||||
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
|
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
|
||||||
>
|
><fa icon="chevron-left"></fa>
|
||||||
<fa icon="chevron-left"></fa>
|
</a>
|
||||||
</button>
|
|
||||||
Import Existing Identity
|
Import Existing Identity
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
@@ -30,7 +29,6 @@
|
|||||||
value="Import Identity"
|
value="Import Identity"
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
@click="onCancelClick()"
|
|
||||||
type="button"
|
type="button"
|
||||||
class="block w-full text-center text-md uppercase bg-slate-500 text-white px-1.5 py-2 rounded-md"
|
class="block w-full text-center text-md uppercase bg-slate-500 text-white px-1.5 py-2 rounded-md"
|
||||||
>
|
>
|
||||||
@@ -47,9 +45,5 @@ import { Options, Vue } from "vue-class-component";
|
|||||||
@Options({
|
@Options({
|
||||||
components: {},
|
components: {},
|
||||||
})
|
})
|
||||||
export default class ImportAccountView extends Vue {
|
export default class ImportAccountView extends Vue {}
|
||||||
public onCancelClick() {
|
|
||||||
this.$router.back();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -4,12 +4,11 @@
|
|||||||
<div id="ViewBreadcrumb" class="mb-8">
|
<div id="ViewBreadcrumb" class="mb-8">
|
||||||
<h1 class="text-lg text-center font-light relative px-7">
|
<h1 class="text-lg text-center font-light relative px-7">
|
||||||
<!-- Cancel -->
|
<!-- Cancel -->
|
||||||
<button
|
<a
|
||||||
@click="$router.go(-1)"
|
href="account-view.html"
|
||||||
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
|
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
|
||||||
>
|
><fa icon="chevron-left" class="fa-fw"></fa>
|
||||||
<fa icon="chevron-left" class="fa-fw"></fa>
|
</a>
|
||||||
</button>
|
|
||||||
[New/Edit] Identity
|
[New/Edit] Identity
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -5,11 +5,11 @@
|
|||||||
<div id="ViewBreadcrumb" class="mb-8">
|
<div id="ViewBreadcrumb" class="mb-8">
|
||||||
<h1 class="text-lg text-center font-light relative px-7">
|
<h1 class="text-lg text-center font-light relative px-7">
|
||||||
<!-- Cancel -->
|
<!-- Cancel -->
|
||||||
<router-link
|
<a
|
||||||
:to="{ name: 'project' }"
|
href="project-view.html"
|
||||||
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
|
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
|
||||||
><fa icon="chevron-left" class="fa-fw"></fa>
|
><fa icon="chevron-left" class="fa-fw"></fa>
|
||||||
</router-link>
|
</a>
|
||||||
|
|
||||||
Make Commitment
|
Make Commitment
|
||||||
</h1>
|
</h1>
|
||||||
|
|||||||
@@ -5,11 +5,11 @@
|
|||||||
<div id="ViewBreadcrumb" class="mb-8">
|
<div id="ViewBreadcrumb" class="mb-8">
|
||||||
<h1 class="text-lg text-center font-light relative px-7">
|
<h1 class="text-lg text-center font-light relative px-7">
|
||||||
<!-- Cancel -->
|
<!-- Cancel -->
|
||||||
<router-link
|
<a
|
||||||
:to="{ name: 'project' }"
|
href="project-view.html"
|
||||||
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
|
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
|
||||||
><fa icon="chevron-left" class="fa-fw"></fa
|
><fa icon="chevron-left" class="fa-fw"></fa>
|
||||||
></router-link>
|
</a>
|
||||||
|
|
||||||
[New/Edit] Project
|
[New/Edit] Project
|
||||||
</h1>
|
</h1>
|
||||||
|
|||||||
@@ -28,11 +28,9 @@
|
|||||||
</li>
|
</li>
|
||||||
<!-- Profile -->
|
<!-- Profile -->
|
||||||
<li class="basis-1/5 rounded-md text-slate-500">
|
<li class="basis-1/5 rounded-md text-slate-500">
|
||||||
<router-link
|
<a href="account-view.html" class="block text-center py-3 px-1"
|
||||||
:to="{ name: 'account' }"
|
|
||||||
class="block text-center py-3 px-1"
|
|
||||||
><fa icon="circle-user" class="fa-fw"></fa
|
><fa icon="circle-user" class="fa-fw"></fa
|
||||||
></router-link>
|
></a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
@@ -43,12 +41,9 @@
|
|||||||
<div id="ViewBreadcrumb" class="mb-8">
|
<div id="ViewBreadcrumb" class="mb-8">
|
||||||
<h1 class="text-lg text-center font-light relative px-7">
|
<h1 class="text-lg text-center font-light relative px-7">
|
||||||
<!-- Back -->
|
<!-- Back -->
|
||||||
<button
|
<a href="" class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
|
||||||
@click="$router.go(-1)"
|
><fa icon="chevron-left" class="fa-fw"></fa
|
||||||
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
|
></a>
|
||||||
>
|
|
||||||
<fa icon="chevron-left" class="fa-fw"></fa>
|
|
||||||
</button>
|
|
||||||
<!-- Context Menu -->
|
<!-- Context Menu -->
|
||||||
<a
|
<a
|
||||||
href=""
|
href=""
|
||||||
@@ -88,10 +83,10 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Commit -->
|
<!-- Commit -->
|
||||||
<router-link
|
<a
|
||||||
:to="{ name: 'new-edit-commitment' }"
|
href="commitment-edit.html"
|
||||||
class="block text-center text-lg font-bold uppercase bg-blue-600 text-white px-2 py-3 rounded-md mb-8"
|
class="block text-center text-lg font-bold uppercase bg-blue-600 text-white px-2 py-3 rounded-md mb-8"
|
||||||
>Make Commitment</router-link
|
>Make Commitment</a
|
||||||
>
|
>
|
||||||
|
|
||||||
<!-- Commitments -->
|
<!-- Commitments -->
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
<template>
|
|
||||||
<section id="Content" class="p-6 pb-24"></section>
|
|
||||||
</template>
|
|
||||||
@@ -12,16 +12,16 @@
|
|||||||
<p class="text-center text-xl mb-4 font-light">
|
<p class="text-center text-xl mb-4 font-light">
|
||||||
Do you already have an identity to import?
|
Do you already have an identity to import?
|
||||||
</p>
|
</p>
|
||||||
<a
|
<router-link
|
||||||
@click="onClickYes()"
|
:to="{ name: 'new-edit-account' }"
|
||||||
class="block w-full text-center text-lg font-bold uppercase bg-blue-600 text-white px-2 py-3 rounded-md mb-2"
|
class="block w-full text-center text-lg font-bold uppercase bg-blue-600 text-white px-2 py-3 rounded-md mb-2"
|
||||||
>
|
>
|
||||||
No
|
No
|
||||||
</a>
|
</router-link>
|
||||||
<a
|
<router-link
|
||||||
@click="onClickNo()"
|
:to="{ name: 'import-account' }"
|
||||||
class="block w-full text-center text-md uppercase bg-slate-500 text-white px-1.5 py-2 rounded-md"
|
class="block w-full text-center text-md uppercase bg-slate-500 text-white px-1.5 py-2 rounded-md"
|
||||||
>Yes</a
|
>Yes</router-link
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
@@ -33,13 +33,5 @@ import { Options, Vue } from "vue-class-component";
|
|||||||
@Options({
|
@Options({
|
||||||
components: {},
|
components: {},
|
||||||
})
|
})
|
||||||
export default class StartView extends Vue {
|
export default class StartView extends Vue {}
|
||||||
public onClickYes() {
|
|
||||||
this.$router.push({ name: "account" });
|
|
||||||
}
|
|
||||||
|
|
||||||
public onClickNo() {
|
|
||||||
this.$router.push({ name: "import-account" });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,10 +1,4 @@
|
|||||||
const { defineConfig } = require("@vue/cli-service");
|
const { defineConfig } = require("@vue/cli-service");
|
||||||
module.exports = defineConfig({
|
module.exports = defineConfig({
|
||||||
transpileDependencies: true,
|
transpileDependencies: true,
|
||||||
configureWebpack: {
|
|
||||||
devtool: "source-map",
|
|
||||||
experiments: {
|
|
||||||
topLevelAwait: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user