@xyo-network/chain-producer 1.18.0 → 1.18.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.
- package/dist/node/ProducerActor.d.ts +28 -109
- package/dist/node/ProducerActor.d.ts.map +1 -1
- package/dist/node/index.mjs +62 -56
- package/dist/node/index.mjs.map +1 -1
- package/dist/node/runProducer.d.ts +3 -6
- package/dist/node/runProducer.d.ts.map +1 -1
- package/package.json +21 -22
- package/src/ProducerActor.ts +88 -22
- package/src/runProducer.ts +16 -49
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import type { Attributes, Counter } from '@opentelemetry/api';
|
|
2
|
-
import type {
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
5
|
-
|
|
6
|
-
|
|
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<{
|
|
6
|
+
rewardAddress: Address;
|
|
7
|
+
}>;
|
|
7
8
|
export declare class ProducerActor extends Actor<ProducerActorParams> {
|
|
8
9
|
static readonly RedeclarationWindow = 10000;
|
|
9
10
|
protected _lastProducedBlock?: HydratedBlockWithHashMeta;
|
|
@@ -23,119 +24,37 @@ export declare class ProducerActor extends Actor<ProducerActorParams> {
|
|
|
23
24
|
private _stakeTotalsViewer?;
|
|
24
25
|
protected get accountBalanceViewer(): AccountBalanceViewer;
|
|
25
26
|
protected get blockRunner(): BlockRunner;
|
|
26
|
-
protected get blockViewer(): BlockViewer
|
|
27
|
-
protected get chainId(): import("@xylabs/sdk-js").
|
|
27
|
+
protected get blockViewer(): BlockViewer<"BlockViewer">;
|
|
28
|
+
protected get chainId(): import("@xylabs/sdk-js").BrandedHex;
|
|
28
29
|
protected get mempoolRunner(): MempoolRunner;
|
|
29
30
|
protected get mempoolViewer(): MempoolViewer;
|
|
31
|
+
protected get rewardAddress(): Lowercase<string> & {
|
|
32
|
+
readonly __hex: true;
|
|
33
|
+
} & {
|
|
34
|
+
readonly __address: true;
|
|
35
|
+
};
|
|
30
36
|
protected get stakeTotalsViewer(): StakeTotalsViewer;
|
|
31
|
-
static paramsHandler<T extends
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
host: string;
|
|
37
|
-
initRewardsCache: boolean;
|
|
38
|
-
port: number;
|
|
39
|
-
mnemonic?: string | undefined;
|
|
40
|
-
};
|
|
41
|
-
bridge: {
|
|
42
|
-
chainRpcApiUrl: string;
|
|
43
|
-
feeFixed: import("@xylabs/sdk-js").Hex;
|
|
44
|
-
feeRateBasisPoints: number;
|
|
45
|
-
host: string;
|
|
46
|
-
maxBridgeAmount: import("@xylabs/sdk-js").Hex;
|
|
47
|
-
minBridgeAmount: import("@xylabs/sdk-js").Hex;
|
|
48
|
-
port: number;
|
|
49
|
-
redisHost: string;
|
|
50
|
-
redisPort: number;
|
|
51
|
-
remoteBridgeContractAddress: import("@xylabs/sdk-js").Address;
|
|
52
|
-
remoteChainId: import("@xylabs/sdk-js").Hex;
|
|
53
|
-
remoteTokenAddress: import("@xylabs/sdk-js").Hex;
|
|
54
|
-
remoteChainWalletPrivateKey: import("@xylabs/sdk-js").Hex;
|
|
55
|
-
escrowAddress?: import("@xylabs/sdk-js").Address | undefined;
|
|
56
|
-
feesAddress?: import("@xylabs/sdk-js").Address | undefined;
|
|
57
|
-
mnemonic?: string | undefined;
|
|
58
|
-
xl1ChainId?: import("@xylabs/sdk-js").Hex | undefined;
|
|
59
|
-
xl1TokenAddress?: import("@xylabs/sdk-js").Hex | undefined;
|
|
60
|
-
};
|
|
61
|
-
chain: {
|
|
62
|
-
id?: import("@xylabs/sdk-js").Hex | undefined;
|
|
63
|
-
genesisRewardAddress?: import("@xylabs/sdk-js").Address | undefined;
|
|
64
|
-
};
|
|
65
|
-
evm: {
|
|
66
|
-
chainId?: string | undefined;
|
|
67
|
-
infura?: {
|
|
68
|
-
projectId?: string | undefined;
|
|
69
|
-
projectSecret?: string | undefined;
|
|
70
|
-
} | undefined;
|
|
71
|
-
jsonRpc?: {
|
|
72
|
-
url?: string | undefined;
|
|
73
|
-
} | undefined;
|
|
74
|
-
};
|
|
75
|
-
mempool: {
|
|
76
|
-
enabled: boolean;
|
|
77
|
-
host: string;
|
|
78
|
-
port: number;
|
|
79
|
-
mnemonic?: string | undefined;
|
|
80
|
-
};
|
|
81
|
-
producer: {
|
|
82
|
-
heartbeatInterval: number;
|
|
83
|
-
minStake: number;
|
|
84
|
-
port: number;
|
|
85
|
-
allowlist?: import("@xylabs/sdk-js").Address[] | undefined;
|
|
86
|
-
disableIntentRedeclaration?: boolean | undefined;
|
|
87
|
-
healthCheckPort?: number | undefined;
|
|
88
|
-
mnemonic?: string | undefined;
|
|
89
|
-
rewardAddress?: string | undefined;
|
|
90
|
-
};
|
|
91
|
-
rewardRedemptionApi: {
|
|
92
|
-
chainRpcApiUrl: string;
|
|
93
|
-
host: string;
|
|
94
|
-
port: number;
|
|
95
|
-
mnemonic?: string | undefined;
|
|
96
|
-
};
|
|
97
|
-
services: {
|
|
98
|
-
accountBalanceViewerEndpoint: string;
|
|
99
|
-
apiEndpoint: string;
|
|
100
|
-
};
|
|
101
|
-
storage: {
|
|
102
|
-
mongo?: {
|
|
103
|
-
connectionString?: string | undefined;
|
|
104
|
-
database?: string | undefined;
|
|
105
|
-
domain?: string | undefined;
|
|
106
|
-
password?: string | undefined;
|
|
107
|
-
username?: string | undefined;
|
|
108
|
-
} | undefined;
|
|
109
|
-
root?: string | undefined;
|
|
110
|
-
};
|
|
111
|
-
telemetry: {
|
|
112
|
-
metrics?: {
|
|
113
|
-
scrape: {
|
|
114
|
-
path: string;
|
|
115
|
-
port: number;
|
|
116
|
-
};
|
|
117
|
-
} | undefined;
|
|
118
|
-
otel?: {
|
|
119
|
-
otlpEndpoint?: string | undefined;
|
|
120
|
-
} | undefined;
|
|
121
|
-
};
|
|
122
|
-
validation: {
|
|
123
|
-
allowedRewardRedeemers?: import("@xylabs/sdk-js").Address[] | undefined;
|
|
124
|
-
allowedRewardEscrowAccountSigners?: import("@xylabs/sdk-js").Address[] | undefined;
|
|
125
|
-
};
|
|
126
|
-
logLevel: "info" | "error" | "warn" | "log" | "debug" | "trace";
|
|
127
|
-
silent: boolean;
|
|
128
|
-
};
|
|
129
|
-
locator: import("@xyo-network/xl1-protocol-sdk").ProviderFactoryLocator;
|
|
37
|
+
static paramsHandler<T extends ProducerActor>(params?: Partial<T['params']>): Promise<{
|
|
38
|
+
rewardAddress: Lowercase<string> & {
|
|
39
|
+
readonly __hex: true;
|
|
40
|
+
} & {
|
|
41
|
+
readonly __address: true;
|
|
130
42
|
};
|
|
131
|
-
displayName: CreatableName | NonNullable<T["displayName"]> | undefined;
|
|
132
|
-
id: CreatableName | T["id"] | undefined;
|
|
133
|
-
logger: import("@xylabs/sdk-js").Logger;
|
|
134
43
|
name?: import("@xylabs/sdk-js").CreatableName;
|
|
135
44
|
statusReporter?: import("@xylabs/sdk-js").CreatableStatusReporter<void> | undefined;
|
|
45
|
+
logger: import("@xylabs/sdk-js").Logger;
|
|
136
46
|
meterProvider?: import("@opentelemetry/api").MeterProvider;
|
|
137
47
|
traceProvider?: import("@opentelemetry/api").TracerProvider;
|
|
48
|
+
account: import("@xyo-network/account-model").AccountInstance;
|
|
49
|
+
context: import("@xyo-network/xl1-sdk").ActorContext;
|
|
50
|
+
displayName: string | (string & {
|
|
51
|
+
__baseClassName: true;
|
|
52
|
+
}) | undefined;
|
|
53
|
+
id: string | (string & {
|
|
54
|
+
__baseClassName: true;
|
|
55
|
+
});
|
|
138
56
|
}>;
|
|
57
|
+
protected static initContext(params: ProducerActorParams): Promise<import("@xyo-network/xl1-sdk").CreatableProviderContext>;
|
|
139
58
|
createHandler(): Promise<void>;
|
|
140
59
|
startHandler(): Promise<void>;
|
|
141
60
|
protected calculateBlocksUntilProducerDeclarationExpiration(currentBlock: number): number;
|
|
@@ -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,
|
|
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;AAQ7C,OAAO,KAAK,EAEV,gBAAgB,EAAE,yBAAyB,EAC3C,cAAc,EACf,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EACL,oBAAoB,EAA+B,KAAK,EAAE,WAAW,EACrE,WAAW,EACX,WAAW,EAKO,aAAa,EAE/B,aAAa,EAIb,iBAAiB,EAGlB,MAAM,sBAAsB,CAAA;AAG7B,MAAM,MAAM,mBAAmB,GAAG,WAAW,CAAC;IAC5C,aAAa,EAAE,OAAO,CAAA;CACvB,CAAC,CAAA;AAKF,qBACa,aAAc,SAAQ,KAAK,CAAC,mBAAmB,CAAC;IAC3D,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,cAAc,CAAC,CAAe;IACtC,OAAO,CAAC,cAAc,CAAC,CAAe;IAEtC,OAAO,CAAC,kBAAkB,CAAc;IAExC,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;IAqBd,aAAa;IAgDb,YAAY;IAe3B,SAAS,CAAC,iDAAiD,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM;cAIzE,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;cAwC7B,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"}
|
package/dist/node/index.mjs
CHANGED
|
@@ -2,11 +2,11 @@ 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 { creatable, isDefined, isUndefined, toHex } from "@xylabs/sdk-js";
|
|
6
|
-
import {
|
|
5
|
+
import { assertEx, creatable, isDefined, isUndefined, toHex } from "@xylabs/sdk-js";
|
|
6
|
+
import { initProducerAccount } from "@xyo-network/chain-orchestration";
|
|
7
7
|
import { SimpleBlockRunner } from "@xyo-network/chain-services";
|
|
8
|
-
import {
|
|
9
|
-
import { AccountBalanceViewerMoniker, BlockRunnerMoniker, BlockViewerMoniker, buildTransaction, createDeclarationIntent, getDefaultConfig, MempoolRunnerMoniker, MempoolViewerMoniker, StakeTotalsViewerMoniker } from "@xyo-network/xl1-
|
|
8
|
+
import { validateHydratedBlock, validateHydratedBlockState } from "@xyo-network/chain-validation";
|
|
9
|
+
import { AccountBalanceViewerMoniker, Actor, asXL1BlockNumber, BlockRunnerMoniker, BlockViewerMoniker, buildJsonRpcProviderLocator, buildTransaction, createDeclarationIntent, getDefaultConfig, HttpRpcTransport, MempoolRunnerMoniker, MempoolViewerMoniker, SimpleBlockRewardViewer, SimpleBlockValidationViewer, StakeTotalsViewerMoniker } from "@xyo-network/xl1-sdk";
|
|
10
10
|
import { Mutex } from "async-mutex";
|
|
11
11
|
function _ts_decorate(decorators, target, key, desc) {
|
|
12
12
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
@@ -55,19 +55,55 @@ var ProducerActor = class _ProducerActor extends Actor {
|
|
|
55
55
|
get mempoolViewer() {
|
|
56
56
|
return this._mempoolViewer;
|
|
57
57
|
}
|
|
58
|
+
get rewardAddress() {
|
|
59
|
+
return this.params.rewardAddress;
|
|
60
|
+
}
|
|
58
61
|
get stakeTotalsViewer() {
|
|
59
62
|
return this._stakeTotalsViewer;
|
|
60
63
|
}
|
|
61
64
|
static async paramsHandler(params) {
|
|
65
|
+
const logger = params?.context?.logger;
|
|
62
66
|
const config = params?.context?.config ?? getDefaultConfig();
|
|
67
|
+
const displayName = params?.displayName ?? "ProducerActor";
|
|
63
68
|
const account = params?.account ?? await initProducerAccount({
|
|
64
69
|
config
|
|
65
70
|
});
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
71
|
+
const id = account?.address.toString() ?? "unknown";
|
|
72
|
+
logger?.info(`Running producer for account ${account.address}`);
|
|
73
|
+
const rewardAddress = params?.rewardAddress ?? account.address;
|
|
74
|
+
logger?.info(`Using reward address ${rewardAddress}`);
|
|
75
|
+
if (rewardAddress === account.address) {
|
|
76
|
+
logger?.warn(`Using producer account address as reward address: ${account.address}`);
|
|
77
|
+
}
|
|
78
|
+
return {
|
|
79
|
+
...await super.paramsHandler({
|
|
80
|
+
...params,
|
|
81
|
+
account,
|
|
82
|
+
displayName,
|
|
83
|
+
id
|
|
84
|
+
}),
|
|
85
|
+
rewardAddress
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
static async initContext(params) {
|
|
89
|
+
const config = params?.context?.config ?? getDefaultConfig();
|
|
90
|
+
const endpoint = assertEx(config.services.apiEndpoint, () => "API endpoint is required in config.services.apiEndpoint");
|
|
91
|
+
const context = await super.initContext(params);
|
|
92
|
+
const transportFactory = /* @__PURE__ */ __name((schemas) => new HttpRpcTransport(endpoint, schemas), "transportFactory");
|
|
93
|
+
const locator = await buildJsonRpcProviderLocator({
|
|
94
|
+
context,
|
|
95
|
+
transportFactory
|
|
70
96
|
});
|
|
97
|
+
locator.register(SimpleBlockRewardViewer.factory(SimpleBlockRewardViewer.dependencies));
|
|
98
|
+
locator.register(SimpleBlockValidationViewer.factory(SimpleBlockValidationViewer.dependencies, {
|
|
99
|
+
state: validateHydratedBlockState,
|
|
100
|
+
protocol: validateHydratedBlock
|
|
101
|
+
}));
|
|
102
|
+
locator.register(SimpleBlockRunner.factory(SimpleBlockRunner.dependencies, {
|
|
103
|
+
account: params.account,
|
|
104
|
+
rewardAddress: params.rewardAddress
|
|
105
|
+
}));
|
|
106
|
+
return locator.context;
|
|
71
107
|
}
|
|
72
108
|
async createHandler() {
|
|
73
109
|
await super.createHandler();
|
|
@@ -86,12 +122,12 @@ var ProducerActor = class _ProducerActor extends Actor {
|
|
|
86
122
|
this._producerActorBlocksPublished = this.meter?.createCounter("producer_actor_blocks_published", {
|
|
87
123
|
description: "Number of blocks published"
|
|
88
124
|
});
|
|
89
|
-
this._accountBalanceViewer = await this.locator
|
|
90
|
-
this._blockRunner = await this.locator
|
|
91
|
-
this._blockViewer = await this.locator
|
|
92
|
-
this._mempoolRunner = await this.locator
|
|
93
|
-
this._mempoolViewer = await this.locator
|
|
94
|
-
this._stakeTotalsViewer = await this.locator
|
|
125
|
+
this._accountBalanceViewer = assertEx(await this.locator?.getInstance(AccountBalanceViewerMoniker), () => "Unable to locate AccountBalanceViewer");
|
|
126
|
+
this._blockRunner = assertEx(await this.locator?.getInstance(BlockRunnerMoniker), () => "Unable to locate BlockRunner");
|
|
127
|
+
this._blockViewer = assertEx(await this.locator?.getInstance(BlockViewerMoniker), () => "Unable to locate BlockViewer");
|
|
128
|
+
this._mempoolRunner = assertEx(await this.locator?.getInstance(MempoolRunnerMoniker), () => "Unable to locate MempoolRunner");
|
|
129
|
+
this._mempoolViewer = assertEx(await this.locator?.getInstance(MempoolViewerMoniker), () => "Unable to locate MempoolViewer");
|
|
130
|
+
this._stakeTotalsViewer = assertEx(await this.locator?.getInstance(StakeTotalsViewerMoniker), () => "Unable to locate StakeTotalsViewer");
|
|
95
131
|
}
|
|
96
132
|
async startHandler() {
|
|
97
133
|
await super.startHandler();
|
|
@@ -216,54 +252,24 @@ ProducerActor = _ts_decorate([
|
|
|
216
252
|
], ProducerActor);
|
|
217
253
|
|
|
218
254
|
// src/runProducer.ts
|
|
219
|
-
import { asAddress,
|
|
255
|
+
import { asAddress, exists, IdLogger } from "@xylabs/sdk-js";
|
|
220
256
|
import { initProducerAccount as initProducerAccount2 } from "@xyo-network/chain-orchestration";
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
import { SimpleBlockRewardViewer, SimpleBlockValidationViewer } from "@xyo-network/xl1-protocol-sdk";
|
|
224
|
-
import { buildJsonRpcProviderLocator } from "@xyo-network/xl1-providers";
|
|
225
|
-
import { HttpRpcTransport } from "@xyo-network/xl1-rpc";
|
|
226
|
-
var getProviderFactoryLocator = /* @__PURE__ */ __name(async (context, account, rewardAddress) => {
|
|
227
|
-
const endpoint = assertEx(context.config.services.apiEndpoint, () => "API endpoint is required in config.services.apiEndpoint");
|
|
228
|
-
const transportFactory = /* @__PURE__ */ __name((schemas) => new HttpRpcTransport(endpoint, schemas), "transportFactory");
|
|
229
|
-
const locator = await buildJsonRpcProviderLocator({
|
|
230
|
-
context,
|
|
231
|
-
transportFactory
|
|
232
|
-
});
|
|
233
|
-
locator.register(SimpleBlockRewardViewer.factory());
|
|
234
|
-
locator.register(SimpleBlockValidationViewer.factory({
|
|
235
|
-
state: validateHydratedBlockState,
|
|
236
|
-
value: validateHydratedBlock
|
|
237
|
-
}));
|
|
238
|
-
locator.register(SimpleBlockRunner2.factory({
|
|
239
|
-
account,
|
|
240
|
-
rewardAddress
|
|
241
|
-
}));
|
|
242
|
-
return locator;
|
|
243
|
-
}, "getProviderFactoryLocator");
|
|
244
|
-
var runProducer = /* @__PURE__ */ __name(async ({ config, logger, orchestrator }) => {
|
|
257
|
+
var runProducer = /* @__PURE__ */ __name(async ({ config, logger, orchestrator, locator }) => {
|
|
258
|
+
const localLogger = logger ?? new IdLogger(logger ?? console, () => "ResolveHelper [runProducer]");
|
|
245
259
|
const account = await initProducerAccount2({
|
|
246
260
|
config
|
|
247
261
|
});
|
|
248
|
-
|
|
262
|
+
localLogger.info(`Running producer for account ${account.address}`);
|
|
249
263
|
const rewardAddress = asAddress(config.producer.rewardAddress, () => "rewardAddress is required in config.producer");
|
|
250
|
-
|
|
251
|
-
const
|
|
252
|
-
config,
|
|
264
|
+
localLogger.info(`Using reward address ${rewardAddress}`);
|
|
265
|
+
const producer = await ProducerActor.create({
|
|
253
266
|
logger,
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
};
|
|
261
|
-
const params = {
|
|
262
|
-
id: "ProducerActor",
|
|
263
|
-
context,
|
|
264
|
-
account
|
|
265
|
-
};
|
|
266
|
-
const producer = await ProducerActor.create(params);
|
|
267
|
+
context: {
|
|
268
|
+
config,
|
|
269
|
+
locator,
|
|
270
|
+
singletons: {}
|
|
271
|
+
}
|
|
272
|
+
});
|
|
267
273
|
const actors = [
|
|
268
274
|
producer
|
|
269
275
|
].filter(exists);
|
package/dist/node/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/ProducerActor.ts","../../src/runProducer.ts"],"sourcesContent":["import type { Attributes, Counter } from '@opentelemetry/api'\nimport type { CreatableName } from '@xylabs/sdk-js'\nimport {\n creatable, isDefined, isUndefined, toHex,\n} from '@xylabs/sdk-js'\nimport {\n Actor, type ActorParams, initProducerAccount,\n} from '@xyo-network/chain-orchestration'\nimport { SimpleBlockRunner } from '@xyo-network/chain-services'\nimport type {\n ChainId,\n ChainStakeIntent, HydratedBlockWithHashMeta,\n XL1BlockNumber,\n} from '@xyo-network/xl1-protocol'\nimport { asXL1BlockNumber } from '@xyo-network/xl1-protocol'\nimport {\n AccountBalanceViewer, AccountBalanceViewerMoniker, BlockRunner, BlockRunnerMoniker,\n BlockViewer, BlockViewerMoniker, buildTransaction,\n Config,\n createDeclarationIntent,\n getDefaultConfig,\n MempoolRunner,\n MempoolRunnerMoniker,\n MempoolViewer,\n MempoolViewerMoniker,\n StakeTotalsViewer,\n StakeTotalsViewerMoniker,\n} from '@xyo-network/xl1-protocol-sdk'\nimport { Mutex } from 'async-mutex'\n\nexport type ProducerActorParams = ActorParams\n\nconst SHOULD_REGISTER_REDECLARATION_INTENT_TIMER = true\nconst TEN_MINUTES = 10 * 60 * 1000 // 10 minutes in milliseconds\n\n@creatable()\nexport class ProducerActor extends Actor<ProducerActorParams> {\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 _mempoolRunner?: MempoolRunner\n private _mempoolViewer?: MempoolViewer\n\n private _produceBlockMutex = new Mutex()\n\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 stakeTotalsViewer() {\n return this._stakeTotalsViewer!\n }\n\n static override async paramsHandler<T extends ActorParams>(params?: Partial<T>) {\n const config: Config = params?.context?.config ?? getDefaultConfig()\n const account = params?.account ?? await initProducerAccount({ config })\n return await super.paramsHandler({\n ...params, name: (params?.name ?? 'Producer') as CreatableName, account,\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 = await this.locator.getInstance<AccountBalanceViewer>(AccountBalanceViewerMoniker)\n this._blockRunner = await this.locator.getInstance<BlockRunner>(BlockRunnerMoniker)\n this._blockViewer = await this.locator.getInstance<BlockViewer>(BlockViewerMoniker)\n this._mempoolRunner = await this.locator.getInstance<MempoolRunner>(MempoolRunnerMoniker)\n this._mempoolViewer = await this.locator.getInstance<MempoolViewer>(MempoolViewerMoniker)\n this._stakeTotalsViewer = await this.locator.getInstance<StakeTotalsViewer>(StakeTotalsViewerMoniker)\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, 1500/* 500 */)\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 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 // If our last produced block was the next block for the current head, we do not\n // need to produce another. This prevents duplicate blocks from being produced\n if (this._lastProducedBlock && this._lastProducedBlock[0].previous === headHash) {\n this.logger?.log('Block already produced:', `0x${toHex(this._lastProducedBlock[0].block)}`, this._lastProducedBlock[0].block)\n } else {\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 = `0x${toHex(nextBlock[0].block)}`\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, nextBlock[0].block)\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 at this time.')\n }\n }\n })\n })\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 })\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 = this._lastProducedBlock?.[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 { Address, Logger } from '@xylabs/sdk-js'\nimport {\n asAddress, assertEx, exists,\n} from '@xylabs/sdk-js'\nimport type { AccountInstance } from '@xyo-network/account-model'\nimport {\n type ActorContext, initProducerAccount, type OrchestratorInstance,\n} from '@xyo-network/chain-orchestration'\nimport { validateHydratedBlock, validateHydratedBlockState } from '@xyo-network/chain-validation'\nimport { SimpleBlockRunner } from '@xyo-network/chain-services'\nimport type {\n Config, CreatableProviderContext, ProviderFactoryLocatorInstance,\n} from '@xyo-network/xl1-protocol-sdk'\nimport { SimpleBlockRewardViewer, SimpleBlockValidationViewer } from '@xyo-network/xl1-protocol-sdk'\nimport { buildJsonRpcProviderLocator } from '@xyo-network/xl1-providers'\nimport {\n HttpRpcTransport, type RpcSchemaMap, type TransportFactory,\n} from '@xyo-network/xl1-rpc'\n\nimport { ProducerActor, type ProducerActorParams } from './ProducerActor.ts'\n\ninterface RunProducerContext {\n config: Config\n locator?: ProviderFactoryLocatorInstance\n logger: Logger\n orchestrator: OrchestratorInstance\n}\n\nconst getProviderFactoryLocator = async (\n context: Omit<CreatableProviderContext, 'locator'>,\n account: AccountInstance,\n rewardAddress: Address,\n) => {\n const endpoint = assertEx(context.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 buildJsonRpcProviderLocator({ context, transportFactory })\n locator.register(SimpleBlockRewardViewer.factory())\n locator.register(SimpleBlockValidationViewer.factory<SimpleBlockValidationViewer>({ state: validateHydratedBlockState, value: validateHydratedBlock }))\n locator.register(SimpleBlockRunner.factory<SimpleBlockRunner>({ account, rewardAddress }))\n return locator\n}\n\nexport const runProducer = async ({\n config, logger, orchestrator,\n}: RunProducerContext) => {\n const account = await initProducerAccount({ config })\n logger.info(`Running producer for account ${account.address}`)\n const rewardAddress = asAddress(config.producer.rewardAddress, () => 'rewardAddress is required in config.producer')\n logger.info(`Using reward address ${rewardAddress}`)\n\n const locator = await getProviderFactoryLocator({\n config, logger, singletons: {},\n }, account, rewardAddress)\n\n const context: ActorContext = {\n locator, config, singletons: locator.context.singletons,\n }\n\n // Create actors\n const params = {\n id: 'ProducerActor', context, account,\n } satisfies ProducerActorParams\n // const apiEndpoint = config.services.apiEndpoint\n // const balances = isDefined(apiEndpoint) ? undefined : await BalanceActor.create(params)\n const producer = await ProducerActor.create(params)\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":["creatable","isDefined","isUndefined","toHex","Actor","initProducerAccount","SimpleBlockRunner","asXL1BlockNumber","AccountBalanceViewerMoniker","BlockRunnerMoniker","BlockViewerMoniker","buildTransaction","createDeclarationIntent","getDefaultConfig","MempoolRunnerMoniker","MempoolViewerMoniker","StakeTotalsViewerMoniker","Mutex","SHOULD_REGISTER_REDECLARATION_INTENT_TIMER","TEN_MINUTES","ProducerActor","Actor","RedeclarationWindow","_lastProducedBlock","_lastRedeclarationIntent","_metricAttributes","_producerActorBlockProductionAttempts","_producerActorBlockProductionChecks","_producerActorBlocksProduced","_producerActorBlocksPublished","_accountBalanceViewer","_blockRunner","_blockViewer","_chainId","_mempoolRunner","_mempoolViewer","_produceBlockMutex","Mutex","_stakeTotalsViewer","accountBalanceViewer","blockRunner","blockViewer","chainId","mempoolRunner","mempoolViewer","stakeTotalsViewer","paramsHandler","params","config","context","getDefaultConfig","account","initProducerAccount","name","createHandler","address","toString","meter","createCounter","description","locator","getInstance","AccountBalanceViewerMoniker","BlockRunnerMoniker","BlockViewerMoniker","MempoolRunnerMoniker","MempoolViewerMoniker","StakeTotalsViewerMoniker","startHandler","registerTimer","produceBlock","redeclareIntent","calculateBlocksUntilProducerDeclarationExpiration","currentBlock","exp","add","spanAsync","isLocked","logger","log","runExclusive","head","headHash","_hash","previous","toHex","block","nextBlock","next","displayBlockNumber","submitBlocks","producer","disableIntentRedeclaration","isUndefined","blocksUntilExpiration","undefined","validateCurrentBalance","error","validateCurrentStake","chain","id","redeclarationIntent","createDeclarationIntent","SimpleBlockRunner","RedeclarationDuration","submitRedeclarationIntent","tx","buildTransaction","asXL1BlockNumber","submitTransactions","isDefined","balances","accountBalances","currentBalance","requiredMinimumStake","currentStake","activeByStaked","asAddress","assertEx","exists","initProducerAccount","validateHydratedBlock","validateHydratedBlockState","SimpleBlockRunner","SimpleBlockRewardViewer","SimpleBlockValidationViewer","buildJsonRpcProviderLocator","HttpRpcTransport","getProviderFactoryLocator","context","account","rewardAddress","endpoint","assertEx","config","services","apiEndpoint","transportFactory","schemas","HttpRpcTransport","locator","buildJsonRpcProviderLocator","register","SimpleBlockRewardViewer","factory","SimpleBlockValidationViewer","state","validateHydratedBlockState","value","validateHydratedBlock","SimpleBlockRunner","runProducer","logger","orchestrator","initProducerAccount","info","address","asAddress","producer","singletons","params","id","ProducerActor","create","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 } from '@xylabs/sdk-js'\nimport {\n assertEx,\n creatable, isDefined, isUndefined, toHex,\n} from '@xylabs/sdk-js'\nimport { initProducerAccount } from '@xyo-network/chain-orchestration'\nimport { SimpleBlockRunner } from '@xyo-network/chain-services'\nimport { validateHydratedBlock, validateHydratedBlockState } from '@xyo-network/chain-validation'\nimport type {\n ChainId,\n ChainStakeIntent, HydratedBlockWithHashMeta,\n XL1BlockNumber,\n} from '@xyo-network/xl1-sdk'\nimport {\n AccountBalanceViewer, AccountBalanceViewerMoniker, Actor, ActorParams, asXL1BlockNumber,\n BlockRunner, BlockRunnerMoniker,\n BlockViewer, BlockViewerMoniker, buildJsonRpcProviderLocator,\n buildTransaction,\n Config,\n createDeclarationIntent,\n getDefaultConfig,\n HttpRpcTransport, MempoolRunner,\n MempoolRunnerMoniker,\n MempoolViewer,\n MempoolViewerMoniker,\n RpcSchemaMap, SimpleBlockRewardViewer,\n SimpleBlockValidationViewer,\n StakeTotalsViewer,\n 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@creatable()\nexport class ProducerActor extends Actor<ProducerActorParams> {\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 _mempoolRunner?: MempoolRunner\n private _mempoolViewer?: MempoolViewer\n\n private _produceBlockMutex = new Mutex()\n\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 transportFactory: TransportFactory = (schemas: RpcSchemaMap) => new HttpRpcTransport(endpoint, schemas)\n const locator = await buildJsonRpcProviderLocator({ context, transportFactory })\n locator.register(SimpleBlockRewardViewer.factory(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, 1500/* 500 */)\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 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 // If our last produced block was the next block for the current head, we do not\n // need to produce another. This prevents duplicate blocks from being produced\n if (this._lastProducedBlock && this._lastProducedBlock[0].previous === headHash) {\n this.logger?.log('Block already produced:', `0x${toHex(this._lastProducedBlock[0].block)}`, this._lastProducedBlock[0].block)\n } else {\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 = `0x${toHex(nextBlock[0].block)}`\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, nextBlock[0].block)\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 at this time.')\n }\n }\n })\n })\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 })\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 = this._lastProducedBlock?.[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: {},\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":["assertEx","creatable","isDefined","isUndefined","toHex","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","ProducerActor","Actor","RedeclarationWindow","_lastProducedBlock","_lastRedeclarationIntent","_metricAttributes","_producerActorBlockProductionAttempts","_producerActorBlockProductionChecks","_producerActorBlocksProduced","_producerActorBlocksPublished","_accountBalanceViewer","_blockRunner","_blockViewer","_chainId","_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","transportFactory","schemas","HttpRpcTransport","locator","buildJsonRpcProviderLocator","register","SimpleBlockRewardViewer","factory","dependencies","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","_hash","previous","toHex","block","nextBlock","next","displayBlockNumber","submitBlocks","producer","disableIntentRedeclaration","isUndefined","blocksUntilExpiration","undefined","validateCurrentBalance","error","validateCurrentStake","chain","redeclarationIntent","createDeclarationIntent","RedeclarationDuration","submitRedeclarationIntent","tx","buildTransaction","asXL1BlockNumber","submitTransactions","isDefined","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","actors","filter","exists","actor","registerActor","start"]}
|
|
@@ -1,12 +1,9 @@
|
|
|
1
|
-
import type { Logger } from '@xylabs/sdk-js';
|
|
2
1
|
import { type OrchestratorInstance } from '@xyo-network/chain-orchestration';
|
|
3
|
-
import type { Config, ProviderFactoryLocatorInstance } from '@xyo-network/xl1-
|
|
4
|
-
interface RunProducerContext {
|
|
2
|
+
import type { BaseContext, Config, ProviderFactoryLocatorInstance } from '@xyo-network/xl1-sdk';
|
|
3
|
+
export interface RunProducerContext extends BaseContext {
|
|
5
4
|
config: Config;
|
|
6
5
|
locator?: ProviderFactoryLocatorInstance;
|
|
7
|
-
logger: Logger;
|
|
8
6
|
orchestrator: OrchestratorInstance;
|
|
9
7
|
}
|
|
10
|
-
export declare const runProducer: ({ config, logger, orchestrator, }: RunProducerContext) => Promise<void>;
|
|
11
|
-
export {};
|
|
8
|
+
export declare const runProducer: ({ config, logger, orchestrator, locator, }: RunProducerContext) => Promise<void>;
|
|
12
9
|
//# sourceMappingURL=runProducer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runProducer.d.ts","sourceRoot":"","sources":["../../src/runProducer.ts"],"names":[],"mappings":"
|
|
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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xyo-network/chain-producer",
|
|
3
|
-
"version": "1.18.
|
|
3
|
+
"version": "1.18.1",
|
|
4
4
|
"description": "XYO Layer One Producer",
|
|
5
5
|
"homepage": "https://xylabs.com",
|
|
6
6
|
"bugs": {
|
|
@@ -49,13 +49,11 @@
|
|
|
49
49
|
"types": "tsc --noEmit -p tsconfig.test.json"
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {
|
|
52
|
-
"@xylabs/sdk-js": "~5.0.
|
|
53
|
-
"@xyo-network/chain-orchestration": "~1.18.
|
|
54
|
-
"@xyo-network/chain-services": "~1.18.
|
|
55
|
-
"@xyo-network/
|
|
56
|
-
"@xyo-network/xl1-
|
|
57
|
-
"@xyo-network/xl1-providers": "~1.18.0",
|
|
58
|
-
"@xyo-network/xl1-rpc": "~1.18.0",
|
|
52
|
+
"@xylabs/sdk-js": "~5.0.61",
|
|
53
|
+
"@xyo-network/chain-orchestration": "~1.18.1",
|
|
54
|
+
"@xyo-network/chain-services": "~1.18.1",
|
|
55
|
+
"@xyo-network/chain-validation": "~1.18.1",
|
|
56
|
+
"@xyo-network/xl1-sdk": "~1.18.2",
|
|
59
57
|
"async-mutex": "~0.5.0"
|
|
60
58
|
},
|
|
61
59
|
"devDependencies": {
|
|
@@ -63,27 +61,28 @@
|
|
|
63
61
|
"@types/compression": "~1.8.1",
|
|
64
62
|
"@types/cors": "~2.8.19",
|
|
65
63
|
"@types/express": "5.0.6",
|
|
66
|
-
"@types/express-serve-static-core": "~5.1.
|
|
67
|
-
"@types/node": "~25.0.
|
|
68
|
-
"@xylabs/sdk-js": "~5.0.
|
|
64
|
+
"@types/express-serve-static-core": "~5.1.1",
|
|
65
|
+
"@types/node": "~25.0.8",
|
|
66
|
+
"@xylabs/sdk-js": "~5.0.61",
|
|
69
67
|
"@xylabs/ts-scripts-yarn3": "~7.2.32",
|
|
70
68
|
"@xylabs/tsconfig": "~7.2.32",
|
|
71
|
-
"@xyo-network/account": "~5.2.
|
|
72
|
-
"@xyo-network/account-model": "~5.2.
|
|
73
|
-
"@xyo-network/archivist-abstract": "~5.2.
|
|
69
|
+
"@xyo-network/account": "~5.2.22",
|
|
70
|
+
"@xyo-network/account-model": "~5.2.22",
|
|
71
|
+
"@xyo-network/archivist-abstract": "~5.2.22",
|
|
74
72
|
"@xyo-network/bios-model": "~7.2.0",
|
|
75
|
-
"@xyo-network/boundwitness-builder": "~5.2.
|
|
76
|
-
"@xyo-network/chain-services": "~1.18.
|
|
77
|
-
"@xyo-network/
|
|
78
|
-
"@xyo-network/module-
|
|
79
|
-
"@xyo-network/
|
|
80
|
-
"@xyo-network/
|
|
73
|
+
"@xyo-network/boundwitness-builder": "~5.2.22",
|
|
74
|
+
"@xyo-network/chain-services": "~1.18.1",
|
|
75
|
+
"@xyo-network/chain-validation": "~1.18.1",
|
|
76
|
+
"@xyo-network/module-abstract-mongodb": "~5.2.22",
|
|
77
|
+
"@xyo-network/module-model-mongodb": "~5.2.22",
|
|
78
|
+
"@xyo-network/node-memory": "~5.2.22",
|
|
79
|
+
"@xyo-network/xl1-sdk": "~1.18.2",
|
|
81
80
|
"dotenv": "~17.2.3",
|
|
82
81
|
"eslint": "^9.39.2",
|
|
83
82
|
"nodemon": "~3.1.11",
|
|
84
83
|
"tslib": "~2.8.1",
|
|
85
84
|
"typescript": "~5.9.3",
|
|
86
|
-
"vitest": "~4.0.
|
|
85
|
+
"vitest": "~4.0.17",
|
|
87
86
|
"vitest-mock-extended": "~3.1.0"
|
|
88
87
|
},
|
|
89
88
|
"engines": {
|
|
@@ -93,4 +92,4 @@
|
|
|
93
92
|
"publishConfig": {
|
|
94
93
|
"access": "restricted"
|
|
95
94
|
}
|
|
96
|
-
}
|
|
95
|
+
}
|
package/src/ProducerActor.ts
CHANGED
|
@@ -1,34 +1,40 @@
|
|
|
1
1
|
import type { Attributes, Counter } from '@opentelemetry/api'
|
|
2
|
-
import type {
|
|
2
|
+
import type { Address } from '@xylabs/sdk-js'
|
|
3
3
|
import {
|
|
4
|
+
assertEx,
|
|
4
5
|
creatable, isDefined, isUndefined, toHex,
|
|
5
6
|
} from '@xylabs/sdk-js'
|
|
6
|
-
import {
|
|
7
|
-
Actor, type ActorParams, initProducerAccount,
|
|
8
|
-
} from '@xyo-network/chain-orchestration'
|
|
7
|
+
import { initProducerAccount } from '@xyo-network/chain-orchestration'
|
|
9
8
|
import { SimpleBlockRunner } from '@xyo-network/chain-services'
|
|
9
|
+
import { validateHydratedBlock, validateHydratedBlockState } from '@xyo-network/chain-validation'
|
|
10
10
|
import type {
|
|
11
11
|
ChainId,
|
|
12
12
|
ChainStakeIntent, HydratedBlockWithHashMeta,
|
|
13
13
|
XL1BlockNumber,
|
|
14
|
-
} from '@xyo-network/xl1-
|
|
15
|
-
import { asXL1BlockNumber } from '@xyo-network/xl1-protocol'
|
|
14
|
+
} from '@xyo-network/xl1-sdk'
|
|
16
15
|
import {
|
|
17
|
-
AccountBalanceViewer, AccountBalanceViewerMoniker,
|
|
18
|
-
|
|
16
|
+
AccountBalanceViewer, AccountBalanceViewerMoniker, Actor, ActorParams, asXL1BlockNumber,
|
|
17
|
+
BlockRunner, BlockRunnerMoniker,
|
|
18
|
+
BlockViewer, BlockViewerMoniker, buildJsonRpcProviderLocator,
|
|
19
|
+
buildTransaction,
|
|
19
20
|
Config,
|
|
20
21
|
createDeclarationIntent,
|
|
21
22
|
getDefaultConfig,
|
|
22
|
-
MempoolRunner,
|
|
23
|
+
HttpRpcTransport, MempoolRunner,
|
|
23
24
|
MempoolRunnerMoniker,
|
|
24
25
|
MempoolViewer,
|
|
25
26
|
MempoolViewerMoniker,
|
|
27
|
+
RpcSchemaMap, SimpleBlockRewardViewer,
|
|
28
|
+
SimpleBlockValidationViewer,
|
|
26
29
|
StakeTotalsViewer,
|
|
27
30
|
StakeTotalsViewerMoniker,
|
|
28
|
-
|
|
31
|
+
TransportFactory,
|
|
32
|
+
} from '@xyo-network/xl1-sdk'
|
|
29
33
|
import { Mutex } from 'async-mutex'
|
|
30
34
|
|
|
31
|
-
export type ProducerActorParams = ActorParams
|
|
35
|
+
export type ProducerActorParams = ActorParams<{
|
|
36
|
+
rewardAddress: Address
|
|
37
|
+
}>
|
|
32
38
|
|
|
33
39
|
const SHOULD_REGISTER_REDECLARATION_INTENT_TIMER = true
|
|
34
40
|
const TEN_MINUTES = 10 * 60 * 1000 // 10 minutes in milliseconds
|
|
@@ -80,16 +86,58 @@ export class ProducerActor extends Actor<ProducerActorParams> {
|
|
|
80
86
|
return this._mempoolViewer!
|
|
81
87
|
}
|
|
82
88
|
|
|
89
|
+
protected get rewardAddress() {
|
|
90
|
+
return this.params.rewardAddress!
|
|
91
|
+
}
|
|
92
|
+
|
|
83
93
|
protected get stakeTotalsViewer() {
|
|
84
94
|
return this._stakeTotalsViewer!
|
|
85
95
|
}
|
|
86
96
|
|
|
87
|
-
static override async paramsHandler<T extends
|
|
88
|
-
const
|
|
97
|
+
static override async paramsHandler<T extends ProducerActor>(params?: Partial<T['params']>) {
|
|
98
|
+
const logger = params?.context?.logger
|
|
99
|
+
const config = params?.context?.config ?? getDefaultConfig()
|
|
100
|
+
const displayName = params?.displayName ?? 'ProducerActor'
|
|
89
101
|
const account = params?.account ?? await initProducerAccount({ config })
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
102
|
+
const id = account?.address.toString() ?? 'unknown'
|
|
103
|
+
logger?.info(`Running producer for account ${account.address}`)
|
|
104
|
+
const rewardAddress = params?.rewardAddress ?? account.address
|
|
105
|
+
logger?.info(`Using reward address ${rewardAddress}`)
|
|
106
|
+
if (rewardAddress === account.address) {
|
|
107
|
+
logger?.warn(`Using producer account address as reward address: ${account.address}`)
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return {
|
|
111
|
+
...await super.paramsHandler({
|
|
112
|
+
...params,
|
|
113
|
+
account,
|
|
114
|
+
displayName,
|
|
115
|
+
id,
|
|
116
|
+
}),
|
|
117
|
+
rewardAddress,
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
protected static override async initContext(
|
|
122
|
+
params: ProducerActorParams,
|
|
123
|
+
) {
|
|
124
|
+
const config: Config = params?.context?.config ?? getDefaultConfig()
|
|
125
|
+
const endpoint = assertEx(config.services.apiEndpoint, () => 'API endpoint is required in config.services.apiEndpoint')
|
|
126
|
+
|
|
127
|
+
const context = await super.initContext(params)
|
|
128
|
+
|
|
129
|
+
const transportFactory: TransportFactory = (schemas: RpcSchemaMap) => new HttpRpcTransport(endpoint, schemas)
|
|
130
|
+
const locator = await buildJsonRpcProviderLocator({ context, transportFactory })
|
|
131
|
+
locator.register(SimpleBlockRewardViewer.factory(SimpleBlockRewardViewer.dependencies))
|
|
132
|
+
locator.register(SimpleBlockValidationViewer.factory<SimpleBlockValidationViewer>(
|
|
133
|
+
SimpleBlockValidationViewer.dependencies,
|
|
134
|
+
{ state: validateHydratedBlockState, protocol: validateHydratedBlock },
|
|
135
|
+
))
|
|
136
|
+
locator.register(SimpleBlockRunner.factory<SimpleBlockRunner>(
|
|
137
|
+
SimpleBlockRunner.dependencies,
|
|
138
|
+
{ account: params.account, rewardAddress: params.rewardAddress },
|
|
139
|
+
))
|
|
140
|
+
return locator.context
|
|
93
141
|
}
|
|
94
142
|
|
|
95
143
|
override async createHandler() {
|
|
@@ -114,12 +162,30 @@ export class ProducerActor extends Actor<ProducerActorParams> {
|
|
|
114
162
|
'producer_actor_blocks_published',
|
|
115
163
|
{ description: 'Number of blocks published' },
|
|
116
164
|
)
|
|
117
|
-
this._accountBalanceViewer =
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
this.
|
|
122
|
-
|
|
165
|
+
this._accountBalanceViewer = assertEx(
|
|
166
|
+
await this.locator?.getInstance<AccountBalanceViewer>(AccountBalanceViewerMoniker),
|
|
167
|
+
() => 'Unable to locate AccountBalanceViewer',
|
|
168
|
+
)
|
|
169
|
+
this._blockRunner = assertEx(
|
|
170
|
+
await this.locator?.getInstance<BlockRunner>(BlockRunnerMoniker),
|
|
171
|
+
() => 'Unable to locate BlockRunner',
|
|
172
|
+
)
|
|
173
|
+
this._blockViewer = assertEx(
|
|
174
|
+
await this.locator?.getInstance<BlockViewer>(BlockViewerMoniker),
|
|
175
|
+
() => 'Unable to locate BlockViewer',
|
|
176
|
+
)
|
|
177
|
+
this._mempoolRunner = assertEx(
|
|
178
|
+
await this.locator?.getInstance<MempoolRunner>(MempoolRunnerMoniker),
|
|
179
|
+
() => 'Unable to locate MempoolRunner',
|
|
180
|
+
)
|
|
181
|
+
this._mempoolViewer = assertEx(
|
|
182
|
+
await this.locator?.getInstance<MempoolViewer>(MempoolViewerMoniker),
|
|
183
|
+
() => 'Unable to locate MempoolViewer',
|
|
184
|
+
)
|
|
185
|
+
this._stakeTotalsViewer = assertEx(
|
|
186
|
+
await this.locator?.getInstance<StakeTotalsViewer>(StakeTotalsViewerMoniker),
|
|
187
|
+
() => 'Unable to locate StakeTotalsViewer',
|
|
188
|
+
)
|
|
123
189
|
}
|
|
124
190
|
|
|
125
191
|
override async startHandler() {
|
package/src/runProducer.ts
CHANGED
|
@@ -1,68 +1,35 @@
|
|
|
1
|
-
import type { Address, Logger } from '@xylabs/sdk-js'
|
|
2
1
|
import {
|
|
3
|
-
asAddress,
|
|
2
|
+
asAddress, exists, IdLogger,
|
|
4
3
|
} from '@xylabs/sdk-js'
|
|
5
|
-
import type
|
|
6
|
-
import {
|
|
7
|
-
type ActorContext, initProducerAccount, type OrchestratorInstance,
|
|
8
|
-
} from '@xyo-network/chain-orchestration'
|
|
9
|
-
import { validateHydratedBlock, validateHydratedBlockState } from '@xyo-network/chain-validation'
|
|
10
|
-
import { SimpleBlockRunner } from '@xyo-network/chain-services'
|
|
4
|
+
import { initProducerAccount, type OrchestratorInstance } from '@xyo-network/chain-orchestration'
|
|
11
5
|
import type {
|
|
12
|
-
|
|
13
|
-
} from '@xyo-network/xl1-
|
|
14
|
-
import { SimpleBlockRewardViewer, SimpleBlockValidationViewer } from '@xyo-network/xl1-protocol-sdk'
|
|
15
|
-
import { buildJsonRpcProviderLocator } from '@xyo-network/xl1-providers'
|
|
16
|
-
import {
|
|
17
|
-
HttpRpcTransport, type RpcSchemaMap, type TransportFactory,
|
|
18
|
-
} from '@xyo-network/xl1-rpc'
|
|
6
|
+
BaseContext, Config, ProviderFactoryLocatorInstance,
|
|
7
|
+
} from '@xyo-network/xl1-sdk'
|
|
19
8
|
|
|
20
|
-
import { ProducerActor
|
|
9
|
+
import { ProducerActor } from './ProducerActor.ts'
|
|
21
10
|
|
|
22
|
-
interface RunProducerContext {
|
|
11
|
+
export interface RunProducerContext extends BaseContext {
|
|
23
12
|
config: Config
|
|
24
13
|
locator?: ProviderFactoryLocatorInstance
|
|
25
|
-
logger: Logger
|
|
26
14
|
orchestrator: OrchestratorInstance
|
|
27
15
|
}
|
|
28
16
|
|
|
29
|
-
const getProviderFactoryLocator = async (
|
|
30
|
-
context: Omit<CreatableProviderContext, 'locator'>,
|
|
31
|
-
account: AccountInstance,
|
|
32
|
-
rewardAddress: Address,
|
|
33
|
-
) => {
|
|
34
|
-
const endpoint = assertEx(context.config.services.apiEndpoint, () => 'API endpoint is required in config.services.apiEndpoint')
|
|
35
|
-
const transportFactory: TransportFactory = (schemas: RpcSchemaMap) => new HttpRpcTransport(endpoint, schemas)
|
|
36
|
-
const locator = await buildJsonRpcProviderLocator({ context, transportFactory })
|
|
37
|
-
locator.register(SimpleBlockRewardViewer.factory())
|
|
38
|
-
locator.register(SimpleBlockValidationViewer.factory<SimpleBlockValidationViewer>({ state: validateHydratedBlockState, value: validateHydratedBlock }))
|
|
39
|
-
locator.register(SimpleBlockRunner.factory<SimpleBlockRunner>({ account, rewardAddress }))
|
|
40
|
-
return locator
|
|
41
|
-
}
|
|
42
|
-
|
|
43
17
|
export const runProducer = async ({
|
|
44
|
-
config, logger, orchestrator,
|
|
18
|
+
config, logger, orchestrator, locator,
|
|
45
19
|
}: RunProducerContext) => {
|
|
20
|
+
const localLogger = logger ?? new IdLogger(logger ?? console, () => 'ResolveHelper [runProducer]')
|
|
46
21
|
const account = await initProducerAccount({ config })
|
|
47
|
-
|
|
22
|
+
localLogger.info(`Running producer for account ${account.address}`)
|
|
48
23
|
const rewardAddress = asAddress(config.producer.rewardAddress, () => 'rewardAddress is required in config.producer')
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
const locator = await getProviderFactoryLocator({
|
|
52
|
-
config, logger, singletons: {},
|
|
53
|
-
}, account, rewardAddress)
|
|
54
|
-
|
|
55
|
-
const context: ActorContext = {
|
|
56
|
-
locator, config, singletons: locator.context.singletons,
|
|
57
|
-
}
|
|
24
|
+
localLogger.info(`Using reward address ${rewardAddress}`)
|
|
58
25
|
|
|
59
26
|
// Create actors
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
27
|
+
const producer = await ProducerActor.create({
|
|
28
|
+
logger,
|
|
29
|
+
context: {
|
|
30
|
+
config, locator, singletons: {},
|
|
31
|
+
},
|
|
32
|
+
})
|
|
66
33
|
const actors = [producer].filter(exists)
|
|
67
34
|
|
|
68
35
|
for (const actor of actors) {
|