@xyo-network/diviner-stateful 2.84.1

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.
Files changed (91) hide show
  1. package/LICENSE +165 -0
  2. package/README.md +13 -0
  3. package/dist/browser/Config.d.cts +21 -0
  4. package/dist/browser/Config.d.cts.map +1 -0
  5. package/dist/browser/Config.d.mts +21 -0
  6. package/dist/browser/Config.d.mts.map +1 -0
  7. package/dist/browser/Config.d.ts +21 -0
  8. package/dist/browser/Config.d.ts.map +1 -0
  9. package/dist/browser/Diviner.d.cts +49 -0
  10. package/dist/browser/Diviner.d.cts.map +1 -0
  11. package/dist/browser/Diviner.d.mts +49 -0
  12. package/dist/browser/Diviner.d.mts.map +1 -0
  13. package/dist/browser/Diviner.d.ts +49 -0
  14. package/dist/browser/Diviner.d.ts.map +1 -0
  15. package/dist/browser/DivinerMixin.d.cts +3758 -0
  16. package/dist/browser/DivinerMixin.d.cts.map +1 -0
  17. package/dist/browser/DivinerMixin.d.mts +3758 -0
  18. package/dist/browser/DivinerMixin.d.mts.map +1 -0
  19. package/dist/browser/DivinerMixin.d.ts +3758 -0
  20. package/dist/browser/DivinerMixin.d.ts.map +1 -0
  21. package/dist/browser/Params.d.cts +8 -0
  22. package/dist/browser/Params.d.cts.map +1 -0
  23. package/dist/browser/Params.d.mts +8 -0
  24. package/dist/browser/Params.d.mts.map +1 -0
  25. package/dist/browser/Params.d.ts +8 -0
  26. package/dist/browser/Params.d.ts.map +1 -0
  27. package/dist/browser/Schema.d.cts +3 -0
  28. package/dist/browser/Schema.d.cts.map +1 -0
  29. package/dist/browser/Schema.d.mts +3 -0
  30. package/dist/browser/Schema.d.mts.map +1 -0
  31. package/dist/browser/Schema.d.ts +3 -0
  32. package/dist/browser/Schema.d.ts.map +1 -0
  33. package/dist/browser/index.cjs +238 -0
  34. package/dist/browser/index.cjs.map +1 -0
  35. package/dist/browser/index.d.cts +6 -0
  36. package/dist/browser/index.d.cts.map +1 -0
  37. package/dist/browser/index.d.mts +6 -0
  38. package/dist/browser/index.d.mts.map +1 -0
  39. package/dist/browser/index.d.ts +6 -0
  40. package/dist/browser/index.d.ts.map +1 -0
  41. package/dist/browser/index.js +218 -0
  42. package/dist/browser/index.js.map +1 -0
  43. package/dist/node/Config.d.cts +21 -0
  44. package/dist/node/Config.d.cts.map +1 -0
  45. package/dist/node/Config.d.mts +21 -0
  46. package/dist/node/Config.d.mts.map +1 -0
  47. package/dist/node/Config.d.ts +21 -0
  48. package/dist/node/Config.d.ts.map +1 -0
  49. package/dist/node/Diviner.d.cts +49 -0
  50. package/dist/node/Diviner.d.cts.map +1 -0
  51. package/dist/node/Diviner.d.mts +49 -0
  52. package/dist/node/Diviner.d.mts.map +1 -0
  53. package/dist/node/Diviner.d.ts +49 -0
  54. package/dist/node/Diviner.d.ts.map +1 -0
  55. package/dist/node/DivinerMixin.d.cts +3758 -0
  56. package/dist/node/DivinerMixin.d.cts.map +1 -0
  57. package/dist/node/DivinerMixin.d.mts +3758 -0
  58. package/dist/node/DivinerMixin.d.mts.map +1 -0
  59. package/dist/node/DivinerMixin.d.ts +3758 -0
  60. package/dist/node/DivinerMixin.d.ts.map +1 -0
  61. package/dist/node/Params.d.cts +8 -0
  62. package/dist/node/Params.d.cts.map +1 -0
  63. package/dist/node/Params.d.mts +8 -0
  64. package/dist/node/Params.d.mts.map +1 -0
  65. package/dist/node/Params.d.ts +8 -0
  66. package/dist/node/Params.d.ts.map +1 -0
  67. package/dist/node/Schema.d.cts +3 -0
  68. package/dist/node/Schema.d.cts.map +1 -0
  69. package/dist/node/Schema.d.mts +3 -0
  70. package/dist/node/Schema.d.mts.map +1 -0
  71. package/dist/node/Schema.d.ts +3 -0
  72. package/dist/node/Schema.d.ts.map +1 -0
  73. package/dist/node/index.d.cts +6 -0
  74. package/dist/node/index.d.cts.map +1 -0
  75. package/dist/node/index.d.mts +6 -0
  76. package/dist/node/index.d.mts.map +1 -0
  77. package/dist/node/index.d.ts +6 -0
  78. package/dist/node/index.d.ts.map +1 -0
  79. package/dist/node/index.js +259 -0
  80. package/dist/node/index.js.map +1 -0
  81. package/dist/node/index.mjs +232 -0
  82. package/dist/node/index.mjs.map +1 -0
  83. package/package.json +78 -0
  84. package/src/Config.ts +24 -0
  85. package/src/Diviner.ts +127 -0
  86. package/src/DivinerMixin.ts +144 -0
  87. package/src/Params.ts +9 -0
  88. package/src/Schema.ts +2 -0
  89. package/src/index.ts +5 -0
  90. package/src/spec/TestManifest.json +51 -0
  91. package/typedoc.json +5 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/Schema.ts","../../src/Config.ts","../../src/Diviner.ts","../../src/DivinerMixin.ts"],"sourcesContent":["export const StatefulDivinerSchema = 'network.xyo.diviner.stateful' as const\nexport type StatefulDivinerSchema = typeof StatefulDivinerSchema\n","import { DivinerConfig } from '@xyo-network/diviner-model'\n\nimport { StatefulDivinerSchema } from './Schema'\n\n/**\n * The schema for a Stateful Diviner config\n */\nexport const StatefulDivinerConfigSchema = `${StatefulDivinerSchema}.config` as const\n/**\n * The schema for a Stateful Diviner config\n */\nexport type StatefulDivinerConfigSchema = typeof StatefulDivinerConfigSchema\n\n/**\n * The config for a Stateful Diviner\n */\nexport type StatefulDivinerConfig = DivinerConfig<{\n schema: StatefulDivinerConfigSchema\n stateStore: {\n archivist: string\n boundWitnessDiviner: string\n payloadDiviner: string\n }\n}>\n","import { assertEx } from '@xylabs/assert'\nimport { AbstractDiviner } from '@xyo-network/abstract-diviner'\nimport { ArchivistWrapper } from '@xyo-network/archivist-wrapper'\nimport { BoundWitnessBuilder } from '@xyo-network/boundwitness-builder'\nimport { isBoundWitness } from '@xyo-network/boundwitness-model'\nimport { BoundWitnessDivinerQueryPayload, BoundWitnessDivinerQuerySchema } from '@xyo-network/diviner-boundwitness-model'\nimport { DivinerConfigSchema, DivinerModule, DivinerModuleEventData } from '@xyo-network/diviner-model'\nimport { DivinerWrapper } from '@xyo-network/diviner-wrapper'\nimport { isModuleState, ModuleState, ModuleStateSchema, StateDictionary } from '@xyo-network/module-model'\nimport { PayloadBuilder } from '@xyo-network/payload-builder'\nimport { Payload } from '@xyo-network/payload-model'\n\nimport { StatefulDivinerConfigSchema } from './Config'\nimport { StatefulDivinerParams } from './Params'\n\nconst moduleName = 'StatefulDiviner'\n\n/**\n * A Diviner that maintains state\n */\nexport abstract class StatefulDiviner<\n TParams extends StatefulDivinerParams = StatefulDivinerParams,\n TIn extends Payload = Payload,\n TOut extends Payload = Payload,\n TEventData extends DivinerModuleEventData<DivinerModule<TParams>, TIn, TOut> = DivinerModuleEventData<DivinerModule<TParams>, TIn, TOut>,\n TState extends StateDictionary = StateDictionary,\n> extends AbstractDiviner<TParams, TIn, TOut, TEventData> {\n static override readonly configSchemas: string[] = [DivinerConfigSchema, StatefulDivinerConfigSchema]\n\n /**\n * The last state\n */\n protected _lastState?: ModuleState<TState>\n\n /**\n * Commit the internal state of the Diviner process. This is similar\n * to a transaction completion in a database and should only be called\n * when results have been successfully persisted to the appropriate\n * external stores.\n * @param nextState The state to commit\n */\n protected async commitState(nextState: ModuleState<TState>) {\n // Don't commit state if no state has changed\n if (nextState.state.offset === this._lastState?.state.offset) return\n this._lastState = nextState\n const archivist = await this.getArchivistForStateStore()\n const [bw] = await new BoundWitnessBuilder().payload(nextState).witness(this.account).build()\n await archivist.insert([bw, nextState])\n }\n\n /**\n * Retrieves the archivist for the specified store\n * @param store The store to retrieve the archivist for\n * @returns The archivist for the specified store\n */\n protected async getArchivistForStateStore() {\n const name = assertEx(this.config?.stateStore.archivist, () => `${moduleName}: Config for stateStore.archivist not specified`)\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve stateStore.archivist`)\n return ArchivistWrapper.wrap(mod, this.account)\n }\n\n /**\n * Retrieves the BoundWitness Diviner for the specified store\n * @param store The store to retrieve the BoundWitness Diviner for\n * @returns The BoundWitness Diviner for the specified store\n */\n protected async getBoundWitnessDivinerForStateStore() {\n const name = assertEx(this.config?.stateStore.boundWitnessDiviner, () => `${moduleName}: Config for stateStore.boundWitnessDiviner not specified`)\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve stateStore.boundWitnessDiviner`)\n return DivinerWrapper.wrap(mod, this.account)\n }\n\n /**\n * Retrieves the Payload Diviner for the specified store\n * @param store The store to retrieve the Payload Diviner for\n * @returns The Payload Diviner for the specified store\n */\n protected async getPayloadDivinerForStateStore() {\n const name = assertEx(this.config?.stateStore?.payloadDiviner, () => `${moduleName}: Config for stateStore.payloadDiviner not specified`)\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve stateStore.payloadDiviner`)\n return DivinerWrapper.wrap(mod, this.account)\n }\n\n /**\n * Retrieves the last state of the Diviner process. Used to recover state after\n * preemptions, reboots, etc.\n */\n protected async retrieveState(): Promise<ModuleState<TState> | undefined> {\n if (this._lastState) return this._lastState\n let hash: string = ''\n const diviner = await this.getBoundWitnessDivinerForStateStore()\n const query = await new PayloadBuilder<BoundWitnessDivinerQueryPayload>({ schema: BoundWitnessDivinerQuerySchema })\n .fields({\n address: this.account.address,\n limit: 1,\n offset: 0,\n order: 'desc',\n payload_schemas: [ModuleStateSchema],\n })\n .build()\n const boundWitnesses = await diviner.divine([query])\n if (boundWitnesses.length > 0) {\n const boundWitness = boundWitnesses[0]\n if (isBoundWitness(boundWitness)) {\n // Find the index for this address in the BoundWitness that is a ModuleState\n hash = boundWitness.addresses\n .map((address, index) => ({ address, index }))\n .filter(({ address }) => address === this.account.address)\n .reduce(\n (prev, curr) => (boundWitness.payload_schemas?.[curr?.index] === ModuleStateSchema ? boundWitness.payload_hashes[curr?.index] : prev),\n '',\n )\n }\n }\n\n // If we able to located the last state\n if (hash) {\n // Get last state\n const archivist = await this.getArchivistForStateStore()\n const payload = (await archivist.get([hash])).find(isModuleState<TState>)\n if (payload) {\n return payload\n }\n }\n return undefined\n }\n}\n","import { assertEx } from '@xylabs/assert'\nimport { asArchivistInstance } from '@xyo-network/archivist'\nimport { BoundWitnessBuilder } from '@xyo-network/boundwitness-builder'\nimport { isBoundWitness } from '@xyo-network/boundwitness-model'\nimport { BoundWitnessDivinerQueryPayload, BoundWitnessDivinerQuerySchema } from '@xyo-network/diviner-boundwitness-model'\nimport { asDivinerInstance } from '@xyo-network/diviner-model'\nimport {\n AnyConfigSchema,\n isModuleState,\n ModuleInstance,\n ModuleParams,\n ModuleState,\n ModuleStateSchema,\n StateDictionary,\n} from '@xyo-network/module-model'\nimport { PayloadBuilder } from '@xyo-network/payload-builder'\n\nimport { StatefulDivinerConfig } from './Config'\n\nexport type StatefulModuleParams = ModuleParams<AnyConfigSchema<StatefulDivinerConfig>>\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type AnyModule<TParams extends StatefulModuleParams = StatefulModuleParams> = new (...args: any[]) => ModuleInstance<TParams>\n\nconst moduleName = 'StatefulModuleMixin'\n\n/**\n * @ignore Inherit from StatefulDiviner instead\n * @param ModuleBase\n * @returns\n */\nexport const StatefulModuleMixin = <\n TParams extends StatefulModuleParams = StatefulModuleParams,\n TModule extends AnyModule<TParams> = AnyModule<TParams>,\n TState extends StateDictionary = StateDictionary,\n>(\n ModuleBase: TModule,\n) => {\n abstract class StatefulModuleBase extends ModuleBase {\n _lastState?: ModuleState<TState>\n\n /**\n * Commit the internal state of the Diviner process. This is similar\n * to a transaction completion in a database and should only be called\n * when results have been successfully persisted to the appropriate\n * external stores.\n * @param nextState The state to commit\n */\n async commitState(nextState: ModuleState<TState>) {\n // Don't commit state if no state has changed\n if (nextState.state.offset === this._lastState?.state.offset) return\n this._lastState = nextState\n const archivist = await this.getArchivistForStore()\n // const [bw] = await new BoundWitnessBuilder().payload(nextState).witness(this.account).build()\n const [bw] = await new BoundWitnessBuilder().payload(nextState).build()\n await archivist.insert([bw, nextState])\n }\n\n /**\n * Retrieves the archivist for the specified store\n * @param store The store to retrieve the archivist for\n * @returns The archivist for the specified store\n */\n async getArchivistForStore() {\n const name = assertEx(this.config?.stateStore?.archivist, () => `${moduleName}: Config for stateStore.archivist not specified`)\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve stateStore.archivist`)\n // return ArchivistWrapper.wrap(mod, this.account)\n const instance = asArchivistInstance(mod)\n return assertEx(instance, () => `${moduleName}: Failed to wrap archivist instance`)\n }\n\n /**\n * Retrieves the BoundWitness Diviner for the specified store\n * @param store The store to retrieve the BoundWitness Diviner for\n * @returns The BoundWitness Diviner for the specified store\n */\n async getBoundWitnessDivinerForStore() {\n const name = assertEx(\n this.config?.stateStore?.boundWitnessDiviner,\n () => `${moduleName}: Config for stateStore.boundWitnessDiviner not specified`,\n )\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve stateStore.boundWitnessDiviner`)\n // return DivinerWrapper.wrap(mod, this.account)\n const instance = asDivinerInstance(mod)\n return assertEx(instance, () => `${moduleName}: Failed to wrap diviner instance`)\n }\n /**\n * Retrieves the Payload Diviner for the specified store\n * @param store The store to retrieve the Payload Diviner for\n * @returns The Payload Diviner for the specified store\n */\n async getPayloadDivinerForStateStore() {\n const name = assertEx(this.config?.stateStore?.payloadDiviner, () => `${moduleName}: Config for stateStore.payloadDiviner not specified`)\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve stateStore.payloadDiviner`)\n // return DivinerWrapper.wrap(mod, this.account)\n const instance = asDivinerInstance(mod)\n return assertEx(instance, () => `${moduleName}: Failed to wrap diviner instance`)\n }\n /**\n * Retrieves the last state of the Diviner process. Used to recover state after\n * preemptions, reboots, etc.\n */\n async retrieveState(): Promise<ModuleState<TState> | undefined> {\n if (this._lastState) return this._lastState\n let hash: string = ''\n const diviner = await this.getBoundWitnessDivinerForStore()\n const query = await new PayloadBuilder<BoundWitnessDivinerQueryPayload>({ schema: BoundWitnessDivinerQuerySchema })\n .fields({\n // address: this.account.address,\n limit: 1,\n offset: 0,\n order: 'desc',\n payload_schemas: [ModuleStateSchema],\n })\n .build()\n const boundWitnesses = await diviner.divine([query])\n if (boundWitnesses.length > 0) {\n const boundWitness = boundWitnesses[0]\n if (isBoundWitness(boundWitness)) {\n // Find the index for this address in the BoundWitness that is a ModuleState\n hash = boundWitness.addresses\n .map((address, index) => ({ address, index }))\n // .filter(({ address }) => address === this.account.address)\n .reduce(\n (prev, curr) => (boundWitness.payload_schemas?.[curr?.index] === ModuleStateSchema ? boundWitness.payload_hashes[curr?.index] : prev),\n '',\n )\n }\n }\n\n // If we able to located the last state\n if (hash) {\n // Get last state\n const archivist = await this.getArchivistForStore()\n const payload = (await archivist.get([hash])).find(isModuleState<TState>)\n if (payload) {\n return payload\n }\n }\n return undefined\n }\n }\n return StatefulModuleBase\n}\n"],"mappings":"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","names":["assertEx","BoundWitnessBuilder","isBoundWitness","BoundWitnessDivinerQuerySchema","isModuleState","ModuleStateSchema","PayloadBuilder","moduleName"]}
package/package.json ADDED
@@ -0,0 +1,78 @@
1
+ {
2
+ "name": "@xyo-network/diviner-stateful",
3
+ "author": {
4
+ "email": "support@xyo.network",
5
+ "name": "XYO Development Team",
6
+ "url": "https://xyo.network"
7
+ },
8
+ "bugs": {
9
+ "email": "support@xyo.network",
10
+ "url": "https://github.com/XYOracleNetwork/sdk-xyo-client-js/issues"
11
+ },
12
+ "dependencies": {
13
+ "@xylabs/assert": "^2.13.20",
14
+ "@xyo-network/abstract-diviner": "~2.84.1",
15
+ "@xyo-network/archivist": "~2.84.1",
16
+ "@xyo-network/archivist-wrapper": "~2.84.1",
17
+ "@xyo-network/boundwitness-builder": "~2.84.1",
18
+ "@xyo-network/boundwitness-model": "~2.84.1",
19
+ "@xyo-network/diviner-boundwitness-model": "~2.84.1",
20
+ "@xyo-network/diviner-model": "~2.84.1",
21
+ "@xyo-network/diviner-wrapper": "~2.84.1",
22
+ "@xyo-network/module-model": "~2.84.1",
23
+ "@xyo-network/payload-builder": "~2.84.1",
24
+ "@xyo-network/payload-model": "~2.84.1"
25
+ },
26
+ "devDependencies": {
27
+ "@xylabs/ts-scripts-yarn3": "^3.2.10",
28
+ "@xylabs/tsconfig": "^3.2.10",
29
+ "@xyo-network/account": "~2.84.1",
30
+ "@xyo-network/diviner-boundwitness-memory": "~2.84.1",
31
+ "@xyo-network/diviner-payload-memory": "~2.84.1",
32
+ "@xyo-network/manifest": "~2.84.1",
33
+ "@xyo-network/memory-archivist": "~2.84.1",
34
+ "@xyo-network/node-memory": "~2.84.1",
35
+ "typescript": "^5.3.3"
36
+ },
37
+ "description": "Primary SDK for using XYO Protocol 2.0",
38
+ "docs": "dist/docs.json",
39
+ "types": "dist/node/index.d.ts",
40
+ "exports": {
41
+ ".": {
42
+ "browser": {
43
+ "require": {
44
+ "types": "./dist/browser/index.d.cts",
45
+ "default": "./dist/browser/index.cjs"
46
+ },
47
+ "import": {
48
+ "types": "./dist/browser/index.d.mts",
49
+ "default": "./dist/browser/index.js"
50
+ }
51
+ },
52
+ "node": {
53
+ "require": {
54
+ "types": "./dist/node/index.d.ts",
55
+ "default": "./dist/node/index.js"
56
+ },
57
+ "import": {
58
+ "types": "./dist/node/index.d.mts",
59
+ "default": "./dist/node/index.mjs"
60
+ }
61
+ }
62
+ },
63
+ "./package.json": "./package.json"
64
+ },
65
+ "main": "dist/node/index.js",
66
+ "module": "dist/node/index.mjs",
67
+ "homepage": "https://xyo.network",
68
+ "license": "LGPL-3.0-only",
69
+ "publishConfig": {
70
+ "access": "public"
71
+ },
72
+ "repository": {
73
+ "type": "git",
74
+ "url": "https://github.com/XYOracleNetwork/sdk-xyo-client-js.git"
75
+ },
76
+ "sideEffects": false,
77
+ "version": "2.84.1"
78
+ }
package/src/Config.ts ADDED
@@ -0,0 +1,24 @@
1
+ import { DivinerConfig } from '@xyo-network/diviner-model'
2
+
3
+ import { StatefulDivinerSchema } from './Schema'
4
+
5
+ /**
6
+ * The schema for a Stateful Diviner config
7
+ */
8
+ export const StatefulDivinerConfigSchema = `${StatefulDivinerSchema}.config` as const
9
+ /**
10
+ * The schema for a Stateful Diviner config
11
+ */
12
+ export type StatefulDivinerConfigSchema = typeof StatefulDivinerConfigSchema
13
+
14
+ /**
15
+ * The config for a Stateful Diviner
16
+ */
17
+ export type StatefulDivinerConfig = DivinerConfig<{
18
+ schema: StatefulDivinerConfigSchema
19
+ stateStore: {
20
+ archivist: string
21
+ boundWitnessDiviner: string
22
+ payloadDiviner: string
23
+ }
24
+ }>
package/src/Diviner.ts ADDED
@@ -0,0 +1,127 @@
1
+ import { assertEx } from '@xylabs/assert'
2
+ import { AbstractDiviner } from '@xyo-network/abstract-diviner'
3
+ import { ArchivistWrapper } from '@xyo-network/archivist-wrapper'
4
+ import { BoundWitnessBuilder } from '@xyo-network/boundwitness-builder'
5
+ import { isBoundWitness } from '@xyo-network/boundwitness-model'
6
+ import { BoundWitnessDivinerQueryPayload, BoundWitnessDivinerQuerySchema } from '@xyo-network/diviner-boundwitness-model'
7
+ import { DivinerConfigSchema, DivinerModule, DivinerModuleEventData } from '@xyo-network/diviner-model'
8
+ import { DivinerWrapper } from '@xyo-network/diviner-wrapper'
9
+ import { isModuleState, ModuleState, ModuleStateSchema, StateDictionary } from '@xyo-network/module-model'
10
+ import { PayloadBuilder } from '@xyo-network/payload-builder'
11
+ import { Payload } from '@xyo-network/payload-model'
12
+
13
+ import { StatefulDivinerConfigSchema } from './Config'
14
+ import { StatefulDivinerParams } from './Params'
15
+
16
+ const moduleName = 'StatefulDiviner'
17
+
18
+ /**
19
+ * A Diviner that maintains state
20
+ */
21
+ export abstract class StatefulDiviner<
22
+ TParams extends StatefulDivinerParams = StatefulDivinerParams,
23
+ TIn extends Payload = Payload,
24
+ TOut extends Payload = Payload,
25
+ TEventData extends DivinerModuleEventData<DivinerModule<TParams>, TIn, TOut> = DivinerModuleEventData<DivinerModule<TParams>, TIn, TOut>,
26
+ TState extends StateDictionary = StateDictionary,
27
+ > extends AbstractDiviner<TParams, TIn, TOut, TEventData> {
28
+ static override readonly configSchemas: string[] = [DivinerConfigSchema, StatefulDivinerConfigSchema]
29
+
30
+ /**
31
+ * The last state
32
+ */
33
+ protected _lastState?: ModuleState<TState>
34
+
35
+ /**
36
+ * Commit the internal state of the Diviner process. This is similar
37
+ * to a transaction completion in a database and should only be called
38
+ * when results have been successfully persisted to the appropriate
39
+ * external stores.
40
+ * @param nextState The state to commit
41
+ */
42
+ protected async commitState(nextState: ModuleState<TState>) {
43
+ // Don't commit state if no state has changed
44
+ if (nextState.state.offset === this._lastState?.state.offset) return
45
+ this._lastState = nextState
46
+ const archivist = await this.getArchivistForStateStore()
47
+ const [bw] = await new BoundWitnessBuilder().payload(nextState).witness(this.account).build()
48
+ await archivist.insert([bw, nextState])
49
+ }
50
+
51
+ /**
52
+ * Retrieves the archivist for the specified store
53
+ * @param store The store to retrieve the archivist for
54
+ * @returns The archivist for the specified store
55
+ */
56
+ protected async getArchivistForStateStore() {
57
+ const name = assertEx(this.config?.stateStore.archivist, () => `${moduleName}: Config for stateStore.archivist not specified`)
58
+ const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve stateStore.archivist`)
59
+ return ArchivistWrapper.wrap(mod, this.account)
60
+ }
61
+
62
+ /**
63
+ * Retrieves the BoundWitness Diviner for the specified store
64
+ * @param store The store to retrieve the BoundWitness Diviner for
65
+ * @returns The BoundWitness Diviner for the specified store
66
+ */
67
+ protected async getBoundWitnessDivinerForStateStore() {
68
+ const name = assertEx(this.config?.stateStore.boundWitnessDiviner, () => `${moduleName}: Config for stateStore.boundWitnessDiviner not specified`)
69
+ const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve stateStore.boundWitnessDiviner`)
70
+ return DivinerWrapper.wrap(mod, this.account)
71
+ }
72
+
73
+ /**
74
+ * Retrieves the Payload Diviner for the specified store
75
+ * @param store The store to retrieve the Payload Diviner for
76
+ * @returns The Payload Diviner for the specified store
77
+ */
78
+ protected async getPayloadDivinerForStateStore() {
79
+ const name = assertEx(this.config?.stateStore?.payloadDiviner, () => `${moduleName}: Config for stateStore.payloadDiviner not specified`)
80
+ const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve stateStore.payloadDiviner`)
81
+ return DivinerWrapper.wrap(mod, this.account)
82
+ }
83
+
84
+ /**
85
+ * Retrieves the last state of the Diviner process. Used to recover state after
86
+ * preemptions, reboots, etc.
87
+ */
88
+ protected async retrieveState(): Promise<ModuleState<TState> | undefined> {
89
+ if (this._lastState) return this._lastState
90
+ let hash: string = ''
91
+ const diviner = await this.getBoundWitnessDivinerForStateStore()
92
+ const query = await new PayloadBuilder<BoundWitnessDivinerQueryPayload>({ schema: BoundWitnessDivinerQuerySchema })
93
+ .fields({
94
+ address: this.account.address,
95
+ limit: 1,
96
+ offset: 0,
97
+ order: 'desc',
98
+ payload_schemas: [ModuleStateSchema],
99
+ })
100
+ .build()
101
+ const boundWitnesses = await diviner.divine([query])
102
+ if (boundWitnesses.length > 0) {
103
+ const boundWitness = boundWitnesses[0]
104
+ if (isBoundWitness(boundWitness)) {
105
+ // Find the index for this address in the BoundWitness that is a ModuleState
106
+ hash = boundWitness.addresses
107
+ .map((address, index) => ({ address, index }))
108
+ .filter(({ address }) => address === this.account.address)
109
+ .reduce(
110
+ (prev, curr) => (boundWitness.payload_schemas?.[curr?.index] === ModuleStateSchema ? boundWitness.payload_hashes[curr?.index] : prev),
111
+ '',
112
+ )
113
+ }
114
+ }
115
+
116
+ // If we able to located the last state
117
+ if (hash) {
118
+ // Get last state
119
+ const archivist = await this.getArchivistForStateStore()
120
+ const payload = (await archivist.get([hash])).find(isModuleState<TState>)
121
+ if (payload) {
122
+ return payload
123
+ }
124
+ }
125
+ return undefined
126
+ }
127
+ }
@@ -0,0 +1,144 @@
1
+ import { assertEx } from '@xylabs/assert'
2
+ import { asArchivistInstance } from '@xyo-network/archivist'
3
+ import { BoundWitnessBuilder } from '@xyo-network/boundwitness-builder'
4
+ import { isBoundWitness } from '@xyo-network/boundwitness-model'
5
+ import { BoundWitnessDivinerQueryPayload, BoundWitnessDivinerQuerySchema } from '@xyo-network/diviner-boundwitness-model'
6
+ import { asDivinerInstance } from '@xyo-network/diviner-model'
7
+ import {
8
+ AnyConfigSchema,
9
+ isModuleState,
10
+ ModuleInstance,
11
+ ModuleParams,
12
+ ModuleState,
13
+ ModuleStateSchema,
14
+ StateDictionary,
15
+ } from '@xyo-network/module-model'
16
+ import { PayloadBuilder } from '@xyo-network/payload-builder'
17
+
18
+ import { StatefulDivinerConfig } from './Config'
19
+
20
+ export type StatefulModuleParams = ModuleParams<AnyConfigSchema<StatefulDivinerConfig>>
21
+
22
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
23
+ export type AnyModule<TParams extends StatefulModuleParams = StatefulModuleParams> = new (...args: any[]) => ModuleInstance<TParams>
24
+
25
+ const moduleName = 'StatefulModuleMixin'
26
+
27
+ /**
28
+ * @ignore Inherit from StatefulDiviner instead
29
+ * @param ModuleBase
30
+ * @returns
31
+ */
32
+ export const StatefulModuleMixin = <
33
+ TParams extends StatefulModuleParams = StatefulModuleParams,
34
+ TModule extends AnyModule<TParams> = AnyModule<TParams>,
35
+ TState extends StateDictionary = StateDictionary,
36
+ >(
37
+ ModuleBase: TModule,
38
+ ) => {
39
+ abstract class StatefulModuleBase extends ModuleBase {
40
+ _lastState?: ModuleState<TState>
41
+
42
+ /**
43
+ * Commit the internal state of the Diviner process. This is similar
44
+ * to a transaction completion in a database and should only be called
45
+ * when results have been successfully persisted to the appropriate
46
+ * external stores.
47
+ * @param nextState The state to commit
48
+ */
49
+ async commitState(nextState: ModuleState<TState>) {
50
+ // Don't commit state if no state has changed
51
+ if (nextState.state.offset === this._lastState?.state.offset) return
52
+ this._lastState = nextState
53
+ const archivist = await this.getArchivistForStore()
54
+ // const [bw] = await new BoundWitnessBuilder().payload(nextState).witness(this.account).build()
55
+ const [bw] = await new BoundWitnessBuilder().payload(nextState).build()
56
+ await archivist.insert([bw, nextState])
57
+ }
58
+
59
+ /**
60
+ * Retrieves the archivist for the specified store
61
+ * @param store The store to retrieve the archivist for
62
+ * @returns The archivist for the specified store
63
+ */
64
+ async getArchivistForStore() {
65
+ const name = assertEx(this.config?.stateStore?.archivist, () => `${moduleName}: Config for stateStore.archivist not specified`)
66
+ const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve stateStore.archivist`)
67
+ // return ArchivistWrapper.wrap(mod, this.account)
68
+ const instance = asArchivistInstance(mod)
69
+ return assertEx(instance, () => `${moduleName}: Failed to wrap archivist instance`)
70
+ }
71
+
72
+ /**
73
+ * Retrieves the BoundWitness Diviner for the specified store
74
+ * @param store The store to retrieve the BoundWitness Diviner for
75
+ * @returns The BoundWitness Diviner for the specified store
76
+ */
77
+ async getBoundWitnessDivinerForStore() {
78
+ const name = assertEx(
79
+ this.config?.stateStore?.boundWitnessDiviner,
80
+ () => `${moduleName}: Config for stateStore.boundWitnessDiviner not specified`,
81
+ )
82
+ const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve stateStore.boundWitnessDiviner`)
83
+ // return DivinerWrapper.wrap(mod, this.account)
84
+ const instance = asDivinerInstance(mod)
85
+ return assertEx(instance, () => `${moduleName}: Failed to wrap diviner instance`)
86
+ }
87
+ /**
88
+ * Retrieves the Payload Diviner for the specified store
89
+ * @param store The store to retrieve the Payload Diviner for
90
+ * @returns The Payload Diviner for the specified store
91
+ */
92
+ async getPayloadDivinerForStateStore() {
93
+ const name = assertEx(this.config?.stateStore?.payloadDiviner, () => `${moduleName}: Config for stateStore.payloadDiviner not specified`)
94
+ const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve stateStore.payloadDiviner`)
95
+ // return DivinerWrapper.wrap(mod, this.account)
96
+ const instance = asDivinerInstance(mod)
97
+ return assertEx(instance, () => `${moduleName}: Failed to wrap diviner instance`)
98
+ }
99
+ /**
100
+ * Retrieves the last state of the Diviner process. Used to recover state after
101
+ * preemptions, reboots, etc.
102
+ */
103
+ async retrieveState(): Promise<ModuleState<TState> | undefined> {
104
+ if (this._lastState) return this._lastState
105
+ let hash: string = ''
106
+ const diviner = await this.getBoundWitnessDivinerForStore()
107
+ const query = await new PayloadBuilder<BoundWitnessDivinerQueryPayload>({ schema: BoundWitnessDivinerQuerySchema })
108
+ .fields({
109
+ // address: this.account.address,
110
+ limit: 1,
111
+ offset: 0,
112
+ order: 'desc',
113
+ payload_schemas: [ModuleStateSchema],
114
+ })
115
+ .build()
116
+ const boundWitnesses = await diviner.divine([query])
117
+ if (boundWitnesses.length > 0) {
118
+ const boundWitness = boundWitnesses[0]
119
+ if (isBoundWitness(boundWitness)) {
120
+ // Find the index for this address in the BoundWitness that is a ModuleState
121
+ hash = boundWitness.addresses
122
+ .map((address, index) => ({ address, index }))
123
+ // .filter(({ address }) => address === this.account.address)
124
+ .reduce(
125
+ (prev, curr) => (boundWitness.payload_schemas?.[curr?.index] === ModuleStateSchema ? boundWitness.payload_hashes[curr?.index] : prev),
126
+ '',
127
+ )
128
+ }
129
+ }
130
+
131
+ // If we able to located the last state
132
+ if (hash) {
133
+ // Get last state
134
+ const archivist = await this.getArchivistForStore()
135
+ const payload = (await archivist.get([hash])).find(isModuleState<TState>)
136
+ if (payload) {
137
+ return payload
138
+ }
139
+ }
140
+ return undefined
141
+ }
142
+ }
143
+ return StatefulModuleBase
144
+ }
package/src/Params.ts ADDED
@@ -0,0 +1,9 @@
1
+ import { DivinerParams } from '@xyo-network/diviner-model'
2
+ import { AnyConfigSchema } from '@xyo-network/module-model'
3
+
4
+ import { StatefulDivinerConfig } from './Config'
5
+
6
+ /**
7
+ * The parameters for a Stateful Diviner
8
+ */
9
+ export type StatefulDivinerParams = DivinerParams<AnyConfigSchema<StatefulDivinerConfig>>
package/src/Schema.ts ADDED
@@ -0,0 +1,2 @@
1
+ export const StatefulDivinerSchema = 'network.xyo.diviner.stateful' as const
2
+ export type StatefulDivinerSchema = typeof StatefulDivinerSchema
package/src/index.ts ADDED
@@ -0,0 +1,5 @@
1
+ export * from './Config'
2
+ export * from './Diviner'
3
+ export * from './DivinerMixin'
4
+ export * from './Params'
5
+ export * from './Schema'
@@ -0,0 +1,51 @@
1
+ {
2
+ "$schema": "https://raw.githubusercontent.com/XYOracleNetwork/sdk-xyo-client-js/main/packages/manifest/src/schema.json",
3
+ "nodes": [
4
+ {
5
+ "config": {
6
+ "name": "DivinerTest",
7
+ "schema": "network.xyo.node.config"
8
+ },
9
+ "modules": {
10
+ "public": [
11
+ {
12
+ "config": {
13
+ "language": "javascript",
14
+ "name": "AddressStateArchivist",
15
+ "schema": "network.xyo.archivist.config"
16
+ }
17
+ },
18
+ {
19
+ "config": {
20
+ "archivist": "AddressStateArchivist",
21
+ "language": "javascript",
22
+ "name": "AddressStateBoundWitnessDiviner",
23
+ "schema": "network.xyo.diviner.boundwitness.config"
24
+ }
25
+ },
26
+ {
27
+ "config": {
28
+ "archivist": "AddressStateArchivist",
29
+ "language": "javascript",
30
+ "name": "AddressStatePayloadDiviner",
31
+ "schema": "network.xyo.diviner.payload.config"
32
+ }
33
+ },
34
+ {
35
+ "config": {
36
+ "language": "javascript",
37
+ "name": "Diviner",
38
+ "schema": "network.xyo.diviner.stateful.config",
39
+ "stateStore": {
40
+ "archivist": "AddressStateArchivist",
41
+ "boundWitnessDiviner": "AddressStateBoundWitnessDiviner",
42
+ "payloadDiviner": "AddressStatePayloadDiviner"
43
+ }
44
+ }
45
+ }
46
+ ]
47
+ }
48
+ }
49
+ ],
50
+ "schema": "network.xyo.manifest"
51
+ }
package/typedoc.json ADDED
@@ -0,0 +1,5 @@
1
+ {
2
+ "$schema": "https://typedoc.org/schema.json",
3
+ "entryPoints": ["src/index.ts"],
4
+ "tsconfig": "./tsconfig.typedoc.json"
5
+ }