Matthew Aaron Raymer
2 years ago
7 changed files with 469 additions and 60 deletions
@ -0,0 +1,65 @@ |
|||||
|
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; |
||||
|
}; |
@ -0,0 +1,100 @@ |
|||||
|
/* 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 }); |
||||
|
*/ |
@ -0,0 +1,151 @@ |
|||||
|
// 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 })
|
Loading…
Reference in new issue