@xyo-network/chain-producer 1.19.5 → 1.19.7

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.
@@ -1,11 +1,12 @@
1
1
  import type { Attributes, Counter } from '@opentelemetry/api';
2
- import type { Address } from '@xylabs/sdk-js';
3
- import type { ChainStakeIntent, HydratedBlockWithHashMeta, XL1BlockNumber } from '@xyo-network/xl1-sdk';
4
- import { AccountBalanceViewer, Actor, ActorParams, BlockRunner, BlockViewer, MempoolRunner, MempoolViewer, StakeTotalsViewer } from '@xyo-network/xl1-sdk';
5
- export type ProducerActorParams = ActorParams<{
2
+ import type { Address, Logger } from '@xylabs/sdk-js';
3
+ import type { ActorParamsV2, ChainStakeIntent, HydratedBlockWithHashMeta, XL1BlockNumber } from '@xyo-network/xl1-sdk';
4
+ import { AccountBalanceViewer, ActorV2, BlockRunner, BlockViewer, MempoolRunner, MempoolViewer, StakeTotalsViewer } from '@xyo-network/xl1-sdk';
5
+ export type ProducerActorParams = ActorParamsV2<{
6
+ logger: Logger;
6
7
  rewardAddress: Address;
7
8
  }>;
8
- export declare class ProducerActor extends Actor<ProducerActorParams> {
9
+ export declare class ProducerActor extends ActorV2<ProducerActorParams> {
9
10
  /**
10
11
  * The interval time (in MS) between block production attempts.
11
12
  */
@@ -35,6 +36,7 @@ export declare class ProducerActor extends Actor<ProducerActorParams> {
35
36
  private _mempoolViewer?;
36
37
  private _produceBlockMutex;
37
38
  private _stakeTotalsViewer?;
39
+ get logger(): Logger;
38
40
  protected get accountBalanceViewer(): AccountBalanceViewer;
39
41
  protected get blockRunner(): BlockRunner;
40
42
  protected get blockViewer(): BlockViewer<"BlockViewer">;
@@ -47,28 +49,22 @@ export declare class ProducerActor extends Actor<ProducerActorParams> {
47
49
  readonly __address: true;
48
50
  };
49
51
  protected get stakeTotalsViewer(): StakeTotalsViewer;
50
- static paramsHandler<T extends ProducerActor>(params?: Partial<T['params']>): Promise<{
52
+ static paramsHandler<T extends ProducerActor>(params: Partial<T['params']>): Promise<{
51
53
  rewardAddress: Lowercase<string> & {
52
54
  readonly __hex: true;
53
55
  } & {
54
56
  readonly __address: true;
55
57
  };
58
+ account: T["params"]["account"];
59
+ logger: import("@xylabs/sdk-js").IdLogger | undefined;
60
+ config: T["params"]["config"];
56
61
  name?: import("@xylabs/sdk-js").CreatableName;
57
62
  statusReporter?: import("@xylabs/sdk-js").CreatableStatusReporter<void> | undefined;
58
- logger: import("@xylabs/sdk-js").Logger;
59
63
  meterProvider?: import("@opentelemetry/api").MeterProvider;
60
64
  traceProvider?: import("@opentelemetry/api").TracerProvider;
61
- account: import("@xyo-network/account-model").AccountInstance;
62
- context: import("@xyo-network/xl1-sdk").ActorContext;
63
- displayName: string | (string & {
64
- __baseClassName: true;
65
- }) | undefined;
66
- id: string | (string & {
67
- __baseClassName: true;
68
- });
69
65
  }>;
70
- protected static initContext(params: ProducerActorParams): Promise<import("@xyo-network/xl1-sdk").CreatableProviderContext>;
71
66
  createHandler(): Promise<void>;
67
+ initLocator(): Promise<import("@xyo-network/xl1-sdk").ProviderFactoryLocatorInstance<import("@xyo-network/xl1-sdk").CreatableProviderContextType>>;
72
68
  startHandler(): Promise<void>;
73
69
  protected calculateBlocksUntilProducerDeclarationExpiration(currentBlock: number): number;
74
70
  protected produceBlock(): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"ProducerActor.d.ts","sourceRoot":"","sources":["../../src/ProducerActor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAA;AAC7D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAA;AAS7C,OAAO,KAAK,EAC8B,gBAAgB,EAAE,yBAAyB,EAAE,cAAc,EACpG,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EACL,oBAAoB,EAA+B,KAAK,EAAE,WAAW,EAAoB,WAAW,EAAsB,WAAW,EACjB,aAAa,EACjI,aAAa,EAA4F,iBAAiB,EAE3H,MAAM,sBAAsB,CAAA;AAG7B,MAAM,MAAM,mBAAmB,GAAG,WAAW,CAAC;IAC5C,aAAa,EAAE,OAAO,CAAA;CACvB,CAAC,CAAA;AAcF,qBACa,aAAc,SAAQ,KAAK,CAAC,mBAAmB,CAAC;IAC3D;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,4BAA4B,QAAO;IAEnD;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,yBAAyB,SAAkD;IAE3F;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,mBAAmB,SAAS;IAE5C,SAAS,CAAC,kBAAkB,CAAC,EAAE,yBAAyB,CAAA;IACxD,SAAS,CAAC,wBAAwB,CAAC,EAAE,gBAAgB,CAAA;IACrD,SAAS,CAAC,iBAAiB,CAAC,EAAE,UAAU,CAAA;IACxC,SAAS,CAAC,qCAAqC,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,CAAA;IACrE,SAAS,CAAC,mCAAmC,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,CAAA;IACnE,SAAS,CAAC,4BAA4B,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,CAAA;IAC5D,SAAS,CAAC,6BAA6B,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,CAAA;IAE7D,OAAO,CAAC,qBAAqB,CAAC,CAAsB;IACpD,OAAO,CAAC,YAAY,CAAC,CAAa;IAClC,OAAO,CAAC,YAAY,CAAC,CAAa;IAClC,OAAO,CAAC,QAAQ,CAAC,CAAS;IAC1B,OAAO,CAAC,mBAAmB,CAAC,CAAQ;IACpC,OAAO,CAAC,aAAa,CAAC,CAAQ;IAC9B,OAAO,CAAC,cAAc,CAAC,CAAe;IACtC,OAAO,CAAC,cAAc,CAAC,CAAe;IACtC,OAAO,CAAC,kBAAkB,CAAc;IACxC,OAAO,CAAC,kBAAkB,CAAC,CAAmB;IAE9C,SAAS,KAAK,oBAAoB,yBAEjC;IAED,SAAS,KAAK,WAAW,gBAExB;IAED,SAAS,KAAK,WAAW,+BAExB;IAED,SAAS,KAAK,OAAO,wCAEpB;IAED,SAAS,KAAK,aAAa,kBAE1B;IAED,SAAS,KAAK,aAAa,kBAE1B;IAED,SAAS,KAAK,aAAa;;;;MAE1B;IAED,SAAS,KAAK,iBAAiB,sBAE9B;WAEqB,aAAa,CAAC,CAAC,SAAS,aAAa,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;;;;;;;;;;;;;;;;;;;;qBAwB1D,WAAW,CACzC,MAAM,EAAE,mBAAmB;IA0Bd,aAAa;IAgDb,YAAY;IAe3B,SAAS,CAAC,iDAAiD,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM;cAIzE,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;cAgF7B,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC;cAiEhC,yBAAyB,CAAC,YAAY,EAAE,cAAc,EAAE,mBAAmB,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;cAkB7G,sBAAsB,IAAI,OAAO,CAAC,OAAO,CAAC;cAe1C,oBAAoB,IAAI,OAAO,CAAC,OAAO,CAAC;CAWzD"}
1
+ {"version":3,"file":"ProducerActor.d.ts","sourceRoot":"","sources":["../../src/ProducerActor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAA;AAC7D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AAUrD,OAAO,KAAK,EACV,aAAa,EAC2B,gBAAgB,EAAE,yBAAyB,EAAE,cAAc,EACpG,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EACL,oBAAoB,EAA+B,OAAO,EAAoB,WAAW,EAAsB,WAAW,EACH,aAAa,EACpI,aAAa,EAA4F,iBAAiB,EAE3H,MAAM,sBAAsB,CAAA;AAG7B,MAAM,MAAM,mBAAmB,GAAG,aAAa,CAAC;IAC9C,MAAM,EAAE,MAAM,CAAA;IACd,aAAa,EAAE,OAAO,CAAA;CACvB,CAAC,CAAA;AAcF,qBACa,aAAc,SAAQ,OAAO,CAAC,mBAAmB,CAAC;IAC7D;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,4BAA4B,QAAO;IAEnD;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,yBAAyB,SAAkD;IAE3F;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,mBAAmB,SAAS;IAE5C,SAAS,CAAC,kBAAkB,CAAC,EAAE,yBAAyB,CAAA;IACxD,SAAS,CAAC,wBAAwB,CAAC,EAAE,gBAAgB,CAAA;IACrD,SAAS,CAAC,iBAAiB,CAAC,EAAE,UAAU,CAAA;IACxC,SAAS,CAAC,qCAAqC,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,CAAA;IACrE,SAAS,CAAC,mCAAmC,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,CAAA;IACnE,SAAS,CAAC,4BAA4B,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,CAAA;IAC5D,SAAS,CAAC,6BAA6B,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,CAAA;IAE7D,OAAO,CAAC,qBAAqB,CAAC,CAAsB;IACpD,OAAO,CAAC,YAAY,CAAC,CAAa;IAClC,OAAO,CAAC,YAAY,CAAC,CAAa;IAClC,OAAO,CAAC,QAAQ,CAAC,CAAS;IAC1B,OAAO,CAAC,mBAAmB,CAAC,CAAQ;IACpC,OAAO,CAAC,aAAa,CAAC,CAAQ;IAC9B,OAAO,CAAC,cAAc,CAAC,CAAe;IACtC,OAAO,CAAC,cAAc,CAAC,CAAe;IACtC,OAAO,CAAC,kBAAkB,CAAc;IACxC,OAAO,CAAC,kBAAkB,CAAC,CAAmB;IAE9C,IAAa,MAAM,WAElB;IAED,SAAS,KAAK,oBAAoB,yBAEjC;IAED,SAAS,KAAK,WAAW,gBAExB;IAED,SAAS,KAAK,WAAW,+BAExB;IAED,SAAS,KAAK,OAAO,wCAEpB;IAED,SAAS,KAAK,aAAa,kBAE1B;IAED,SAAS,KAAK,aAAa,kBAE1B;IAED,SAAS,KAAK,aAAa;;;;MAE1B;IAED,SAAS,KAAK,iBAAiB,sBAE9B;WAEqB,aAAa,CAAC,CAAC,SAAS,aAAa,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;;;;;;;;;;;;;;IAe1E,aAAa;IAgDtB,WAAW;IAyBF,YAAY;IAe3B,SAAS,CAAC,iDAAiD,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM;cAIzE,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;cAgF7B,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC;cAiEhC,yBAAyB,CAAC,YAAY,EAAE,cAAc,EAAE,mBAAmB,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;cAkB7G,sBAAsB,IAAI,OAAO,CAAC,OAAO,CAAC;cAe1C,oBAAoB,IAAI,OAAO,CAAC,OAAO,CAAC;CAWzD"}
@@ -2,12 +2,13 @@ var __defProp = Object.defineProperty;
2
2
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
3
 
4
4
  // src/ProducerActor.ts
5
- import { asAddress, assertEx, creatable, isDefined, isUndefined, toHex } from "@xylabs/sdk-js";
6
- import { EvmChainContractViewer, EvmStakeTotalsViewer } from "@xyo-network/chain-ethereum";
7
- import { initEvmProvider, initProducerAccount } from "@xyo-network/chain-orchestration";
5
+ import { assertEx, creatable, isDefined, isUndefined, toHex } from "@xylabs/sdk-js";
6
+ import { buildTelemetryConfig, initEvmProvidersIfAvailable } from "@xyo-network/chain-orchestration";
8
7
  import { SimpleBlockRunner } from "@xyo-network/chain-services";
8
+ import { initTelemetry } from "@xyo-network/chain-telemetry";
9
+ import { startupSpanAsync } from "@xyo-network/chain-utils";
9
10
  import { validateHydratedBlock, validateHydratedBlockState } from "@xyo-network/chain-validation";
10
- import { AccountBalanceViewerMoniker, Actor, asXL1BlockNumber, BlockRunnerMoniker, BlockViewerMoniker, buildJsonRpcProviderLocator, buildTransaction, createDeclarationIntent, getDefaultConfig, HttpRpcTransport, MempoolRunnerMoniker, MempoolViewerMoniker, SimpleBlockRewardViewer, SimpleBlockValidationViewer, StakeTotalsViewerMoniker } from "@xyo-network/xl1-sdk";
11
+ import { AccountBalanceViewerMoniker, ActorV2, asXL1BlockNumber, BlockRunnerMoniker, BlockViewerMoniker, buildJsonRpcProviderLocatorV2, buildTransaction, createDeclarationIntent, DefaultMetricsScrapePorts, HttpRpcTransport, MempoolRunnerMoniker, MempoolViewerMoniker, SimpleBlockRewardViewer, SimpleBlockValidationViewer, StakeTotalsViewerMoniker } from "@xyo-network/xl1-sdk";
11
12
  import { Mutex } from "async-mutex";
12
13
  function _ts_decorate(decorators, target, key, desc) {
13
14
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
@@ -23,7 +24,7 @@ var toFormattedBlockReference = /* @__PURE__ */ __name((blockBoundWitness) => {
23
24
  prefix: true
24
25
  })}]`;
25
26
  }, "toFormattedBlockReference");
26
- var ProducerActor = class _ProducerActor extends Actor {
27
+ var ProducerActor = class _ProducerActor extends ActorV2 {
27
28
  static {
28
29
  __name(this, "ProducerActor");
29
30
  }
@@ -56,6 +57,9 @@ var ProducerActor = class _ProducerActor extends Actor {
56
57
  _mempoolViewer;
57
58
  _produceBlockMutex = new Mutex();
58
59
  _stakeTotalsViewer;
60
+ get logger() {
61
+ return assertEx(super.logger, () => "Logger is required for ProducerActor");
62
+ }
59
63
  get accountBalanceViewer() {
60
64
  return this._accountBalanceViewer;
61
65
  }
@@ -81,61 +85,18 @@ var ProducerActor = class _ProducerActor extends Actor {
81
85
  return this._stakeTotalsViewer;
82
86
  }
83
87
  static async paramsHandler(params) {
84
- const logger = params?.context?.logger;
85
- const config = params?.context?.config ?? getDefaultConfig();
86
- const displayName = params?.displayName ?? "ProducerActor";
87
- const account = params?.account ?? await initProducerAccount({
88
- config
89
- });
90
- const id = account?.address.toString() ?? "unknown";
91
- logger?.info(`Running producer for account ${account.address}`);
92
- const rewardAddress = params?.rewardAddress ?? account.address;
88
+ const superParams = await super.paramsHandler(params);
89
+ const { logger, account } = superParams;
90
+ const rewardAddress = params.rewardAddress ?? account.address;
93
91
  logger?.info(`Using reward address ${rewardAddress}`);
94
92
  if (rewardAddress === account.address) {
95
93
  logger?.warn(`Using producer account address as reward address: ${account.address}`);
96
94
  }
97
95
  return {
98
- ...await super.paramsHandler({
99
- ...params,
100
- account,
101
- displayName,
102
- id
103
- }),
96
+ ...superParams,
104
97
  rewardAddress
105
98
  };
106
99
  }
107
- static async initContext(params) {
108
- const config = params?.context?.config ?? getDefaultConfig();
109
- const endpoint = assertEx(config.services.apiEndpoint, () => "API endpoint is required in config.services.apiEndpoint");
110
- const context = await super.initContext(params);
111
- const chainId = assertEx(config.chain.id, () => "Chain ID is required in config.chain.id");
112
- const transportFactory = /* @__PURE__ */ __name((schemas) => new HttpRpcTransport(endpoint, schemas), "transportFactory");
113
- const locator = await buildJsonRpcProviderLocator({
114
- context,
115
- transportFactory
116
- });
117
- const runner = await initEvmProvider({
118
- config
119
- });
120
- locator.register(EvmChainContractViewer.factory(EvmChainContractViewer.dependencies, {
121
- address: asAddress(chainId),
122
- runner
123
- }));
124
- locator.register(EvmStakeTotalsViewer.factory(EvmStakeTotalsViewer.dependencies, {
125
- address: asAddress(chainId),
126
- runner
127
- }));
128
- locator.register(SimpleBlockRewardViewer.factory(SimpleBlockRewardViewer.dependencies));
129
- locator.register(SimpleBlockValidationViewer.factory(SimpleBlockValidationViewer.dependencies, {
130
- state: validateHydratedBlockState,
131
- protocol: validateHydratedBlock
132
- }));
133
- locator.register(SimpleBlockRunner.factory(SimpleBlockRunner.dependencies, {
134
- account: params.account,
135
- rewardAddress: params.rewardAddress
136
- }));
137
- return locator.context;
138
- }
139
100
  async createHandler() {
140
101
  await super.createHandler();
141
102
  this._metricAttributes = {
@@ -160,6 +121,27 @@ var ProducerActor = class _ProducerActor extends Actor {
160
121
  this._mempoolViewer = assertEx(await this.locator?.getInstance(MempoolViewerMoniker), () => "Unable to locate MempoolViewer");
161
122
  this._stakeTotalsViewer = assertEx(await this.locator?.getInstance(StakeTotalsViewerMoniker), () => "Unable to locate StakeTotalsViewer");
162
123
  }
124
+ async initLocator() {
125
+ const config = this.config;
126
+ const endpoint = assertEx(config.services.apiEndpoint, () => "API endpoint is required in config.services.apiEndpoint");
127
+ const transportFactory = /* @__PURE__ */ __name((schemas) => new HttpRpcTransport(endpoint, schemas), "transportFactory");
128
+ const locator = await buildJsonRpcProviderLocatorV2(config, transportFactory);
129
+ const version = "1.0.0";
130
+ const telemetryConfig = buildTelemetryConfig(config, this.name, version, DefaultMetricsScrapePorts.producer);
131
+ const { traceProvider, meterProvider } = await startupSpanAsync("initTelemetry", () => initTelemetry(telemetryConfig));
132
+ locator.context.traceProvider = traceProvider;
133
+ locator.context.meterProvider = meterProvider;
134
+ locator.register(SimpleBlockRewardViewer.factory(SimpleBlockRewardViewer.dependencies, {}));
135
+ locator.register(SimpleBlockValidationViewer.factory(SimpleBlockValidationViewer.dependencies, {
136
+ state: validateHydratedBlockState,
137
+ protocol: validateHydratedBlock
138
+ }));
139
+ locator.register(SimpleBlockRunner.factory(SimpleBlockRunner.dependencies, {
140
+ account: this.params.account,
141
+ rewardAddress: this.params.rewardAddress
142
+ }));
143
+ return await initEvmProvidersIfAvailable(locator);
144
+ }
163
145
  async startHandler() {
164
146
  await super.startHandler();
165
147
  this.registerTimer("BlockProductionTimer", async () => {
@@ -303,24 +285,22 @@ ProducerActor = _ts_decorate([
303
285
  ], ProducerActor);
304
286
 
305
287
  // src/runProducer.ts
306
- import { asAddress as asAddress2, exists, IdLogger } from "@xylabs/sdk-js";
307
- import { initProducerAccount as initProducerAccount2 } from "@xyo-network/chain-orchestration";
308
- var runProducer = /* @__PURE__ */ __name(async ({ config, logger, orchestrator, locator }) => {
288
+ import { asAddress, exists, IdLogger } from "@xylabs/sdk-js";
289
+ import { initProducerAccount } from "@xyo-network/chain-orchestration";
290
+ var runProducer = /* @__PURE__ */ __name(async ({ config, logger = console, orchestrator }) => {
309
291
  const localLogger = logger ?? new IdLogger(logger ?? console, () => "ResolveHelper [runProducer]");
310
- const account = await initProducerAccount2({
292
+ const account = await initProducerAccount({
311
293
  config
312
294
  });
313
295
  localLogger.info(`Running producer for account ${account.address}`);
314
- const rewardAddress = asAddress2(config.producer.rewardAddress, () => "rewardAddress is required in config.producer");
296
+ const rewardAddress = asAddress(config.producer.rewardAddress, () => "rewardAddress is required in config.producer");
315
297
  localLogger.info(`Using reward address ${rewardAddress}`);
316
298
  const producer = await ProducerActor.create({
299
+ account,
300
+ config,
317
301
  logger,
318
- context: {
319
- config,
320
- locator,
321
- singletons: {},
322
- caches: {}
323
- }
302
+ rewardAddress,
303
+ name: "xl1-producer"
324
304
  });
325
305
  const actors = [
326
306
  producer
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/ProducerActor.ts","../../src/runProducer.ts"],"sourcesContent":["import type { Attributes, Counter } from '@opentelemetry/api'\nimport type { Address } from '@xylabs/sdk-js'\nimport {\n asAddress, assertEx, creatable, isDefined, isUndefined,\n toHex,\n} from '@xylabs/sdk-js'\nimport { EvmChainContractViewer, EvmStakeTotalsViewer } from '@xyo-network/chain-ethereum'\nimport { initEvmProvider, initProducerAccount } from '@xyo-network/chain-orchestration'\nimport { SimpleBlockRunner } from '@xyo-network/chain-services'\nimport { validateHydratedBlock, validateHydratedBlockState } from '@xyo-network/chain-validation'\nimport type {\n BlockBoundWitnessWithHashMeta, ChainId, ChainStakeIntent, HydratedBlockWithHashMeta, XL1BlockNumber,\n} from '@xyo-network/xl1-sdk'\nimport {\n AccountBalanceViewer, AccountBalanceViewerMoniker, Actor, ActorParams, asXL1BlockNumber, BlockRunner, BlockRunnerMoniker, BlockViewer, BlockViewerMoniker,\n buildJsonRpcProviderLocator, buildTransaction, Config, createDeclarationIntent, getDefaultConfig, HttpRpcTransport, MempoolRunner, MempoolRunnerMoniker,\n MempoolViewer, MempoolViewerMoniker, RpcSchemaMap, SimpleBlockRewardViewer, SimpleBlockValidationViewer, StakeTotalsViewer, StakeTotalsViewerMoniker,\n TransportFactory,\n} from '@xyo-network/xl1-sdk'\nimport { Mutex } from 'async-mutex'\n\nexport type ProducerActorParams = ActorParams<{\n rewardAddress: Address\n}>\n\nconst SHOULD_REGISTER_REDECLARATION_INTENT_TIMER = true\nconst TEN_MINUTES = 10 * 60 * 1000 // 10 minutes in milliseconds\n\n/**\n * Formats a hydrated block with hash meta into a string representation of its hash and block number.\n * @param blockBoundWitness The hydrated block with hash meta to format\n * @returns The formatted block reference string\n */\nconst toFormattedBlockReference = (blockBoundWitness: BlockBoundWitnessWithHashMeta): string => {\n return `${blockBoundWitness.block} [${toHex(blockBoundWitness._hash, { prefix: true })}]`\n}\n\n@creatable()\nexport class ProducerActor extends Actor<ProducerActorParams> {\n /**\n * The interval time (in MS) between block production attempts.\n */\n static readonly BlockSubmissionCheckInterval = 1500 // 1.5 seconds\n\n /**\n * The threshold time (in MS) for resubmitting the same block number if the head has not changed.\n */\n static readonly HeadResubmissionThreshold = ProducerActor.BlockSubmissionCheckInterval * 30\n\n /**\n * The window (in blocks) before expiration to attempt redeclaration of producer intent.\n */\n static readonly RedeclarationWindow = 10_000\n\n protected _lastProducedBlock?: HydratedBlockWithHashMeta\n protected _lastRedeclarationIntent?: ChainStakeIntent\n protected _metricAttributes?: Attributes\n protected _producerActorBlockProductionAttempts?: Counter<Attributes>\n protected _producerActorBlockProductionChecks?: Counter<Attributes>\n protected _producerActorBlocksProduced?: Counter<Attributes>\n protected _producerActorBlocksPublished?: Counter<Attributes>\n\n private _accountBalanceViewer?: AccountBalanceViewer\n private _blockRunner?: BlockRunner\n private _blockViewer?: BlockViewer\n private _chainId?: ChainId\n private _lastHeadChangeTime?: number\n private _lastHeadHash?: string\n private _mempoolRunner?: MempoolRunner\n private _mempoolViewer?: MempoolViewer\n private _produceBlockMutex = new Mutex()\n private _stakeTotalsViewer?: StakeTotalsViewer\n\n protected get accountBalanceViewer() {\n return this._accountBalanceViewer!\n }\n\n protected get blockRunner() {\n return this._blockRunner!\n }\n\n protected get blockViewer() {\n return this._blockViewer!\n }\n\n protected get chainId() {\n return this._chainId!\n }\n\n protected get mempoolRunner() {\n return this._mempoolRunner!\n }\n\n protected get mempoolViewer() {\n return this._mempoolViewer!\n }\n\n protected get rewardAddress() {\n return this.params.rewardAddress!\n }\n\n protected get stakeTotalsViewer() {\n return this._stakeTotalsViewer!\n }\n\n static override async paramsHandler<T extends ProducerActor>(params?: Partial<T['params']>) {\n const logger = params?.context?.logger\n const config = params?.context?.config ?? getDefaultConfig()\n const displayName = params?.displayName ?? 'ProducerActor'\n const account = params?.account ?? await initProducerAccount({ config })\n const id = account?.address.toString() ?? 'unknown'\n logger?.info(`Running producer for account ${account.address}`)\n const rewardAddress = params?.rewardAddress ?? account.address\n logger?.info(`Using reward address ${rewardAddress}`)\n if (rewardAddress === account.address) {\n logger?.warn(`Using producer account address as reward address: ${account.address}`)\n }\n\n return {\n ...await super.paramsHandler({\n ...params,\n account,\n displayName,\n id,\n }),\n rewardAddress,\n }\n }\n\n protected static override async initContext(\n params: ProducerActorParams,\n ) {\n const config: Config = params?.context?.config ?? getDefaultConfig()\n const endpoint = assertEx(config.services.apiEndpoint, () => 'API endpoint is required in config.services.apiEndpoint')\n\n const context = await super.initContext(params)\n\n const chainId = assertEx(config.chain.id, () => 'Chain ID is required in config.chain.id')\n\n const transportFactory: TransportFactory = (schemas: RpcSchemaMap) => new HttpRpcTransport(endpoint, schemas)\n const locator = await buildJsonRpcProviderLocator({ context, transportFactory })\n const runner = await initEvmProvider({ config })\n locator.register(EvmChainContractViewer.factory<EvmChainContractViewer>(EvmChainContractViewer.dependencies, { address: asAddress(chainId), runner }))\n locator.register(EvmStakeTotalsViewer.factory<EvmStakeTotalsViewer>(EvmStakeTotalsViewer.dependencies, { address: asAddress(chainId), runner }))\n locator.register(SimpleBlockRewardViewer.factory<SimpleBlockRewardViewer>(SimpleBlockRewardViewer.dependencies))\n locator.register(SimpleBlockValidationViewer.factory<SimpleBlockValidationViewer>(\n SimpleBlockValidationViewer.dependencies,\n { state: validateHydratedBlockState, protocol: validateHydratedBlock },\n ))\n locator.register(SimpleBlockRunner.factory<SimpleBlockRunner>(\n SimpleBlockRunner.dependencies,\n { account: params.account, rewardAddress: params.rewardAddress },\n ))\n return locator.context\n }\n\n override async createHandler() {\n await super.createHandler()\n // Create the consistent meter attributes that will\n // be included with all metrics from this actor\n this._metricAttributes = { address: this.account.address.toString() }\n // Create the metrics\n this._producerActorBlockProductionChecks = this.meter?.createCounter(\n 'producer_actor_block_production_checks',\n { description: 'Number of block production checks' },\n )\n this._producerActorBlockProductionAttempts = this.meter?.createCounter(\n 'producer_actor_block_production_attempts',\n { description: 'Number of block production attempts' },\n )\n this._producerActorBlocksProduced = this.meter?.createCounter(\n 'producer_actor_blocks_produced',\n { description: 'Number of blocks produced' },\n )\n this._producerActorBlocksPublished = this.meter?.createCounter(\n 'producer_actor_blocks_published',\n { description: 'Number of blocks published' },\n )\n this._accountBalanceViewer = assertEx(\n await this.locator?.getInstance<AccountBalanceViewer>(AccountBalanceViewerMoniker),\n () => 'Unable to locate AccountBalanceViewer',\n )\n this._blockRunner = assertEx(\n await this.locator?.getInstance<BlockRunner>(BlockRunnerMoniker),\n () => 'Unable to locate BlockRunner',\n )\n this._blockViewer = assertEx(\n await this.locator?.getInstance<BlockViewer>(BlockViewerMoniker),\n () => 'Unable to locate BlockViewer',\n )\n this._mempoolRunner = assertEx(\n await this.locator?.getInstance<MempoolRunner>(MempoolRunnerMoniker),\n () => 'Unable to locate MempoolRunner',\n )\n this._mempoolViewer = assertEx(\n await this.locator?.getInstance<MempoolViewer>(MempoolViewerMoniker),\n () => 'Unable to locate MempoolViewer',\n )\n this._stakeTotalsViewer = assertEx(\n await this.locator?.getInstance<StakeTotalsViewer>(StakeTotalsViewerMoniker),\n () => 'Unable to locate StakeTotalsViewer',\n )\n }\n\n override async startHandler() {\n await super.startHandler()\n // Register a timer to check if we should produce a block\n this.registerTimer('BlockProductionTimer', async () => {\n await this.produceBlock()\n }, 2000, ProducerActor.BlockSubmissionCheckInterval)\n\n if (SHOULD_REGISTER_REDECLARATION_INTENT_TIMER) {\n // Register a timer to check if we should redeclare the producer\n this.registerTimer('ProducerRedeclarationTimer', async () => {\n await this.redeclareIntent()\n }, TEN_MINUTES, TEN_MINUTES)\n }\n }\n\n protected calculateBlocksUntilProducerDeclarationExpiration(currentBlock: number): number {\n return (this._lastRedeclarationIntent?.exp ?? currentBlock) - currentBlock\n }\n\n protected async produceBlock(): Promise<void> {\n this._producerActorBlockProductionChecks?.add(1, this._metricAttributes)\n await this.spanAsync('produceBlock', async () => {\n if (this._produceBlockMutex.isLocked()) {\n this.logger?.log('Skipping block production, previous production still in progress')\n return\n }\n\n // eslint-disable-next-line complexity\n await this._produceBlockMutex.runExclusive(async () => {\n // Get the updated head\n const head = (await this.blockViewer.currentBlock())[0]\n // Check if we've already produced the next block for this head\n const headHash = head._hash\n\n // Track head changes\n const currentTime = Date.now()\n if (this._lastHeadHash !== headHash) {\n // Log the head change\n const lastHeadHashHex = isDefined(this._lastHeadHash) ? `0x${this._lastHeadHash}` : 'undefined'\n const currentHeadHashHex = `0x${headHash}`\n this.logger?.log(`Found updated head ${lastHeadHashHex} -> ${currentHeadHashHex}`)\n\n // Update the head change info\n this._lastHeadHash = headHash\n this._lastHeadChangeTime = currentTime\n }\n\n // Check if we should resubmit due to stale head\n const timeSinceHeadChange = isDefined(this._lastHeadChangeTime) ? currentTime - this._lastHeadChangeTime : 0\n\n // If we have never produced a block or the last produced block was not built on the current head we\n // need to attempt to produce a new block\n const shouldSubmit = !this._lastProducedBlock || this._lastProducedBlock[0].previous !== headHash\n\n // If the head has not changed determine if we should resubmit again based on head staleness\n const shouldResubmit = timeSinceHeadChange > ProducerActor.HeadResubmissionThreshold\n\n // Determine if we should submit or resubmit\n const shouldSubmitBlock = shouldSubmit || shouldResubmit\n\n if (shouldSubmitBlock) {\n // If we are resubmitting due to stale head\n if (shouldResubmit) {\n // Log that we are resubmitting due to stale head\n this.logger?.log(`Resubmitting block due to stale head. Head ${toFormattedBlockReference(head)} unchanged for ${timeSinceHeadChange}ms`)\n // Reset timer since we're resubmitting\n this._lastHeadChangeTime = currentTime\n }\n this._producerActorBlockProductionAttempts?.add(1, this._metricAttributes)\n // Produce the next block\n const nextBlock = await this.blockRunner.next(head)\n // If it was produced\n if (nextBlock) {\n const displayBlockNumber = toFormattedBlockReference(nextBlock[0])\n this.logger?.log('Produced block:', displayBlockNumber)\n this._producerActorBlocksProduced?.add(1, this._metricAttributes)\n // Insert the block into the chain\n await this.mempoolRunner.submitBlocks([nextBlock])\n this.logger?.log('Published block:', displayBlockNumber)\n this._producerActorBlocksPublished?.add(1, this._metricAttributes)\n // Record that we have produced a block so we do not produce it again\n this._lastProducedBlock = nextBlock\n } else {\n this.logger?.log('No block produced for submission.')\n }\n } else {\n // Log that we are not submitting a block at this time\n let nonSubmissionMessage = 'No block submission required at this time'\n // If we have already produced a block\n if (isDefined(this._lastProducedBlock)) {\n // include that info in the log\n nonSubmissionMessage = nonSubmissionMessage + `, already produced: ${toFormattedBlockReference(this._lastProducedBlock[0])}`\n }\n this.logger?.log(`${nonSubmissionMessage}.`)\n }\n })\n }, { ...this.context, timeBudgetLimit: 1000 })\n }\n\n protected async redeclareIntent(): Promise<void> {\n await this.spanAsync('redeclareIntent', async () => {\n // Decide if we should redeclare intent\n if (this.config.producer.disableIntentRedeclaration) return\n\n // Get the current block\n const head = (await this.blockViewer.currentBlock())[0]\n if (isUndefined(head)) return\n const currentBlock = head.block\n\n // // Calculate the time until the producer's declaration expires\n const blocksUntilExpiration = this.calculateBlocksUntilProducerDeclarationExpiration(currentBlock)\n\n // Allow the producer time to redeclare itself via block production\n // (for free) before submitting a redeclaration intent transaction.\n if (blocksUntilExpiration > ProducerActor.RedeclarationWindow * 0.1) {\n // Clear any previous redeclaration intent\n this._lastRedeclarationIntent = undefined\n // No need to redeclare yet\n return\n }\n\n // If we already have a valid redeclaration intent, do not create another\n // unless it has expired.\n if (this._lastRedeclarationIntent) {\n // Check if the last redeclaration intent is still valid\n if (this._lastRedeclarationIntent.exp > currentBlock) return\n // If it has expired, clear the last redeclaration intent\n this._lastRedeclarationIntent = undefined\n }\n\n // Check if we have a valid balance before declaring intent\n if (!await this.validateCurrentBalance()) {\n this.logger?.error(\n `Add balance to address ${this.account.address} for the producer to declare it's intent.`,\n )\n return\n }\n\n // Check if we have a valid stake before declaring intent\n if (!(await this.validateCurrentStake())) {\n this.logger?.error(\n `Add stake to contract address ${this.config.chain.id}`\n + ' for the producer to declare it\\'s intent.',\n )\n return\n }\n\n // Create a redeclaration intent\n this.logger?.log('Creating redeclaration intent for producer:', this.account.address)\n const redeclarationIntent = createDeclarationIntent(\n this.account.address,\n 'producer',\n currentBlock,\n currentBlock + SimpleBlockRunner.RedeclarationDuration,\n )\n\n // Submit the redeclaration intent\n await this.submitRedeclarationIntent(currentBlock, redeclarationIntent)\n\n // On successful submission, save the redeclaration intent\n this._lastRedeclarationIntent = redeclarationIntent\n }, { ...this.context, timeBudgetLimit: 1000 })\n }\n\n protected async submitRedeclarationIntent(currentBlock: XL1BlockNumber, redeclarationIntent: ChainStakeIntent): Promise<void> {\n this.logger?.log('Submitting redeclaration intent for producer:', this.account.address)\n // Create a transaction to submit the redeclaration intent\n const tx = await buildTransaction(\n this.chainId,\n [redeclarationIntent],\n [],\n this.account,\n currentBlock,\n asXL1BlockNumber(currentBlock + 1000, true),\n )\n\n // Submit the redeclaration intent\n await this.mempoolRunner.submitTransactions([tx])\n\n this.logger?.log('Submitted redeclaration intent for producer:', this.account.address)\n }\n\n protected async validateCurrentBalance(): Promise<boolean> {\n // Check if we have a valid balance before declaring intent\n const head = (await this.blockViewer.currentBlock())?.[0]?._hash\n if (isDefined(head)) {\n const balances = await this.accountBalanceViewer.accountBalances([this.account.address], { head })\n const currentBalance = balances[this.account.address] ?? 0n\n if (currentBalance <= 0n) {\n this.logger?.error(`Producer ${this.account.address} has no balance.`)\n return false\n }\n return true\n }\n return true\n }\n\n protected async validateCurrentStake(): Promise<boolean> {\n // Use StakeIntentService to get the required minimum stake\n const requiredMinimumStake = 1n // this.stakeIntentService.getRequiredMinimumStakeForIntent('producer')\n // Check if we have a valid stake before declaring intent\n const currentStake = await this.stakeTotalsViewer.activeByStaked(this.account.address)\n if (currentStake < requiredMinimumStake) {\n this.logger?.error(`Producer ${this.account.address} has insufficient stake.`)\n return false\n }\n return true\n }\n}\n","import {\n asAddress, exists, IdLogger,\n} from '@xylabs/sdk-js'\nimport { initProducerAccount, type OrchestratorInstance } from '@xyo-network/chain-orchestration'\nimport type {\n BaseContext, Config, ProviderFactoryLocatorInstance,\n} from '@xyo-network/xl1-sdk'\n\nimport { ProducerActor } from './ProducerActor.ts'\n\nexport interface RunProducerContext extends BaseContext {\n config: Config\n locator?: ProviderFactoryLocatorInstance\n orchestrator: OrchestratorInstance\n}\n\nexport const runProducer = async ({\n config, logger, orchestrator, locator,\n}: RunProducerContext) => {\n const localLogger = logger ?? new IdLogger(logger ?? console, () => 'ResolveHelper [runProducer]')\n const account = await initProducerAccount({ config })\n localLogger.info(`Running producer for account ${account.address}`)\n const rewardAddress = asAddress(config.producer.rewardAddress, () => 'rewardAddress is required in config.producer')\n localLogger.info(`Using reward address ${rewardAddress}`)\n\n // Create actors\n const producer = await ProducerActor.create({\n logger,\n context: {\n config, locator, singletons: {}, caches: {},\n },\n })\n const actors = [producer].filter(exists)\n\n for (const actor of actors) {\n // Register the actor with the orchestrator\n await orchestrator.registerActor(actor)\n }\n // Start the orchestrator => automatically activates the actor\n await orchestrator.start()\n}\n"],"mappings":"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","names":["asAddress","assertEx","creatable","isDefined","isUndefined","toHex","EvmChainContractViewer","EvmStakeTotalsViewer","initEvmProvider","initProducerAccount","SimpleBlockRunner","validateHydratedBlock","validateHydratedBlockState","AccountBalanceViewerMoniker","Actor","asXL1BlockNumber","BlockRunnerMoniker","BlockViewerMoniker","buildJsonRpcProviderLocator","buildTransaction","createDeclarationIntent","getDefaultConfig","HttpRpcTransport","MempoolRunnerMoniker","MempoolViewerMoniker","SimpleBlockRewardViewer","SimpleBlockValidationViewer","StakeTotalsViewerMoniker","Mutex","SHOULD_REGISTER_REDECLARATION_INTENT_TIMER","TEN_MINUTES","toFormattedBlockReference","blockBoundWitness","block","toHex","_hash","prefix","ProducerActor","Actor","BlockSubmissionCheckInterval","HeadResubmissionThreshold","RedeclarationWindow","_lastProducedBlock","_lastRedeclarationIntent","_metricAttributes","_producerActorBlockProductionAttempts","_producerActorBlockProductionChecks","_producerActorBlocksProduced","_producerActorBlocksPublished","_accountBalanceViewer","_blockRunner","_blockViewer","_chainId","_lastHeadChangeTime","_lastHeadHash","_mempoolRunner","_mempoolViewer","_produceBlockMutex","Mutex","_stakeTotalsViewer","accountBalanceViewer","blockRunner","blockViewer","chainId","mempoolRunner","mempoolViewer","rewardAddress","params","stakeTotalsViewer","paramsHandler","logger","context","config","getDefaultConfig","displayName","account","initProducerAccount","id","address","toString","info","warn","initContext","endpoint","assertEx","services","apiEndpoint","chain","transportFactory","schemas","HttpRpcTransport","locator","buildJsonRpcProviderLocator","runner","initEvmProvider","register","EvmChainContractViewer","factory","dependencies","asAddress","EvmStakeTotalsViewer","SimpleBlockRewardViewer","SimpleBlockValidationViewer","state","validateHydratedBlockState","protocol","validateHydratedBlock","SimpleBlockRunner","createHandler","meter","createCounter","description","getInstance","AccountBalanceViewerMoniker","BlockRunnerMoniker","BlockViewerMoniker","MempoolRunnerMoniker","MempoolViewerMoniker","StakeTotalsViewerMoniker","startHandler","registerTimer","produceBlock","redeclareIntent","calculateBlocksUntilProducerDeclarationExpiration","currentBlock","exp","add","spanAsync","isLocked","log","runExclusive","head","headHash","currentTime","Date","now","lastHeadHashHex","isDefined","currentHeadHashHex","timeSinceHeadChange","shouldSubmit","previous","shouldResubmit","shouldSubmitBlock","nextBlock","next","displayBlockNumber","submitBlocks","nonSubmissionMessage","timeBudgetLimit","producer","disableIntentRedeclaration","isUndefined","blocksUntilExpiration","undefined","validateCurrentBalance","error","validateCurrentStake","redeclarationIntent","createDeclarationIntent","RedeclarationDuration","submitRedeclarationIntent","tx","buildTransaction","asXL1BlockNumber","submitTransactions","balances","accountBalances","currentBalance","requiredMinimumStake","currentStake","activeByStaked","asAddress","exists","IdLogger","initProducerAccount","runProducer","config","logger","orchestrator","locator","localLogger","IdLogger","console","account","initProducerAccount","info","address","rewardAddress","asAddress","producer","ProducerActor","create","context","singletons","caches","actors","filter","exists","actor","registerActor","start"]}
1
+ {"version":3,"sources":["../../src/ProducerActor.ts","../../src/runProducer.ts"],"sourcesContent":["import type { Attributes, Counter } from '@opentelemetry/api'\nimport type { Address, Logger } from '@xylabs/sdk-js'\nimport {\n assertEx, creatable, isDefined, isUndefined,\n toHex,\n} from '@xylabs/sdk-js'\nimport { buildTelemetryConfig, initEvmProvidersIfAvailable } from '@xyo-network/chain-orchestration'\nimport { SimpleBlockRunner } from '@xyo-network/chain-services'\nimport { initTelemetry } from '@xyo-network/chain-telemetry'\nimport { startupSpanAsync } from '@xyo-network/chain-utils'\nimport { validateHydratedBlock, validateHydratedBlockState } from '@xyo-network/chain-validation'\nimport type {\n ActorParamsV2,\n BlockBoundWitnessWithHashMeta, ChainId, ChainStakeIntent, HydratedBlockWithHashMeta, XL1BlockNumber,\n} from '@xyo-network/xl1-sdk'\nimport {\n AccountBalanceViewer, AccountBalanceViewerMoniker, ActorV2, asXL1BlockNumber, BlockRunner, BlockRunnerMoniker, BlockViewer, BlockViewerMoniker,\n buildJsonRpcProviderLocatorV2, buildTransaction, createDeclarationIntent, DefaultMetricsScrapePorts, HttpRpcTransport, MempoolRunner, MempoolRunnerMoniker,\n MempoolViewer, MempoolViewerMoniker, RpcSchemaMap, SimpleBlockRewardViewer, SimpleBlockValidationViewer, StakeTotalsViewer, StakeTotalsViewerMoniker,\n TransportFactory,\n} from '@xyo-network/xl1-sdk'\nimport { Mutex } from 'async-mutex'\n\nexport type ProducerActorParams = ActorParamsV2<{\n logger: Logger\n rewardAddress: Address\n}>\n\nconst SHOULD_REGISTER_REDECLARATION_INTENT_TIMER = true\nconst TEN_MINUTES = 10 * 60 * 1000 // 10 minutes in milliseconds\n\n/**\n * Formats a hydrated block with hash meta into a string representation of its hash and block number.\n * @param blockBoundWitness The hydrated block with hash meta to format\n * @returns The formatted block reference string\n */\nconst toFormattedBlockReference = (blockBoundWitness: BlockBoundWitnessWithHashMeta): string => {\n return `${blockBoundWitness.block} [${toHex(blockBoundWitness._hash, { prefix: true })}]`\n}\n\n@creatable()\nexport class ProducerActor extends ActorV2<ProducerActorParams> {\n /**\n * The interval time (in MS) between block production attempts.\n */\n static readonly BlockSubmissionCheckInterval = 1500 // 1.5 seconds\n\n /**\n * The threshold time (in MS) for resubmitting the same block number if the head has not changed.\n */\n static readonly HeadResubmissionThreshold = ProducerActor.BlockSubmissionCheckInterval * 30\n\n /**\n * The window (in blocks) before expiration to attempt redeclaration of producer intent.\n */\n static readonly RedeclarationWindow = 10_000\n\n protected _lastProducedBlock?: HydratedBlockWithHashMeta\n protected _lastRedeclarationIntent?: ChainStakeIntent\n protected _metricAttributes?: Attributes\n protected _producerActorBlockProductionAttempts?: Counter<Attributes>\n protected _producerActorBlockProductionChecks?: Counter<Attributes>\n protected _producerActorBlocksProduced?: Counter<Attributes>\n protected _producerActorBlocksPublished?: Counter<Attributes>\n\n private _accountBalanceViewer?: AccountBalanceViewer\n private _blockRunner?: BlockRunner\n private _blockViewer?: BlockViewer\n private _chainId?: ChainId\n private _lastHeadChangeTime?: number\n private _lastHeadHash?: string\n private _mempoolRunner?: MempoolRunner\n private _mempoolViewer?: MempoolViewer\n private _produceBlockMutex = new Mutex()\n private _stakeTotalsViewer?: StakeTotalsViewer\n\n override get logger() {\n return assertEx(super.logger, () => 'Logger is required for ProducerActor')\n }\n\n protected get accountBalanceViewer() {\n return this._accountBalanceViewer!\n }\n\n protected get blockRunner() {\n return this._blockRunner!\n }\n\n protected get blockViewer() {\n return this._blockViewer!\n }\n\n protected get chainId() {\n return this._chainId!\n }\n\n protected get mempoolRunner() {\n return this._mempoolRunner!\n }\n\n protected get mempoolViewer() {\n return this._mempoolViewer!\n }\n\n protected get rewardAddress() {\n return this.params.rewardAddress!\n }\n\n protected get stakeTotalsViewer() {\n return this._stakeTotalsViewer!\n }\n\n static override async paramsHandler<T extends ProducerActor>(params: Partial<T['params']>) {\n const superParams = await super.paramsHandler(params)\n const { logger, account } = superParams\n const rewardAddress = params.rewardAddress ?? account.address\n logger?.info(`Using reward address ${rewardAddress}`)\n if (rewardAddress === account.address) {\n logger?.warn(`Using producer account address as reward address: ${account.address}`)\n }\n\n return {\n ...superParams,\n rewardAddress,\n }\n }\n\n override async createHandler() {\n await super.createHandler()\n // Create the consistent meter attributes that will\n // be included with all metrics from this actor\n this._metricAttributes = { address: this.account.address.toString() }\n // Create the metrics\n this._producerActorBlockProductionChecks = this.meter?.createCounter(\n 'producer_actor_block_production_checks',\n { description: 'Number of block production checks' },\n )\n this._producerActorBlockProductionAttempts = this.meter?.createCounter(\n 'producer_actor_block_production_attempts',\n { description: 'Number of block production attempts' },\n )\n this._producerActorBlocksProduced = this.meter?.createCounter(\n 'producer_actor_blocks_produced',\n { description: 'Number of blocks produced' },\n )\n this._producerActorBlocksPublished = this.meter?.createCounter(\n 'producer_actor_blocks_published',\n { description: 'Number of blocks published' },\n )\n this._accountBalanceViewer = assertEx(\n await this.locator?.getInstance<AccountBalanceViewer>(AccountBalanceViewerMoniker),\n () => 'Unable to locate AccountBalanceViewer',\n )\n this._blockRunner = assertEx(\n await this.locator?.getInstance<BlockRunner>(BlockRunnerMoniker),\n () => 'Unable to locate BlockRunner',\n )\n this._blockViewer = assertEx(\n await this.locator?.getInstance<BlockViewer>(BlockViewerMoniker),\n () => 'Unable to locate BlockViewer',\n )\n this._mempoolRunner = assertEx(\n await this.locator?.getInstance<MempoolRunner>(MempoolRunnerMoniker),\n () => 'Unable to locate MempoolRunner',\n )\n this._mempoolViewer = assertEx(\n await this.locator?.getInstance<MempoolViewer>(MempoolViewerMoniker),\n () => 'Unable to locate MempoolViewer',\n )\n this._stakeTotalsViewer = assertEx(\n await this.locator?.getInstance<StakeTotalsViewer>(StakeTotalsViewerMoniker),\n () => 'Unable to locate StakeTotalsViewer',\n )\n }\n\n async initLocator() {\n const config = this.config\n const endpoint = assertEx(config.services.apiEndpoint, () => 'API endpoint is required in config.services.apiEndpoint')\n const transportFactory: TransportFactory = (schemas: RpcSchemaMap) => new HttpRpcTransport(endpoint, schemas)\n const locator = await buildJsonRpcProviderLocatorV2(config, transportFactory)\n\n const version = '1.0.0'\n const telemetryConfig = buildTelemetryConfig(config, this.name, version, DefaultMetricsScrapePorts.producer)\n const { traceProvider, meterProvider } = await startupSpanAsync('initTelemetry', () => initTelemetry(telemetryConfig))\n\n locator.context.traceProvider = traceProvider\n locator.context.meterProvider = meterProvider\n\n locator.register(SimpleBlockRewardViewer.factory<SimpleBlockRewardViewer>(SimpleBlockRewardViewer.dependencies, {}))\n locator.register(SimpleBlockValidationViewer.factory<SimpleBlockValidationViewer>(\n SimpleBlockValidationViewer.dependencies,\n { state: validateHydratedBlockState, protocol: validateHydratedBlock },\n ))\n locator.register(SimpleBlockRunner.factory<SimpleBlockRunner>(\n SimpleBlockRunner.dependencies,\n { account: this.params.account, rewardAddress: this.params.rewardAddress },\n ))\n return await initEvmProvidersIfAvailable(locator)\n }\n\n override async startHandler() {\n await super.startHandler()\n // Register a timer to check if we should produce a block\n this.registerTimer('BlockProductionTimer', async () => {\n await this.produceBlock()\n }, 2000, ProducerActor.BlockSubmissionCheckInterval)\n\n if (SHOULD_REGISTER_REDECLARATION_INTENT_TIMER) {\n // Register a timer to check if we should redeclare the producer\n this.registerTimer('ProducerRedeclarationTimer', async () => {\n await this.redeclareIntent()\n }, TEN_MINUTES, TEN_MINUTES)\n }\n }\n\n protected calculateBlocksUntilProducerDeclarationExpiration(currentBlock: number): number {\n return (this._lastRedeclarationIntent?.exp ?? currentBlock) - currentBlock\n }\n\n protected async produceBlock(): Promise<void> {\n this._producerActorBlockProductionChecks?.add(1, this._metricAttributes)\n await this.spanAsync('produceBlock', async () => {\n if (this._produceBlockMutex.isLocked()) {\n this.logger?.log('Skipping block production, previous production still in progress')\n return\n }\n\n // eslint-disable-next-line complexity\n await this._produceBlockMutex.runExclusive(async () => {\n // Get the updated head\n const head = (await this.blockViewer.currentBlock())[0]\n // Check if we've already produced the next block for this head\n const headHash = head._hash\n\n // Track head changes\n const currentTime = Date.now()\n if (this._lastHeadHash !== headHash) {\n // Log the head change\n const lastHeadHashHex = isDefined(this._lastHeadHash) ? `0x${this._lastHeadHash}` : 'undefined'\n const currentHeadHashHex = `0x${headHash}`\n this.logger?.log(`Found updated head ${lastHeadHashHex} -> ${currentHeadHashHex}`)\n\n // Update the head change info\n this._lastHeadHash = headHash\n this._lastHeadChangeTime = currentTime\n }\n\n // Check if we should resubmit due to stale head\n const timeSinceHeadChange = isDefined(this._lastHeadChangeTime) ? currentTime - this._lastHeadChangeTime : 0\n\n // If we have never produced a block or the last produced block was not built on the current head we\n // need to attempt to produce a new block\n const shouldSubmit = !this._lastProducedBlock || this._lastProducedBlock[0].previous !== headHash\n\n // If the head has not changed determine if we should resubmit again based on head staleness\n const shouldResubmit = timeSinceHeadChange > ProducerActor.HeadResubmissionThreshold\n\n // Determine if we should submit or resubmit\n const shouldSubmitBlock = shouldSubmit || shouldResubmit\n\n if (shouldSubmitBlock) {\n // If we are resubmitting due to stale head\n if (shouldResubmit) {\n // Log that we are resubmitting due to stale head\n this.logger?.log(`Resubmitting block due to stale head. Head ${toFormattedBlockReference(head)} unchanged for ${timeSinceHeadChange}ms`)\n // Reset timer since we're resubmitting\n this._lastHeadChangeTime = currentTime\n }\n this._producerActorBlockProductionAttempts?.add(1, this._metricAttributes)\n // Produce the next block\n const nextBlock = await this.blockRunner.next(head)\n // If it was produced\n if (nextBlock) {\n const displayBlockNumber = toFormattedBlockReference(nextBlock[0])\n this.logger?.log('Produced block:', displayBlockNumber)\n this._producerActorBlocksProduced?.add(1, this._metricAttributes)\n // Insert the block into the chain\n await this.mempoolRunner.submitBlocks([nextBlock])\n this.logger?.log('Published block:', displayBlockNumber)\n this._producerActorBlocksPublished?.add(1, this._metricAttributes)\n // Record that we have produced a block so we do not produce it again\n this._lastProducedBlock = nextBlock\n } else {\n this.logger?.log('No block produced for submission.')\n }\n } else {\n // Log that we are not submitting a block at this time\n let nonSubmissionMessage = 'No block submission required at this time'\n // If we have already produced a block\n if (isDefined(this._lastProducedBlock)) {\n // include that info in the log\n nonSubmissionMessage = nonSubmissionMessage + `, already produced: ${toFormattedBlockReference(this._lastProducedBlock[0])}`\n }\n this.logger?.log(`${nonSubmissionMessage}.`)\n }\n })\n }, { ...this.context, timeBudgetLimit: 1000 })\n }\n\n protected async redeclareIntent(): Promise<void> {\n await this.spanAsync('redeclareIntent', async () => {\n // Decide if we should redeclare intent\n if (this.config.producer.disableIntentRedeclaration) return\n\n // Get the current block\n const head = (await this.blockViewer.currentBlock())[0]\n if (isUndefined(head)) return\n const currentBlock = head.block\n\n // // Calculate the time until the producer's declaration expires\n const blocksUntilExpiration = this.calculateBlocksUntilProducerDeclarationExpiration(currentBlock)\n\n // Allow the producer time to redeclare itself via block production\n // (for free) before submitting a redeclaration intent transaction.\n if (blocksUntilExpiration > ProducerActor.RedeclarationWindow * 0.1) {\n // Clear any previous redeclaration intent\n this._lastRedeclarationIntent = undefined\n // No need to redeclare yet\n return\n }\n\n // If we already have a valid redeclaration intent, do not create another\n // unless it has expired.\n if (this._lastRedeclarationIntent) {\n // Check if the last redeclaration intent is still valid\n if (this._lastRedeclarationIntent.exp > currentBlock) return\n // If it has expired, clear the last redeclaration intent\n this._lastRedeclarationIntent = undefined\n }\n\n // Check if we have a valid balance before declaring intent\n if (!await this.validateCurrentBalance()) {\n this.logger?.error(\n `Add balance to address ${this.account.address} for the producer to declare it's intent.`,\n )\n return\n }\n\n // Check if we have a valid stake before declaring intent\n if (!(await this.validateCurrentStake())) {\n this.logger?.error(\n `Add stake to contract address ${this.config.chain.id}`\n + ' for the producer to declare it\\'s intent.',\n )\n return\n }\n\n // Create a redeclaration intent\n this.logger?.log('Creating redeclaration intent for producer:', this.account.address)\n const redeclarationIntent = createDeclarationIntent(\n this.account.address,\n 'producer',\n currentBlock,\n currentBlock + SimpleBlockRunner.RedeclarationDuration,\n )\n\n // Submit the redeclaration intent\n await this.submitRedeclarationIntent(currentBlock, redeclarationIntent)\n\n // On successful submission, save the redeclaration intent\n this._lastRedeclarationIntent = redeclarationIntent\n }, { ...this.context, timeBudgetLimit: 1000 })\n }\n\n protected async submitRedeclarationIntent(currentBlock: XL1BlockNumber, redeclarationIntent: ChainStakeIntent): Promise<void> {\n this.logger?.log('Submitting redeclaration intent for producer:', this.account.address)\n // Create a transaction to submit the redeclaration intent\n const tx = await buildTransaction(\n this.chainId,\n [redeclarationIntent],\n [],\n this.account,\n currentBlock,\n asXL1BlockNumber(currentBlock + 1000, true),\n )\n\n // Submit the redeclaration intent\n await this.mempoolRunner.submitTransactions([tx])\n\n this.logger?.log('Submitted redeclaration intent for producer:', this.account.address)\n }\n\n protected async validateCurrentBalance(): Promise<boolean> {\n // Check if we have a valid balance before declaring intent\n const head = (await this.blockViewer.currentBlock())?.[0]?._hash\n if (isDefined(head)) {\n const balances = await this.accountBalanceViewer.accountBalances([this.account.address], { head })\n const currentBalance = balances[this.account.address] ?? 0n\n if (currentBalance <= 0n) {\n this.logger?.error(`Producer ${this.account.address} has no balance.`)\n return false\n }\n return true\n }\n return true\n }\n\n protected async validateCurrentStake(): Promise<boolean> {\n // Use StakeIntentService to get the required minimum stake\n const requiredMinimumStake = 1n // this.stakeIntentService.getRequiredMinimumStakeForIntent('producer')\n // Check if we have a valid stake before declaring intent\n const currentStake = await this.stakeTotalsViewer.activeByStaked(this.account.address)\n if (currentStake < requiredMinimumStake) {\n this.logger?.error(`Producer ${this.account.address} has insufficient stake.`)\n return false\n }\n return true\n }\n}\n","import type { CreatableName } from '@xylabs/sdk-js'\nimport {\n asAddress, exists, IdLogger,\n} from '@xylabs/sdk-js'\nimport { initProducerAccount, type OrchestratorInstance } from '@xyo-network/chain-orchestration'\nimport { type BaseContext, type Config } from '@xyo-network/xl1-sdk'\n\nimport type { ProducerActorParams } from './ProducerActor.ts'\nimport { ProducerActor } from './ProducerActor.ts'\n\nexport interface RunProducerContext extends BaseContext {\n config: Config\n orchestrator: OrchestratorInstance\n}\n\nexport const runProducer = async ({\n config, logger = console, orchestrator,\n}: RunProducerContext) => {\n const localLogger = logger ?? new IdLogger(logger ?? console, () => 'ResolveHelper [runProducer]')\n const account = await initProducerAccount({ config })\n localLogger.info(`Running producer for account ${account.address}`)\n const rewardAddress = asAddress(config.producer.rewardAddress, () => 'rewardAddress is required in config.producer')\n localLogger.info(`Using reward address ${rewardAddress}`)\n\n // Create actors\n const producer = await ProducerActor.create({\n account, config, logger, rewardAddress, name: 'xl1-producer' as CreatableName,\n } satisfies ProducerActorParams)\n const actors = [producer].filter(exists)\n\n for (const actor of actors) {\n // Register the actor with the orchestrator\n await orchestrator.registerActor(actor)\n }\n // Start the orchestrator => automatically activates the actor\n await orchestrator.start()\n}\n"],"mappings":";;;;AAEA,SACEA,UAAUC,WAAWC,WAAWC,aAChCC,aACK;AACP,SAASC,sBAAsBC,mCAAmC;AAClE,SAASC,yBAAyB;AAClC,SAASC,qBAAqB;AAC9B,SAASC,wBAAwB;AACjC,SAASC,uBAAuBC,kCAAkC;AAKlE,SACwBC,6BAA6BC,SAASC,kBAA+BC,oBAAiCC,oBAC5HC,+BAA+BC,kBAAkBC,yBAAyBC,2BAA2BC,kBAAiCC,sBACvHC,sBAAoCC,yBAAyBC,6BAAgDC,gCAEvH;AACP,SAASC,aAAa;;;;;;;;AAOtB,IAAMC,6CAA6C;AACnD,IAAMC,cAAc,KAAK,KAAK;AAO9B,IAAMC,4BAA4B,wBAACC,sBAAAA;AACjC,SAAO,GAAGA,kBAAkBC,KAAK,KAAKC,MAAMF,kBAAkBG,OAAO;IAAEC,QAAQ;EAAK,CAAA,CAAA;AACtF,GAFkC;AAK3B,IAAMC,gBAAN,MAAMA,uBAAsBC,QAAAA;SAAAA;;;;;;EAIjC,OAAgBC,+BAA+B;;;;EAK/C,OAAgBC,4BAA4BH,eAAcE,+BAA+B;;;;EAKzF,OAAgBE,sBAAsB;EAE5BC;EACAC;EACAC;EACAC;EACAC;EACAC;EACAC;EAEFC;EACAC;EACAC;EACAC;EACAC;EACAC;EACAC;EACAC;EACAC,qBAAqB,IAAIC,MAAAA;EACzBC;EAER,IAAaC,SAAS;AACpB,WAAOC,SAAS,MAAMD,QAAQ,MAAM,sCAAA;EACtC;EAEA,IAAcE,uBAAuB;AACnC,WAAO,KAAKb;EACd;EAEA,IAAcc,cAAc;AAC1B,WAAO,KAAKb;EACd;EAEA,IAAcc,cAAc;AAC1B,WAAO,KAAKb;EACd;EAEA,IAAcc,UAAU;AACtB,WAAO,KAAKb;EACd;EAEA,IAAcc,gBAAgB;AAC5B,WAAO,KAAKX;EACd;EAEA,IAAcY,gBAAgB;AAC5B,WAAO,KAAKX;EACd;EAEA,IAAcY,gBAAgB;AAC5B,WAAO,KAAKC,OAAOD;EACrB;EAEA,IAAcE,oBAAoB;AAChC,WAAO,KAAKX;EACd;EAEA,aAAsBY,cAAuCF,QAA8B;AACzF,UAAMG,cAAc,MAAM,MAAMD,cAAcF,MAAAA;AAC9C,UAAM,EAAET,QAAQa,QAAO,IAAKD;AAC5B,UAAMJ,gBAAgBC,OAAOD,iBAAiBK,QAAQC;AACtDd,YAAQe,KAAK,wBAAwBP,aAAAA,EAAe;AACpD,QAAIA,kBAAkBK,QAAQC,SAAS;AACrCd,cAAQgB,KAAK,qDAAqDH,QAAQC,OAAO,EAAE;IACrF;AAEA,WAAO;MACL,GAAGF;MACHJ;IACF;EACF;EAEA,MAAeS,gBAAgB;AAC7B,UAAM,MAAMA,cAAAA;AAGZ,SAAKjC,oBAAoB;MAAE8B,SAAS,KAAKD,QAAQC,QAAQI,SAAQ;IAAG;AAEpE,SAAKhC,sCAAsC,KAAKiC,OAAOC,cACrD,0CACA;MAAEC,aAAa;IAAoC,CAAA;AAErD,SAAKpC,wCAAwC,KAAKkC,OAAOC,cACvD,4CACA;MAAEC,aAAa;IAAsC,CAAA;AAEvD,SAAKlC,+BAA+B,KAAKgC,OAAOC,cAC9C,kCACA;MAAEC,aAAa;IAA4B,CAAA;AAE7C,SAAKjC,gCAAgC,KAAK+B,OAAOC,cAC/C,mCACA;MAAEC,aAAa;IAA6B,CAAA;AAE9C,SAAKhC,wBAAwBY,SAC3B,MAAM,KAAKqB,SAASC,YAAkCC,2BAAAA,GACtD,MAAM,uCAAA;AAER,SAAKlC,eAAeW,SAClB,MAAM,KAAKqB,SAASC,YAAyBE,kBAAAA,GAC7C,MAAM,8BAAA;AAER,SAAKlC,eAAeU,SAClB,MAAM,KAAKqB,SAASC,YAAyBG,kBAAAA,GAC7C,MAAM,8BAAA;AAER,SAAK/B,iBAAiBM,SACpB,MAAM,KAAKqB,SAASC,YAA2BI,oBAAAA,GAC/C,MAAM,gCAAA;AAER,SAAK/B,iBAAiBK,SACpB,MAAM,KAAKqB,SAASC,YAA2BK,oBAAAA,GAC/C,MAAM,gCAAA;AAER,SAAK7B,qBAAqBE,SACxB,MAAM,KAAKqB,SAASC,YAA+BM,wBAAAA,GACnD,MAAM,oCAAA;EAEV;EAEA,MAAMC,cAAc;AAClB,UAAMC,SAAS,KAAKA;AACpB,UAAMC,WAAW/B,SAAS8B,OAAOE,SAASC,aAAa,MAAM,yDAAA;AAC7D,UAAMC,mBAAqC,wBAACC,YAA0B,IAAIC,iBAAiBL,UAAUI,OAAAA,GAA1D;AAC3C,UAAMd,UAAU,MAAMgB,8BAA8BP,QAAQI,gBAAAA;AAE5D,UAAMI,UAAU;AAChB,UAAMC,kBAAkBC,qBAAqBV,QAAQ,KAAKW,MAAMH,SAASI,0BAA0BC,QAAQ;AAC3G,UAAM,EAAEC,eAAeC,cAAa,IAAK,MAAMC,iBAAiB,iBAAiB,MAAMC,cAAcR,eAAAA,CAAAA;AAErGlB,YAAQ2B,QAAQJ,gBAAgBA;AAChCvB,YAAQ2B,QAAQH,gBAAgBA;AAEhCxB,YAAQ4B,SAASC,wBAAwBC,QAAiCD,wBAAwBE,cAAc,CAAC,CAAA,CAAA;AACjH/B,YAAQ4B,SAASI,4BAA4BF,QAC3CE,4BAA4BD,cAC5B;MAAEE,OAAOC;MAA4BC,UAAUC;IAAsB,CAAA,CAAA;AAEvEpC,YAAQ4B,SAASS,kBAAkBP,QACjCO,kBAAkBN,cAClB;MAAExC,SAAS,KAAKJ,OAAOI;MAASL,eAAe,KAAKC,OAAOD;IAAc,CAAA,CAAA;AAE3E,WAAO,MAAMoD,4BAA4BtC,OAAAA;EAC3C;EAEA,MAAeuC,eAAe;AAC5B,UAAM,MAAMA,aAAAA;AAEZ,SAAKC,cAAc,wBAAwB,YAAA;AACzC,YAAM,KAAKC,aAAY;IACzB,GAAG,KAAMtF,eAAcE,4BAA4B;AAEnD,QAAIV,4CAA4C;AAE9C,WAAK6F,cAAc,8BAA8B,YAAA;AAC/C,cAAM,KAAKE,gBAAe;MAC5B,GAAG9F,aAAaA,WAAAA;IAClB;EACF;EAEU+F,kDAAkDC,cAA8B;AACxF,YAAQ,KAAKnF,0BAA0BoF,OAAOD,gBAAgBA;EAChE;EAEA,MAAgBH,eAA8B;AAC5C,SAAK7E,qCAAqCkF,IAAI,GAAG,KAAKpF,iBAAiB;AACvE,UAAM,KAAKqF,UAAU,gBAAgB,YAAA;AACnC,UAAI,KAAKxE,mBAAmByE,SAAQ,GAAI;AACtC,aAAKtE,QAAQuE,IAAI,kEAAA;AACjB;MACF;AAGA,YAAM,KAAK1E,mBAAmB2E,aAAa,YAAA;AAEzC,cAAMC,QAAQ,MAAM,KAAKrE,YAAY8D,aAAY,GAAI,CAAA;AAErD,cAAMQ,WAAWD,KAAKlG;AAGtB,cAAMoG,cAAcC,KAAKC,IAAG;AAC5B,YAAI,KAAKnF,kBAAkBgF,UAAU;AAEnC,gBAAMI,kBAAkBC,UAAU,KAAKrF,aAAa,IAAI,KAAK,KAAKA,aAAa,KAAK;AACpF,gBAAMsF,qBAAqB,KAAKN,QAAAA;AAChC,eAAK1E,QAAQuE,IAAI,sBAAsBO,eAAAA,OAAsBE,kBAAAA,EAAoB;AAGjF,eAAKtF,gBAAgBgF;AACrB,eAAKjF,sBAAsBkF;QAC7B;AAGA,cAAMM,sBAAsBF,UAAU,KAAKtF,mBAAmB,IAAIkF,cAAc,KAAKlF,sBAAsB;AAI3G,cAAMyF,eAAe,CAAC,KAAKpG,sBAAsB,KAAKA,mBAAmB,CAAA,EAAGqG,aAAaT;AAGzF,cAAMU,iBAAiBH,sBAAsBxG,eAAcG;AAG3D,cAAMyG,oBAAoBH,gBAAgBE;AAE1C,YAAIC,mBAAmB;AAErB,cAAID,gBAAgB;AAElB,iBAAKpF,QAAQuE,IAAI,8CAA8CpG,0BAA0BsG,IAAAA,CAAAA,kBAAuBQ,mBAAAA,IAAuB;AAEvI,iBAAKxF,sBAAsBkF;UAC7B;AACA,eAAK1F,uCAAuCmF,IAAI,GAAG,KAAKpF,iBAAiB;AAEzE,gBAAMsG,YAAY,MAAM,KAAKnF,YAAYoF,KAAKd,IAAAA;AAE9C,cAAIa,WAAW;AACb,kBAAME,qBAAqBrH,0BAA0BmH,UAAU,CAAA,CAAE;AACjE,iBAAKtF,QAAQuE,IAAI,mBAAmBiB,kBAAAA;AACpC,iBAAKrG,8BAA8BiF,IAAI,GAAG,KAAKpF,iBAAiB;AAEhE,kBAAM,KAAKsB,cAAcmF,aAAa;cAACH;aAAU;AACjD,iBAAKtF,QAAQuE,IAAI,oBAAoBiB,kBAAAA;AACrC,iBAAKpG,+BAA+BgF,IAAI,GAAG,KAAKpF,iBAAiB;AAEjE,iBAAKF,qBAAqBwG;UAC5B,OAAO;AACL,iBAAKtF,QAAQuE,IAAI,mCAAA;UACnB;QACF,OAAO;AAEL,cAAImB,uBAAuB;AAE3B,cAAIX,UAAU,KAAKjG,kBAAkB,GAAG;AAEtC4G,mCAAuBA,uBAAuB,uBAAuBvH,0BAA0B,KAAKW,mBAAmB,CAAA,CAAE,CAAA;UAC3H;AACA,eAAKkB,QAAQuE,IAAI,GAAGmB,oBAAAA,GAAuB;QAC7C;MACF,CAAA;IACF,GAAG;MAAE,GAAG,KAAKzC;MAAS0C,iBAAiB;IAAK,CAAA;EAC9C;EAEA,MAAgB3B,kBAAiC;AAC/C,UAAM,KAAKK,UAAU,mBAAmB,YAAA;AAEtC,UAAI,KAAKtC,OAAOa,SAASgD,2BAA4B;AAGrD,YAAMnB,QAAQ,MAAM,KAAKrE,YAAY8D,aAAY,GAAI,CAAA;AACrD,UAAI2B,YAAYpB,IAAAA,EAAO;AACvB,YAAMP,eAAeO,KAAKpG;AAG1B,YAAMyH,wBAAwB,KAAK7B,kDAAkDC,YAAAA;AAIrF,UAAI4B,wBAAwBrH,eAAcI,sBAAsB,KAAK;AAEnE,aAAKE,2BAA2BgH;AAEhC;MACF;AAIA,UAAI,KAAKhH,0BAA0B;AAEjC,YAAI,KAAKA,yBAAyBoF,MAAMD,aAAc;AAEtD,aAAKnF,2BAA2BgH;MAClC;AAGA,UAAI,CAAC,MAAM,KAAKC,uBAAsB,GAAI;AACxC,aAAKhG,QAAQiG,MACX,0BAA0B,KAAKpF,QAAQC,OAAO,2CAA2C;AAE3F;MACF;AAGA,UAAI,CAAE,MAAM,KAAKoF,qBAAoB,GAAK;AACxC,aAAKlG,QAAQiG,MACX,iCAAiC,KAAKlE,OAAOoE,MAAMC,EAAE,2CACnD;AAEJ;MACF;AAGA,WAAKpG,QAAQuE,IAAI,+CAA+C,KAAK1D,QAAQC,OAAO;AACpF,YAAMuF,sBAAsBC,wBAC1B,KAAKzF,QAAQC,SACb,YACAoD,cACAA,eAAeP,kBAAkB4C,qBAAqB;AAIxD,YAAM,KAAKC,0BAA0BtC,cAAcmC,mBAAAA;AAGnD,WAAKtH,2BAA2BsH;IAClC,GAAG;MAAE,GAAG,KAAKpD;MAAS0C,iBAAiB;IAAK,CAAA;EAC9C;EAEA,MAAgBa,0BAA0BtC,cAA8BmC,qBAAsD;AAC5H,SAAKrG,QAAQuE,IAAI,iDAAiD,KAAK1D,QAAQC,OAAO;AAEtF,UAAM2F,KAAK,MAAMC,iBACf,KAAKrG,SACL;MAACgG;OACD,CAAA,GACA,KAAKxF,SACLqD,cACAyC,iBAAiBzC,eAAe,KAAM,IAAA,CAAA;AAIxC,UAAM,KAAK5D,cAAcsG,mBAAmB;MAACH;KAAG;AAEhD,SAAKzG,QAAQuE,IAAI,gDAAgD,KAAK1D,QAAQC,OAAO;EACvF;EAEA,MAAgBkF,yBAA2C;AAEzD,UAAMvB,QAAQ,MAAM,KAAKrE,YAAY8D,aAAY,KAAM,CAAA,GAAI3F;AAC3D,QAAIwG,UAAUN,IAAAA,GAAO;AACnB,YAAMoC,WAAW,MAAM,KAAK3G,qBAAqB4G,gBAAgB;QAAC,KAAKjG,QAAQC;SAAU;QAAE2D;MAAK,CAAA;AAChG,YAAMsC,iBAAiBF,SAAS,KAAKhG,QAAQC,OAAO,KAAK;AACzD,UAAIiG,kBAAkB,IAAI;AACxB,aAAK/G,QAAQiG,MAAM,YAAY,KAAKpF,QAAQC,OAAO,kBAAkB;AACrE,eAAO;MACT;AACA,aAAO;IACT;AACA,WAAO;EACT;EAEA,MAAgBoF,uBAAyC;AAEvD,UAAMc,uBAAuB;AAE7B,UAAMC,eAAe,MAAM,KAAKvG,kBAAkBwG,eAAe,KAAKrG,QAAQC,OAAO;AACrF,QAAImG,eAAeD,sBAAsB;AACvC,WAAKhH,QAAQiG,MAAM,YAAY,KAAKpF,QAAQC,OAAO,0BAA0B;AAC7E,aAAO;IACT;AACA,WAAO;EACT;AACF;;;;;;ACvZA,SACEqG,WAAWC,QAAQC,gBACd;AACP,SAASC,2BAAsD;AAWxD,IAAMC,cAAc,8BAAO,EAChCC,QAAQC,SAASC,SAASC,aAAY,MACnB;AACnB,QAAMC,cAAcH,UAAU,IAAII,SAASJ,UAAUC,SAAS,MAAM,6BAAA;AACpE,QAAMI,UAAU,MAAMC,oBAAoB;IAAEP;EAAO,CAAA;AACnDI,cAAYI,KAAK,gCAAgCF,QAAQG,OAAO,EAAE;AAClE,QAAMC,gBAAgBC,UAAUX,OAAOY,SAASF,eAAe,MAAM,8CAAA;AACrEN,cAAYI,KAAK,wBAAwBE,aAAAA,EAAe;AAGxD,QAAME,WAAW,MAAMC,cAAcC,OAAO;IAC1CR;IAASN;IAAQC;IAAQS;IAAeK,MAAM;EAChD,CAAA;AACA,QAAMC,SAAS;IAACJ;IAAUK,OAAOC,MAAAA;AAEjC,aAAWC,SAASH,QAAQ;AAE1B,UAAMb,aAAaiB,cAAcD,KAAAA;EACnC;AAEA,QAAMhB,aAAakB,MAAK;AAC1B,GArB2B;","names":["assertEx","creatable","isDefined","isUndefined","toHex","buildTelemetryConfig","initEvmProvidersIfAvailable","SimpleBlockRunner","initTelemetry","startupSpanAsync","validateHydratedBlock","validateHydratedBlockState","AccountBalanceViewerMoniker","ActorV2","asXL1BlockNumber","BlockRunnerMoniker","BlockViewerMoniker","buildJsonRpcProviderLocatorV2","buildTransaction","createDeclarationIntent","DefaultMetricsScrapePorts","HttpRpcTransport","MempoolRunnerMoniker","MempoolViewerMoniker","SimpleBlockRewardViewer","SimpleBlockValidationViewer","StakeTotalsViewerMoniker","Mutex","SHOULD_REGISTER_REDECLARATION_INTENT_TIMER","TEN_MINUTES","toFormattedBlockReference","blockBoundWitness","block","toHex","_hash","prefix","ProducerActor","ActorV2","BlockSubmissionCheckInterval","HeadResubmissionThreshold","RedeclarationWindow","_lastProducedBlock","_lastRedeclarationIntent","_metricAttributes","_producerActorBlockProductionAttempts","_producerActorBlockProductionChecks","_producerActorBlocksProduced","_producerActorBlocksPublished","_accountBalanceViewer","_blockRunner","_blockViewer","_chainId","_lastHeadChangeTime","_lastHeadHash","_mempoolRunner","_mempoolViewer","_produceBlockMutex","Mutex","_stakeTotalsViewer","logger","assertEx","accountBalanceViewer","blockRunner","blockViewer","chainId","mempoolRunner","mempoolViewer","rewardAddress","params","stakeTotalsViewer","paramsHandler","superParams","account","address","info","warn","createHandler","toString","meter","createCounter","description","locator","getInstance","AccountBalanceViewerMoniker","BlockRunnerMoniker","BlockViewerMoniker","MempoolRunnerMoniker","MempoolViewerMoniker","StakeTotalsViewerMoniker","initLocator","config","endpoint","services","apiEndpoint","transportFactory","schemas","HttpRpcTransport","buildJsonRpcProviderLocatorV2","version","telemetryConfig","buildTelemetryConfig","name","DefaultMetricsScrapePorts","producer","traceProvider","meterProvider","startupSpanAsync","initTelemetry","context","register","SimpleBlockRewardViewer","factory","dependencies","SimpleBlockValidationViewer","state","validateHydratedBlockState","protocol","validateHydratedBlock","SimpleBlockRunner","initEvmProvidersIfAvailable","startHandler","registerTimer","produceBlock","redeclareIntent","calculateBlocksUntilProducerDeclarationExpiration","currentBlock","exp","add","spanAsync","isLocked","log","runExclusive","head","headHash","currentTime","Date","now","lastHeadHashHex","isDefined","currentHeadHashHex","timeSinceHeadChange","shouldSubmit","previous","shouldResubmit","shouldSubmitBlock","nextBlock","next","displayBlockNumber","submitBlocks","nonSubmissionMessage","timeBudgetLimit","disableIntentRedeclaration","isUndefined","blocksUntilExpiration","undefined","validateCurrentBalance","error","validateCurrentStake","chain","id","redeclarationIntent","createDeclarationIntent","RedeclarationDuration","submitRedeclarationIntent","tx","buildTransaction","asXL1BlockNumber","submitTransactions","balances","accountBalances","currentBalance","requiredMinimumStake","currentStake","activeByStaked","asAddress","exists","IdLogger","initProducerAccount","runProducer","config","logger","console","orchestrator","localLogger","IdLogger","account","initProducerAccount","info","address","rewardAddress","asAddress","producer","ProducerActor","create","name","actors","filter","exists","actor","registerActor","start"]}
@@ -1,9 +1,8 @@
1
1
  import { type OrchestratorInstance } from '@xyo-network/chain-orchestration';
2
- import type { BaseContext, Config, ProviderFactoryLocatorInstance } from '@xyo-network/xl1-sdk';
2
+ import { type BaseContext, type Config } from '@xyo-network/xl1-sdk';
3
3
  export interface RunProducerContext extends BaseContext {
4
4
  config: Config;
5
- locator?: ProviderFactoryLocatorInstance;
6
5
  orchestrator: OrchestratorInstance;
7
6
  }
8
- export declare const runProducer: ({ config, logger, orchestrator, locator, }: RunProducerContext) => Promise<void>;
7
+ export declare const runProducer: ({ config, logger, orchestrator, }: RunProducerContext) => Promise<void>;
9
8
  //# sourceMappingURL=runProducer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"runProducer.d.ts","sourceRoot":"","sources":["../../src/runProducer.ts"],"names":[],"mappings":"AAGA,OAAO,EAAuB,KAAK,oBAAoB,EAAE,MAAM,kCAAkC,CAAA;AACjG,OAAO,KAAK,EACV,WAAW,EAAE,MAAM,EAAE,8BAA8B,EACpD,MAAM,sBAAsB,CAAA;AAI7B,MAAM,WAAW,kBAAmB,SAAQ,WAAW;IACrD,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,8BAA8B,CAAA;IACxC,YAAY,EAAE,oBAAoB,CAAA;CACnC;AAED,eAAO,MAAM,WAAW,GAAU,4CAE/B,kBAAkB,kBAsBpB,CAAA"}
1
+ {"version":3,"file":"runProducer.d.ts","sourceRoot":"","sources":["../../src/runProducer.ts"],"names":[],"mappings":"AAIA,OAAO,EAAuB,KAAK,oBAAoB,EAAE,MAAM,kCAAkC,CAAA;AACjG,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,MAAM,EAAE,MAAM,sBAAsB,CAAA;AAKpE,MAAM,WAAW,kBAAmB,SAAQ,WAAW;IACrD,MAAM,EAAE,MAAM,CAAA;IACd,YAAY,EAAE,oBAAoB,CAAA;CACnC;AAED,eAAO,MAAM,WAAW,GAAU,mCAE/B,kBAAkB,kBAmBpB,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xyo-network/chain-producer",
3
- "version": "1.19.5",
3
+ "version": "1.19.7",
4
4
  "description": "XYO Layer One Producer",
5
5
  "homepage": "https://xylabs.com",
6
6
  "bugs": {
@@ -49,12 +49,13 @@
49
49
  "types": "tsc --noEmit -p tsconfig.test.json"
50
50
  },
51
51
  "dependencies": {
52
- "@xylabs/sdk-js": "~5.0.64",
53
- "@xyo-network/chain-ethereum": "~1.19.5",
54
- "@xyo-network/chain-orchestration": "~1.19.5",
55
- "@xyo-network/chain-services": "~1.19.5",
56
- "@xyo-network/chain-validation": "~1.19.5",
57
- "@xyo-network/xl1-sdk": "~1.21.10",
52
+ "@xylabs/sdk-js": "~5.0.65",
53
+ "@xyo-network/chain-orchestration": "~1.19.7",
54
+ "@xyo-network/chain-services": "~1.19.7",
55
+ "@xyo-network/chain-telemetry": "~1.19.7",
56
+ "@xyo-network/chain-utils": "~1.19.7",
57
+ "@xyo-network/chain-validation": "~1.19.7",
58
+ "@xyo-network/xl1-sdk": "~1.22.30",
58
59
  "async-mutex": "~0.5.0"
59
60
  },
60
61
  "devDependencies": {
@@ -63,8 +64,8 @@
63
64
  "@types/cors": "~2.8.19",
64
65
  "@types/express": "5.0.6",
65
66
  "@types/express-serve-static-core": "~5.1.1",
66
- "@types/node": "~25.1.0",
67
- "@xylabs/sdk-js": "~5.0.64",
67
+ "@types/node": "~25.2.1",
68
+ "@xylabs/sdk-js": "~5.0.65",
68
69
  "@xylabs/ts-scripts-yarn3": "~7.3.2",
69
70
  "@xylabs/tsconfig": "~7.3.2",
70
71
  "@xyo-network/account": "~5.3.2",
@@ -72,13 +73,13 @@
72
73
  "@xyo-network/archivist-abstract": "~5.3.2",
73
74
  "@xyo-network/bios-model": "~7.2.1",
74
75
  "@xyo-network/boundwitness-builder": "~5.3.2",
75
- "@xyo-network/chain-services": "~1.19.5",
76
- "@xyo-network/chain-validation": "~1.19.5",
76
+ "@xyo-network/chain-services": "~1.19.7",
77
+ "@xyo-network/chain-validation": "~1.19.7",
77
78
  "@xyo-network/module-abstract-mongodb": "~5.3.2",
78
79
  "@xyo-network/module-model-mongodb": "~5.3.2",
79
80
  "@xyo-network/node-memory": "~5.3.2",
80
- "@xyo-network/xl1-sdk": "~1.21.10",
81
- "dotenv": "~17.2.3",
81
+ "@xyo-network/xl1-sdk": "~1.22.30",
82
+ "dotenv": "~17.2.4",
82
83
  "eslint": "^9.39.2",
83
84
  "nodemon": "~3.1.11",
84
85
  "tslib": "~2.8.1",
@@ -1,25 +1,28 @@
1
1
  import type { Attributes, Counter } from '@opentelemetry/api'
2
- import type { Address } from '@xylabs/sdk-js'
2
+ import type { Address, Logger } from '@xylabs/sdk-js'
3
3
  import {
4
- asAddress, assertEx, creatable, isDefined, isUndefined,
4
+ assertEx, creatable, isDefined, isUndefined,
5
5
  toHex,
6
6
  } from '@xylabs/sdk-js'
7
- import { EvmChainContractViewer, EvmStakeTotalsViewer } from '@xyo-network/chain-ethereum'
8
- import { initEvmProvider, initProducerAccount } from '@xyo-network/chain-orchestration'
7
+ import { buildTelemetryConfig, initEvmProvidersIfAvailable } from '@xyo-network/chain-orchestration'
9
8
  import { SimpleBlockRunner } from '@xyo-network/chain-services'
9
+ import { initTelemetry } from '@xyo-network/chain-telemetry'
10
+ import { startupSpanAsync } from '@xyo-network/chain-utils'
10
11
  import { validateHydratedBlock, validateHydratedBlockState } from '@xyo-network/chain-validation'
11
12
  import type {
13
+ ActorParamsV2,
12
14
  BlockBoundWitnessWithHashMeta, ChainId, ChainStakeIntent, HydratedBlockWithHashMeta, XL1BlockNumber,
13
15
  } from '@xyo-network/xl1-sdk'
14
16
  import {
15
- AccountBalanceViewer, AccountBalanceViewerMoniker, Actor, ActorParams, asXL1BlockNumber, BlockRunner, BlockRunnerMoniker, BlockViewer, BlockViewerMoniker,
16
- buildJsonRpcProviderLocator, buildTransaction, Config, createDeclarationIntent, getDefaultConfig, HttpRpcTransport, MempoolRunner, MempoolRunnerMoniker,
17
+ AccountBalanceViewer, AccountBalanceViewerMoniker, ActorV2, asXL1BlockNumber, BlockRunner, BlockRunnerMoniker, BlockViewer, BlockViewerMoniker,
18
+ buildJsonRpcProviderLocatorV2, buildTransaction, createDeclarationIntent, DefaultMetricsScrapePorts, HttpRpcTransport, MempoolRunner, MempoolRunnerMoniker,
17
19
  MempoolViewer, MempoolViewerMoniker, RpcSchemaMap, SimpleBlockRewardViewer, SimpleBlockValidationViewer, StakeTotalsViewer, StakeTotalsViewerMoniker,
18
20
  TransportFactory,
19
21
  } from '@xyo-network/xl1-sdk'
20
22
  import { Mutex } from 'async-mutex'
21
23
 
22
- export type ProducerActorParams = ActorParams<{
24
+ export type ProducerActorParams = ActorParamsV2<{
25
+ logger: Logger
23
26
  rewardAddress: Address
24
27
  }>
25
28
 
@@ -36,7 +39,7 @@ const toFormattedBlockReference = (blockBoundWitness: BlockBoundWitnessWithHashM
36
39
  }
37
40
 
38
41
  @creatable()
39
- export class ProducerActor extends Actor<ProducerActorParams> {
42
+ export class ProducerActor extends ActorV2<ProducerActorParams> {
40
43
  /**
41
44
  * The interval time (in MS) between block production attempts.
42
45
  */
@@ -71,6 +74,10 @@ export class ProducerActor extends Actor<ProducerActorParams> {
71
74
  private _produceBlockMutex = new Mutex()
72
75
  private _stakeTotalsViewer?: StakeTotalsViewer
73
76
 
77
+ override get logger() {
78
+ return assertEx(super.logger, () => 'Logger is required for ProducerActor')
79
+ }
80
+
74
81
  protected get accountBalanceViewer() {
75
82
  return this._accountBalanceViewer!
76
83
  }
@@ -103,57 +110,21 @@ export class ProducerActor extends Actor<ProducerActorParams> {
103
110
  return this._stakeTotalsViewer!
104
111
  }
105
112
 
106
- static override async paramsHandler<T extends ProducerActor>(params?: Partial<T['params']>) {
107
- const logger = params?.context?.logger
108
- const config = params?.context?.config ?? getDefaultConfig()
109
- const displayName = params?.displayName ?? 'ProducerActor'
110
- const account = params?.account ?? await initProducerAccount({ config })
111
- const id = account?.address.toString() ?? 'unknown'
112
- logger?.info(`Running producer for account ${account.address}`)
113
- const rewardAddress = params?.rewardAddress ?? account.address
113
+ static override async paramsHandler<T extends ProducerActor>(params: Partial<T['params']>) {
114
+ const superParams = await super.paramsHandler(params)
115
+ const { logger, account } = superParams
116
+ const rewardAddress = params.rewardAddress ?? account.address
114
117
  logger?.info(`Using reward address ${rewardAddress}`)
115
118
  if (rewardAddress === account.address) {
116
119
  logger?.warn(`Using producer account address as reward address: ${account.address}`)
117
120
  }
118
121
 
119
122
  return {
120
- ...await super.paramsHandler({
121
- ...params,
122
- account,
123
- displayName,
124
- id,
125
- }),
123
+ ...superParams,
126
124
  rewardAddress,
127
125
  }
128
126
  }
129
127
 
130
- protected static override async initContext(
131
- params: ProducerActorParams,
132
- ) {
133
- const config: Config = params?.context?.config ?? getDefaultConfig()
134
- const endpoint = assertEx(config.services.apiEndpoint, () => 'API endpoint is required in config.services.apiEndpoint')
135
-
136
- const context = await super.initContext(params)
137
-
138
- const chainId = assertEx(config.chain.id, () => 'Chain ID is required in config.chain.id')
139
-
140
- const transportFactory: TransportFactory = (schemas: RpcSchemaMap) => new HttpRpcTransport(endpoint, schemas)
141
- const locator = await buildJsonRpcProviderLocator({ context, transportFactory })
142
- const runner = await initEvmProvider({ config })
143
- locator.register(EvmChainContractViewer.factory<EvmChainContractViewer>(EvmChainContractViewer.dependencies, { address: asAddress(chainId), runner }))
144
- locator.register(EvmStakeTotalsViewer.factory<EvmStakeTotalsViewer>(EvmStakeTotalsViewer.dependencies, { address: asAddress(chainId), runner }))
145
- locator.register(SimpleBlockRewardViewer.factory<SimpleBlockRewardViewer>(SimpleBlockRewardViewer.dependencies))
146
- locator.register(SimpleBlockValidationViewer.factory<SimpleBlockValidationViewer>(
147
- SimpleBlockValidationViewer.dependencies,
148
- { state: validateHydratedBlockState, protocol: validateHydratedBlock },
149
- ))
150
- locator.register(SimpleBlockRunner.factory<SimpleBlockRunner>(
151
- SimpleBlockRunner.dependencies,
152
- { account: params.account, rewardAddress: params.rewardAddress },
153
- ))
154
- return locator.context
155
- }
156
-
157
128
  override async createHandler() {
158
129
  await super.createHandler()
159
130
  // Create the consistent meter attributes that will
@@ -202,6 +173,31 @@ export class ProducerActor extends Actor<ProducerActorParams> {
202
173
  )
203
174
  }
204
175
 
176
+ async initLocator() {
177
+ const config = this.config
178
+ const endpoint = assertEx(config.services.apiEndpoint, () => 'API endpoint is required in config.services.apiEndpoint')
179
+ const transportFactory: TransportFactory = (schemas: RpcSchemaMap) => new HttpRpcTransport(endpoint, schemas)
180
+ const locator = await buildJsonRpcProviderLocatorV2(config, transportFactory)
181
+
182
+ const version = '1.0.0'
183
+ const telemetryConfig = buildTelemetryConfig(config, this.name, version, DefaultMetricsScrapePorts.producer)
184
+ const { traceProvider, meterProvider } = await startupSpanAsync('initTelemetry', () => initTelemetry(telemetryConfig))
185
+
186
+ locator.context.traceProvider = traceProvider
187
+ locator.context.meterProvider = meterProvider
188
+
189
+ locator.register(SimpleBlockRewardViewer.factory<SimpleBlockRewardViewer>(SimpleBlockRewardViewer.dependencies, {}))
190
+ locator.register(SimpleBlockValidationViewer.factory<SimpleBlockValidationViewer>(
191
+ SimpleBlockValidationViewer.dependencies,
192
+ { state: validateHydratedBlockState, protocol: validateHydratedBlock },
193
+ ))
194
+ locator.register(SimpleBlockRunner.factory<SimpleBlockRunner>(
195
+ SimpleBlockRunner.dependencies,
196
+ { account: this.params.account, rewardAddress: this.params.rewardAddress },
197
+ ))
198
+ return await initEvmProvidersIfAvailable(locator)
199
+ }
200
+
205
201
  override async startHandler() {
206
202
  await super.startHandler()
207
203
  // Register a timer to check if we should produce a block
@@ -1,21 +1,20 @@
1
+ import type { CreatableName } from '@xylabs/sdk-js'
1
2
  import {
2
3
  asAddress, exists, IdLogger,
3
4
  } from '@xylabs/sdk-js'
4
5
  import { initProducerAccount, type OrchestratorInstance } from '@xyo-network/chain-orchestration'
5
- import type {
6
- BaseContext, Config, ProviderFactoryLocatorInstance,
7
- } from '@xyo-network/xl1-sdk'
6
+ import { type BaseContext, type Config } from '@xyo-network/xl1-sdk'
8
7
 
8
+ import type { ProducerActorParams } from './ProducerActor.ts'
9
9
  import { ProducerActor } from './ProducerActor.ts'
10
10
 
11
11
  export interface RunProducerContext extends BaseContext {
12
12
  config: Config
13
- locator?: ProviderFactoryLocatorInstance
14
13
  orchestrator: OrchestratorInstance
15
14
  }
16
15
 
17
16
  export const runProducer = async ({
18
- config, logger, orchestrator, locator,
17
+ config, logger = console, orchestrator,
19
18
  }: RunProducerContext) => {
20
19
  const localLogger = logger ?? new IdLogger(logger ?? console, () => 'ResolveHelper [runProducer]')
21
20
  const account = await initProducerAccount({ config })
@@ -25,11 +24,8 @@ export const runProducer = async ({
25
24
 
26
25
  // Create actors
27
26
  const producer = await ProducerActor.create({
28
- logger,
29
- context: {
30
- config, locator, singletons: {}, caches: {},
31
- },
32
- })
27
+ account, config, logger, rewardAddress, name: 'xl1-producer' as CreatableName,
28
+ } satisfies ProducerActorParams)
33
29
  const actors = [producer].filter(exists)
34
30
 
35
31
  for (const actor of actors) {