@xyo-network/os-runtime 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +165 -0
- package/README.md +13 -0
- package/dist/neutral/index.d.ts +1656 -0
- package/dist/neutral/index.mjs +3432 -0
- package/dist/neutral/index.mjs.map +1 -0
- package/package.json +78 -0
- package/src/Caller.ts +221 -0
- package/src/DappCallerBase.ts +52 -0
- package/src/DefaultsQueries.ts +27 -0
- package/src/OsCallerBase.ts +55 -0
- package/src/PubSubBridgeCaller.ts +30 -0
- package/src/XyOs.ts +125 -0
- package/src/XyOsBase.ts +119 -0
- package/src/XyOsDapp.ts +90 -0
- package/src/access-interfaces/ValidDappAccessInterfaces.ts +8 -0
- package/src/access-interfaces/index.ts +2 -0
- package/src/access-interfaces/registered-names/helpers/AccessNodeQueries.ts +59 -0
- package/src/access-interfaces/registered-names/helpers/index.ts +2 -0
- package/src/access-interfaces/registered-names/helpers/resource/AbstractXnsCaller.ts +38 -0
- package/src/access-interfaces/registered-names/helpers/resource/RegistrationsResource.ts +54 -0
- package/src/access-interfaces/registered-names/helpers/resource/RegistrationsResourceQueries.ts +22 -0
- package/src/access-interfaces/registered-names/helpers/resource/index.ts +3 -0
- package/src/access-interfaces/registered-names/index.ts +1 -0
- package/src/adapter/Base.ts +96 -0
- package/src/adapter/Network.ts +31 -0
- package/src/adapter/Settings.ts +30 -0
- package/src/adapter/index.ts +2 -0
- package/src/adapters/OsPubSubBridgeNetwork.ts +10 -0
- package/src/adapters/OsSettings.ts +7 -0
- package/src/adapters/OsXyoPublicNetwork.ts +9 -0
- package/src/adapters/index.ts +3 -0
- package/src/classes/cache/RunningAccessDappCache.ts +21 -0
- package/src/classes/cache/RunningDappCache.ts +50 -0
- package/src/classes/cache/index.ts +2 -0
- package/src/classes/dapp/DefaultsResource.ts +65 -0
- package/src/classes/dapp/access/Caller.ts +73 -0
- package/src/classes/dapp/access/Queries.ts +38 -0
- package/src/classes/dapp/access/Resource.ts +63 -0
- package/src/classes/dapp/access/index.ts +3 -0
- package/src/classes/dapp/index.ts +2 -0
- package/src/classes/index.ts +8 -0
- package/src/classes/lib/DappCreatorParams.ts +16 -0
- package/src/classes/lib/Insertable.ts +14 -0
- package/src/classes/lib/index.ts +2 -0
- package/src/classes/menu/Caller.ts +76 -0
- package/src/classes/menu/Queries.ts +59 -0
- package/src/classes/menu/Resource.ts +103 -0
- package/src/classes/menu/index.ts +2 -0
- package/src/classes/node/Creator.ts +96 -0
- package/src/classes/node/DefaultPayloads/DappAccessPayloads.ts +17 -0
- package/src/classes/node/DefaultPayloads/DefaultPayloads.ts +33 -0
- package/src/classes/node/DefaultPayloads/NodeInfoPayload.ts +27 -0
- package/src/classes/node/DefaultPayloads/SigningKeyPayloads.ts +85 -0
- package/src/classes/node/DefaultPayloads/index.ts +1 -0
- package/src/classes/node/ExternalModulePermissions/ExternalModulePermissions.ts +47 -0
- package/src/classes/node/ExternalModulePermissions/index.ts +1 -0
- package/src/classes/node/createDappContext.ts +52 -0
- package/src/classes/node/index.ts +3 -0
- package/src/classes/registration/DappRegistrationService.ts +146 -0
- package/src/classes/registration/DappRegistry.ts +121 -0
- package/src/classes/registration/ValidateDappAccessDiviner/Config.ts +19 -0
- package/src/classes/registration/ValidateDappAccessDiviner/Diviner.ts +132 -0
- package/src/classes/registration/ValidateDappAccessDiviner/index.ts +2 -0
- package/src/classes/registration/index.ts +2 -0
- package/src/classes/settings/Caller.ts +76 -0
- package/src/classes/settings/CallerBase.ts +24 -0
- package/src/classes/settings/Resource.ts +79 -0
- package/src/classes/settings/SettingsQueries.ts +38 -0
- package/src/classes/settings/badge/Caller.ts +30 -0
- package/src/classes/settings/badge/Queries.ts +18 -0
- package/src/classes/settings/badge/Resource.ts +54 -0
- package/src/classes/settings/badge/index.ts +2 -0
- package/src/classes/settings/index.ts +5 -0
- package/src/classes/system/ManageSystemDapps.ts +131 -0
- package/src/classes/system/Queries.ts +69 -0
- package/src/classes/system/index.ts +1 -0
- package/src/event/bus/Connection.ts +31 -0
- package/src/event/bus/EventBus.ts +145 -0
- package/src/event/bus/PubSubConnection.ts +28 -0
- package/src/event/bus/index.ts +3 -0
- package/src/event/connections/DappAccessRequest.ts +11 -0
- package/src/event/connections/DappsReady.ts +9 -0
- package/src/event/connections/ExposeDappRequest.ts +11 -0
- package/src/event/connections/OsPubSubNetworkReady.ts +12 -0
- package/src/event/connections/OsSettingsReady.ts +12 -0
- package/src/event/connections/OsXyoPublicReady.ts +12 -0
- package/src/event/connections/index.ts +6 -0
- package/src/event/index.ts +2 -0
- package/src/helpers/index.ts +1 -0
- package/src/helpers/monitor/XyOsMonitor.ts +52 -0
- package/src/helpers/monitor/index.ts +2 -0
- package/src/helpers/monitor/types.ts +5 -0
- package/src/index.ts +22 -0
- package/src/intent/Caller.ts +72 -0
- package/src/intent/Resource.ts +66 -0
- package/src/intent/index.ts +2 -0
- package/src/lib/ExternalStore.ts +7 -0
- package/src/lib/Listener.ts +1 -0
- package/src/lib/ModuleAccountPaths.ts +29 -0
- package/src/lib/ModuleNames.ts +3 -0
- package/src/lib/NameTransforms.ts +31 -0
- package/src/lib/PayloadStore.ts +98 -0
- package/src/lib/ResourceStores.ts +7 -0
- package/src/lib/index.ts +10 -0
- package/src/lib/initializeXns.ts +16 -0
- package/src/lib/isPayload.ts +24 -0
- package/src/lib/tokenPlacesSplit.ts +17 -0
- package/src/loadOsNode.ts +43 -0
- package/src/manifest/ManifestReplaceableTokens.ts +17 -0
- package/src/manifest/index.ts +2 -0
- package/src/manifest/os-node.manifest.json +132 -0
- package/src/manifests/dapp-window.manifest.json +36 -0
- package/src/manifests/index.ts +1 -0
- package/src/profileModuleEvents.ts +43 -0
- package/src/stack/Base.ts +153 -0
- package/src/stack/Manager.ts +48 -0
- package/src/stack/Map.ts +20 -0
- package/src/stack/OsPubSubNetworkStack.ts +70 -0
- package/src/stack/OsSettingsStack.ts +24 -0
- package/src/stack/XyoPublicNetworkStack.ts +32 -0
- package/src/stack/index.ts +6 -0
- package/src/types/global.d.ts +9 -0
- package/src/types/images.d.ts +5 -0
- package/src/utils/buildWalletSeedPhrasePayload.ts +41 -0
- package/src/utils/getApiDomain.ts +14 -0
- package/src/utils/index.ts +3 -0
- package/src/utils/renameObjKey.ts +22 -0
- package/src/wallet/DappSeedPhraseRepository.ts +95 -0
- package/src/wallet/SeedPhraseRepository.ts +32 -0
- package/src/wallet/index.ts +2 -0
- package/typedoc.json +5 -0
- package/xy.config.ts +10 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { assertEx } from '@xylabs/assert'
|
|
2
|
+
import type { DappId, RegisteredDapp, WindowDappNodeSet, XyOsContext } from '@xyo-network/os-model'
|
|
3
|
+
import { Mutex } from 'async-mutex'
|
|
4
|
+
|
|
5
|
+
import { XyOs } from '../../XyOs.ts'
|
|
6
|
+
import { createDappContext, DappContextCreator } from '../node/index.ts'
|
|
7
|
+
|
|
8
|
+
const findOrCreateMutex = new Mutex()
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* A cache for running node instances
|
|
12
|
+
*/
|
|
13
|
+
export class RunningDappCache {
|
|
14
|
+
private static _cache: { [key: DappId]: WindowDappNodeSet } = {}
|
|
15
|
+
|
|
16
|
+
static async findOrCreate(dapp: RegisteredDapp, xyOs: XyOsContext, allowedNames: string[], xnsNodeUrl: string | undefined, xnsNetwork: string | undefined): Promise<WindowDappNodeSet> {
|
|
17
|
+
const dappId = dapp.config.name
|
|
18
|
+
|
|
19
|
+
return await XyOs.monitor<WindowDappNodeSet>(
|
|
20
|
+
async () =>
|
|
21
|
+
await findOrCreateMutex.runExclusive(async () => {
|
|
22
|
+
const existingWindowDappSet = RunningDappCache.get(dappId)
|
|
23
|
+
if (existingWindowDappSet) {
|
|
24
|
+
console.debug('[DEBUG]', `RunningDappCache, using existing node for ${dappId}`)
|
|
25
|
+
const existingDappContext = assertEx(existingWindowDappSet.context, () => 'No context found in existing dapp node')
|
|
26
|
+
await DappContextCreator.primeDappArchivist(existingDappContext, xyOs, dappId)
|
|
27
|
+
return existingWindowDappSet
|
|
28
|
+
}
|
|
29
|
+
console.debug('[DEBUG]', 'RunningDappCache:creating', dappId)
|
|
30
|
+
const windowDappSet = await createDappContext(dapp, xyOs, allowedNames, xnsNodeUrl, xnsNetwork)
|
|
31
|
+
RunningDappCache.set(dappId, windowDappSet)
|
|
32
|
+
|
|
33
|
+
return windowDappSet
|
|
34
|
+
}),
|
|
35
|
+
{ additionalProperties: { dappId }, name: 'Loading dApp' },
|
|
36
|
+
)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
static get(key: DappId): WindowDappNodeSet | undefined {
|
|
40
|
+
return this._cache[key]
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
static has(key?: DappId) {
|
|
44
|
+
return key ? !!this._cache[key] : false
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
static set(key: DappId, value: WindowDappNodeSet) {
|
|
48
|
+
this._cache[key] = value
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { assertEx } from '@xylabs/assert'
|
|
2
|
+
import type { DappInjectableParams, NodeOsInfo, XyOsContext } from '@xyo-network/os-model'
|
|
3
|
+
import { isDappInjectableParams, isNodeOsInfo } from '@xyo-network/os-model'
|
|
4
|
+
|
|
5
|
+
import { DappCallerBase } from '../../DappCallerBase.ts'
|
|
6
|
+
import { DappDefaultsResourceQueries } from '../../DefaultsQueries.ts'
|
|
7
|
+
import type { Listener, ResourceStore } from '../../lib/index.ts'
|
|
8
|
+
import { PayloadStore } from '../../lib/index.ts'
|
|
9
|
+
|
|
10
|
+
export type DappDefaultsResourceViews = 'nodeOsInfo' | 'dappInjectableParamsFromRoute'
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* A resource for interacting with Dapp Defaults
|
|
14
|
+
*/
|
|
15
|
+
export class DappDefaultsResource extends DappCallerBase implements ResourceStore<DappDefaultsResourceViews> {
|
|
16
|
+
private _dappInjectableParamsFromRouteListener: PayloadStore<DappInjectableParams> | undefined
|
|
17
|
+
private _nodeOsInfoListener: PayloadStore<NodeOsInfo> | undefined
|
|
18
|
+
|
|
19
|
+
constructor(context: XyOsContext) {
|
|
20
|
+
super(context)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
get dappInjectableParamsFromRouteListener() {
|
|
24
|
+
return assertEx(this._dappInjectableParamsFromRouteListener, () => 'DappInjectableParams not found')
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
get nodeOsInfoListener() {
|
|
28
|
+
return assertEx(this._nodeOsInfoListener, () => 'NodeOsInfo not found')
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
get subscriptions() {
|
|
32
|
+
return {
|
|
33
|
+
dappInjectableParamsFromRoute: (cb: Listener) => this.dappInjectableParamsFromRouteListener.subscribe(cb),
|
|
34
|
+
nodeOsInfo: (cb: Listener) => this.nodeOsInfoListener.subscribe(cb),
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
get views() {
|
|
39
|
+
return {
|
|
40
|
+
dappInjectableParamsFromRoute: () => this.dappInjectableParamsFromRouteListener.getSnapshot(),
|
|
41
|
+
nodeOsInfo: () => this.nodeOsInfoListener.getSnapshot(),
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
cleanupListeners() {
|
|
46
|
+
this.nodeOsInfoListener.cleanupListeners()
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
async start() {
|
|
50
|
+
const archivist = await this.getDappArchivist()
|
|
51
|
+
const diviner = await this.getDappArchivistPayloadDiviner()
|
|
52
|
+
|
|
53
|
+
this._nodeOsInfoListener = await PayloadStore.create<NodeOsInfo>({
|
|
54
|
+
archivist,
|
|
55
|
+
getLatest: async () => await DappDefaultsResourceQueries.getNodeOsInfo(diviner),
|
|
56
|
+
idFunction: isNodeOsInfo,
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
this._dappInjectableParamsFromRouteListener = await PayloadStore.create<DappInjectableParams>({
|
|
60
|
+
archivist,
|
|
61
|
+
getLatest: async () => await DappDefaultsResourceQueries.getDappInjectableParamsFromRoute(diviner),
|
|
62
|
+
idFunction: isDappInjectableParams,
|
|
63
|
+
})
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { assertEx } from '@xylabs/assert'
|
|
2
|
+
import { ModuleFactoryLocator } from '@xyo-network/module-factory-locator'
|
|
3
|
+
import { asNodeInstance } from '@xyo-network/node-model'
|
|
4
|
+
import type {
|
|
5
|
+
PostRegistrationHandler,
|
|
6
|
+
RegisteredDappAccess,
|
|
7
|
+
RegisteredDappSet,
|
|
8
|
+
RegisteredDappSetResult,
|
|
9
|
+
XyOsContext } from '@xyo-network/os-model'
|
|
10
|
+
import {
|
|
11
|
+
isRegisteredDappAccessDappSet,
|
|
12
|
+
} from '@xyo-network/os-model'
|
|
13
|
+
import { PayloadBuilder } from '@xyo-network/payload-builder'
|
|
14
|
+
|
|
15
|
+
import { OsCallerBase } from '../../../OsCallerBase.ts'
|
|
16
|
+
import { RunningDappAccessCache, RunningDappCache } from '../../cache/index.ts'
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Caller for managing Dapp Access Nodes
|
|
20
|
+
* Start nodes that have been registered as accessible
|
|
21
|
+
* Grab their Access Node(s)
|
|
22
|
+
* Put RegisteredDappAccess payloads in RegisteredDappInterfacesArchivist
|
|
23
|
+
* Keep Service running that can service requests for Access Nodes
|
|
24
|
+
**/
|
|
25
|
+
export class DappAccessCaller extends OsCallerBase implements PostRegistrationHandler {
|
|
26
|
+
constructor(
|
|
27
|
+
context: XyOsContext,
|
|
28
|
+
private registeredDapps: RegisteredDappSetResult[],
|
|
29
|
+
private allowedNames: string[],
|
|
30
|
+
private xnsNodeUrl: string | undefined,
|
|
31
|
+
private xnsNetwork: string | undefined,
|
|
32
|
+
private platformLocator = new ModuleFactoryLocator(),
|
|
33
|
+
) {
|
|
34
|
+
super(context)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async start() {
|
|
38
|
+
const registeredDappAccessDappSets = this.registeredDapps.filter(isRegisteredDappAccessDappSet)
|
|
39
|
+
for (const registeredDappSet of registeredDappAccessDappSets) {
|
|
40
|
+
const context = await this.buildRunningDappCache(registeredDappSet, this.allowedNames)
|
|
41
|
+
|
|
42
|
+
for (const dappAccessor of registeredDappSet.dapp.accessors) {
|
|
43
|
+
await this.cacheAccessNode(dappAccessor, context)
|
|
44
|
+
await this.saveRegisteredDappInterfaces(dappAccessor)
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
private async buildRunningDappCache(registeredDappSet: RegisteredDappSet, allowedNames: string[]) {
|
|
50
|
+
const { context } = await RunningDappCache.findOrCreate(registeredDappSet.dapp, this.context, allowedNames, this.xnsNodeUrl, this.xnsNetwork)
|
|
51
|
+
if (!context) throw new Error('Dapp context not found')
|
|
52
|
+
return context
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
private async cacheAccessNode(dappAccessor: RegisteredDappAccess, context: XyOsContext) {
|
|
56
|
+
const accessNodeId = dappAccessor.rootModuleId
|
|
57
|
+
const accessNodeModule = assertEx(await context.root.resolve(accessNodeId), () => 'Access Node Module not found')
|
|
58
|
+
const accessNode = asNodeInstance(accessNodeModule, () => 'Access Node Module is not a NodeInstance')
|
|
59
|
+
|
|
60
|
+
RunningDappAccessCache.set(dappAccessor.registeringDappId, accessNode)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
private async saveRegisteredDappInterfaces(registeredDappAccess: RegisteredDappAccess) {
|
|
64
|
+
const archivist = await this.getRegisteredDappInterfacesArchivist()
|
|
65
|
+
|
|
66
|
+
const hash = await PayloadBuilder.dataHash(registeredDappAccess)
|
|
67
|
+
const [existing] = await archivist.get([hash])
|
|
68
|
+
if (existing) return
|
|
69
|
+
|
|
70
|
+
await archivist.insert([registeredDappAccess])
|
|
71
|
+
console.debug('[DEBUG] -', `Registered ${registeredDappAccess.registeringDappId} with ${registeredDappAccess.name} interface`)
|
|
72
|
+
}
|
|
73
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { DivinerInstance } from '@xyo-network/diviner-model'
|
|
2
|
+
import { PayloadDivinerQuerySchema } from '@xyo-network/diviner-payload-model'
|
|
3
|
+
import type { DappAccessRequest, RegisteredDappAccess } from '@xyo-network/os-model'
|
|
4
|
+
import { DappAccessRequestSchema, RegisteredDappAccessSchema } from '@xyo-network/os-model'
|
|
5
|
+
import type { WithMeta } from '@xyo-network/payload-model'
|
|
6
|
+
|
|
7
|
+
const noResults: unknown[] = []
|
|
8
|
+
|
|
9
|
+
export const DappAccessRequestQueries = {
|
|
10
|
+
async getAccessRequests(diviner: DivinerInstance) {
|
|
11
|
+
const query = {
|
|
12
|
+
limit: 1,
|
|
13
|
+
schema: PayloadDivinerQuerySchema,
|
|
14
|
+
schemas: [DappAccessRequestSchema],
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const results = (await diviner.divine([query])) as WithMeta<DappAccessRequest>[]
|
|
18
|
+
|
|
19
|
+
if (results.length === 0) {
|
|
20
|
+
return noResults as WithMeta<DappAccessRequest>[]
|
|
21
|
+
}
|
|
22
|
+
return results
|
|
23
|
+
},
|
|
24
|
+
async getRegisteredInterfaces(diviner: DivinerInstance) {
|
|
25
|
+
const query = {
|
|
26
|
+
limit: 1,
|
|
27
|
+
schema: PayloadDivinerQuerySchema,
|
|
28
|
+
schemas: [RegisteredDappAccessSchema],
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const results = (await diviner.divine([query])) as WithMeta<RegisteredDappAccess>[]
|
|
32
|
+
|
|
33
|
+
if (results.length === 0) {
|
|
34
|
+
return noResults as WithMeta<RegisteredDappAccess>[]
|
|
35
|
+
}
|
|
36
|
+
return results
|
|
37
|
+
},
|
|
38
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { assertEx } from '@xylabs/assert'
|
|
2
|
+
import type { DappAccessRequest, RegisteredDappAccess, XyOsContext } from '@xyo-network/os-model'
|
|
3
|
+
import { isDappAccessRequestWithMeta, isRegisteredDappAccess } from '@xyo-network/os-model'
|
|
4
|
+
|
|
5
|
+
import { DappCallerBase } from '../../../DappCallerBase.ts'
|
|
6
|
+
import type { Listener, ResourceStore } from '../../../lib/index.ts'
|
|
7
|
+
import { PayloadStore } from '../../../lib/index.ts'
|
|
8
|
+
import { DappAccessRequestQueries } from './Queries.ts'
|
|
9
|
+
|
|
10
|
+
export type DappAccessRequestViews = 'accessRequests' | 'registeredInterfaces'
|
|
11
|
+
|
|
12
|
+
export class DappAccessRequestResource extends DappCallerBase implements ResourceStore<DappAccessRequestViews> {
|
|
13
|
+
private _accessRequestListener: PayloadStore<DappAccessRequest> | undefined
|
|
14
|
+
private _registeredInterfacesListener: PayloadStore<RegisteredDappAccess> | undefined
|
|
15
|
+
|
|
16
|
+
constructor(context: XyOsContext) {
|
|
17
|
+
super(context)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
get accessRequestListener() {
|
|
21
|
+
return assertEx(this._accessRequestListener, () => 'accessRequests note found')
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
get registeredInterfacesListener() {
|
|
25
|
+
return assertEx(this._registeredInterfacesListener, () => 'registeredInterfaces note found')
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
get subscriptions() {
|
|
29
|
+
return {
|
|
30
|
+
accessRequests: (cb: Listener) => this.accessRequestListener.subscribe(cb),
|
|
31
|
+
registeredInterfaces: (cb: Listener) => this.registeredInterfacesListener.subscribe(cb),
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
get views() {
|
|
36
|
+
return {
|
|
37
|
+
accessRequests: () => this.accessRequestListener.getSnapshot(),
|
|
38
|
+
registeredInterfaces: () => this.registeredInterfacesListener.getSnapshot(),
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
cleanupListeners(): void {
|
|
43
|
+
this.accessRequestListener.cleanupListeners()
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Start the resource
|
|
47
|
+
async start() {
|
|
48
|
+
const archivist = await this.getDappArchivist()
|
|
49
|
+
const diviner = await this.getDappArchivistPayloadDiviner()
|
|
50
|
+
|
|
51
|
+
this._accessRequestListener = await PayloadStore.create<DappAccessRequest>({
|
|
52
|
+
archivist,
|
|
53
|
+
getLatest: async () => await DappAccessRequestQueries.getAccessRequests(diviner),
|
|
54
|
+
idFunction: isDappAccessRequestWithMeta,
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
this._registeredInterfacesListener = await PayloadStore.create<RegisteredDappAccess>({
|
|
58
|
+
archivist,
|
|
59
|
+
getLatest: async () => await DappAccessRequestQueries.getRegisteredInterfaces(diviner),
|
|
60
|
+
idFunction: isRegisteredDappAccess,
|
|
61
|
+
})
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export * from './cache/index.ts'
|
|
2
|
+
export * from './dapp/index.ts'
|
|
3
|
+
export * from './lib/index.ts'
|
|
4
|
+
export * from './menu/index.ts'
|
|
5
|
+
export * from './node/index.ts'
|
|
6
|
+
export * from './registration/index.ts'
|
|
7
|
+
export * from './settings/index.ts'
|
|
8
|
+
export * from './system/index.ts'
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { ModuleManifest } from '@xyo-network/manifest'
|
|
2
|
+
import type { ModuleFactoryLocator } from '@xyo-network/module-factory-locator'
|
|
3
|
+
import type { DappName, DappPackageManifestPayload, XyOsContext } from '@xyo-network/os-model'
|
|
4
|
+
import type { WalletInstance } from '@xyo-network/wallet-model'
|
|
5
|
+
|
|
6
|
+
export type DappNodesCreatorParams = {
|
|
7
|
+
config: {
|
|
8
|
+
dappName: DappName
|
|
9
|
+
payload: DappPackageManifestPayload
|
|
10
|
+
privateChildren?: ModuleManifest[]
|
|
11
|
+
publicChildren?: ModuleManifest[]
|
|
12
|
+
}
|
|
13
|
+
context: XyOsContext
|
|
14
|
+
locator?: ModuleFactoryLocator
|
|
15
|
+
wallet: WalletInstance
|
|
16
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { DappName, XyOsContext } from '@xyo-network/os-model'
|
|
2
|
+
import type { Payload } from '@xyo-network/payload-model'
|
|
3
|
+
|
|
4
|
+
export interface InsertableConstructor {
|
|
5
|
+
new (_xyOs: XyOsContext, dappName: DappName): DefaultPayloadsInsertable
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
type InsertableConstructorParams = ConstructorParameters<InsertableConstructor>
|
|
9
|
+
|
|
10
|
+
export interface DefaultPayloadsInsertable {
|
|
11
|
+
payloads(): Promise<Payload[]>
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const createInsertable = (insertable: InsertableConstructor, ...params: InsertableConstructorParams) => new insertable(...params)
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { PayloadDivinerQuerySchema } from '@xyo-network/diviner-payload-model'
|
|
2
|
+
import type {
|
|
3
|
+
DappInjectableParams,
|
|
4
|
+
DappNavItemSelection,
|
|
5
|
+
XyOsContext } from '@xyo-network/os-model'
|
|
6
|
+
import {
|
|
7
|
+
DappInjectableParamsSchema,
|
|
8
|
+
DappNavItemSelectionSchema,
|
|
9
|
+
} from '@xyo-network/os-model'
|
|
10
|
+
import { PayloadBuilder } from '@xyo-network/payload-builder'
|
|
11
|
+
import type { Payload, WithMeta } from '@xyo-network/payload-model'
|
|
12
|
+
|
|
13
|
+
import { DappCaller } from '../../Caller.ts'
|
|
14
|
+
|
|
15
|
+
export class DappMenuCaller extends DappCaller {
|
|
16
|
+
constructor(context: XyOsContext) {
|
|
17
|
+
super(context)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Add new Payloads to the dappArchivist if they haven't already
|
|
22
|
+
*
|
|
23
|
+
* @param {Payload[]} payloads
|
|
24
|
+
*/
|
|
25
|
+
async add(payloads: Payload[], force = false) {
|
|
26
|
+
const dappArchivist = await this.getDappArchivist()
|
|
27
|
+
|
|
28
|
+
for (const payload of payloads) {
|
|
29
|
+
const hash = await PayloadBuilder.dataHash(payload)
|
|
30
|
+
const [existing] = await dappArchivist.get([hash])
|
|
31
|
+
if (!existing || force) {
|
|
32
|
+
await dappArchivist.insert(payloads)
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async currentNavSelection(): Promise<DappNavItemSelection[] | undefined> {
|
|
38
|
+
const diviner = await this.getDappArchivistPayloadDiviner()
|
|
39
|
+
const query = {
|
|
40
|
+
limit: 1,
|
|
41
|
+
order: 'desc',
|
|
42
|
+
schema: PayloadDivinerQuerySchema,
|
|
43
|
+
schemas: [DappNavItemSelectionSchema],
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return (await diviner.divine([query])) as WithMeta<DappNavItemSelection>[]
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/*
|
|
50
|
+
* Indicate to the system that a nav item was selected
|
|
51
|
+
*
|
|
52
|
+
* @param {string} path
|
|
53
|
+
* @params {string} injectableParamsPath
|
|
54
|
+
* @returns Promise
|
|
55
|
+
*/
|
|
56
|
+
async makeNavItemSelection(path: string, injectableParamsPath?: string): Promise<void> {
|
|
57
|
+
const dappArchivist = await this.getDappArchivist()
|
|
58
|
+
const payload: DappNavItemSelection = {
|
|
59
|
+
path,
|
|
60
|
+
schema: DappNavItemSelectionSchema,
|
|
61
|
+
timestamp: Date.now(),
|
|
62
|
+
}
|
|
63
|
+
await dappArchivist.insert([payload])
|
|
64
|
+
|
|
65
|
+
if (injectableParamsPath) {
|
|
66
|
+
const injectableParams: DappInjectableParams = {
|
|
67
|
+
params: {},
|
|
68
|
+
path: injectableParamsPath,
|
|
69
|
+
schema: DappInjectableParamsSchema,
|
|
70
|
+
source: 'route',
|
|
71
|
+
timestamp: Date.now(),
|
|
72
|
+
}
|
|
73
|
+
await dappArchivist.insert([injectableParams])
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { DivinerInstance } from '@xyo-network/diviner-model'
|
|
2
|
+
import type { PayloadDivinerQueryPayload } from '@xyo-network/diviner-payload-model'
|
|
3
|
+
import { PayloadDivinerQuerySchema } from '@xyo-network/diviner-payload-model'
|
|
4
|
+
import type {
|
|
5
|
+
DappNavItem,
|
|
6
|
+
DappNavItemSelection,
|
|
7
|
+
DappNavMenuConfig } from '@xyo-network/os-model'
|
|
8
|
+
import {
|
|
9
|
+
DappNavItemSchema,
|
|
10
|
+
DappNavItemSelectionSchema,
|
|
11
|
+
DappNavMenuConfigSchema,
|
|
12
|
+
} from '@xyo-network/os-model'
|
|
13
|
+
import type { WithMeta, WithSources } from '@xyo-network/payload-model'
|
|
14
|
+
|
|
15
|
+
const NO_ITEMS: unknown[] = []
|
|
16
|
+
|
|
17
|
+
export const DappMenuQueries = {
|
|
18
|
+
async getMenuConfigs(diviner: DivinerInstance): Promise<WithSources<WithMeta<DappNavMenuConfig>>[]> {
|
|
19
|
+
const query: PayloadDivinerQueryPayload = {
|
|
20
|
+
limit: 1,
|
|
21
|
+
order: 'desc',
|
|
22
|
+
schema: PayloadDivinerQuerySchema,
|
|
23
|
+
schemas: [DappNavMenuConfigSchema],
|
|
24
|
+
}
|
|
25
|
+
return (await diviner.divine([query])) as WithMeta<WithSources<DappNavMenuConfig>>[]
|
|
26
|
+
},
|
|
27
|
+
|
|
28
|
+
async getMenuItems(diviner: DivinerInstance) {
|
|
29
|
+
const query: PayloadDivinerQueryPayload = {
|
|
30
|
+
order: 'desc',
|
|
31
|
+
schema: PayloadDivinerQuerySchema,
|
|
32
|
+
schemas: [DappNavItemSchema],
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const results = (await diviner.divine([query])) as WithMeta<WithSources<DappNavItem>>[]
|
|
36
|
+
return results.length > 0 ? results : (NO_ITEMS as WithMeta<WithSources<DappNavItem>>[])
|
|
37
|
+
},
|
|
38
|
+
|
|
39
|
+
async getNavItemSelections(diviner: DivinerInstance) {
|
|
40
|
+
const query: PayloadDivinerQueryPayload = {
|
|
41
|
+
limit: 1,
|
|
42
|
+
order: 'desc',
|
|
43
|
+
schema: PayloadDivinerQuerySchema,
|
|
44
|
+
schemas: [DappNavItemSelectionSchema],
|
|
45
|
+
}
|
|
46
|
+
const results = (await diviner.divine([query])) as WithMeta<WithSources<DappNavItemSelection>>[]
|
|
47
|
+
return results.length > 0 ? results : (NO_ITEMS as WithMeta<WithSources<DappNavItemSelection>>[])
|
|
48
|
+
},
|
|
49
|
+
|
|
50
|
+
async getVisibleMenuItems(diviner: DivinerInstance) {
|
|
51
|
+
const query: PayloadDivinerQueryPayload = {
|
|
52
|
+
order: 'desc',
|
|
53
|
+
schema: PayloadDivinerQuerySchema,
|
|
54
|
+
schemas: [DappNavItemSchema],
|
|
55
|
+
}
|
|
56
|
+
const results = (await diviner.divine([query])) as WithMeta<WithSources<DappNavItem>>[]
|
|
57
|
+
return results.filter(menuItem => menuItem.hidden !== true).sort((a, b) => ((a.weight ?? 0) > (b.weight ?? 0) ? 1 : -1))
|
|
58
|
+
},
|
|
59
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { assertEx } from '@xylabs/assert'
|
|
2
|
+
import type { DappNavItem, DappNavItemSelection, DappNavMenuConfig, XyOsContext } from '@xyo-network/os-model'
|
|
3
|
+
import { isDappNavItemSelection, isDappNavMenuConfig } from '@xyo-network/os-model'
|
|
4
|
+
import type { Payload, WithMeta, WithSources } from '@xyo-network/payload-model'
|
|
5
|
+
|
|
6
|
+
import { DappCaller } from '../../Caller.ts'
|
|
7
|
+
import type { Listener, ResourceStore } from '../../lib/index.ts'
|
|
8
|
+
import { PayloadStore } from '../../lib/index.ts'
|
|
9
|
+
import { DappMenuQueries } from './Queries.ts'
|
|
10
|
+
|
|
11
|
+
export type DappMenuResourceViews = 'menuConfigs' | 'menuItems' | 'menuItemsVisible' | 'menuItemSelections'
|
|
12
|
+
|
|
13
|
+
export type NavPayloadType<T extends Payload = Payload> = WithMeta<WithSources<T>>[]
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* A Repository for interacting with dapp menu items and config
|
|
17
|
+
*/
|
|
18
|
+
export class DappMenuResource extends DappCaller implements ResourceStore<DappMenuResourceViews> {
|
|
19
|
+
private _menuConfigListener: PayloadStore<DappNavMenuConfig> | undefined
|
|
20
|
+
private _menuItemListener: PayloadStore<DappNavItem> | undefined
|
|
21
|
+
private _menuItemSelectionListener: PayloadStore<DappNavItemSelection> | undefined
|
|
22
|
+
private _menuItemVisibleListener: PayloadStore<DappNavItem> | undefined
|
|
23
|
+
|
|
24
|
+
constructor(xyOsContext: XyOsContext) {
|
|
25
|
+
super(xyOsContext)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
get menuConfigListener() {
|
|
29
|
+
return assertEx(this._menuConfigListener, () => 'menuConfigListener note found')
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
get menuItemListener() {
|
|
33
|
+
return assertEx(this._menuItemListener, () => 'menuItemListener note found')
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
get menuItemSelectionListener() {
|
|
37
|
+
return assertEx(this._menuItemSelectionListener, () => 'menuItemSelectionListener note found')
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
get menuItemVisibleListener() {
|
|
41
|
+
return assertEx(this._menuItemVisibleListener, () => 'menuItemVisibleListener note found')
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** subscribe to latest set of payloads */
|
|
45
|
+
get subscriptions() {
|
|
46
|
+
return {
|
|
47
|
+
menuConfigs: (cb: Listener) => this.menuConfigListener.subscribe(cb),
|
|
48
|
+
menuItemSelections: (cb: Listener) => this.menuItemSelectionListener.subscribe(cb),
|
|
49
|
+
menuItems: (cb: Listener) => this.menuItemListener.subscribe(cb),
|
|
50
|
+
menuItemsVisible: (cb: Listener) => this.menuItemVisibleListener.subscribe(cb),
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Return the latest menu payloads from the repository
|
|
56
|
+
*/
|
|
57
|
+
get views() {
|
|
58
|
+
return {
|
|
59
|
+
menuConfigs: () => this.menuConfigListener.getSnapshot(),
|
|
60
|
+
menuItemSelections: () => this.menuItemSelectionListener.getSnapshot(),
|
|
61
|
+
menuItems: () => this.menuItemListener.getSnapshot(),
|
|
62
|
+
menuItemsVisible: () => this.menuItemVisibleListener.getSnapshot(),
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Remove all listeners and reset their class members
|
|
68
|
+
*/
|
|
69
|
+
cleanupListeners() {
|
|
70
|
+
this.menuConfigListener.cleanupListeners()
|
|
71
|
+
this.menuItemListener.cleanupListeners()
|
|
72
|
+
this.menuItemSelectionListener.cleanupListeners()
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Start the resource
|
|
77
|
+
*/
|
|
78
|
+
async start(): Promise<void> {
|
|
79
|
+
const dappArchivist = await this.getDappArchivist()
|
|
80
|
+
const dappArchivistPayloadDiviner = await this.getDappArchivistPayloadDiviner()
|
|
81
|
+
|
|
82
|
+
this._menuConfigListener = await PayloadStore.create<DappNavMenuConfig>({
|
|
83
|
+
archivist: dappArchivist,
|
|
84
|
+
getLatest: async () => await DappMenuQueries.getMenuConfigs(dappArchivistPayloadDiviner),
|
|
85
|
+
idFunction: isDappNavMenuConfig,
|
|
86
|
+
})
|
|
87
|
+
this._menuItemListener = await PayloadStore.create<DappNavItem>({
|
|
88
|
+
archivist: dappArchivist,
|
|
89
|
+
getLatest: async () => await DappMenuQueries.getMenuItems(dappArchivistPayloadDiviner),
|
|
90
|
+
idFunction: isDappNavMenuConfig,
|
|
91
|
+
})
|
|
92
|
+
this._menuItemVisibleListener = await PayloadStore.create<DappNavItem>({
|
|
93
|
+
archivist: dappArchivist,
|
|
94
|
+
getLatest: async () => await DappMenuQueries.getVisibleMenuItems(dappArchivistPayloadDiviner),
|
|
95
|
+
idFunction: isDappNavMenuConfig,
|
|
96
|
+
})
|
|
97
|
+
this._menuItemSelectionListener = await PayloadStore.create<DappNavItemSelection>({
|
|
98
|
+
archivist: dappArchivist,
|
|
99
|
+
getLatest: async () => await DappMenuQueries.getNavItemSelections(dappArchivistPayloadDiviner),
|
|
100
|
+
idFunction: isDappNavItemSelection,
|
|
101
|
+
})
|
|
102
|
+
}
|
|
103
|
+
}
|