@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,98 @@
|
|
|
1
|
+
import type { ArchivistInstance, ArchivistModuleEventData } from '@xyo-network/archivist'
|
|
2
|
+
import type { Payload, WithMeta, WithSources } from '@xyo-network/payload-model'
|
|
3
|
+
|
|
4
|
+
import type { ExternalStore } from './ExternalStore.ts'
|
|
5
|
+
import type { Listener } from './Listener.ts'
|
|
6
|
+
|
|
7
|
+
export interface PayloadStoreConfig<T extends Payload = Payload> {
|
|
8
|
+
archivist: ArchivistInstance
|
|
9
|
+
getLatest: () => Promise<WithMeta<WithSources<T>>[]>
|
|
10
|
+
idFunction: (schema: Payload) => boolean
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export class PayloadStore<T extends Payload = Payload> implements ExternalStore {
|
|
14
|
+
latest: WithMeta<T>[] = []
|
|
15
|
+
private deleteListeners: WeakRef<(args: ArchivistModuleEventData['deleted']) => void>[] = []
|
|
16
|
+
private insertListeners: WeakRef<(args: ArchivistModuleEventData['inserted']) => void>[] = []
|
|
17
|
+
private listeners: Listener[] = []
|
|
18
|
+
|
|
19
|
+
private constructor(private archivist: ArchivistInstance) {}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Initialize listeners on the archivist that update class member variables when new payloads are inserted
|
|
23
|
+
*/
|
|
24
|
+
static async create<T extends Payload = Payload>({ archivist, getLatest, idFunction }: PayloadStoreConfig<T>) {
|
|
25
|
+
const instance = new this<T>(archivist)
|
|
26
|
+
|
|
27
|
+
const insertListener = async ({ payloads }: ArchivistModuleEventData['inserted']) => {
|
|
28
|
+
// if any of the newly inserted payloads pass the idFunction check, rerun the query
|
|
29
|
+
if (payloads.some(idFunction)) {
|
|
30
|
+
instance.latest = await getLatest()
|
|
31
|
+
instance.emitChange()
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// when payloads are deleted, rerun the diviner query
|
|
36
|
+
const deleteListener = async () => {
|
|
37
|
+
instance.latest = await getLatest()
|
|
38
|
+
instance.emitChange()
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const weakRefInsertListener = new WeakRef(insertListener)
|
|
42
|
+
const weakRefDeleteListener = new WeakRef(deleteListener)
|
|
43
|
+
const insertListenerRef = weakRefInsertListener.deref()
|
|
44
|
+
const deleteListenerRef = weakRefDeleteListener.deref()
|
|
45
|
+
|
|
46
|
+
if (insertListenerRef) instance.archivist.on('inserted', insertListenerRef)
|
|
47
|
+
if (deleteListenerRef) instance.archivist.on('deleted', deleteListenerRef)
|
|
48
|
+
|
|
49
|
+
instance.insertListeners.push(weakRefInsertListener)
|
|
50
|
+
instance.deleteListeners.push(weakRefDeleteListener)
|
|
51
|
+
|
|
52
|
+
instance.latest = await getLatest()
|
|
53
|
+
return instance
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Remove all listeners and reset their class members
|
|
58
|
+
*/
|
|
59
|
+
cleanupListeners() {
|
|
60
|
+
this.removeListeners(this.insertListeners, 'inserted')
|
|
61
|
+
this.removeListeners(this.deleteListeners, 'deleted')
|
|
62
|
+
this.insertListeners = []
|
|
63
|
+
this.deleteListeners = []
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Get the current value of the store
|
|
68
|
+
*/
|
|
69
|
+
getSnapshot(): WithMeta<WithSources<T>>[] {
|
|
70
|
+
return this.latest
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Add a call back function that is invoked when new Payloads are inserted
|
|
75
|
+
*
|
|
76
|
+
* @param {PayloadListener} onStoreChange
|
|
77
|
+
*/
|
|
78
|
+
subscribe(onStoreChange: Listener) {
|
|
79
|
+
this.listeners.push(onStoreChange)
|
|
80
|
+
return () => {
|
|
81
|
+
this.listeners = this.listeners.filter(l => l !== onStoreChange)
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
private emitChange() {
|
|
86
|
+
for (const listener of this.listeners) {
|
|
87
|
+
listener()
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
92
|
+
private removeListeners(listeners: WeakRef<(args: any) => void>[], eventName: string) {
|
|
93
|
+
for (const listener of listeners) {
|
|
94
|
+
const listenerRef = listener.deref()
|
|
95
|
+
if (listenerRef) this.archivist.off(eventName, listenerRef)
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
package/src/lib/index.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export * from './ExternalStore.ts'
|
|
2
|
+
export * from './initializeXns.ts'
|
|
3
|
+
export * from './isPayload.ts'
|
|
4
|
+
export * from './Listener.ts'
|
|
5
|
+
export * from './ModuleAccountPaths.ts'
|
|
6
|
+
export * from './ModuleNames.ts'
|
|
7
|
+
export * from './NameTransforms.ts'
|
|
8
|
+
export * from './PayloadStore.ts'
|
|
9
|
+
export * from './ResourceStores.ts'
|
|
10
|
+
export * from './tokenPlacesSplit.ts'
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { asDivinerInstance } from '@xyo-network/diviner-model'
|
|
2
|
+
import { ResolveHelper } from '@xyo-network/module-model'
|
|
3
|
+
import { NameRegistrarTransformer } from '@xyo-network/module-resolver'
|
|
4
|
+
import type { NodeInstance } from '@xyo-network/node-model'
|
|
5
|
+
|
|
6
|
+
export const initializeXns = async (xnsNode: NodeInstance) => {
|
|
7
|
+
if (ResolveHelper.transformers.length === 0) {
|
|
8
|
+
const registrarDiviner = asDivinerInstance(await xnsNode?.resolve('AddressRecords:AddressRecordIndexDiviner'))
|
|
9
|
+
if (registrarDiviner) {
|
|
10
|
+
const transformer = new NameRegistrarTransformer(registrarDiviner, 'xyo')
|
|
11
|
+
ResolveHelper.transformers = [transformer]
|
|
12
|
+
return true
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
return false
|
|
16
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { AsObjectFactory } from '@xylabs/object'
|
|
2
|
+
import type { Payload, Schema } from '@xyo-network/payload-model'
|
|
3
|
+
|
|
4
|
+
export const isObject = (x: unknown): x is Record<string | symbol | number, unknown> => {
|
|
5
|
+
return typeof x === 'object' && !Array.isArray(x)
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export const isAnyPayload = (obj: unknown): obj is Payload => {
|
|
9
|
+
if (isObject(obj)) {
|
|
10
|
+
return typeof obj.schema === 'string'
|
|
11
|
+
}
|
|
12
|
+
return false
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const isPayload
|
|
16
|
+
= <T extends Payload>(schema: Schema[]) =>
|
|
17
|
+
(obj: unknown): obj is T => {
|
|
18
|
+
if (isAnyPayload(obj)) {
|
|
19
|
+
return schema.includes(obj.schema)
|
|
20
|
+
}
|
|
21
|
+
return false
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export const asPayload = <T extends Payload>(schema: Schema[]) => AsObjectFactory.create(isPayload<T>(schema))
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { assertEx } from '@xylabs/assert'
|
|
2
|
+
|
|
3
|
+
export const tokenPlacesSplit = (value: bigint, places: number): [bigint, bigint] => {
|
|
4
|
+
assertEx(places >= 0, () => 'Places has to be >= 0')
|
|
5
|
+
const factor = BigInt(10 ** Math.abs(places))
|
|
6
|
+
const remainder = value % factor
|
|
7
|
+
const wholeValue = value / factor
|
|
8
|
+
return [wholeValue, remainder]
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const tokenPlacesSplitString = (value: bigint | undefined, places: number): string => {
|
|
12
|
+
if (value === undefined) {
|
|
13
|
+
return '-'
|
|
14
|
+
}
|
|
15
|
+
const [wholeValue, remainder] = tokenPlacesSplit(value, places)
|
|
16
|
+
return `${wholeValue}.${remainder.toString().padStart(Math.abs(places), '0')}`
|
|
17
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { WalletInstance } from '@xyo-network/account'
|
|
2
|
+
import { IndexedDbArchivist } from '@xyo-network/archivist-indexeddb'
|
|
3
|
+
import { IndexedDbPayloadDiviner } from '@xyo-network/diviner-payload-indexeddb'
|
|
4
|
+
import type { PackageManifestPayload } from '@xyo-network/manifest'
|
|
5
|
+
import { ManifestWrapper } from '@xyo-network/manifest-wrapper'
|
|
6
|
+
import { ModuleFactoryLocator } from '@xyo-network/module-factory-locator'
|
|
7
|
+
import type { AttachableNodeInstance } from '@xyo-network/node-model'
|
|
8
|
+
|
|
9
|
+
import { osNodeManifest } from './manifest/index.ts'
|
|
10
|
+
|
|
11
|
+
// NOTE: Path "0'" is reserved for the exposed node in the kernel
|
|
12
|
+
const OS_NODE_PATH = "1'"
|
|
13
|
+
|
|
14
|
+
const getDefaultOsNodeLocator = (): ModuleFactoryLocator => {
|
|
15
|
+
const locator = new ModuleFactoryLocator()
|
|
16
|
+
locator.register(IndexedDbArchivist, { 'network.xyo.archivist.persistence.scope': 'device' })
|
|
17
|
+
locator.register(IndexedDbPayloadDiviner, { 'network.xyo.archivist.persistence.scope': 'device' })
|
|
18
|
+
return locator
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const loadOsNode = async (
|
|
22
|
+
osWallet: WalletInstance,
|
|
23
|
+
locator?: ModuleFactoryLocator,
|
|
24
|
+
): Promise<[AttachableNodeInstance]> => {
|
|
25
|
+
try {
|
|
26
|
+
// Create wallets for the OS & kernel nodes
|
|
27
|
+
const osNodeWallet = await osWallet.derivePath(OS_NODE_PATH)
|
|
28
|
+
|
|
29
|
+
// Create the OS node manifest
|
|
30
|
+
const osNodeLocator: ModuleFactoryLocator = locator ?? getDefaultOsNodeLocator()
|
|
31
|
+
const manifestWrapper = new ManifestWrapper(osNodeManifest as PackageManifestPayload, osNodeWallet, osNodeLocator)
|
|
32
|
+
|
|
33
|
+
// Create the OS & kernel nodes
|
|
34
|
+
const osNode = (await manifestWrapper.loadNodes())[0]
|
|
35
|
+
|
|
36
|
+
return [osNode]
|
|
37
|
+
} catch (e) {
|
|
38
|
+
const error = e as Error
|
|
39
|
+
console.error(`Error creating os node: ${error.message}`)
|
|
40
|
+
console.error(`Error creating os node: ${error.stack}`)
|
|
41
|
+
throw new Error(`Error creating os node: ${error.message}`)
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { getXnsDomain } from '@xyo-network/kernel'
|
|
2
|
+
import type { Payload } from '@xyo-network/payload-model'
|
|
3
|
+
|
|
4
|
+
export const ManifestReplaceableTokens = (xnsNodeUrl: string | undefined, xnsNetwork: string | undefined) => ({
|
|
5
|
+
'[REPLACE_WITH_NS_NODE_URL]': getXnsDomain(xnsNodeUrl, xnsNetwork),
|
|
6
|
+
})
|
|
7
|
+
|
|
8
|
+
export const ReplaceManifestTokens = (manifest: Payload, xnsNodeUrl: string | undefined, xnsNetwork: string | undefined) => {
|
|
9
|
+
// Replace ReplaceableTokens in the manifest
|
|
10
|
+
let stringifiedManifestReplaced = JSON.stringify(manifest)
|
|
11
|
+
|
|
12
|
+
for (const [token, value] of Object.entries(ManifestReplaceableTokens(xnsNodeUrl, xnsNetwork))) {
|
|
13
|
+
stringifiedManifestReplaced = stringifiedManifestReplaced.replaceAll(token, value)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return JSON.parse(stringifiedManifestReplaced)
|
|
17
|
+
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://raw.githubusercontent.com/XYOracleNetwork/sdk-xyo-client-js/main/packages/manifest/src/compilations/dapp-package-manifest-schema.json",
|
|
3
|
+
"nodes": [
|
|
4
|
+
{
|
|
5
|
+
"config": {
|
|
6
|
+
"accountPath": "0'",
|
|
7
|
+
"name": "OsNode",
|
|
8
|
+
"schema": "network.xyo.node.config"
|
|
9
|
+
},
|
|
10
|
+
"modules": {
|
|
11
|
+
"private": [],
|
|
12
|
+
"public": [
|
|
13
|
+
{
|
|
14
|
+
"config": {
|
|
15
|
+
"accountPath": "1'",
|
|
16
|
+
"name": "OSArchivist",
|
|
17
|
+
"dbName": "OSArchivist",
|
|
18
|
+
"labels": {
|
|
19
|
+
"network.xyo.archivist.persistence.scope": "device"
|
|
20
|
+
},
|
|
21
|
+
"storeName": "payloads",
|
|
22
|
+
"parents": {
|
|
23
|
+
"read": [
|
|
24
|
+
"Archivist"
|
|
25
|
+
]
|
|
26
|
+
},
|
|
27
|
+
"schema": "network.xyo.archivist.config"
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"config": {
|
|
32
|
+
"accountPath": "3'",
|
|
33
|
+
"name": "DappsArchivist",
|
|
34
|
+
"dbName": "DappsArchivist",
|
|
35
|
+
"labels": {
|
|
36
|
+
"network.xyo.archivist.persistence.scope": "device"
|
|
37
|
+
},
|
|
38
|
+
"storeName": "payloads",
|
|
39
|
+
"schema": "network.xyo.archivist.config"
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"config": {
|
|
44
|
+
"archivist": "DappsArchivist",
|
|
45
|
+
"dbVersion": 1,
|
|
46
|
+
"name": "DappsArchivistPayloadDiviner",
|
|
47
|
+
"labels": {
|
|
48
|
+
"network.xyo.archivist.persistence.scope": "device"
|
|
49
|
+
},
|
|
50
|
+
"schema": "network.xyo.diviner.payload.config"
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"config": {
|
|
55
|
+
"accountPath": "4'",
|
|
56
|
+
"dbName": "IntentArchivist",
|
|
57
|
+
"name": "IntentArchivist",
|
|
58
|
+
"storeName": "payloads",
|
|
59
|
+
"labels": {
|
|
60
|
+
"network.xyo.archivist.persistence.scope": "device"
|
|
61
|
+
},
|
|
62
|
+
"schema": "network.xyo.archivist.config"
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
"config": {
|
|
67
|
+
"accountPath": "7",
|
|
68
|
+
"archivist": "IntentArchivist",
|
|
69
|
+
"dbVersion": 1,
|
|
70
|
+
"name": "IntentArchivistPayloadDiviner",
|
|
71
|
+
"labels": {
|
|
72
|
+
"network.xyo.archivist.persistence.scope": "device"
|
|
73
|
+
},
|
|
74
|
+
"schema": "network.xyo.diviner.payload.config",
|
|
75
|
+
"storeName": "payloads"
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"config": {
|
|
80
|
+
"accountPath": "8",
|
|
81
|
+
"name": "RegisteredDappInterfacesArchivist",
|
|
82
|
+
"schema": "network.xyo.archivist.memory.config"
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
"config": {
|
|
87
|
+
"accountPath": "9'",
|
|
88
|
+
"name": "DappsArchivistDevelopment",
|
|
89
|
+
"parents": {
|
|
90
|
+
"write": [
|
|
91
|
+
"DappsArchivist"
|
|
92
|
+
]
|
|
93
|
+
},
|
|
94
|
+
"schema": "network.xyo.archivist.memory.config"
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
"config": {
|
|
99
|
+
"accountPath": "10",
|
|
100
|
+
"archivist": "DappsArchivistDevelopment",
|
|
101
|
+
"dbVersion": 1,
|
|
102
|
+
"name": "DappsArchivistPayloadDivinerDevelopment",
|
|
103
|
+
"labels": {
|
|
104
|
+
"network.xyo.generic.payload.diviner": "GenericPayloadDiviner"
|
|
105
|
+
},
|
|
106
|
+
"schema": "network.xyo.diviner.payload.generic.config"
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
"config": {
|
|
111
|
+
"name": "OsPubSubNetworkStackNode",
|
|
112
|
+
"schema": "network.xyo.node.config"
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
"config": {
|
|
117
|
+
"name": "OsSettingsStackNode",
|
|
118
|
+
"schema": "network.xyo.node.config"
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
"config": {
|
|
123
|
+
"name": "OsXyoPublicNetworkStackNode",
|
|
124
|
+
"schema": "network.xyo.node.config"
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
]
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
],
|
|
131
|
+
"schema": "network.xyo.manifest.package.dapp"
|
|
132
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://raw.githubusercontent.com/XYOracleNetwork/sdk-xyo-client-js/main/packages/manifest/src/compilations/dapp-package-manifest-schema.json",
|
|
3
|
+
"nodes": [
|
|
4
|
+
{
|
|
5
|
+
"config": {
|
|
6
|
+
"accountPath": "0'",
|
|
7
|
+
"name": "Dapp",
|
|
8
|
+
"schema": "network.xyo.node.config"
|
|
9
|
+
},
|
|
10
|
+
"modules": {
|
|
11
|
+
"private": [],
|
|
12
|
+
"public": [
|
|
13
|
+
{
|
|
14
|
+
"config": {
|
|
15
|
+
"accountPath": "0'/0'",
|
|
16
|
+
"name": "DappArchivist",
|
|
17
|
+
"schema": "network.xyo.archivist.memory.config"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"config": {
|
|
22
|
+
"accountPath": "0'/1'",
|
|
23
|
+
"archivist": "DappArchivist",
|
|
24
|
+
"labels": {
|
|
25
|
+
"network.xyo.generic.payload.diviner": "GenericPayloadDiviner"
|
|
26
|
+
},
|
|
27
|
+
"name": "DappArchivistPayloadDiviner",
|
|
28
|
+
"schema": "network.xyo.diviner.payload.config"
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
]
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
],
|
|
35
|
+
"schema": "network.xyo.manifest.package.dapp"
|
|
36
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as DappWindowManifest } from './dapp-window.manifest.json'
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { Address } from '@xylabs/hex'
|
|
2
|
+
import type { QuerySendStartedEventArgs } from '@xyo-network/bridge-model'
|
|
3
|
+
import type { ModuleInstance } from '@xyo-network/module-model'
|
|
4
|
+
import { PayloadBuilder } from '@xyo-network/payload-builder'
|
|
5
|
+
|
|
6
|
+
const DISPLAY_EVENT_COUNT_FREQUENCY = 100 as const
|
|
7
|
+
|
|
8
|
+
export interface ProfileEventsData {
|
|
9
|
+
allEventCount: number
|
|
10
|
+
eventCounts: { [key: string | number | symbol]: number }
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const profileData: Record<Address, ProfileEventsData> = {}
|
|
14
|
+
|
|
15
|
+
export const profileModuleEvents = (mod: ModuleInstance) => {
|
|
16
|
+
const modRef = new WeakRef(mod) // prevent memory leak
|
|
17
|
+
mod.onAny(async (eventName, args) => {
|
|
18
|
+
const mod = modRef.deref()
|
|
19
|
+
if (mod) {
|
|
20
|
+
const data = profileData[mod.address] ?? { allEventCount: 0, eventCounts: {} }
|
|
21
|
+
profileData[mod.address] = data
|
|
22
|
+
data.allEventCount += 1
|
|
23
|
+
data.eventCounts[eventName] = (data.eventCounts[eventName] ?? 0) + 1
|
|
24
|
+
if (eventName === 'querySendStarted') {
|
|
25
|
+
const { query, payloads = [] } = args as QuerySendStartedEventArgs
|
|
26
|
+
const pairs = await PayloadBuilder.dataHashPairs(payloads)
|
|
27
|
+
const foundPair = pairs.find(([, hash]) => hash === query.query)
|
|
28
|
+
if (foundPair) {
|
|
29
|
+
const [payload] = foundPair
|
|
30
|
+
console.log(`querySendStarted: ${payload.schema}`)
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
if (eventName === 'querySendFinished') {
|
|
34
|
+
const { query } = args as QuerySendStartedEventArgs
|
|
35
|
+
console.log(`querySendFinished: ${query.query}`)
|
|
36
|
+
}
|
|
37
|
+
if (data.allEventCount % DISPLAY_EVENT_COUNT_FREQUENCY === 0) {
|
|
38
|
+
console.log(`[PROFILE] - ${mod.id} Event Counts:`)
|
|
39
|
+
console.log(data.eventCounts)
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
})
|
|
43
|
+
}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { assertEx } from '@xylabs/assert'
|
|
2
|
+
import { forget } from '@xylabs/forget'
|
|
3
|
+
import type { BaseParams } from '@xylabs/object'
|
|
4
|
+
import { BaseEmitter } from '@xyo-network/module-abstract'
|
|
5
|
+
import type { ModuleIdentifier } from '@xyo-network/module-model'
|
|
6
|
+
import { isModuleInstance } from '@xyo-network/module-model'
|
|
7
|
+
import type { AttachableNodeInstance } from '@xyo-network/node-model'
|
|
8
|
+
import { asAttachableNodeInstance } from '@xyo-network/node-model'
|
|
9
|
+
import type { AdapterSetCreator, NodeAdapter, NodeAdapterBaseEvents, StackBaseEvents, StackInitializer, XyOsContext } from '@xyo-network/os-model'
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Stack Base Class
|
|
13
|
+
*
|
|
14
|
+
* Listens for changes in adapter connections, update the stack node, and emits events when the stack is ready
|
|
15
|
+
*/
|
|
16
|
+
export class StackBase extends BaseEmitter<BaseParams, StackBaseEvents> implements StackInitializer {
|
|
17
|
+
// flag to check that all adapters are initialized
|
|
18
|
+
initialized = false
|
|
19
|
+
|
|
20
|
+
// adapters to initialize into the stack
|
|
21
|
+
private _adapterSet: NodeAdapter[]
|
|
22
|
+
|
|
23
|
+
private _context: XyOsContext
|
|
24
|
+
|
|
25
|
+
// stack node
|
|
26
|
+
private _stack: AttachableNodeInstance | undefined
|
|
27
|
+
|
|
28
|
+
// stack node module identifier for the stack
|
|
29
|
+
private _stackNodeModuleId: ModuleIdentifier
|
|
30
|
+
|
|
31
|
+
// list of initialized nodes
|
|
32
|
+
private initializedNodes: AttachableNodeInstance[] = []
|
|
33
|
+
|
|
34
|
+
// list of listeners - lister type not important since its only recalled to stop listening
|
|
35
|
+
|
|
36
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
37
|
+
private listeners: { adapter: NodeAdapter; eventName: string; listener: (args: any) => void }[] = []
|
|
38
|
+
|
|
39
|
+
constructor(context: XyOsContext, adapterSet: AdapterSetCreator, stackNodeModuleId: ModuleIdentifier) {
|
|
40
|
+
super({})
|
|
41
|
+
this._context = context
|
|
42
|
+
this._adapterSet = adapterSet(assertEx(this.context.kernel, 'Kernel access required'))
|
|
43
|
+
this._stackNodeModuleId = stackNodeModuleId
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
get adapterSet(): NodeAdapter[] {
|
|
47
|
+
return assertEx(this._adapterSet, () => `${this.stackNodeModuleId} adapters not initialized`)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
get context(): XyOsContext {
|
|
51
|
+
return assertEx(this._context, () => `${this.stackNodeModuleId} stack context not initialized`)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
get stack(): AttachableNodeInstance {
|
|
55
|
+
return assertEx(this._stack, () => `${this.stackNodeModuleId} stack node not initialized`)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
get stackNodeModuleId(): ModuleIdentifier {
|
|
59
|
+
return assertEx(this._stackNodeModuleId, () => 'Stack node module identifier not initialized')
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
initialize() {
|
|
63
|
+
this.assignStack()
|
|
64
|
+
// watch for adapter connection changes
|
|
65
|
+
for (const adapter of this.adapterSet) {
|
|
66
|
+
// listen for driver ready events
|
|
67
|
+
const driverReadyListener = async ({ node }: NodeAdapterBaseEvents['driverReady']) => await this.handleDriverReady(node)
|
|
68
|
+
adapter.on('driverReady', driverReadyListener)
|
|
69
|
+
this.listeners.push({ adapter: adapter, eventName: 'driverReady', listener: driverReadyListener })
|
|
70
|
+
|
|
71
|
+
// listen for driver error events
|
|
72
|
+
const driverErrorListener = async ({ error }: NodeAdapterBaseEvents['driverError']) => {
|
|
73
|
+
console.error(`Error updating ${this.stackNodeModuleId} stack node`, error)
|
|
74
|
+
await this.emit('driverError', { error })
|
|
75
|
+
}
|
|
76
|
+
adapter.on('driverError', driverErrorListener)
|
|
77
|
+
this.listeners.push({ adapter: adapter, eventName: 'driverError', listener: driverErrorListener })
|
|
78
|
+
|
|
79
|
+
// start the adapter
|
|
80
|
+
const startAdapter = async () => await adapter.start()
|
|
81
|
+
forget(startAdapter())
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Stops the stack
|
|
87
|
+
*/
|
|
88
|
+
stop() {
|
|
89
|
+
for (const { eventName, listener, adapter } of this.listeners) {
|
|
90
|
+
// stop the adapter
|
|
91
|
+
adapter.off(eventName, listener)
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Adds a node to the stack. Idempotent to avoid adding the
|
|
97
|
+
* same node multiple times
|
|
98
|
+
* @param node The node to add to the stack
|
|
99
|
+
* @returns
|
|
100
|
+
*/
|
|
101
|
+
private async addNodeToStackNode(node: AttachableNodeInstance) {
|
|
102
|
+
// Locate the stack node
|
|
103
|
+
const stackNode = await this.getStackNode()
|
|
104
|
+
|
|
105
|
+
// If the node is already attached as there's no need to re-attach
|
|
106
|
+
const existingModule = await stackNode.resolve(node.address, { direction: 'down' })
|
|
107
|
+
if (isModuleInstance(existingModule)) return
|
|
108
|
+
|
|
109
|
+
// Register & attach the new node
|
|
110
|
+
await stackNode.register?.(node)
|
|
111
|
+
await stackNode.attach?.(node.address, true)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
private assignStack() {
|
|
115
|
+
const assign = async () => {
|
|
116
|
+
const stackNode = await this.getStackNode()
|
|
117
|
+
this._stack = stackNode
|
|
118
|
+
}
|
|
119
|
+
forget(assign())
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
private async getStackNode() {
|
|
123
|
+
const mod = assertEx(await this.context.root.resolve(this.stackNodeModuleId), () => `${this.stackNodeModuleId} not found`)
|
|
124
|
+
return asAttachableNodeInstance(mod, () => `${this.stackNodeModuleId} not a NodeInstance`)
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
private async handleDriverReady(node: AttachableNodeInstance) {
|
|
128
|
+
try {
|
|
129
|
+
// eagerly emit that the driver is ready
|
|
130
|
+
await this.emit('driverReady', { node })
|
|
131
|
+
|
|
132
|
+
await this.addNodeToStackNode(node)
|
|
133
|
+
|
|
134
|
+
await this.updateInitializationState(node)
|
|
135
|
+
} catch (error) {
|
|
136
|
+
console.error(`Error updating ${this.stackNodeModuleId} stack node`, node.id, error)
|
|
137
|
+
await this.emit('stackError', { error: error as Error })
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
private async updateInitializationState(node: AttachableNodeInstance) {
|
|
142
|
+
// update the initialized nodes list
|
|
143
|
+
this.initializedNodes.push(node)
|
|
144
|
+
|
|
145
|
+
// update the initialized flag
|
|
146
|
+
this.initialized = this.adapterSet.every(n => n.initialized)
|
|
147
|
+
|
|
148
|
+
// notify all initialized listeners
|
|
149
|
+
if (this.initialized) {
|
|
150
|
+
await this.emit('initialized', { stack: await this.getStackNode() })
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { AdapterSetCreator, StackInitializer, XyOsContext } from '@xyo-network/os-model'
|
|
2
|
+
|
|
3
|
+
import type { StackBase } from './Base.ts'
|
|
4
|
+
|
|
5
|
+
export interface StackConstructor {
|
|
6
|
+
new (context: XyOsContext, adapters: AdapterSetCreator): StackBase
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface UninitializedStackSet {
|
|
10
|
+
adapters: AdapterSetCreator
|
|
11
|
+
stack: StackConstructor
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface UninitializedStackMap {
|
|
15
|
+
[key: string]: UninitializedStackSet
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export class StackManager {
|
|
19
|
+
private initializedStacksMap: Map<string, StackInitializer> = new Map()
|
|
20
|
+
private stackMap: UninitializedStackMap
|
|
21
|
+
|
|
22
|
+
constructor(stackMap: UninitializedStackMap) {
|
|
23
|
+
this.stackMap = stackMap
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
private get stacks() {
|
|
27
|
+
return this.initializedStacksMap
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
getStack<TStack = StackBase>(key: string) {
|
|
31
|
+
return this.initializedStacksMap.get(key) as TStack | undefined
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
initialize(context: XyOsContext) {
|
|
35
|
+
for (const [key, stackSet] of Object.entries(this.stackMap)) {
|
|
36
|
+
const { stack: Stack, adapters: stackNodeModuleId } = stackSet
|
|
37
|
+
const initializedStack = new Stack(context, stackNodeModuleId)
|
|
38
|
+
initializedStack.initialize()
|
|
39
|
+
this.stacks.set(key, initializedStack)
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
stop() {
|
|
44
|
+
for (const stack of this.stacks.values()) {
|
|
45
|
+
stack.stop()
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|