etherealengine
etherealengine copied to clipboard
[Story] Verifiable Credentials can be issued via an action
The issueCredential() function will live in a VerifiableCredentialSystem.ts file, in packages/client-core/src/systems. It will be triggered when an action query is met.
(A system is a module with a default export of an async function that returns a regular (sync) function, that runs on every frame. Since triggering an 'issue & store a VC event' should happen only once, we'll need to use some kind of event to implement it.)
My suggested implementation:
In packages/engine/src/credentials/:
- CredentialAction.ts -- Isomorphic
- CrednetialSystem.ts -- Isomorphic
- CredentialVerificationSystem.ts -- Server-only
// in instancechannel channels.ts
initSystems(world, [{
type: SystemUpdateType.UPDATE,
systemModulePromise: import('./credentials/CredentialVerificationSystem')
}])
// in initializeEngine.ts
initSystems(world, [{
type: SystemUpdateType.UPDATE,
systemModulePromise: import('./credentials/CredentialSystem')
}])
// in CredentialAction.ts
export class CredentialAction {
static requestVerify = defineAction({
type: 'xre.credential.requestVerify',
credential: matches.any,
$cache: true,
$topic: NetworkTopics.world
})
static didVerify = defineAction({
$from: matchesHostId,
type: 'xre.credential.didVerify',
credential: matches.any,
$cache: true,
$topic: NetworkTopics.world
})
}
// in clientInputListener (for now, we can hook this to a trigger volume next)
addListener(window, 'keydown', () => {
// if c key is pressed, request credential from user
// requestCredential() =>
dispatchAction(
CredentialAction.requestVerifyCredential({
credential: {} // credential object
})
)
})
// In CredentialVerificationSystem.ts
const requestVerifyCredential = (credential) => {
// verify credential
// if verified, dispatch action to set credential
// if not verified, dispatch action to set error
dispatchAction(
CredentialAction.didVerifyCredential({credential})
)
}
const CredentialVerifierSystem = () => {
const requestVerifyCredentialActions = createActionQueue(CredentialAction.requestVerifyCredential.matches)
return () => {
for (action of requestVerifyCredentialActions()) requestVerifyCredential(action.credential)
}
}
// In CredentialSystem.ts
function updateCredentialState(action:CredentialAction.didVerifyCredential.matches._TYPE) {
if (action.$from !== Engine.instnace.currentWorld.hostId) return
const credential = action.credential
const credentialState = getState(CredentialState).userCredentials
credentialState[userId].push(credential)
}
const CredentialSystem = () => {
const didVerifyCredentialActions = createActionQueue(CredentialAction.didVerifyCredential.matches)
return () => {
for (action of didVerifyCredentialActions()) updateCredentialState(action)
}
}
Implemented in PR #6871, closing.